Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Calculate sequence properties like GC content, molecular weight, isoelectric point, and GC skew using Biopython. Use when analyzing sequence composition, computing physical properties, or comparing sequences.
.claude/skills/bio-sequence-properties/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 15% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 67% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 94% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 49% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 95% | 0% |
<!--
#
#
-->
Calculate physical and chemical properties of biological sequences using Biopython.
pythonfrom Bio.Seq import Seq from Bio.SeqUtils import gc_fraction, molecular_weight, GC123, GC_skew, nt_search, seq1, seq3 from Bio.SeqUtils.ProtParam import ProteinAnalysis
pythonfrom Bio.SeqUtils import gc_fraction seq = Seq('ATGCGATCGATCGATCGATCG') gc = gc_fraction(seq) # Returns 0.476... (fraction) gc_percent = gc * 100 # Convert to percentage
Handle ambiguous bases:
pythongc = gc_fraction(seq, ambiguous='ignore') # Ignore N bases in calculation gc = gc_fraction(seq, ambiguous='weighted') # Weight by probability
Analyze GC content at each codon position (useful for codon bias analysis):
pythonfrom Bio.SeqUtils import GC123 seq = Seq('ATGCGATCGATCGATCGATCG') gc_total, gc_pos1, gc_pos2, gc_pos3 = GC123(seq) # gc_total: overall GC% # gc_pos1: GC% at 1st codon position # gc_pos2: GC% at 2nd codon position # gc_pos3: GC% at 3rd codon position (wobble)
Calculate (G-C)/(G+C) in sliding windows to identify replication origins:
pythonfrom Bio.SeqUtils import GC_skew seq = Seq('ATGCGATCGATCGATCGATCG' * 10) skew_values = GC_skew(seq, window=100) # Returns list of skew values
pythonfrom Bio.SeqUtils import molecular_weight dna = Seq('ATGCGATCG') mw = molecular_weight(dna) # Single-stranded DNA weight # Double-stranded DNA mw_ds = molecular_weight(dna, double_stranded=True) # Circular DNA mw_circ = molecular_weight(dna, circular=True) # RNA rna = Seq('AUGCGAUCG') mw_rna = molecular_weight(rna, seq_type='RNA') # Protein protein = Seq('MRCRS') mw_prot = molecular_weight(protein, seq_type='protein')
pythonfrom Bio.SeqUtils import MeltingTemp seq = Seq('ATGCGATCGATCG') # Basic Tm (Wallace rule - short oligos) tm_wallace = MeltingTemp.Tm_Wallace(seq) # GC method (more accurate for longer sequences) tm_gc = MeltingTemp.Tm_GC(seq) # Nearest neighbor (most accurate) tm_nn = MeltingTemp.Tm_NN(seq) # With salt correction tm_corrected = MeltingTemp.Tm_NN(seq, Na=50, Mg=1.5)
Built-in search that handles IUPAC ambiguity codes:
pythonfrom Bio.SeqUtils import nt_search seq = 'ATGCGATCGATCGATNGATC' # Search for pattern with ambiguous bases result = nt_search(seq, 'GATNGATC') # N matches any base # Returns: ['GATNGATC', 8] - pattern and position(s)
pythondef base_composition(seq): seq_str = str(seq).upper() total = len(seq_str) return {base: seq_str.count(base) / total * 100 for base in 'ATGC'}
Convert between 1-letter and 3-letter amino acid codes:
pythonfrom Bio.SeqUtils import seq1, seq3 # 3-letter to 1-letter one_letter = seq1('MetAlaGlyTrp') # Returns 'MAGW' # 1-letter to 3-letter three_letter = seq3('MAGW') # Returns 'MetAlaGlyTrp' # With custom separator three_letter = seq3('MAGW', join='-') # Returns 'Met-Ala-Gly-Trp'
pythonfrom Bio.SeqUtils.ProtParam import ProteinAnalysis protein = ProteinAnalysis('MAEGEITTFTALTEKFNLPPGNYKKPKLLYCSNG')
pythonmw = protein.molecular_weight() # Molecular weight in Daltons pi = protein.isoelectric_point() # Isoelectric point aa_comp = protein.amino_acids_percent # Amino acid composition (property) aa_count = protein.count_amino_acids() # Raw amino acid counts
pythoninstability = protein.instability_index() # < 40 = stable, > 40 = unstable gravy = protein.gravy() # Negative = hydrophilic, Positive = hydrophobic arom = protein.aromaticity() # Fraction of Phe+Trp+Tyr
pythoncharge = protein.charge_at_pH(7.0) # Net charge at pH 7.0 charge_acidic = protein.charge_at_pH(4.0) charge_basic = protein.charge_at_pH(10.0)
pythonflexibility = protein.flexibility() # List of flexibility values per residue # Based on Vihinen, 1994 scale
pythonhelix, turn, sheet = protein.secondary_structure_fraction()
pythoneps_reduced, eps_cystine = protein.molar_extinction_coefficient() # eps_reduced: all Cys are reduced # eps_cystine: all Cys form disulfide bonds
Calculate profiles using any amino acid scale:
python# Kyte-Doolittle hydropathy profile kd_scale = {'A': 1.8, 'R': -4.5, 'N': -3.5, ...} profile = protein.protein_scale(kd_scale, window=7)
pythonfrom Bio import SeqIO from Bio.SeqUtils import gc_fraction def analyze_fasta(filename): results = [] for record in SeqIO.parse(filename, 'fasta'): results.append({ 'id': record.id, 'length': len(record.seq), 'gc': gc_fraction(record.seq) * 100 }) return results
pythonfrom Bio.SeqUtils import gc_fraction def gc_distribution(seq, window_size=100, step=50): gc_values = [] for i in range(0, len(seq) - window_size + 1, step): window = seq[i:i + window_size] gc_values.append((i, gc_fraction(window) * 100)) return gc_values
pythonfrom Bio.SeqUtils import GC_skew def gc_skew_analysis(seq, window=1000): skew = GC_skew(seq, window=window) positions = list(range(0, len(seq) - window + 1, window)) cumulative = [] total = 0 for s in skew: total += s cumulative.append(total) return positions, skew, cumulative
pythonfrom Bio.SeqUtils.ProtParam import ProteinAnalysis def protein_report(sequence): protein = ProteinAnalysis(str(sequence).replace('*', '')) helix, turn, sheet = protein.secondary_structure_fraction() return { 'length': len(sequence), 'molecular_weight': protein.molecular_weight(), 'isoelectric_point': protein.isoelectric_point(), 'charge_at_pH7': protein.charge_at_pH(7.0), 'instability_index': protein.instability_index(), 'gravy': protein.gravy(), 'aromaticity': protein.aromaticity(), 'helix_fraction': helix, 'turn_fraction': turn, 'sheet_fraction': sheet, }
pythonfrom collections import Counter def dinucleotide_freq(seq): seq_str = str(seq) dinucs = [seq_str[i:i+2] for i in range(len(seq_str) - 1)] counts = Counter(dinucs) total = sum(counts.values()) return {di: count / total for di, count in counts.items()}
pythondef cpg_ratio(seq): seq_str = str(seq).upper() cpg = seq_str.count('CG') c = seq_str.count('C') g = seq_str.count('G') expected = (c * g) / len(seq_str) if len(seq_str) > 0 else 0 return cpg / expected if expected > 0 else 0
| Property | Function | Notes | |----------|----------|-------| | GC content | gc_fraction() | Returns fraction (0-1) | | GC by position | GC123() | Total, pos1, pos2, pos3 | | GC skew | GC_skew() | (G-C)/(G+C) in windows | | Molecular weight | molecular_weight() | In Daltons | | Melting temp | MeltingTemp.Tm_*() | Multiple methods | | IUPAC search | nt_search() | Handles ambiguity codes |
| Property | Method | Typical Range | |----------|--------|---------------| | MW | molecular_weight() | Daltons | | pI | isoelectric_point() | 0-14 | | Charge | charge_at_pH(pH) | Varies | | Instability | instability_index() | <40 stable | | GRAVY | gravy() | -2 to +2 | | Aromaticity | aromaticity() | 0-0.15 | | Flexibility | flexibility() | Per-residue list |
| Function | Input | Output | |----------|-------|--------| | seq1() | 'MetAlaGly' | 'MAG' | | seq3() | 'MAG' | 'MetAlaGly' |
| Error | Cause | Solution | |-------|-------|----------| | KeyError in ProteinAnalysis | Non-standard amino acid | Remove X, , etc. | | Wrong MW | Wrong seq_type | Specify 'RNA' or 'protein' | | Invalid Tm | Sequence too short | Use >10 bp for accurate Tm | | Empty GC_skew | Sequence shorter than window | Reduce window size |
Need sequence properties?
├── DNA/RNA sequence?
│ ├── GC content? → gc_fraction()
│ ├── GC at codon positions? → GC123()
│ ├── GC skew (replication origin)? → GC_skew()
│ ├── Molecular weight? → molecular_weight()
│ ├── Melting temperature? → MeltingTemp.Tm_NN()
│ └── Search with IUPAC codes? → nt_search()
├── Protein sequence?
│ └── Create ProteinAnalysis object
│ ├── Size → molecular_weight()
│ ├── Charge → isoelectric_point(), charge_at_pH()
│ ├── Stability → instability_index()
│ ├── Hydrophobicity → gravy()
│ ├── Flexibility → flexibility()
│ └── Structure → secondary_structure_fraction()
└── Convert amino acid codes?
└── seq1() / seq3()<!-- AUTHOR_SIGNATURE: 9a7f3c2e-MD-BABU-MIA-2026-MSSM-SECURE -->
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 18,842 | 8,734 | -54% | 1 | 1 | 0% | 4,422 | 5,106 | +15% | 0 | 0 | — |
case-02 | fail→pass | 17,212 | 8,230 | -52% | 1 | 1 | 0% | 3,017 | 5,046 | +67% | 0 | 0 | — |
case-03 | fail→pass | 11,623 | 7,090 | -39% | 1 | 1 | 0% | 2,349 | 4,557 | +94% | 0 | 0 | — |
case-20 | pass→pass | 11,796 | 8,232 | -30% | 1 | 1 | 0% | 2,332 | 4,920 | +111% | 0 | 0 | — |
case-04 | fail→pass | 14,891 | 7,061 | -53% | 1 | 1 | 0% | 3,023 | 4,502 | +49% | 0 | 0 | — |
case-05 | pass→pass | 17,297 | 3,677 | -79% | 1 | 1 | 0% | 2,513 | 3,716 | +48% | 0 | 0 | — |
case-06 | pass→pass | 10,911 | 5,046 | -54% | 1 | 1 | 0% | 2,218 | 4,051 | +83% | 0 | 0 | — |
case-07 | fail→pass | 12,858 | 8,236 | -36% | 1 | 1 | 0% | 2,447 | 4,761 | +95% | 0 | 0 | — |
case-08 | fail→pass | 6,637 | 3,657 | -45% | 1 | 1 | 0% | 1,453 | 3,889 | +168% | 0 | 0 | — |
case-09 | pass→pass | 6,749 | 4,146 | -39% | 1 | 1 | 0% | 1,406 | 3,963 | +182% | 0 | 0 | — |
case-10 | fail→pass | 14,056 | 5,368 | -62% | 1 | 1 | 0% | 3,189 | 4,236 | +33% | 0 | 0 | — |
case-11 | pass→pass | 12,509 | 3,970 | -68% | 1 | 1 | 0% | 2,066 | 3,831 | +85% | 0 | 0 | — |
case-12 | pass→pass | 13,407 | 5,016 | -63% | 1 | 1 | 0% | 2,595 | 4,107 | +58% | 0 | 0 | — |
case-13 | fail→pass | 10,463 | 7,945 | -24% | 1 | 1 | 0% | 2,250 | 4,780 | +112% | 0 | 0 | — |
case-14 | pass→pass | 12,489 | 7,973 | -36% | 1 | 1 | 0% | 2,468 | 4,717 | +91% | 0 | 0 | — |
case-15 | fail→pass | 17,005 | 3,940 | -77% | 1 | 1 | 0% | 3,753 | 3,886 | +4% | 0 | 0 | — |
case-16 | fail→pass | 14,973 | 9,800 | -35% | 1 | 1 | 0% | 3,048 | 5,083 | +67% | 0 | 0 | — |
case-17 | pass→pass | 10,164 | 4,808 | -53% | 1 | 1 | 0% | 2,074 | 4,045 | +95% | 0 | 0 | — |
case-18 | fail→pass | 9,191 | 6,174 | -33% | 1 | 1 | 0% | 1,901 | 4,350 | +129% | 0 | 0 | — |
case-19 | pass→pass | 9,874 | 5,695 | -42% | 1 | 1 | 0% | 1,872 | 4,348 | +132% | 0 | 0 | — |
case-21 | pass→pass | 9,963 | 7,039 | -29% | 1 | 1 | 0% | 2,109 | 4,639 | +120% | 0 | 0 | — |
case-22 | pass→pass | 11,347 | 8,173 | -28% | 1 | 1 | 0% | 2,287 | 4,752 | +108% | 0 | 0 | — |
case-23 | pass→pass | 19,875 | 13,256 | -33% | 1 | 1 | 0% | 4,448 | 6,108 | +37% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +48 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 7/26/2026 | +23% |
Other measured skills in the registry, with their headline benchmark lift.