Lesson 1 of 10 ⏱ 55 min ✓ Free

Python Setup & Jupyter for Bioinformatics

Python is the primary language of modern bioinformatics. Set up your environment correctly with conda, install the essential packages, and get Jupyter running — your interactive workspace for sequence analysis.

01 Why Python for biology?

If you work in bioinformatics, you will write Python. Not because someone decided this arbitrarily — but because Python became the dominant language of this field for very concrete reasons. Every major analysis tool — Snakemake, Scanpy, MACS3, DeepVariant — is written in Python. The libraries for handling biological data are mature and actively maintained. And the syntax is readable enough that a biologist, not a computer scientist, can learn it productively.

Bash handles pipelines, file operations, and process management on the command line. Python handles everything more complex: parsing file formats, computing statistics on sequences, building reusable functions, querying databases, and producing publication-quality figures. The two languages work together — Bash orchestrates the pipeline, Python does the analysis inside each step.

💡 A real example from a bioinformatics lab

You receive 48 RNA-seq FASTQ files. A Bash script loops over them and calls STAR to align each one. The counts from STAR go into a folder. A Python script then reads all count files, builds a gene-by-sample matrix, filters low-count genes, and writes a clean TSV that DESeq2 will read in R. That Python script is always custom — written by a bioinformatician for that specific project. That is the script you will be able to write after this module.

A second example: Sorghum bicolor has a GC content of ~61%. When you sequence a sample and suspect contamination, you write a Python script that reads each FASTQ read, computes GC content, and flags reads that deviate more than 15% from the expected value. Ten lines of Python. This lesson teaches you the foundation for exactly that.

Python versions

Python 2 is dead and removed from all major Linux distributions. Every bioinformatics tool you will encounter requires Python 3. The current stable version is Python 3.12. This course uses 3.10 or higher throughout. Never install system-wide packages — always use a conda environment.

02 Setting up with conda

The first rule of bioinformatics Python: never install packages into system Python. The Python that ships with Ubuntu is owned by the operating system. Installing packages into it can break system tools. Instead, create a dedicated conda environment called bioinfo-py — an isolated Python installation with its own packages, completely separate from the system.

💡 Why a dedicated environment?

Imagine two projects running in parallel. Project A needs Biopython 1.79 and numpy 1.23. Project B needs Biopython 1.83 and numpy 1.26. If they share one Python installation, the packages conflict and one project breaks. Conda environments solve this by giving each project its own isolated Python with its own dependency versions.

In bioinformatics this is not optional — tools like MACS3, Scanpy, and pysam each have strict and often conflicting dependency trees. Environments are how professionals stay sane. You will create a new environment for each major analysis in your career.

Create the bioinfo-py environment

📁 Run from: anywhere — this is a terminal command
bash
# Create a fresh conda environment named "bioinfo-py"
# with Python 3.12 — the current stable release
conda create -n bioinfo-py python=3.12 -y

# Activate it — your prompt will change to (bioinfo-py)
conda activate bioinfo-py

# Confirm you are using the environment's Python, not the system one
which python
/home/shajedur/miniforge3/envs/bioinfo-py/bin/python

python --version
Python 3.12.x
💡 The path returned by which python must contain your environment name (envs/bioinfo-py). If it shows /usr/bin/python, the environment is not active. Run conda activate bioinfo-py again.

Create your working directory

All scripts and notebooks for this course live in one folder. Create it now and keep it organised from lesson 1.

📁 Run from: ~ (your home directory)
bash
# Create the full directory structure for the course
mkdir -p ~/python-bioinfo-scripts/notebooks
mkdir -p ~/python-bioinfo-scripts/scripts
mkdir -p ~/python-bioinfo-scripts/data/raw
mkdir -p ~/python-bioinfo-scripts/data/processed
mkdir -p ~/python-bioinfo-scripts/results

# Confirm the structure was created
ls -lh ~/python-bioinfo-scripts/
drwxr-xr-x  notebooks/
drwxr-xr-x  scripts/
drwxr-xr-x  data/
drwxr-xr-x  results/

03 Essential packages

Python's power in bioinformatics comes from its ecosystem. Five packages cover the vast majority of what you will do in this course and in a real lab:

💡 Why these five packages specifically?

