$npx -y skills add GPTomics/bioSkills --skill alignment-sortingSort alignment files by coordinate or read name using samtools and pysam. Use when preparing BAM files for indexing, variant calling, or paired-end analysis.
| 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 | # Alignment Sorting |
| 13 | |
| 14 | Sort alignment files by coordinate or read name using samtools and pysam. |
| 15 | |
| 16 | **"Sort a BAM file"** -> Reorder reads by genomic coordinate (for indexing/variant calling) or by name (for paired-end processing). |
| 17 | - CLI: `samtools sort -o sorted.bam input.bam` |
| 18 | - Python: `pysam.sort('-o', 'sorted.bam', 'input.bam')` |
| 19 | |
| 20 | ## Sort Orders |
| 21 | |
| 22 | | Order | Flag | Use Case | |
| 23 | |-------|------|----------| |
| 24 | | Coordinate | default | Indexing, visualization, variant calling | |
| 25 | | Name | `-n` | Paired-end processing, fixmate, markdup | |
| 26 | | Tag | `-t TAG` | Sort by specific tag value | |
| 27 | |
| 28 | ## samtools sort |
| 29 | |
| 30 | ### Sort by Coordinate (Default) |
| 31 | ```bash |
| 32 | samtools sort -o sorted.bam input.bam |
| 33 | ``` |
| 34 | |
| 35 | ### Sort by Read Name |
| 36 | ```bash |
| 37 | samtools sort -n -o namesorted.bam input.bam |
| 38 | ``` |
| 39 | |
| 40 | ### Multi-threaded Sorting |
| 41 | ```bash |
| 42 | samtools sort -@ 8 -o sorted.bam input.bam |
| 43 | ``` |
| 44 | |
| 45 | ### Control Memory Usage |
| 46 | ```bash |
| 47 | samtools sort -m 4G -@ 4 -o sorted.bam input.bam |
| 48 | ``` |
| 49 | |
| 50 | ### Set Temporary Directory |
| 51 | ```bash |
| 52 | samtools sort -T /tmp/sort_tmp -o sorted.bam input.bam |
| 53 | ``` |
| 54 | |
| 55 | ### Specify Output Format |
| 56 | ```bash |
| 57 | # Output as BAM (default) |
| 58 | samtools sort -O bam -o sorted.bam input.bam |
| 59 | |
| 60 | # Output as CRAM |
| 61 | samtools sort -O cram --reference ref.fa -o sorted.cram input.bam |
| 62 | ``` |
| 63 | |
| 64 | ### Sort by Tag |
| 65 | ```bash |
| 66 | # Sort by cell barcode (10x Genomics) |
| 67 | samtools sort -t CB -o sorted_by_barcode.bam input.bam |
| 68 | ``` |
| 69 | |
| 70 | ### Pipe from Aligner |
| 71 | ```bash |
| 72 | bwa mem ref.fa reads.fq | samtools sort -o aligned.bam |
| 73 | ``` |
| 74 | |
| 75 | ## samtools collate vs sort -n |
| 76 | |
| 77 | | Tool | Algorithm | Speed | Memory | Output guarantee | |
| 78 | |------|-----------|-------|--------|------------------| |
| 79 | | `sort -n` | Full lexicographic sort by QNAME | Slowest | Spills to `-T` | Strict total order by name | |
| 80 | | `collate` | Hash-bucket grouping | ~3-10x faster | Bounded | Mates adjacent; between-mate order undefined | |
| 81 | |
| 82 | Use `collate` when extracting paired FASTQ, re-aligning, or streaming through markdup. Use `sort -n` only when a tool requires true lexicographic name order (e.g. RSEM, Salmon alignment-mode). |
| 83 | |
| 84 | ```bash |
| 85 | # Fast paired FASTQ extraction |
| 86 | samtools collate -O -u in.bam tmp_prefix | \ |
| 87 | samtools fastq -1 R1.fq.gz -2 R2.fq.gz -0 /dev/null -s /dev/null -n - |
| 88 | |
| 89 | # Markdup pre-processing (collate beats sort -n here) |
| 90 | samtools collate -O -u in.bam tmp_prefix | \ |
| 91 | samtools fixmate -m -u - - | \ |
| 92 | samtools sort -u - | \ |
| 93 | samtools markdup - out.bam |
| 94 | ``` |
| 95 | |
| 96 | ### Sort Order Required by Downstream Tool |
| 97 | |
| 98 | | Operation | Required sort | |
| 99 | |-----------|---------------| |
| 100 | | `samtools index` | coordinate (hard requirement) | |
| 101 | | `samtools fixmate -m` | name (or collate; needs mates adjacent) | |
| 102 | | `samtools markdup` | coordinate (after fixmate) | |
| 103 | | GATK MarkDuplicatesSpark | coordinate or queryname | |
| 104 | | `samtools mpileup` / `bcftools mpileup` | coordinate | |
| 105 | | GATK HaplotypeCaller, Mutect2 | coordinate | |
| 106 | | featureCounts / HTSeq | coordinate or name (`-p` for paired) | |
| 107 | | umi_tools dedup | coordinate (with index) | |
| 108 | | fgbio GroupReadsByUmi | any order accepted (template-coordinate recommended to avoid an internal re-sort) | |
| 109 | | fgbio CallMolecularConsensusReads | grouped by MI tag (consumes GroupReadsByUmi output) | |
| 110 | | Sniffles, cuteSV, Manta, Delly | coordinate (need SA tags) | |
| 111 | | Salmon alignment-mode | name | |
| 112 | | RSEM (with STAR `--quantMode TranscriptomeSAM`) | name (hard requirement) | |
| 113 | |
| 114 | ## Check Sort Order |
| 115 | |
| 116 | ### From Header |
| 117 | ```bash |
| 118 | samtools view -H input.bam | grep "^@HD" |
| 119 | # SO:coordinate = coordinate sorted |
| 120 | # SO:queryname = name sorted |
| 121 | # SO:unsorted = not sorted |
| 122 | ``` |
| 123 | |
| 124 | ### Verify Sorted |
| 125 | ```bash |
| 126 | # Check if coordinate sorted (returns 0 if sorted). Reset the position tracker |
| 127 | # on each new contig, else the POS reset at every chromosome boundary of a |
| 128 | # correctly sorted multi-contig BAM would falsely report "unsorted". |
| 129 | samtools view input.bam | awk '$3!=c {c=$3; prev=0} $4<prev {exit 1} {prev=$4}' |
| 130 | # Simpler and authoritative: trust the @HD SO: header shown above. |
| 131 | ``` |
| 132 | |
| 133 | ## pysam Python Alternative |
| 134 | |
| 135 | ### Sort with pysam |
| 136 | ```python |
| 137 | import pysam |
| 138 | |
| 139 | pysam.sort('-o', 'sorted.bam', 'input.bam') |
| 140 | ``` |
| 141 | |
| 142 | ### Sort by Name |
| 143 | ```python |
| 144 | pysam.sort('-n', '-o', 'namesorted.bam', 'input.bam') |
| 145 | ``` |
| 146 | |
| 147 | ### Sort with Options |
| 148 | ```python |
| 149 | pysam.sort('-@', '4', '-m', '2G', '-o', 'sorted.bam', 'input.bam') |
| 150 | ``` |
| 151 | |
| 152 | ### Avoid In-Python Sorting |
| 153 | |
| 154 | Do not load BAM records into a list and call `sorted()`. `pysam.sort()` calls samtools' |