This skill enables AI agents to help you extract, slice, and concatenate biological sequences with Biopython. It covers bare-Seq slicing, carrying a sub-region of an annotated record (with quality scores and features) into a new record, coordinate-system conversion, and joining sequences. The central judgment it encodes is what metadata survives a SeqRecord slice and how to avoid the 0-based vs 1-based off-by-one.
pip install biopython
Tell your AI agent what you want to do:
"Extract nucleotides 100 to 500 from my sequence and return a Seq."
"My GFF says the feature spans 1234 to 5678 (1-based inclusive). Slice the matching subsequence without an off-by-one."
"This interval came from a BED file (0-based). Extract it correctly."
"Slice positions 100-400 out of this FASTQ record but keep the per-base quality scores."
"Extract this region of a GenBank record and carry the organism and taxonomy into the new record."
"Splice these three exon coordinate pairs into a single mRNA sequence."
"Extract every CDS feature from this GenBank file, strand-aware."
"Split this coding sequence into codons."
"Concatenate these sequences with NNNNNN between each."
"Give me 50 bp on each side of position 1000."
Seq slice or a SeqRecord slice (qualities/features to keep).feature.extract() for strand-aware/joined locations.annotations dict explicitly when carrying a sub-region into a new record.Python and Biopython slice 0-based and half-open: seq[0] is the first base, seq[0:3] returns three bases (0, 1, 2), seq[100:200] returns 100 bases. File formats differ:
seq[start-1:end]. The exclusive Python end already cancels the inclusive file end, so the end needs no change.Bio.SeqFeature locations store 0-based start and Python-style end, so feature.extract(record.seq) slices correctly and handles strand and joined exons.record[start:end] preserves id, name, description, and molecule_type, and auto-slices per-letter data (PHRED quality in letter_annotations) to match. It keeps only features fully contained in the range, with recalculated locations. It SILENTLY drops the annotations dict (organism, taxonomy, references), dbxrefs, and any feature straddling the boundary. A stride such as record[::2] drops features entirely. Copy what you need: sub.annotations = record.annotations.copy().
SeqRecord (not record.seq) when per-base qualities or contained features must ride along.annotations after a SeqRecord slice; slicing always drops it without warning.seq[::-1] reverses but does NOT complement; use reverse_complement() for the opposite strand.feature.extract(record.seq) for any strand-aware or joined/compound location instead of a manual slice.sum() over slices needs a Seq('') start value; the default 0 cannot be added to a Seq.str(record.seq) with len() first; undefined content raises UndefinedSequenceError.