numpy gives you fast numerical arrays — essential when you have a matrix of 20,000 genes × 500 samples and need to compute means, standard deviations, or correlations across all of them in milliseconds. Plain Python lists are too slow for this.

pandas gives you DataFrames — the table structure you will use to hold count matrices, VCF metadata, sample annotation files, and any tabular output from alignment tools. Think of it as a programmable spreadsheet.

biopython understands biological file formats natively — FASTA, FASTQ, GenBank, BLAST XML, VCF — so you do not have to write parsers from scratch. It also wraps common operations: translation, reverse complement, sequence alignment scoring.

matplotlib and seaborn produce the plots that go into papers: coverage plots, heatmaps, volcano plots, PCA scatter plots. Seaborn is built on top of matplotlib and adds statistical visualisations with less code.

📁 Run from: anywhere — conda environment must be active first
bash
# Activate your environment (if not already active)
conda activate bioinfo-py

# Install all core packages in one command
# -c conda-forge  : the community-maintained package channel (more up-to-date)
# -c bioconda     : the biology-specific package channel (biopython lives here)
# -y              : auto-confirm without prompts
conda install -c conda-forge -c bioconda -y \
  numpy pandas biopython matplotlib seaborn jupyterlab ipykernel

# Verify every package installed correctly
# If any line throws an error, re-run the install above
python -c "import numpy, pandas, Bio, matplotlib, seaborn; print('All packages OK')"
All packages OK
Package What it does Used in lesson
numpyFast numerical arrays and mathsLesson 5
pandasDataFrames for tabular genomic dataLesson 5
biopythonBiological file format parsersLesson 6
matplotlibCore plotting libraryLesson 8
seabornStatistical visualisationLesson 8
jupyterlabInteractive notebook environmentThis lesson
ipykernelRegisters your conda env as a Jupyter kernelThis lesson
⚠️ Never use sudo pip install for bioinformatics packages. Always install inside an active conda environment. If your prompt shows (base) instead of (bioinfo-py), your packages will go to the wrong place.

04 Jupyter notebooks

A Jupyter notebook is an interactive document that mixes code, output, and explanation in a single file. You write Python in cells, run each cell individually, and see the result immediately below — including plots, tables, and printed output. The file is saved as .ipynb (IPython Notebook).

💡 Why notebooks matter in bioinformatics

In a traditional script (.py file), you run the whole thing at once. When it crashes on line 200, you restart from scratch. In a notebook, you run cells one at a time. You can load a 2 GB FASTQ file into memory in cell 1, then experiment with different filtering approaches in cells 2–10, without reloading the data each time. This iterative style matches how biology research actually works — you explore first, then formalise.

Most bioinformatics publications and tutorials share their analysis as Jupyter notebooks. GitHub renders them directly in the browser. When you push your notebooks to GitHub, anyone can read your code and see your results without running anything. This is why notebooks are the standard format for reproducible bioinformatics analysis.

That said: notebooks are for exploration; scripts are for pipelines. In production, you convert a finished notebook into a clean .py script. Lesson 9 covers this transition.

Register your conda environment as a Jupyter kernel

By default, JupyterLab uses its own built-in Python. You need to register your bioinfo-py environment so Jupyter knows about it and can run code inside it.

📁 Run from: anywhere — bioinfo-py environment must be active
bash
# Make sure bioinfo-py is active
conda activate bioinfo-py

# Register the environment as a Jupyter kernel
# --user   : installs for your user only (no sudo needed)
# --name   : the internal kernel name
# --display-name : what you see in the Jupyter kernel selector
python -m ipykernel install \
  --user \
  --name bioinfo-py \
  --display-name "Python (bioinfo-py)"

Installed kernelspec bioinfo-py in /home/shajedur/.local/share/jupyter/kernels/bioinfo-py

# Confirm the kernel was registered
jupyter kernelspec list
Available kernels:
  python3       /home/shajedur/miniforge3/share/jupyter/kernels/python3
  bioinfo-py    /home/shajedur/.local/share/jupyter/kernels/bioinfo-py

Launch JupyterLab

📁 Run from: ~/python-bioinfo-scripts
bash
# Navigate to your course folder first
# (JupyterLab opens with this folder as its root)
cd ~/python-bioinfo-scripts

# Launch JupyterLab
# This starts a local server and opens a browser tab automatically
jupyter lab

