Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Create restriction maps showing enzyme cut positions on DNA sequences using Biopython Bio.Restriction. Visualize cut sites, calculate distances between sites, and generate text or graphical maps. Use when creating or analyzing restriction maps.
.claude/skills/bio-restriction-mapping/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 105% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 49% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 22% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 148% | 0% |
| case-14 | ✗→✓ | ▲ Improved | -45% | 0% |
<!--
#
#
-->
pythonfrom Bio import SeqIO from Bio.Restriction import EcoRI, BamHI, HindIII, RestrictionBatch, Analysis record = SeqIO.read('sequence.fasta', 'fasta') seq = record.seq batch = RestrictionBatch([EcoRI, BamHI, HindIII]) analysis = Analysis(batch, seq) # Print formatted map analysis.print_as('map')
python# Map format (visual) analysis.print_as('map') # Linear format (list) analysis.print_as('linear') # Tabular format analysis.print_as('tabulate') # Get as string instead of printing map_str = analysis.format_as('map') linear_str = analysis.format_as('linear')
pythonfrom Bio.Restriction import EcoRI, BamHI ecori_sites = EcoRI.search(seq) bamhi_sites = BamHI.search(seq) # All cut positions sorted all_sites = sorted(ecori_sites + bamhi_sites) # Calculate distances between consecutive sites distances = [] for i in range(len(all_sites) - 1): dist = all_sites[i + 1] - all_sites[i] distances.append((all_sites[i], all_sites[i + 1], dist)) print(f'{all_sites[i]} -> {all_sites[i + 1]}: {dist} bp')
pythonfrom Bio import SeqIO from Bio.Restriction import RestrictionBatch, Analysis from Bio.Restriction import EcoRI, BamHI, HindIII, XhoI, NotI record = SeqIO.read('plasmid.fasta', 'fasta') seq = record.seq seq_len = len(seq) enzymes = RestrictionBatch([EcoRI, BamHI, HindIII, XhoI, NotI]) analysis = Analysis(enzymes, seq, linear=False) print(f'Restriction Map: {record.id}') print(f'Length: {seq_len} bp (circular)') print('=' * 50) results = analysis.full() all_cuts = [] for enzyme, sites in results.items(): for site in sites: all_cuts.append((site, str(enzyme))) all_cuts.sort(key=lambda x: x[0]) print('\nCut sites (5\' -> 3\'):') for pos, enz in all_cuts: pct = (pos / seq_len) * 100 print(f' {pos:6d} bp ({pct:5.1f}%) - {enz}')
pythondef draw_restriction_map(seq, results, width=80): '''Draw a simple text restriction map''' seq_len = len(seq) scale = width / seq_len # Header print(f'0{" " * (width - 6)}{seq_len}') print('|' + '-' * (width - 2) + '|') # Plot each enzyme for enzyme, sites in results.items(): if not sites: continue line = [' '] * width for site in sites: pos = int(site * scale) if pos >= width: pos = width - 1 line[pos] = '|' print(''.join(line) + f' {enzyme}') print('|' + '-' * (width - 2) + '|') # Usage batch = RestrictionBatch([EcoRI, BamHI, HindIII]) analysis = Analysis(batch, seq) results = analysis.full() draw_restriction_map(seq, results)
pythonfrom Bio import SeqIO from Bio.Restriction import RestrictionBatch, Analysis, EcoRI, BamHI record = SeqIO.read('plasmid.gb', 'genbank') seq = record.seq enzymes = RestrictionBatch([EcoRI, BamHI]) analysis = Analysis(enzymes, seq, linear=False) results = analysis.full() print('Restriction Sites and Overlapping Features:') print('=' * 60) for enzyme, sites in results.items(): for site in sites: print(f'\n{enzyme} at position {site}:') for feature in record.features: start = int(feature.location.start) end = int(feature.location.end) if start <= site <= end: feat_type = feature.type label = feature.qualifiers.get('label', feature.qualifiers.get('gene', ['unknown']))[0] print(f' Within {feat_type}: {label} ({start}-{end})')
pythondef export_restriction_map(seq, results, output_file, seq_name='sequence'): '''Export restriction map to text file''' with open(output_file, 'w') as f: f.write(f'Restriction Map: {seq_name}\n') f.write(f'Length: {len(seq)} bp\n') f.write('=' * 50 + '\n\n') all_cuts = [] for enzyme, sites in results.items(): for site in sites: all_cuts.append((site, str(enzyme))) all_cuts.sort() f.write('Site\tPosition\tFrom_Start\n') for pos, enz in all_cuts: f.write(f'{enz}\t{pos}\t{pos}\n') f.write('\n\nFragment sizes between sites:\n') if all_cuts: positions = sorted([c[0] for c in all_cuts]) for i in range(len(positions) - 1): size = positions[i + 1] - positions[i] f.write(f'{positions[i]} -> {positions[i + 1]}: {size} bp\n') # Usage export_restriction_map(seq, results, 'restriction_map.txt', record.id)
pythondef circular_distances(sites, seq_len): '''Calculate fragment sizes for circular DNA''' if not sites: return [] sites = sorted(sites) fragments = [] # Between consecutive sites for i in range(len(sites) - 1): fragments.append(sites[i + 1] - sites[i]) # Wrap-around fragment wrap = (seq_len - sites[-1]) + sites[0] fragments.append(wrap) return fragments # Usage ecori_sites = EcoRI.search(seq, linear=False) fragments = circular_distances(ecori_sites, len(seq)) print(f'EcoRI fragments (circular): {fragments}')
<!-- 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-22 | pass→pass | 11,847 | 8,402 | -29% | 1 | 1 | 0% | 2,336 | 3,434 | +47% | 0 | 0 | — |
case-07 | fail→pass | 5,860 | 3,789 | -35% | 1 | 1 | 0% | 1,145 | 2,346 | +105% | 0 | 0 | — |
case-01 | fail→pass | 9,591 | 5,443 | -43% | 1 | 1 | 0% | 2,053 | 3,060 | +49% | 0 | 0 | — |
case-02 | fail→fail | 25,284 | 15,417 | -39% | 1 | 1 | 0% | 3,928 | 3,847 | -2% | 0 | 0 | — |
case-08 | pass→pass | 6,282 | 4,291 | -32% | 1 | 1 | 0% | 1,169 | 2,554 | +118% | 0 | 0 | — |
case-03 | pass→pass | 11,388 | 8,086 | -29% | 1 | 1 | 0% | 2,466 | 3,671 | +49% | 0 | 0 | — |
case-04 | fail→pass | 9,945 | 3,191 | -68% | 1 | 1 | 0% | 1,944 | 2,380 | +22% | 0 | 0 | — |
case-05 | pass→pass | 5,458 | 2,966 | -46% | 1 | 1 | 0% | 1,049 | 2,404 | +129% | 0 | 0 | — |
case-06 | fail→pass | 5,496 | 5,053 | -8% | 1 | 1 | 0% | 1,097 | 2,718 | +148% | 0 | 0 | — |
case-09 | fail→fail | 6,678 | 4,281 | -36% | 1 | 1 | 0% | 1,166 | 2,652 | +127% | 0 | 0 | — |
case-10 | pass→pass | 3,788 | 3,502 | -8% | 1 | 1 | 0% | 718 | 2,512 | +250% | 0 | 0 | — |
case-11 | pass→pass | 9,029 | 4,144 | -54% | 1 | 1 | 0% | 1,575 | 2,548 | +62% | 0 | 0 | — |
case-12 | pass→pass | 6,968 | 2,844 | -59% | 1 | 1 | 0% | 1,329 | 2,359 | +78% | 0 | 0 | — |
case-13 | pass→pass | 18,621 | 13,328 | -28% | 1 | 1 | 0% | 3,358 | 4,322 | +29% | 0 | 0 | — |
case-14 | fail→pass | 23,430 | 3,479 | -85% | 1 | 1 | 0% | 4,435 | 2,448 | -45% | 0 | 0 | — |
case-15 | pass→pass | 4,086 | 2,809 | -31% | 1 | 1 | 0% | 713 | 2,243 | +215% | 0 | 0 | — |
case-16 | pass→pass | 5,398 | 3,844 | -29% | 1 | 1 | 0% | 1,037 | 2,524 | +143% | 0 | 0 | — |
case-21 | pass→fail | 13,621 | 15,847 | +16% | 1 | 1 | 0% | 2,703 | 5,276 | +95% | 0 | 0 | — |
case-17 | fail→pass | 5,682 | 4,582 | -19% | 1 | 1 | 0% | 1,075 | 2,721 | +153% | 0 | 0 | — |
case-18 | pass→pass | 7,600 | 4,999 | -34% | 1 | 1 | 0% | 1,465 | 2,666 | +82% | 0 | 0 | — |
case-19 | pass→pass | 5,674 | 5,493 | -3% | 1 | 1 | 0% | 1,076 | 2,840 | +164% | 0 | 0 | — |
case-20 | pass→pass | 10,460 | 8,677 | -17% | 1 | 1 | 0% | 1,967 | 3,606 | +83% | 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. 22 cases were attempted. The headline lift of +23 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
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/24/2026 | +32% |
Other measured skills in the registry, with their headline benchmark lift.