| name | python-bio-python-introduction |
| description | Foundational Python for biology - count nucleotides, compute GC content, use f-strings/loops/functions, and set up biopython/pandas/numpy via pip/venv/conda. Use when a beginner asks how to start with Python for bioinformatics, write a first DNA-parsing script, calculate GC content from a raw string, or install BioPython/scanpy/pysam in a virtualenv or conda environment. |
| tool_type | python |
| primary_tool | biopython |
Python Introduction for Bioinformatics
When to Use
- Onboarding someone new to Python who wants a biology-flavored first program (nucleotide counting, GC content).
- Choosing which scientific/bio Python packages to install for a given task (BioPython, pandas, pysam, scanpy, scikit-bio).
- Setting up a reproducible environment with
venv or conda before starting any bioinformatics project.
- Explaining core language pitfalls (f-strings, mutable defaults, 0- vs 1-based coordinates) that trip up biologists writing their first scripts.
- Quick BioPython
Seq demo (complement, reverse complement, transcription, translation).
Version Compatibility
- Python ≥ 3.10 (f-strings,
str.maketrans, walrus operator all stable)
- biopython ≥ 1.83 (
Bio.SeqUtils.gc_fraction; older code used the removed GC() function)
- pandas ≥ 2.1, numpy ≥ 1.26 (only needed once you move past raw strings to tabular data)
Prerequisites
- No prior programming experience required for this skill itself.
pip install biopython (or conda install -c bioconda biopython) for the Bio.Seq demo.
- A terminal for
venv/conda environment setup.
Goal: Count nucleotides and compute GC content from a raw DNA string
Approach: Use str.count() for a one-off tally, or a loop over a dict when you need per-base percentages in one pass. GC content (fraction of G+C) is one of the first statistics computed on any new sequence — it correlates with melting temperature and gene density.
def nucleotide_counts(dna: str) -> dict:
"""Return counts of A/C/G/T in a DNA string using str.count()."""
dna = dna.upper()
return {base: dna.count(base) for base in "ACGT"}
def nucleotide_percentages(dna: str) -> dict:
"""Return per-base percentages via a single pass through the sequence."""
counts = {"A": 0, "C": 0, "G": 0, "T": 0}
for nt in dna.upper():
if nt in counts:
counts[nt] += 1
total = len(dna)
return {base: count / total * 100 for base, count in counts.items()}
def gc_content(sequence: str) -> float:
"""Calculate GC content of a DNA sequence as a percentage (0-100)."""
sequence = sequence.upper()
gc = sequence.count("G") + sequence.count("C")
return gc / len(sequence) * 100
if __name__ == "__main__":
dna =
counts = nucleotide_counts(dna)
()
gc = gc_content(dna)
()
gc < :
()
gc > :
()
:
()
Goal: Basic sequence manipulation with BioPython's Seq
Approach: Bio.Seq.Seq wraps a string with biology-aware methods (complement, reverse_complement, transcribe, translate) so you don't hand-roll base-pairing tables for routine tasks.
def biopython_demo(sequence: str = "ATGAAACCCGGGTAA") -> None:
"""Show core Bio.Seq operations: complement, RC, transcription, translation, GC."""
from Bio.Seq import Seq
from Bio.SeqUtils import gc_fraction
seq = Seq(sequence)
print(f"Sequence: {seq}")
print(f"Complement: {seq.complement()}")
print(f"Reverse complement: {seq.reverse_complement()}")
print(f"Transcribed (RNA): {seq.transcribe()}")
print(f"Translated: {seq.translate()}")
print(f"GC fraction: {gc_fraction(seq):.3f}")
if __name__ == "__main__":
biopython_demo()
Goal: Set up an isolated environment for a bioinformatics project
Approach: Use venv for a pure-Python project; use conda when you also need compiled, non-Python tools (BLAST, samtools) in the same environment.
python -m venv bioenv
source bioenv/bin/activate
pip install biopython pandas numpy matplotlib seaborn
pip install -r requirements.txt
pip list
deactivate
conda create -n bioenv python=3.11
conda activate bioenv
conda install -c conda-forge biopython pandas matplotlib
conda install -c bioconda blast samtools
Pitfalls
- f-strings vs
% formatting: f-strings (f"GC = {gc:.2f}%") are the modern approach (Python ≥3.6); older code uses "GC = %.2f%%" % gc.
print() returns None: never write result = print(...) expecting to capture output — assign the value directly instead.
- Mutable default arguments: never
def f(x=[]); use def f(x=None): x = x if x is not None else [].
- 0-based vs 1-based coordinates: Python slicing/ranges are half-open
[start, stop) and 0-based, but genomic coordinate systems (GFF, VCF, 1-based) are not — off-by-one errors are the most common bug when converting between them.
- Deep vs shallow copy: nested structures (e.g. a list of per-sample count dicts) need
copy.deepcopy(); list.copy() only copies the top level.
Bio.SeqUtils.GC() is gone: newer BioPython uses gc_fraction() (returns 0-1, not 0-100) — multiply by 100 if you want a percentage.
See Also
biopython — deeper Bio.Seq/Bio.SeqIO/Bio.SeqUtils reference
bio-sequence-io-read-sequences — reading FASTA/FASTQ files instead of raw strings
bio-sequence-manipulation-seq-objects — Seq object operations in depth
bio-sequence-manipulation-transcription-translation — transcription/translation details