# You will see output like:
# [I] Serving notebooks from local directory: /home/shajedur/python-bioinfo-scripts
# [I] Jupyter Server is running at: http://localhost:8888/lab?token=abc123...
# A browser tab opens automatically. If it doesn't: copy the URL into Firefox.
💡 To stop JupyterLab, go back to the terminal and press Ctrl+C twice. Your notebooks are saved as .ipynb files in whichever folder you launched from. Never close the terminal while Jupyter is running — it will shut down.

Select the right kernel

When you create a new notebook in JupyterLab, you will be asked to select a kernel. Always choose "Python (bioinfo-py)" — the one you just registered. This ensures the notebook has access to numpy, pandas, biopython, and all the other packages you installed. If you accidentally use the wrong kernel, click the kernel name in the top-right corner of the notebook to switch it.

05 Your first notebook

Create a new notebook in JupyterLab: File → New → Notebook, then select the Python (bioinfo-py) kernel. Save it as notebooks/lesson-01-setup.ipynb. Now type the following cells — one cell at a time, running each with Shift+Enter.

Cell 1 — Verify packages and print versions

📁 Inside notebook: notebooks/lesson-01-setup.ipynb
python — cell 1
# Cell 1: confirm every package is available and print its version
import numpy as np
import pandas as pd
import Bio
import matplotlib
import seaborn

print(f"numpy      : {np.__version__}")
print(f"pandas     : {pd.__version__}")
print(f"biopython  : {Bio.__version__}")
print(f"matplotlib : {matplotlib.__version__}")
print(f"seaborn    : {seaborn.__version__}")
print("\\n✓ All packages loaded successfully.")

Expected output after pressing Shift+Enter:

output
numpy      : 1.26.x
pandas     : 2.x.x
biopython  : 1.83
matplotlib : 3.8.x
seaborn    : 0.13.x

✓ All packages loaded successfully.

Cell 2 — Your first sequence analysis in a notebook

💡 GC content — why it matters

GC content is the percentage of bases in a DNA sequence that are Guanine or Cytosine. It matters in three practical contexts: (1) PCR primer design — primers need 40–60% GC to bind at the right temperature; (2) quality control — reads with unusual GC content relative to the reference genome signal bias or contamination; (3) species identitySorghum bicolor has ~61% GC content, so a metagenomic sample with very different GC distribution warrants investigation.

python — cell 2
# Cell 2: analyse a DNA sequence — length, GC content, reverse complement

# A real Sorghum bicolor gene fragment (SbDREB2 transcription factor)
sequence = "ATGGCGAGCGACGAGCTGCAGCAGCTGCAGCAGCAGATGCAGCAGCAGCAGCCGCCGCCG"

# 1. Length
length = len(sequence)

# 2. GC content
gc = (sequence.count("G") + sequence.count("C")) / length * 100

# 3. Reverse complement
# str.maketrans creates a character-by-character substitution table
# A→T, T→A, G→C, C→G
# Then [::-1] reverses the complemented string
comp_map   = str.maketrans("ATGC", "TACG")
rev_comp   = sequence.translate(comp_map)[::-1]

# 4. Print report
print(f"Sequence   : {sequence}")
print(f"Length     : {length} bp")
print(f"GC content : {gc:.1f}%")
print(f"RevComp    : {rev_comp}")
output
Sequence   : ATGGCGAGCGACGAGCTGCAGCAGCTGCAGCAGCAGATGCAGCAGCAGCAGCCGCCGCCG
Length     : 60 bp
GC content : 68.3%
RevComp    : CGGCGGCGGCTGCTGCTGCTGCTGTGCTGCTGCTGCAGCTGCTGCTCGTCGCTGCCAT

Cell 3 — Your first plot

python — cell 3
# Cell 3: plot base composition as a bar chart
# %matplotlib inline makes plots appear inside the notebook
import matplotlib.pyplot as plt

bases  = ["A", "T", "G", "C"]
counts = [sequence.count(b) for b in bases]
colors = ["#e8b72a", "#f42a41", "#006a4e", "#3b82f6"]

fig, ax = plt.subplots(figsize=(6, 4))
ax.bar(bases, counts, color=colors, edgecolor="white", linewidth=1.5)
ax.set_title("Base composition — SbDREB2 fragment", fontsize=13, fontweight="bold")
ax.set_xlabel("Base")
ax.set_ylabel("Count")
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
plt.tight_layout()
plt.show()

