$npx -y skills add GPTomics/bioSkills --skill bam-statisticsGenerate alignment statistics using samtools flagstat, stats, depth, coverage, and mosdepth. Use when assessing alignment quality, calculating coverage, or generating QC reports.
| 1 | ## Version Compatibility |
| 2 | |
| 3 | Reference examples tested with: pysam 0.22+, samtools 1.19+ |
| 4 | |
| 5 | Before using code patterns, verify installed versions match. If versions differ: |
| 6 | - Python: `pip show <package>` then `help(module.function)` to check signatures |
| 7 | - CLI: `<tool> --version` then `<tool> --help` to confirm flags |
| 8 | |
| 9 | If code throws ImportError, AttributeError, or TypeError, introspect the installed |
| 10 | package and adapt the example to match the actual API rather than retrying. |
| 11 | |
| 12 | # BAM Statistics |
| 13 | |
| 14 | **"Get alignment statistics and coverage from my BAM file"** -> Generate read counts, mapping rates, per-chromosome statistics, depth profiles, and coverage summaries. |
| 15 | - CLI: `samtools flagstat`, `samtools stats`, `samtools depth`, `samtools coverage` (samtools) |
| 16 | - Python: `pysam.AlignmentFile` with `pileup()` and `get_index_statistics()` (pysam) |
| 17 | |
| 18 | Generate alignment statistics using samtools and pysam. |
| 19 | |
| 20 | ## Quick Summary Commands |
| 21 | |
| 22 | | Question | Best tool | Why | |
| 23 | |----------|-----------|-----| |
| 24 | | Quick read counts by FLAG category | `samtools flagstat` | Fast; counts secondary+supp in totals | |
| 25 | | Per-chromosome counts | `samtools idxstats` | Fast (needs index); **counts secondary+supp** | |
| 26 | | Insert size, MAPQ, error, GC | `samtools stats -r ref.fa` | Comprehensive; feeds MultiQC | |
| 27 | | Per-position depth (small region) | `samtools depth` or pysam pileup | Slow on full genome | |
| 28 | | Per-position depth (genome-wide) | **`mosdepth`** | 3-10x faster than `samtools depth` | |
| 29 | | Per-region coverage (BED) | `mosdepth --by regions.bed` | Production default | |
| 30 | | Coverage histogram / cumulative | `mosdepth -t 4 --no-per-base` | Single-pass histogram | |
| 31 | | Breadth at depth thresholds | `mosdepth --thresholds 1,10,30,100` | Standard exome QC | |
| 32 | | Targeted enrichment QC | `picard CollectHsMetrics` | PCT_OFF_BAIT, FOLD_80_BASE_PENALTY, AT/GC dropout | |
| 33 | | Cross-sample contamination | `verifybamid2`, `somalier` | FREEMIX < 0.01 expected | |
| 34 | |
| 35 | ### What Each Tool Counts (and Doesn't) |
| 36 | |
| 37 | | Counting category | flagstat | stats | idxstats | |
| 38 | |-------------------|----------|-------|----------| |
| 39 | | Primary alignments | `in total` minus supp | `raw total sequences` | mapped column | |
| 40 | | Secondary | `secondary` line | filtered out | counted in mapped | |
| 41 | | Supplementary | `supplementary` line | filtered out | counted in mapped | |
| 42 | | Mapping rate denominator | total *including* supp | primary only | mapped+unmapped | |
| 43 | |
| 44 | For long-read data where one read produces many supplementary alignments, the senior cross-check: |
| 45 | ``` |
| 46 | input_read_count = flagstat_total - secondary - supplementary |
| 47 | = stats_raw_total_sequences |
| 48 | ``` |
| 49 | Reports of "the file has 1.2M reads" where the input was actually 800k with 400k supplementary chimeric splits trace to flagstat misinterpretation. |
| 50 | |
| 51 | ## samtools flagstat |
| 52 | |
| 53 | Fast summary of alignment flags. |
| 54 | |
| 55 | ```bash |
| 56 | samtools flagstat input.bam |
| 57 | ``` |
| 58 | |
| 59 | Output: |
| 60 | ``` |
| 61 | 10000000 + 0 in total (QC-passed reads + QC-failed reads) |
| 62 | 9950000 + 0 primary |
| 63 | 0 + 0 secondary |
| 64 | 50000 + 0 supplementary |
| 65 | 0 + 0 duplicates |
| 66 | 0 + 0 primary duplicates |
| 67 | 9800000 + 0 mapped (98.00% : N/A) |
| 68 | 9750000 + 0 primary mapped (97.99% : N/A) |
| 69 | 9950000 + 0 paired in sequencing |
| 70 | 4975000 + 0 read1 |
| 71 | 4975000 + 0 read2 |
| 72 | 9700000 + 0 properly paired (97.49% : N/A) |
| 73 | 9720000 + 0 with itself and mate mapped |
| 74 | 30000 + 0 singletons (0.30% : N/A) |
| 75 | 15000 + 0 with mate mapped to a different chr |
| 76 | 10000 + 0 with mate mapped to a different chr (mapQ>=5) |
| 77 | ``` |
| 78 | (samtools 1.13+ adds the `primary`, `primary duplicates`, and `primary mapped` lines shown above.) |
| 79 | |
| 80 | ### Multi-threaded |
| 81 | ```bash |
| 82 | samtools flagstat -@ 4 input.bam |
| 83 | ``` |
| 84 | |
| 85 | ### Output to File |
| 86 | ```bash |
| 87 | samtools flagstat input.bam > flagstat.txt |
| 88 | ``` |
| 89 | |
| 90 | ## samtools idxstats |
| 91 | |
| 92 | Per-chromosome read counts (requires index). |
| 93 | |
| 94 | ```bash |
| 95 | samtools idxstats input.bam |
| 96 | ``` |
| 97 | |
| 98 | Output format: `chrom length mapped unmapped` |
| 99 | ``` |
| 100 | chr1 248956422 5000000 1000 |
| 101 | chr2 242193529 4800000 800 |
| 102 | chrM 16569 50000 100 |
| 103 | * 0 0 150000 |
| 104 | ``` |
| 105 | |
| 106 | ### Parse idxstats |
| 107 | ```bash |
| 108 | # Total mapped reads |
| 109 | samtools idxstats input.bam | awk '{sum += $3} END {print sum}' |
| 110 | |
| 111 | # Mitochondrial percentage |
| 112 | samtools idxstats input.bam | awk ' |
| 113 | /^chrM/ {mt = $3} |
| 114 | {total += $3} |
| 115 | END {print mt/total*100 "% mitochondrial"}' |
| 116 | ``` |
| 117 | |
| 118 | ## samtools stats |
| 119 | |
| 120 | Comprehensive statistics including insert size, base quality, and more. |
| 121 | |
| 122 | ```bash |
| 123 | samtools stats input.bam > stats.txt |
| 124 | ``` |
| 125 | |
| 126 | ### View Summary Numbers |
| 127 | ```bash |
| 128 | samtools stats input.bam | grep "^SN" |
| 129 | ``` |
| 130 | |
| 131 | Key summary fields: |
| 132 | - `raw total sequences` - Total reads |
| 133 | - `reads mapped` - Mapped reads |
| 134 | - `reads mapped and paired` - Properly paired |
| 135 | - `insert size average` - Mean insert size |
| 136 | - `insert size standard deviation` - Insert size spread |
| 137 | - `average length` - Mean read length |
| 138 | - `error rate` - Mismatch rate |
| 139 | |
| 140 | ### Gener |