Large-Scale Genomic Data Processing
Educational Bioinformatics Pipeline Reference · macOS · GRCh37 / GRCh38
Executive Summary
This project demonstrates a complete personal genome bioinformatics pipeline executed on macOS. The work is centered on NA12878 — a real woman who donated her genome to science — whose sequencing data is freely available as a gold-standard reference from the Genome in a Bottle (GIAB) consortium.
Installation Guide — macOS
Everything below runs on macOS Apple Silicon (M1/M2/M3/M4) or Intel Mac. The only prerequisite is Homebrew — macOS's standard package manager.
Step 1 — Install Homebrew (if not already installed)
# Paste this into Terminal — it installs Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Verify installation
brew --version
Step 2 — Install Core Bioinformatics Tools
# samtools — reads, indexes, and queries genome FASTA and BAM files
brew install samtools
# bcftools — reads, queries, and filters VCF variant call files
brew install bcftools
# htslib — provides bgzip (block gzip) and tabix (indexed compression)
brew install htslib
# bwa — aligns short DNA reads to a reference genome
brew install bwa
# Java — required by snpEff (annotation engine)
brew install openjdk@17
echo 'export PATH="/opt/homebrew/opt/openjdk@17/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
# Verify Java is working
java -version
Step 3 — Install snpEff (Variant Annotator)
snpEff is not on Homebrew — install it manually. It is a Java program distributed as a ZIP file.
# Create a working directory
mkdir -p ~/na12878_pipeline && cd ~/na12878_pipeline
# Download snpEff
curl -L https://snpeff.blob.core.windows.net/versions/snpEff_latest_core.zip -o snpEff.zip
# Unzip it
unzip snpEff.zip
# Download the GRCh38 annotation database (one-time, ~3 GB)
java -jar snpEff/snpEff.jar download GRCh38.109
# Verify snpEff works
java -jar snpEff/snpEff.jar -version
Step 4 — Install Miniconda (for snpEff conda environment — optional)
# Download Miniconda installer for Apple Silicon
curl -O https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh
# Run installer
bash Miniconda3-latest-MacOSX-arm64.sh
# Restart terminal, then create a dedicated snpEff environment
conda create -n snpeff_env -c bioconda snpeff -y
conda activate snpeff_env
Step 5 — Install Python Visualization Tools
# Install pip packages for plotting
pip3 install matplotlib pandas numpy biopython
# Verify
python3 -c "import matplotlib; print('matplotlib', matplotlib.__version__)"
Full Tool Reference
| Tool | Install Command | What It Does |
|---|---|---|
samtools | brew install samtools | Query, index, and manipulate genome FASTA and aligned BAM files |
bcftools | brew install bcftools | Read, filter, and query VCF variant call files |
bgzip | brew install htslib | Block-gzip compress large genomic files for indexed random access |
tabix | brew install htslib | Index compressed VCF/FASTA so you can jump to any position instantly |
bwa | brew install bwa | Align short sequencing reads to a reference genome |
snpEff | Manual ZIP install | Annotate variants with gene consequences (missense, splice, silent…) |
gzcat | Built into macOS | Stream a .gz file without extracting it to disk |
grep | Built into macOS | Search for patterns inside a text stream |
sed | Built into macOS | Stream editor — filter or transform lines of text |
awk | Built into macOS | Column-aware text processor — perform calculations on genomic data fields |
Downloading the Human Genome — The Single 3-Billion-Line File
The human genome reference (GRCh38) is a single compressed FASTA file. It contains the complete DNA sequence of a "consensus" human being — all 23 chromosome pairs, roughly 3.1 billion base pairs, written out as A/T/C/G characters and wrapped at 80 characters per line.
Option A — Download GRCh38 from NCBI (Authoritative Source)
mkdir -p ~/na12878_pipeline && cd ~/na12878_pipeline
# Full primary assembly — all chromosomes — ~900 MB compressed (~3 GB unzipped)
curl -O https://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/000/001/405/GCA_000001405.15_GRCh38/GCA_000001405.15_GRCh38_assembly_structure/Primary_Assembly/assembled_chromosomes/FASTA/chroms/GRCh38_major_release_seqs_for_alignment_pipelines.fa.gz
# OR — faster mirror from Ensembl
curl -O https://ftp.ensembl.org/pub/release-110/fasta/homo_sapiens/dna/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz
# OR — UCSC hg38 (same genome, different chromosome naming: chr1 vs 1)
rsync -avzP rsync://hgdownload.soe.ucsc.edu/goldenPath/hg38/bigZips/hg38.fa.gz .
chr1, chr2…. Ensembl uses 1, 2…. This matters — bcftools and tabix will fail if your VCF uses one naming convention and your reference uses another.
Option B — Download NA12878 Real Variant Calls (GIAB Gold Standard)
cd ~/na12878_pipeline
# High-confidence variant VCF for NA12878 against GRCh38
curl -O https://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/release/NA12878_HG001/NISTv3.3.2/GRCh38/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_PGandRTGphasetransfer.vcf.gz
# Download the index file too (required for tabix random access)
curl -O https://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/release/NA12878_HG001/NISTv3.3.2/GRCh38/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_PGandRTGphasetransfer.vcf.gz.tbi
# Rename to something shorter for convenience
mv HG001_GRCh38_GIAB_highconf_*.vcf.gz na12878.vcf.gz
mv HG001_GRCh38_GIAB_highconf_*.vcf.gz.tbi na12878.vcf.gz.tbi
Index the Reference Genome for Fast Querying
Before you can query specific coordinates, the genome file must be indexed. This creates a lookup table so tools can jump directly to any position without reading the entire file.
# Step 1 — Block-gzip compress the reference (if not already bgzip'd)
bgzip -c Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz > ref_grch38.fna.bgz
# Step 2 — Build the FASTA index (.fai file)
samtools faidx ref_grch38.fna.bgz
# This creates ref_grch38.fna.bgz.fai — a lookup table of chromosome positions
# Step 3 — Index the VCF for random access
tabix -p vcf na12878.vcf.gz
# Step 4 — Index VCF with bcftools (alternative, creates .csi index)
bcftools index na12878.vcf.gz
File Sizes to Expect
| File | Compressed | Uncompressed | Lines |
|---|---|---|---|
| GRCh38 reference FASTA | ~900 MB | ~3.2 GB | ~38–40 million |
| NA12878 VCF (GIAB) | ~450 MB | ~2.5 GB | ~4.2 million variants |
| NA12878 consensus FASTA | ~800 MB | ~3.1 GB | ~38 million |
| bwa index files (total) | — | ~8–10 GB | 5 auxiliary files |
| snpEff GRCh38.109 database | — | ~3 GB | Gene annotation DB |
Complete Query Reference — Every Command Explained
This section covers every tool used to query the 3-billion-line genome file. Each command is broken down: what it does, why you use it, and what output to expect.
1. Stream a Compressed File Without Extracting It
gzcat reads a .gz file and outputs its contents as a text stream — no decompression to disk. This is the foundation of every genomic query on macOS.
# Stream the entire genome into your terminal (DO NOT run alone — will print forever)
gzcat ref_grch38.fna.bgz
# Always pipe gzcat into another command that controls the output
gzcat ref_grch38.fna.bgz | head -n 5 # first 5 lines only
gzcat ref_grch38.fna.bgz | wc -l # count total lines (slow — reads all 38M)
gzcat ref_grch38.fna.bgz | grep "^>" # show only chromosome headers
2. Peek at the File Without Opening It
# Show first 10 lines
gzcat ref_grch38.fna.bgz | head -n 10
# Show last 10 lines (reads entire file — slow on 3 GB)
gzcat ref_grch38.fna.bgz | tail -n 10
# Show first 20 lines of a specific chromosome (chr22)
gzcat ref_grch38.fna.bgz | sed -n '/^>chr22/,/^>/p' | head -n 20
# Count how many chromosomes are in the file
gzcat ref_grch38.fna.bgz | grep -c "^>"
3. samtools faidx — Query Exact Coordinates (Fastest Method)
samtools faidx uses the index to jump directly to any genomic coordinate in milliseconds — no reading from the start. This is how you query specific genes or regions.
# Pull a single base at a specific position
samtools faidx ref_grch38.fna.bgz chr17:43094464-43094464
# Pull the entire BRCA1 gene region
samtools faidx ref_grch38.fna.bgz chr17:43044295-43125483
# Pull a region from chromosome 22
samtools faidx ref_grch38.fna.bgz chr22:1-50000
# Pull multiple regions at once
samtools faidx ref_grch38.fna.bgz chr17:43044295-43125483 chr22:1-100000
# List all chromosomes and their sizes (from the .fai index)
cut -f1,2 ref_grch38.fna.bgz.fai
# Output format: FASTA header + sequence
# >chr17:43044295-43125483
# ATCGATCGATCG...
4. bcftools — Query the Variant Database (VCF File)
The VCF file contains 4.2 million positions where NA12878's DNA differs from the reference. bcftools is the primary tool for querying it.
# ─── BASIC QUERIES ───────────────────────────────
# Show VCF header (metadata about the file)
bcftools view -h na12878.vcf.gz | less
# Show first 10 variant records
bcftools view na12878.vcf.gz | grep -v "^#" | head -10
# Count total number of variants
bcftools view na12878.vcf.gz | grep -vc "^#"
# ─── FILTER BY CHROMOSOME / REGION ──────────────
# All variants on chromosome 22
bcftools view -r chr22 na12878.vcf.gz | less
# Variants in a specific gene region (BRCA1)
bcftools view -r chr17:43044295-43125483 na12878.vcf.gz
# Save region to a new file
bcftools view -r chr17:43044295-43125483 na12878.vcf.gz -o brca1_variants.vcf
# Multiple regions at once
bcftools view -r chr17:43044295-43125483,chr22:1-5000000 na12878.vcf.gz
# ─── FILTER BY VARIANT TYPE ──────────────────────
# Show only SNPs (single nucleotide changes)
bcftools view -v snps na12878.vcf.gz | head -20
# Show only indels (insertions + deletions)
bcftools view -v indels na12878.vcf.gz | head -20
# Count SNPs
bcftools view -v snps na12878.vcf.gz | grep -vc "^#"
# Count indels
bcftools view -v indels na12878.vcf.gz | grep -vc "^#"
# ─── STATISTICS ──────────────────────────────────
# Full stats report (ts/tv ratio, indel sizes, quality distribution)
bcftools stats na12878.vcf.gz > na12878_stats.txt
less na12878_stats.txt
# Quick summary stats
bcftools stats na12878.vcf.gz | grep "^SN"
# ─── ADVANCED QUERIES ────────────────────────────
# Extract only the chromosome, position, ref, alt columns
bcftools query -f '%CHROM\t%POS\t%REF\t%ALT\n' na12878.vcf.gz | head -20
# Count insertions (ALT longer than REF)
bcftools view -v indels na12878.vcf.gz | awk '!/^#/ && length($5) > length($4)' | wc -l
# Count deletions (REF longer than ALT)
bcftools view -v indels na12878.vcf.gz | awk '!/^#/ && length($4) > length($5)' | wc -l
# Find the largest indels (most disruptive)
bcftools view -v indels na12878.vcf.gz | awk '!/^#/ {print length($4)-length($5), $0}' | sort -n | tail -10
# Check if a specific position has a variant
bcftools view -r chr17:43094464-43094464 na12878.vcf.gz
5. tabix — Indexed Random Access (Jump to Any Position Instantly)
tabix is like a GPS for a compressed genomic file. Once a file is indexed, it can seek directly to any chromosome:position without reading from the start.
# Build a tabix index on a VCF (creates .tbi file)
tabix -p vcf na12878.vcf.gz
# Query a region directly — millisecond access on a 450 MB file
tabix na12878.vcf.gz chr17:43044295-43125483
# Query chromosome 22 entirely
tabix na12878.vcf.gz chr22
# List all chromosomes in the file
tabix -l na12878.vcf.gz
# Build a tabix index on a FASTA file
tabix -p fasta genome.fasta.gz
6. grep — Pattern Search Inside Any Genomic File
# Find all chromosome headers in FASTA
gzcat ref_grch38.fna.bgz | grep "^>"
# Find a specific chromosome header
gzcat ref_grch38.fna.bgz | grep "^>chr22"
# Show chr22 header + the next 5 lines of sequence
gzcat ref_grch38.fna.bgz | grep "^>chr22" -A 5
# Count how many lines contain a specific motif (e.g. BRCA1 gene ID)
bcftools view na12878.vcf.gz | grep -c "BRCA1"
# Search VCF for a specific rs-ID (dbSNP variant identifier)
bcftools view na12878.vcf.gz | grep "rs28897672"
# Count lines NOT starting with # (count actual variants, skip header)
bcftools view na12878.vcf.gz | grep -vc "^#"
7. sed — Stream Filter by Range
sed is the tool that isolates one chromosome from the 38-million-line genome stream.
# Isolate chromosome 22 from start to the next chromosome header
gzcat ref_grch38.fna.bgz | sed -n '/^>chr22/,/^>chr[^2]/p' | head -20
# How it works:
# -n suppress default printing
# /^>chr22/ start printing when this pattern is matched
# ,/^>chr/ stop printing when ANY new chromosome header is matched
# p print the matching range
# Isolate lines between two patterns and save to file
gzcat ref_grch38.fna.bgz | sed -n '/^>chr22/,/^>chrX/p' > chr22_only.fasta
8. awk — Column Math on Genomic Data
awk treats each line as columns separated by tabs. VCF files have 8+ tab-separated columns — awk lets you calculate on them.
# VCF column structure:
# $1=CHROM $2=POS $3=ID $4=REF $5=ALT $6=QUAL $7=FILTER $8=INFO
# Print chromosome and position of every variant
bcftools view na12878.vcf.gz | awk '!/^#/ {print $1, $2}'
# Calculate indel size (positive = deletion, negative = insertion)
bcftools view -v indels na12878.vcf.gz | awk '!/^#/ {print length($4)-length($5), $1, $2}'
# Show only variants with quality score above 50
bcftools view na12878.vcf.gz | awk '!/^#/ && $6 > 50'
# Count variants per chromosome
bcftools view na12878.vcf.gz | awk '!/^#/ {count[$1]++} END {for(c in count) print c, count[c]}' | sort -V
9. snpEff — Annotate What Variants Actually Do
# Annotate chr22 only (memory-safe, ~3 GB RAM)
bcftools view -r chr22 na12878.vcf.gz | \
java -Xmx8g -jar snpEff/snpEff.jar GRCh38.109 - > chr22_annotated.vcf
# Annotate full genome (requires 16 GB free RAM)
java -Xmx16g -jar snpEff/snpEff.jar GRCh38.109 na12878.vcf.gz > na12878_annotated.vcf 2>snpeff.log
# Monitor progress while running
tail -f snpeff.log
# After annotation — compress and index the output
bgzip na12878_annotated.vcf
tabix -p vcf na12878_annotated.vcf.gz
# Query annotated file for missense variants only
bcftools view na12878_annotated.vcf.gz | grep "missense_variant"
# Query annotated file for BRCA1 gene
grep BRCA1 snpEff_genes.txt
# Open the HTML summary report in browser
open snpEff_summary.html
10. Full Pipeline — From Download to Annotation in One Flow
# ─── COMPLETE PIPELINE ───────────────────────────────────────────
mkdir -p ~/na12878_pipeline && cd ~/na12878_pipeline
# 1. Download reference genome
curl -O https://ftp.ensembl.org/pub/release-110/fasta/homo_sapiens/dna/Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz
# 2. Download NA12878 variant calls
curl -O https://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/release/NA12878_HG001/NISTv3.3.2/GRCh38/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_PGandRTGphasetransfer.vcf.gz
curl -O https://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/release/NA12878_HG001/NISTv3.3.2/GRCh38/HG001_GRCh38_GIAB_highconf_CG-IllFB-IllGATKHC-Ion-10X-SOLID_CHROM1-X_v.3.3.2_highconf_PGandRTGphasetransfer.vcf.gz.tbi
mv HG001_GRCh38_GIAB_highconf_*.vcf.gz na12878.vcf.gz
mv HG001_GRCh38_GIAB_highconf_*.vcf.gz.tbi na12878.vcf.gz.tbi
# 3. Compress and index the reference
bgzip -c Homo_sapiens.GRCh38.dna.primary_assembly.fa.gz > ref_grch38.fna.bgz
samtools faidx ref_grch38.fna.bgz
# 4. Index the VCF
bcftools index na12878.vcf.gz
# 5. Quick sanity check — list chromosomes, count variants
tabix -l na12878.vcf.gz
bcftools view na12878.vcf.gz | grep -vc "^#"
# 6. Annotate chr22 (memory-safe first run)
bcftools view -r chr22 na12878.vcf.gz | \
java -Xmx8g -jar snpEff/snpEff.jar GRCh38.109 - > chr22_annotated.vcf
# 7. View results
open snpEff_summary.html
The Woman Behind the Genome: NA12878
Who Is NA12878?
NA12878 is the sample identifier assigned to a real woman known within the global genomics community as HG001. She is a Utah resident of Northern and Western European ancestry — a mother, grandmother, and one of the most important people in the history of modern genetics. She voluntarily donated a blood sample to science, knowing it would be sequenced and made publicly available for research around the world.
Her genome has been sequenced more times than any other human genome in history. It serves as the foundational quality control standard used by every major sequencing center, software developer, and bioinformatics researcher on Earth.
The CEPH Collection (1980s)
NA12878's story begins with the Centre d'Etude du Polymorphisme Humain (CEPH), a French genetics institute founded in Paris in 1983. CEPH recruited large three-generation families and collected DNA samples from grandparents, parents, and children. These families, called the CEPH pedigrees, gave scientists the ability to track how genetic variants are inherited across generations — a process called linkage analysis.
NA12878 belongs to CEPH family 1463. The "NA" prefix stands for North American. The "12878" is her permanent, anonymized lab identifier. She is one member of a multi-generation family that donated samples together, allowing scientists to verify which variants she inherited from which parent.
Genome in a Bottle (GIAB) — The Gold Standard
In 2011, the National Institute of Standards and Technology (NIST) launched the Genome in a Bottle Consortium. Their mission: create a human genome reference so deeply verified that it could be trusted as a universal benchmark. NA12878 was selected as the first subject.
Her genome was sequenced using every major sequencing technology available — Illumina short reads, Pacific Biosciences long reads, Oxford Nanopore, Complete Genomics, Ion Torrent, and more — and the results were cross-validated against each other to produce a high-confidence variant call set: a list of every position in her genome where she differs from the reference, with the highest confidence rating in the field.
| Technology Used | Coverage Depth | Purpose |
|---|---|---|
| Illumina (short reads) | 300× | High-accuracy SNP calling |
| Pacific Biosciences (long reads) | ~60× | Structural variant resolution |
| Oxford Nanopore | ~30× | Phasing and long-range context |
| Complete Genomics | ~200× | Independent SNP validation |
| Ion Torrent | ~150× | Indel accuracy cross-check |
Her Scientific Legacy
NA12878's genome has been downloaded millions of times. It is used to:
- Validate every new DNA sequencing machine before it goes to market
- Test and benchmark bioinformatics software (aligners, variant callers, annotation tools)
- Train machine learning models that detect cancer mutations and rare diseases
- Calibrate clinical laboratory pipelines before they process real patient samples
- Serve as a teaching resource — exactly as in this project
Every time a hospital sequences a cancer patient's tumor to find the right treatment, the pipeline that produced that result was likely validated against NA12878 first. Her contribution is immeasurable.
Core Data Pipeline: Stream, Filter, Truncate
The fundamental technique in this project is Unix piping — connecting tools so data flows through them sequentially in memory, never touching the disk. This allows processing a multi-gigabyte compressed genome file without ever extracting it.
# Full command — isolate chr22 from a compressed 38M-line genome
gzcat genome_23chromosomes.fasta.gz | sed -n '/_chr22_/,/_chrX_/p' | head -n 20
| Phase | Command | Function | Technical Advantage |
|---|---|---|---|
| 1. Stream | gzcat file.fasta.gz |
Reads and decompresses on the fly | No disk extraction — saves multi-GB of storage and eliminates I/O bottleneck |
| 2. Filter | sed -n '/_chr22_/,/_chrX_/p' |
Suppresses all output until chr22 header is matched; stops at chrX | Isolates one chromosome boundary instantly from millions of lines |
| 3. Halt | head -n 20 |
Captures first 20 lines, sends SIGPIPE upstream to terminate the pipeline | Acts as system brakes — prevents flooding from 50M+ base pairs of sequence |
Additional Streaming Commands
# List all chromosome headers (catalog the file contents, no sequence)
gzcat genome_23chromosomes.fasta.gz | grep ">"
# Find chr22 and show 5 lines of sequence context
gzcat genome_23chromosomes.fasta.gz | grep "chr22" -A 5
# Peek at first lines of a gzipped consensus FASTA
zcat na12878_consensus.fa.gz | head
Building the Personal Genome — NA12878 Consensus
A "personal genome" is constructed by taking the universal human reference sequence (GRCh38) and applying one individual's specific variant calls on top of it. The result is a FASTA file where every position reflects that person's actual DNA, not the generic average.
The Three Build Components
| File | Description | Status |
|---|---|---|
na12878.vcf.gz |
Real variant calls from the GIAB consortium — 4.2M+ positions where NA12878 differs from reference | Verified |
na12878_consensus.fa |
3 GB FASTA — GRCh38 reference with all GIAB variants applied. Chromosome lengths are shorter than reference at correct positions, confirming real indels were incorporated. | Verified |
ref_grch38.fna.bgz |
GRCh38 reference genome (bgzip compressed, samtools indexed) | Indexed |
What the Central Database Contains
The variant calls in na12878.vcf.gz are cross-referenced against major public databases:
| Database | Host | Contents | Used For |
|---|---|---|---|
| dbSNP | NCBI | 800M+ SNP records across all known human populations | Assigning rs-IDs to NA12878 variants — links each position to global frequency data |
| ClinVar | NCBI | Clinical significance of variants (pathogenic, benign, VUS) | Identifying which of NA12878's 4.2M variants have known disease associations |
| gnomAD | Broad Institute | Allele frequencies from 140,000+ humans | Population frequency comparison — how common is each variant across humanity |
| GIAB Benchmark | NIST | High-confidence variant calls for NA12878 | The ground truth — used to validate that our pipeline called variants correctly |
| Ensembl / RefSeq | EMBL / NCBI | Gene annotations on GRCh38 | Mapping variants to genes (used by snpEff for functional annotation) |
Complete Command Reference
bcftools — Variant Analysis
# Index the VCF file (required before most operations)
bcftools index -f na12878.vcf.gz
# Full variant statistics report → save to file
bcftools stats na12878.vcf.gz > na12878_stats.txt
# Extract the BRCA1 gene region (chr17:43044295–43125483)
bcftools view -r chr17:43044295-43125483 na12878.vcf.gz > brca1_variants.vcf
# Count total SNPs
bcftools view -v snps na12878.vcf.gz | grep -vc "^#"
# Count total indels
bcftools view -v indels na12878.vcf.gz | grep -vc "^#"
# Count insertions (ALT longer than REF)
bcftools view -v indels na12878.vcf.gz | awk 'length($5) > length($4)' | wc -l
# Count deletions (REF longer than ALT)
bcftools view -v indels na12878.vcf.gz | awk 'length($4) > length($5)' | wc -l
# Rank indels by size — find the largest structural variants
bcftools view -v indels na12878.vcf.gz | awk '{print length($4)-length($5), $0}' | sort -n | tail
# Inspect a specific coordinate
bcftools view -r chr17:43094464-43094464 na12878.vcf.gz
# Check for phase set (PS) tags in VCF header
bcftools view -h na12878.vcf.gz | grep PS
snpEff — Functional Annotation
# Annotate VCF with gene consequences against GRCh38 Ensembl 109
java -Xmx8g -jar snpEff/snpEff.jar GRCh38.109 na12878.vcf.gz > na12878_annotated.vcf
# Compress and index the annotated output
bgzip na12878_annotated.vcf
tabix -p vcf na12878_annotated.vcf.gz
# Check BRCA1 annotation results
grep BRCA1 snpEff_genes.txt | head
# Open HTML summary in browser
open snpEff_summary.html
samtools — Reference Lookup
# Pull a single base from the reference genome at a specific coordinate
samtools faidx ref_grch38.fna.bgz chr17:43094464-43094464
bwa — Alignment Index Build
# Build search index for the consensus genome (~45–90 min for 3 GB)
# Produces: .bwt .pac .ann .amb .sa auxiliary files
bwa index na12878_consensus.fa
# Build index for GRCh38 reference (same duration)
bwa index ref_grch38.fna.bgz
# After indexing: align reads and compare flagstat output between
# personalized consensus vs generic reference
Chromosomal Ancestry Architecture
Source: 23andMe Ancestry Composition (0.5 confidence phasing threshold) · Reference assembly: GRCh37/hg19.
Humans carry two copies of every chromosome — one inherited from each parent. Copy 1 and Copy 2 below represent these independent maternal/paternal inheritances.
| Chromosome | Copy | Start (bp) | End (bp) | Length (bp) | Assigned Panel |
|---|---|---|---|---|---|
| chr1 | 1 | 90,013,233 | 150,811,446 | 60,798,213 | West Asian & N. African |
| chr2 | 1 | 52,384,668 | 76,488,564 | 24,103,896 | West Asian & N. African |
| chr2 | 1 | 71,579,697 | 76,488,564 | 4,908,867 | Broadly N. West Asian |
| chr2 | 1 | 222,330,122 | 243,041,411 | 20,711,289 | West Asian & N. African |
| chr2 | 1 | 222,330,122 | 226,890,057 | 4,559,935 | Broadly N. West Asian |
| chr2 | 1 | 226,890,057 | 243,041,411 | 16,151,354 | Anatolian |
| chr3 | 1 | 93,903,807 | 96,505,890 | 2,602,083 | Unassigned — Gap A |
| chr3 | 1 | 137,044,802 | 138,933,322 | 1,888,520 | Unassigned — Gap B |
| chr3 | 2 | 66,206 | 173,734,047 | 173,667,841 | West Asian & N. African |
| chr3 | 2 | 66,206 | 2,235,255 | 2,169,049 | Broadly N. West Asian |
| chr3 | 2 | 2,379,000 | 173,734,047 | 171,355,047 | Broadly N. West Asian |
| chr4 | 2 | 155,273,743 | 156,602,205 | 1,328,462 | Unassigned — Gap C |
| chr4 | 2 | 156,602,205 | 190,125,925 | 33,523,720 | West Asian & N. African |
| chr6 | 1 | 174,798 | 73,493,534 | 73,318,736 | Anatolian |
| chr6 | 1 | 124,264,783 | 148,587,096 | 24,322,313 | Anatolian |
| chr7 | 1 | 7,358,814 | 104,145,765 | 96,786,951 | Anatolian |
| chr8 | 1 | 103,686,204 | 119,113,078 | 15,426,874 | Arab, Egyptian & Levantine |
| chr10 | 2 | 24,850,941 | 102,918,486 | 78,067,545 | Anatolian |
| chr13 | 1 | 49,545,811 | 51,272,084 | 1,726,273 | Unassigned — Gap D |
| chr13 | 2 | 19,503,422 | 43,695,449 | 24,192,027 | Anatolian |
| chr13 | 2 | 105,172,434 | 106,216,087 | 1,043,653 | Unassigned — Gap E |
| chr18 | 2 | 51,751,722 | 53,824,882 | 2,073,160 | Unassigned — Gap F |
| chr19 | 1 | 54,085,335 | 59,097,933 | 5,012,598 | Anatolian |
| chr19 | 2 | 14,719,254 | 15,949,405 | 1,230,151 | Unassigned — Gap G |
| chr21 | 1 | 21,856,748 | 24,719,961 | 2,863,213 | Unassigned — Gap H |
| chr21 | 2 | 21,856,748 | 48,099,610 | 26,242,862 | Anatolian |
Algorithmic Gap Resolution
An Unassigned segment does not mean missing DNA. It means those nucleotides match multiple reference panels with equal statistical confidence — the algorithm cannot choose a winner. By examining what flanks the gap on both sides (the flanking context resolution method), the underlying structure becomes clear.
Gaps A & B — Chromosome 3, Copy 1
A: 93.9M–96.5M (2.60 Mb) | B: 137.0M–138.9M (1.88 Mb)
Both gaps are embedded inside a dominant long-range Greek & Balkan / Southern European ancestral block. They are small, both flanks carry identical signatures — these are uniform European blocks with common polymorphic variations that the reference panel cannot sub-classify. No lineage break. Continuous Aegean heritage.
Gap C — Chromosome 4, Copy 2
C: 155.3M–156.6M (1.32 Mb)
This is a textbook meiotic recombination breakpoint. The DNA upstream of 155,273,743 tracks to the Southern European / Italian reference panel. The DNA immediately downstream of 156,602,205 transitions directly into a West Asian & North African / Cypriot segment. The gap is the precise structural bridge linking the European and Eastern Mediterranean ancestral branches.
Gaps D & E — Chromosome 13
D: 49.5M–51.2M (1.72 Mb) | E: 105.2M–106.2M (1.04 Mb)
Gap D is an internal Southern European transition. Gap E is tightly flanked by a general Southern European segment and a Greek & Balkan block, confirming continuous Greek heritage across both boundaries.
Gaps F, G, H — Chr 18, 19, 21
F: 51.7M–53.8M | G: 14.7M–15.9M | H: 21.8M–24.7M
These are consistently bounded on one side by Anatolian / West Asian blocks and on the other by Southern European / Greek segments. They act as regional transition boundaries — reflecting centuries of historic genetic overlap between the populations of Asia Minor, Cyprus, and the Aegean basin.
Mitochondrial Haplogroup: H15a1
Mitochondrial DNA (mtDNA) is inherited exclusively through the maternal line — mother to child, unchanged except for rare mutations. Every mutation that accumulates in the mtDNA over thousands of generations creates a branch in the maternal family tree. The terminal branch is the haplogroup.
The Four Defining Mutations
| Position | Role |
|---|---|
| 1023 & 1438 | Branch separation within the ancient H15 lineage — splits H15 from other H sub-groups |
| 16298 | Establishes the H15a sub-branch — the hypervariable region transition |
| 8152 | The definitive mutation locking lineage directly into H15a1 — the terminal identifier |
Modern Geographic Distribution
Unlike broad Western European H branches that dominate the Iberian Peninsula and Atlantic coast, modern H15a1 carriers concentrate specifically around:
- Greece & the Aegean Islands
- Cyprus
- Armenia
- Iran & northern Iraq
- Tajikistan & the Caucasus corridor
This distribution maps directly onto the autosomal chromosome pattern in Section 5 — the same Eastern Mediterranean / Anatolia / Levant signature appears in both independent data streams.
Comparison: Anonymized Profile vs. Central Reference Database
The following comparison maps the chromosomal ancestry segments from this pipeline against the population panels in the 23andMe reference database (derived from gnomAD, HGDP, 1000 Genomes, and proprietary reference panels). Percentages reflect proportion of assigned base pairs per ancestry cluster.
Autosomal Ancestry Distribution (Assigned Segments Only)
NA12878 vs. Anonymized Profile — Key Differences
| Feature | NA12878 (Reference Standard) | Anonymized Profile (This Pipeline) |
|---|---|---|
| Primary ancestry | Northern & Western European (British Isles / Utah CEPH cohort) | Anatolian / Eastern Mediterranean / Aegean |
| mtDNA haplogroup | H (broad Western European branch) | H15a1 (Eastern Mediterranean / Aegean specific) |
| Reference assembly | GRCh38 (pipeline uses GRCh38 for consensus build) | GRCh37/hg19 (23andMe ancestry composition) |
| Sequencing depth | 300× (multiple platforms, GIAB verified) | Consumer SNP microarray (~650,000 positions genotyped) |
| Total variants vs. reference | 4.2M+ in high-confidence call set | SNP array — subset of common variant positions only |
| Phasing | Full trio phasing (3-generation family data) | Statistical phasing at 0.5 confidence threshold |
| Primary ancestral signal | Northwestern European — low admixture | Deeply admixed Aegean / Asia Minor / Levant — complex mosaic |
How the Comparison Pipeline Works
When comparing this profile's chromosome segments to the central database, the process follows these steps:
- Phased segment extraction: 23andMe's internal algorithm phases the ~650,000 SNP positions into maternal and paternal haplotypes (Copy 1 / Copy 2)
- Reference panel matching: Each phased segment is compared against 31 reference populations using a Hidden Markov Model (HMM) — the same statistical method used in scientific population genetics
- Boundary detection: Recombination breakpoints are identified where population signatures change — these are the segment boundaries in the coordinate ledger
- Confidence thresholding: At 0.5 threshold, segments are only assigned when the top reference panel match has at least 50% posterior probability — tighter than the default 0.3 setting
- Gap classification: Regions where no panel exceeds the threshold are marked Unassigned — these are the 8 gap windows in the dataset
Completed Pipeline Run: snpEff Annotation Results
The following results were produced by running the full annotation pipeline on the NA12878 dataset on macOS Apple Silicon. The full 3.6 million variant run required a memory workaround — details below.
-Xmx16g.
Chromosome 22 Variant Classification — From Least to Most Significant
snpEff assigns each variant a functional consequence based on where it falls in the genome. Severity increases from top to bottom.
| Category | Count | Location | Protein Impact | Significance |
|---|---|---|---|---|
| Intergenic / Upstream / Downstream | ~65,000 | Outside gene boundaries — the "desert" of the genome | None | Very Low |
| Intron variant | 147,704 | Inside a gene, in the non-coding "junk" spaces between exons | Usually none — introns are spliced out | Low |
| Non-coding exon | 3,108 | Inside a functional gene region — but for RNA genes, not protein-coding | May affect RNA gene regulation | Moderate |
| Synonymous / Silent | 502 | Inside protein-coding gene | None — same amino acid due to genetic code redundancy | Moderate |
| Splice region | 159 | At the cut-and-paste boundaries where the cell reads gene segments | Can break how a gene is assembled — may produce wrong protein | High |
| Missense / Amino acid change | 453 | Inside protein-coding gene | Changes an amino acid — the protein building block is swapped | Most Significant |
Visual Outputs Generated
| File | What It Shows | How to Open |
|---|---|---|
na12878_karyogram.png |
Full genome map showing where mutations are densest across all 23 chromosomes — visually identifies hotspot regions | open ~/na12878_pipeline/*.png |
na12878_indels.png |
Histogram of insertion/deletion lengths — shows whether mutations are small (1–2 bp) or large structural events |
Critical Gene Comparison Results
The pipeline also extracted and compared variants in four clinically significant genes against the reference genome:
| Gene | Full Name | Clinical Relevance | Why It Was Analyzed |
|---|---|---|---|
| BRCA1 | Breast Cancer 1 | Hereditary breast and ovarian cancer risk | Most studied cancer-risk gene. Variants here have direct clinical screening implications. |
| APOE | Apolipoprotein E | Alzheimer's disease risk (APOE ε4 allele) | The ε4 variant triples Alzheimer's risk. Identifying which allele(s) are present is a major research target. |
| TP53 | Tumor Protein p53 | Cancer suppressor — "guardian of the genome" | Mutated in over 50% of all human cancers. Baseline variant status matters for cancer risk profiling. |
| MTHFR | Methylenetetrahydrofolate reductase | Folate metabolism, cardiovascular and neurological risk | Two common variants (C677T, A1298C) affect how the body processes B vitamins and homocysteine. |
Commands: View Results & Scale to Full Genome
# Open all generated PNG graphs
open ~/na12878_pipeline/*.png
# ─────────────────────────────────────────────────────
# To run snpEff on the FULL 3.6M variant dataset:
# Restart Mac first to clear RAM, then:
# ─────────────────────────────────────────────────────
cd ~/na12878_pipeline
/opt/homebrew/Caskroom/miniconda/base/bin/conda run -n snpeff_env \
snpEff -Xmx16g GRCh38.99 na12878.vcf.gz > na12878_annotated.vcf 2>snpeff.log
# -Xmx16g = allow snpEff to use up to 16 GB RAM
# Requires at least 16 GB free before running
# Monitor progress: tail -f snpeff.log
macOS Compatibility Notes
The zcat Problem on macOS
| Platform | Command | Handles .gz? | Reason |
|---|---|---|---|
| Linux | zcat | Yes | GNU version handles both .Z and .gz |
| macOS | zcat | No | BSD version expects legacy .Z (LZW) format only |
| macOS | gzcat | Yes | Natively handles modern Gzip (DEFLATE) streams |
| macOS | gunzip -c | Yes | Alternative — decompresses to stdout without saving |
# Error you will see on macOS with the wrong command:
# zcat: can't stat: genome.fasta.gz (genome.fasta.gz.Z): No such file or directory
# Correct macOS commands:
gzcat genome.fasta.gz | head
gunzip -c genome.fasta.gz | head
Convert This Report to PDF
# Install pandoc and a minimal LaTeX engine
brew install pandoc basictex
# Convert the Markdown report to a PDF
pandoc GENOMIC_PIPELINE_REPORT.md -o Genomic_Operations_Report.pdf
Or open this HTML file in any browser and use Cmd + P → Save as PDF for a direct PDF export of this full reference page.