Running this cell produces a bar chart showing the count of each base — directly inside the notebook, below the cell. This is the core workflow of exploratory bioinformatics analysis.

Advertisement In-article ad · AdSense unit goes here

06 Quick reference

Task Command Notes
Create environmentconda create -n bioinfo-py python=3.12 -yOne time setup
Activate environmentconda activate bioinfo-pyEvery new terminal session
Check active Pythonwhich pythonMust show envs/bioinfo-py path
Install packagesconda install -c conda-forge -c bioconda numpy pandas biopython matplotlib seaborn jupyterlabInside active env only
Register kernelpython -m ipykernel install --user --name bioinfo-py --display-name "Python (bioinfo-py)"One time
List kernelsjupyter kernelspec listVerify registration
Launch JupyterLabjupyter labRun from course folder
Stop JupyterLabCtrl+C twice in terminalSave notebook first
Run notebook cellShift+EnterRuns cell and moves to next
Check package versionpython -c "import numpy; print(numpy.__version__)"From terminal

07 Exercises

Complete all four exercises inside JupyterLab. Create a single notebook called notebooks/lesson-01-exercises.ipynb and add each exercise as a new cell. Run each cell with Shift+Enter before moving on.

1 Activate and verify

Activate the bioinfo-py environment in your terminal, launch JupyterLab, create a new notebook, select the Python (bioinfo-py) kernel, and print the version of all five packages in one cell. Every version should print without error.

▶ Show answer
import numpy, pandas, Bio, matplotlib, seaborn
print(f"numpy      {numpy.__version__}")
print(f"pandas     {pandas.__version__}")
print(f"biopython  {Bio.__version__}")
print(f"matplotlib {matplotlib.__version__}")
print(f"seaborn    {seaborn.__version__}")
2 Analyse a maize sequence

Copy the GC content code from Cell 2 above. Replace the sequence with this Zea mays (maize) Ubiquitin promoter fragment and rerun. What is the GC content? Is it higher or lower than the sorghum fragment?

sequence to use
AGATCTTGCGCGCTATAAATACGCGCTATATATAGCGCGCGCGATATATATCGCGCGATAT
▶ Show answer
sequence = "AGATCTTGCGCGCTATAAATACGCGCTATATATAGCGCGCGCGATATATATCGCGCGATAT"
gc = (sequence.count("G") + sequence.count("C")) / len(sequence) * 100
print(f"GC content: {gc:.1f}%")
# ~43% — AT-rich compared to the sorghum fragment (68%)
# Ubiquitin promoter regions are often AT-rich in grasses
3 Build a GC content function

In a new cell, write a function called gc_content(seq) that takes any DNA string and returns the GC percentage as a float. Test it on three sequences of your choice and print the results.

💡 Define functions with def function_name(parameter):. The function body is indented. Use return to send a value back to the caller.
▶ Show answer
def gc_content(seq):
    """Return GC content as a percentage (float)."""
    seq = seq.upper()
    return (seq.count("G") + seq.count("C")) / len(seq) * 100

print(gc_content("ATATATATAT"))   # 20.0 — AT-rich
print(gc_content("ATGCATGCAT"))   # 50.0 — balanced
print(gc_content("GCGCGCGCGC"))   # 100.0 — GC-rich
4 Challenge — categorise multiple sequences

Create a Python list containing five different DNA sequences of your choice (at least 20 bp each). Loop over the list, call your gc_content() function on each, and print whether each sequence is AT-rich (<50%), balanced (50–60%), or GC-rich (>60%). Print the sequence number, GC%, and category on one line.

▶ Show answer
sequences = [
    "ATATATATATATATATAT",
    "ATGCATGCATGCATGCAT",
    "GCGCGCGCGCGCGCGCGC",
    "ATGGCGAGCGACGAGCTG",
    "AGATCTTGCGCGCTATAA",
]

for i, seq in enumerate(sequences, 1):
    gc = gc_content(seq)
    if   gc < 50: cat = "AT-rich"
    elif gc <= 60: cat = "Balanced"
    else:          cat = "GC-rich"
    print(f"Seq {i}: {gc:.1f}%  →  {cat}")

Your progress saves automatically in this browser.

Advertisement 300 × 250 medium rectangle · AdSense unit goes here