Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Filter alignments by flags, mapping quality, and regions using samtools view and pysam. Use when extracting specific reads, removing low-quality alignments, or subsetting to target regions.
.claude/skills/bio-alignment-filtering/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 56% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 265% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 96% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 75% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 135% | 0% |
<!--
#
#
-->
Filter alignments by flags, quality, and regions using samtools and pysam.
| Option | Description | |--------|-------------| | -f FLAG | Include reads with ALL bits set | | -F FLAG | Exclude reads with ANY bits set | | -G FLAG | Exclude reads with ALL bits set | | -q MAPQ | Minimum mapping quality | | -L BED | Include reads overlapping regions |
| Flag | Hex | Meaning | |------|-----|---------| | 1 | 0x1 | Paired | | 2 | 0x2 | Proper pair | | 4 | 0x4 | Unmapped | | 8 | 0x8 | Mate unmapped | | 16 | 0x10 | Reverse strand | | 32 | 0x20 | Mate reverse strand | | 64 | 0x40 | First in pair (read1) | | 128 | 0x80 | Second in pair (read2) | | 256 | 0x100 | Secondary alignment | | 512 | 0x200 | Failed QC | | 1024 | 0x400 | Duplicate | | 2048 | 0x800 | Supplementary |
bashsamtools view -F 4 -o mapped.bam input.bam
bashsamtools view -f 4 -o unmapped.bam input.bam
bashsamtools view -f 2 -o proper.bam input.bam
bashsamtools view -F 1024 -o nodup.bam input.bam
bashsamtools view -F 2304 -o primary.bam input.bam
bashsamtools view -F 256 -F 2048 -o primary.bam input.bam # Or combined: -F 2304
bashsamtools view -f 64 -o read1.bam input.bam
bashsamtools view -f 128 -o read2.bam input.bam
bashsamtools view -F 16 -o forward.bam input.bam
bashsamtools view -f 16 -o reverse.bam input.bam
bashsamtools view -q 30 -o highqual.bam input.bam
bashsamtools view -F 4 -q 30 -o filtered.bam input.bam
| MAPQ | Meaning | |------|---------| | 0 | Mapped to multiple locations equally well | | 20 | ~1% chance of wrong mapping | | 30 | ~0.1% chance of wrong mapping | | 40 | ~0.01% chance of wrong mapping | | 60 | Unique mapping (BWA max) |
bashsamtools view -o region.bam input.bam chr1:1000000-2000000
bashsamtools view -o regions.bam input.bam chr1:1000-2000 chr2:3000-4000
bashsamtools view -L targets.bed -o targets.bam input.bam
bashsamtools view -q 30 -L targets.bed -o filtered.bam input.bam
bash# Primary, mapped, non-duplicate, MAPQ >= 30 samtools view -F 3332 -q 30 -o filtered.bam input.bam # 3332 = 4 (unmapped) + 256 (secondary) + 1024 (duplicate) + 2048 (supplementary)
bash# Properly paired, primary, no duplicates, MAPQ >= 20 samtools view -f 2 -F 3328 -q 20 -o clean.bam input.bam # 3328 = 256 (secondary) + 1024 (duplicate) + 2048 (supplementary) # Note: -f 2 (proper pair) implies mapped, so -F 4 is not strictly needed
bash# Remove duplicates and low MAPQ samtools view -F 1024 -q 30 -o filtered.bam input.bam
bash# Keep ~10% of reads samtools view -s 0.1 -o subset.bam input.bam # With seed for reproducibility samtools view -s 42.1 -o subset.bam input.bam
bash# Calculate fraction needed total=$(samtools view -c input.bam) frac=$(echo "scale=4; 1000000 / $total" | bc) samtools view -s "$frac" -o subset.bam input.bam
pythonimport pysam with pysam.AlignmentFile('input.bam', 'rb') as infile: with pysam.AlignmentFile('filtered.bam', 'wb', header=infile.header) as outfile: for read in infile: if read.is_unmapped: continue if read.mapping_quality < 30: continue if read.is_duplicate: continue outfile.write(read)
pythonimport pysam def passes_filter(read): if read.is_unmapped: return False if read.is_secondary or read.is_supplementary: return False if read.is_duplicate: return False if read.mapping_quality < 30: return False return True with pysam.AlignmentFile('input.bam', 'rb') as infile: with pysam.AlignmentFile('filtered.bam', 'wb', header=infile.header) as outfile: for read in infile: if passes_filter(read): outfile.write(read)
pythonimport pysam with pysam.AlignmentFile('input.bam', 'rb') as infile: with pysam.AlignmentFile('region.bam', 'wb', header=infile.header) as outfile: for read in infile.fetch('chr1', 1000000, 2000000): outfile.write(read)
pythonimport pysam def read_bed(bed_path): regions = [] with open(bed_path) as f: for line in f: if line.startswith('#'): continue parts = line.strip().split('\t') regions.append((parts[0], int(parts[1]), int(parts[2]))) return regions regions = read_bed('targets.bed') with pysam.AlignmentFile('input.bam', 'rb') as infile: with pysam.AlignmentFile('targets.bam', 'wb', header=infile.header) as outfile: for chrom, start, end in regions: for read in infile.fetch(chrom, start, end): outfile.write(read)
pythonimport pysam import random random.seed(42) fraction = 0.1 with pysam.AlignmentFile('input.bam', 'rb') as infile: with pysam.AlignmentFile('subset.bam', 'wb', header=infile.header) as outfile: for read in infile: if random.random() < fraction: outfile.write(read)
| Task | samtools command | |------|------------------| | Mapped only | view -F 4 | | Unmapped only | view -f 4 | | Properly paired | view -f 2 | | Primary only | view -F 2304 | | No duplicates | view -F 1024 | | High MAPQ | view -q 30 | | Region | view file.bam chr1:1-1000 | | BED regions | view -L file.bed | | Subsample 10% | view -s 0.1 | | Standard filter | view -F 3332 -q 30 |
| Purpose | Flags | |---------|-------| | Clean reads | -F 3332 -q 30 (mapped, primary, no dups, high qual) | | Variant calling | -f 2 -F 3328 -q 20 (proper pair, primary, no dups) | | Coverage analysis | -F 1284 -q 1 (mapped, primary, no dups) | | Count unique | -F 2304 (primary only) |
Flag breakdowns:
<!-- AUTHOR_SIGNATURE: 9a7f3c2e-MD-BABU-MIA-2026-MSSM-SECURE -->
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-07 | pass→pass | 9,471 | 5,644 | -40% | 1 | 1 | 0% | 1,731 | 3,607 | +108% | 0 | 0 | — |
case-01 | fail→pass | 15,443 | 11,906 | -23% | 1 | 1 | 0% | 3,479 | 5,426 | +56% | 0 | 0 | — |
case-02 | fail→pass | 4,708 | 2,555 | -46% | 1 | 1 | 0% | 845 | 3,087 | +265% | 0 | 0 | — |
case-03 | pass→pass | 13,952 | 9,370 | -33% | 1 | 1 | 0% | 2,488 | 4,476 | +80% | 0 | 0 | — |
case-04 | fail→pass | 11,853 | 7,502 | -37% | 1 | 1 | 0% | 2,044 | 4,014 | +96% | 0 | 0 | — |
case-05 | pass→pass | 12,682 | 8,043 | -37% | 1 | 1 | 0% | 2,315 | 4,157 | +80% | 0 | 0 | — |
case-06 | fail→pass | 11,253 | 6,095 | -46% | 1 | 1 | 0% | 2,087 | 3,649 | +75% | 0 | 0 | — |
case-08 | pass→pass | 8,461 | 5,674 | -33% | 1 | 1 | 0% | 1,667 | 3,327 | +100% | 0 | 0 | — |
case-09 | pass→pass | 6,043 | 2,761 | -54% | 1 | 1 | 0% | 1,094 | 3,075 | +181% | 0 | 0 | — |
case-10 | pass→pass | 5,589 | 3,518 | -37% | 1 | 1 | 0% | 1,077 | 3,248 | +202% | 0 | 0 | — |
case-11 | pass→pass | 8,023 | 7,726 | -4% | 1 | 1 | 0% | 1,503 | 3,355 | +123% | 0 | 0 | — |
case-12 | pass→pass | 13,315 | 13,607 | +2% | 1 | 1 | 0% | 2,868 | 5,598 | +95% | 0 | 0 | — |
case-13 | fail→pass | 7,754 | 6,128 | -21% | 1 | 1 | 0% | 1,666 | 3,917 | +135% | 0 | 0 | — |
case-14 | pass→pass | 6,329 | 6,149 | -3% | 1 | 1 | 0% | 1,165 | 3,338 | +187% | 0 | 0 | — |
case-15 | pass→pass | 9,991 | 6,713 | -33% | 1 | 1 | 0% | 1,876 | 3,801 | +103% | 0 | 0 | — |
case-16 | pass→pass | 6,147 | 2,159 | -65% | 1 | 1 | 0% | 1,020 | 2,955 | +190% | 0 | 0 | — |
case-17 | pass→pass | 10,897 | 9,134 | -16% | 1 | 1 | 0% | 1,991 | 4,295 | +116% | 0 | 0 | — |
case-18 | pass→pass | 9,622 | 5,378 | -44% | 1 | 1 | 0% | 1,759 | 3,563 | +103% | 0 | 0 | — |
case-19 | fail→pass | 11,239 | 7,721 | -31% | 1 | 1 | 0% | 2,273 | 4,298 | +89% | 0 | 0 | — |
case-20 | pass→pass | 5,867 | 4,977 | -15% | 1 | 1 | 0% | 1,102 | 3,490 | +217% | 0 | 0 | — |
case-21 | pass→pass | 4,935 | 3,107 | -37% | 1 | 1 | 0% | 969 | 3,131 | +223% | 0 | 0 | — |
case-22 | pass→pass | 8,474 | 5,415 | -36% | 1 | 1 | 0% | 1,570 | 3,616 | +130% | 0 | 0 | — |
case-23 | pass→pass | 11,106 | 5,349 | -52% | 1 | 1 | 0% | 1,499 | 3,572 | +138% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +26 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 7/26/2026 | +9% |
Other measured skills in the registry, with their headline benchmark lift.