Skip to content

Commit ddc65c9

Browse files
authored
Merge pull request #73 from AyushSemwal/annot_demux_refactor
* Default annotation model switched from 10x3p_sc_ont_013 (Conv+CRF) to 10x3p_sc_ont_016 (CNN-BiLSTM-CRF, 3 conv × 64 filters, 1 BiLSTM × 32 units). Empirically validated to ~525 kb on 4× L40S. * GPU stability hardening — bounded join→SIGTERM→SIGKILL worker shutdown to prevent NCCL ring corruption across jobs, predict_with_backoff now raises on stale model after K.clear_session(), XLA disabled (tf2crf Viterbi incompatibility on TF 2.15), CUDA_VISIBLE_DEVICES no longer blanked when no GPUs found, model state persisted across length bins. * QC enhancements — new --gene-body-bed flag accepting RSeQC-style BED12 (replaces auto-extraction from GTF); single-pass BAM scan is significantly faster. * Training/simulation — new --min-flank/--max-flank for terminal cDNA flanks, separate from interior --min/max-spacer; pre-flight read-length math corrected in assess-model. * Observability — every pipeline stage reports peak memory + elapsed time; logs and artifacts include the model name. * Bug fixes — barcode-correct falls back to bundled seq_orders.yaml when only --model-name is given; extract_annotated_seqs no longer crashes on empty Starts. * Documentation — resource_requirements.qmd re-anchored on _016 (bpt 6,644 → 2,916, k 73.4 → 32.2 KB/bp); new --max-batch-size per-VRAM-tier tuning guidance; XLA references removed; tentative-figures disclaimer added pending per-GPU benchmarking.
2 parents 85d1676 + 382c5fd commit ddc65c9

41 files changed

Lines changed: 920 additions & 376 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/test.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ jobs:
3737
shell: bash -l {0}
3838
run: |
3939
mkdir -p tests/10x3p/data tests/references
40-
curl -L "https://www.dropbox.com/scl/fi/k18rs7icrw7la7ogoi9bh/10x3p_sc_ont_013.h5?rlkey=ssw6ylhpvwe3e96jmwm0j3pzg&st=5byhrx7t&dl=0" -o models/10x3p_sc_ont_013.h5
41-
curl -L "https://www.dropbox.com/scl/fi/2plk01thb9q1o8gqgmgks/10x3p_sc_ont_013_params.yaml?rlkey=twtqwmpsyv6ecqeh7a2c5k6tx&dl=0" -o models/10x3p_sc_ont_013_params.yaml
42-
curl -L "https://www.dropbox.com/scl/fi/inz070k8k7kfpibnj9lkt/10x3p_sc_ont_013_lbl_bin.pkl?rlkey=pwhonyomb3i4d13yjat8cxpro&dl=0" -o models/10x3p_sc_ont_013_lbl_bin.pkl
40+
curl -L "https://www.dropbox.com/scl/fi/gmmifxp964fe66qvv3nfk/10x3p_sc_ont_016.h5?rlkey=vqqob3hxrqsuq8540su1aw985&st=bwk2kblf&dl=0" -o models/10x3p_sc_ont_016.h5
41+
curl -L "https://www.dropbox.com/scl/fi/7almukao9vykewf4p73eg/10x3p_sc_ont_016_params.yaml?rlkey=ge8fhouxvvya3umlzryk8mvtq&st=zn01vxqc&dl=0" -o models/10x3p_sc_ont_016_params.yaml
42+
curl -L "https://www.dropbox.com/scl/fi/4wvup62v1sgh7v84899ud/10x3p_sc_ont_016_lbl_bin.pkl?rlkey=m0xt4vzdpfc0ztj91zw93ko8p&st=y5skyjsq&dl=0" -o models/10x3p_sc_ont_016_lbl_bin.pkl
4343
curl -L "https://www.dropbox.com/scl/fi/9203pc2gz45u419kze446/hg38_gencode_chr21.fa?rlkey=k1co80pso7zsvb8oiqqc1o1dy&st=e0e92h5h&dl=1" -o tests/references/hg38_gencode_chr21.fa
4444
curl -L "https://www.dropbox.com/scl/fi/9zvh26moro7frfho818ko/hg38_gencode_chr21.gtf?rlkey=v3s05m9ap3srpjhvl5yfjfeq7&st=hn6mufoq&dl=0" -o tests/references/hg38_gencode_chr21.gtf
45+
curl -L "https://www.dropbox.com/scl/fi/98ykmaori9zrqf0q1qn36/hg38.HouseKeepingGenes.bed.gz?rlkey=dqjabcby9b9owso30njfpauyt&st=zmvxk4pp&dl=0" -o tests/references/hg38.HouseKeepingGenes.bed.gz
4546
4647
- name: Run Pytest with coverage
4748
shell: bash -l {0}

docs/webpages/model_training/assess_model.qmd

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ pannable plots with hover tooltips. This is the primary artifact for reviewing m
146146
| `--transcriptome` | TEXT | None | Transcriptome FASTA for realistic cDNA | Recommended for realistic assessment |
147147
| `--min-spacer` | INT | 0 | Minimum spacer length between concatenated fragments | Adjust if your data has inter-fragment cDNA |
148148
| `--max-spacer` | INT | 50 | Maximum spacer length between concatenated fragments | Adjust if your data has inter-fragment cDNA |
149+
| `--min-flank` | INT | 0 | Minimum length of random cDNA flank at each terminal end of a read | Rarely changed |
150+
| `--max-flank` | INT | 50 | Maximum length of random cDNA flank at each terminal end of a read | Raise (e.g. 200–300) to cover real ONT adapter-flank lengths and reduce edge false positives |
149151
| `--max-trunc-5p` | INT | 0 | Max 5' truncation (bp) | Enable to test truncated read handling |
150152
| `--max-trunc-3p` | INT | 0 | Max 3' truncation (bp) | Enable to test truncated read handling |
151153
| `--threads` | INT | 2 | CPU threads | Increase for faster simulation |
@@ -162,7 +164,7 @@ pannable plots with hover tooltips. This is the primary artifact for reviewing m
162164

163165
```bash
164166
tranquillyzer assess-model \
165-
10x3p_sc_ont_013 \
167+
10x3p_sc_ont_016 \
166168
models/ \
167169
assessment_output/ \
168170
--num-reads 500 \

docs/webpages/model_training/simulate_data_cli.qmd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ For background on how reads are simulated and why, see [Read Structure Simulatio
2929
| `--rc` / `--no-rc` | FLAG | `--rc` | Include reverse complements (doubles the training set) | Disable only if your protocol has a fixed known orientation |
3030
| `--transcriptome` | TEXT | None | Transcriptome FASTA for realistic cDNA generation | Recommended — improves model accuracy on real data |
3131
| `--invalid-fraction` | FLOAT | 0.3 | Fraction of reads generated as structurally invalid artifacts | Increase if your data has many malformed reads |
32+
| `--min-spacer` | INT | 0 | Minimum length of random cDNA spacer between concatenated fragments | Rarely changed |
33+
| `--max-spacer` | INT | 50 | Maximum length of random cDNA spacer between concatenated fragments | Raise to cover longer real chimeric junctions |
34+
| `--min-flank` | INT | 0 | Minimum length of random cDNA flank at each terminal end of a read | Rarely changed |
35+
| `--max-flank` | INT | 50 | Maximum length of random cDNA flank at each terminal end of a read | Raise (e.g. 200–300) to cover real ONT adapter-flank lengths and reduce edge false positives |
3236

3337
# Example Usage
3438

docs/webpages/model_training/train_model.qmd

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,9 @@ Reads are converted to integer tokens before training:
5050
| T | 4 |
5151
| N | 5 |
5252

53-
This mapping is governed by the `vocab_size` parameter (default: 5, for the five nucleotide symbols). The padding token
54-
(0) is used only to make reads within a batch the same length and does not represent a nucleotide.
53+
This mapping is governed by the `vocab_size` parameter (default: 6, covering the four DNA bases, the ambiguity
54+
symbol `N`, and the padding token). The padding token (0) is used only to make reads within a batch the same length
55+
and does not represent a nucleotide.
5556

5657
## Embedding Layer
5758

@@ -79,7 +80,7 @@ The key parameters are:
7980

8081
- **`conv_kernel_size`** (default: 25): how wide a motif each layer can detect at once. Larger kernels help detect
8182
longer protocol motifs and smooth local noise, but values that are too large may blur sharp boundary cues.
82-
- **`conv_filters`** (default: 128 per layer): the number of distinct motif detectors per layer. More filters means
83+
- **`conv_filters`** (default: 64 per layer): the number of distinct motif detectors per layer. More filters means
8384
more pattern capacity at the cost of memory and compute. If boundaries are being missed or adapters vary across
8485
reads, increasing filters is often more effective than adding more layers.
8586
- **`conv_layers`** (default: 3): how many convolutional stages are stacked. More layers allow hierarchical motif
@@ -109,7 +110,7 @@ sequence in order and retaining information over long distances.
109110
_Tranquillyzer_ uses a **bidirectional** LSTM by default, meaning it reads the sequence both left-to-right and
110111
right-to-left. This allows each position to be interpreted using context from both sides.
111112

112-
- **`lstm_units`** (default: 96): the size of the LSTM's internal memory. Increasing units improves the model's ability
113+
- **`lstm_units`** (default: 32): the size of the LSTM's internal memory. Increasing units improves the model's ability
113114
to track long-range structure but increases compute and can overfit.
114115
- **`lstm_layers`** (default: 1): stacking multiple LSTMs increases modeling power but is often unnecessary for
115116
standard protocols.

docs/webpages/model_training/train_model_cli.qmd

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ parameter values. If you want to search over multiple values for a parameter, pr
5555
10x3p_sc_ont:
5656
batch_size: 128
5757
train_fraction: 0.8
58-
vocab_size: 5
58+
vocab_size: 6
5959
embedding_dim: 128
6060
conv_layers: 3
61-
conv_filters: [128, 128, 128]
61+
conv_filters: [64, 64, 64]
6262
conv_kernel_sizes: [25, 25, 25]
63-
dilation_rates: [1, 3, 5]
63+
dilation_rates: [1, 1, 1]
6464
lstm_layers: 1
65-
lstm_units: [96]
65+
lstm_units: [32]
6666
bidirectional: true
6767
crf_layer: true
6868
attention_heads: 0
@@ -100,14 +100,14 @@ other _Tranquillyzer_ commands.
100100
10x3p_sc_ont:
101101
batch_size: 128
102102
train_fraction: 0.8
103-
vocab_size: 5
103+
vocab_size: 6
104104
embedding_dim: 128
105105
conv_layers: 3
106-
conv_filters: [128, 128, 128]
106+
conv_filters: [64, 64, 64]
107107
conv_kernel_sizes: [25, 25, 25]
108-
dilation_rates: [1, 3, 5]
108+
dilation_rates: [1, 1, 1]
109109
lstm_layers: 1
110-
lstm_units: [96]
110+
lstm_units: [32]
111111
bidirectional: true
112112
crf_layer: true
113113
attention_heads: 0

docs/webpages/pipeline/annotation.qmd

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ whitelist-free workflow):
2626

2727
```bash
2828
tranquillyzer annotate-reads \
29-
--model-name 10x3p_sc_ont_013 \
29+
--model-name 10x3p_sc_ont_016 \
3030
--gpu-mem 48 \
3131
--threads 12 \
3232
OUTPUT_DIR
@@ -38,7 +38,7 @@ Use this when you have a whitelist and want the fastest path to demultiplexed re
3838

3939
```bash
4040
tranquillyzer annotate-reads \
41-
--model-name 10x3p_sc_ont_013 \
41+
--model-name 10x3p_sc_ont_016 \
4242
--gpu-mem 48 \
4343
--threads 12 \
4444
--run-barcode-correction \
@@ -69,7 +69,7 @@ automatically pick up from the last completed chunk. Progress is tracked in a ch
6969
|---|:--:|---|---|
7070
| `OUTPUT_DIR` | required | Base output directory | |
7171
| `WHITELIST_FILE` | optional | Barcode whitelist TSV | Required if using `--run-barcode-correction` |
72-
| `--model-name` | `10x3p_sc_ont_013` | Model to use for inference | Set to match your protocol |
72+
| `--model-name` | `10x3p_sc_ont_016` | Model to use for inference | Set to match your protocol |
7373
| `--seq-order-file` | `utils/seq_orders.yaml` | Library definition file | Only if using a custom file |
7474
| `--gpu-mem` | 12 GB | GPU memory budget | Always set to your actual VRAM |
7575
| `--target-tokens` | 1,200,000 | Token budget per GPU | See [Resource Requirements](resource_requirements.qmd) |

docs/webpages/pipeline/barcode_demux.qmd

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ tranquillyzer barcode-correct \
7373
| `INPUT_DIR` | required | Directory containing annotation_metadata/ | |
7474
| `WHITELIST_FILE` | required | TSV with barcode columns | |
7575
| `--output-dir` | `INPUT_DIR` | Where to write corrected output | Set if you want separate output |
76-
| `--model-name` | `10x3p_sc_ont_013` | Model for barcode column resolution | Match your annotation model |
76+
| `--model-name` | `10x3p_sc_ont_016` | Model for barcode column resolution | Match your annotation model |
7777
| `--bc-lv-threshold` | 2 | Max Levenshtein distance for fuzzy matching | Increase for noisier barcodes |
7878
| `--run-demux` | off | Demultiplex concurrently | Enable to get FASTA/FASTQ output |
7979
| `--output-fmt` | `fasta` | Demux format | Use `fastq` if quality scores available |
@@ -92,7 +92,7 @@ using count-based knee-point detection.
9292

9393
```bash
9494
tranquillyzer annotate-reads \
95-
--model-name 10x3p_sc_ont_013 \
95+
--model-name 10x3p_sc_ont_016 \
9696
--gpu-mem 48 \
9797
OUTPUT_DIR
9898
```
@@ -101,7 +101,7 @@ tranquillyzer annotate-reads \
101101

102102
```bash
103103
tranquillyzer generate-whitelist \
104-
--model-name 10x3p_sc_ont_013 \
104+
--model-name 10x3p_sc_ont_016 \
105105
--expected-cells 5000 \
106106
OUTPUT_DIR
107107
```
@@ -126,7 +126,7 @@ tranquillyzer generate-whitelist \
126126
| Option | Default | Description | When to change |
127127
|---|:--:|---|---|
128128
| `OUTPUT_DIR` | required | Annotation output directory | |
129-
| `--model-name` | `10x3p_sc_ont_013` | Model for barcode column resolution | Match your annotation model |
129+
| `--model-name` | `10x3p_sc_ont_016` | Model for barcode column resolution | Match your annotation model |
130130
| `--expected-cells` | None (auto) | Hint for expected number of cells | Provide if known for better knee detection |
131131
| `--min-cell-ratio` | 0.50 | Knee threshold as fraction of cliff-top count | Lower to include more cells; raise for stricter filtering |
132132
| `--min-reads-per-barcode` | 3 | Minimum reads for a barcode to be considered | Increase for noisier data |

docs/webpages/pipeline/qc_metrics.qmd

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Providing an aligned BAM file (with CB and UB tags) enables:
3333
- **Unique UMIs per cell**
3434
- **Mapping rate per cell**
3535
- **Duplicate rate per cell**
36-
- **Gene body coverage** (also requires `--gtf`)
36+
- **Gene body coverage** (also requires `--gene-body-bed`)
3737

3838
## Tier 3: Gene Quantification Metrics (Requires `--counts-matrix` and `--gtf`)
3939

@@ -66,9 +66,30 @@ tranquillyzer qc-metrics \
6666
--bam aligned_files/dup_marked.bam \
6767
--counts-matrix counts_matrix.tsv \
6868
--gtf gencode.v44.annotation.gtf \
69+
--gene-body-bed hg38.HouseKeepingGenes.bed.gz \
6970
INPUT_DIR
7071
```
7172

73+
## Gene Body Coverage
74+
75+
The gene body coverage plot follows the [RSeQC convention](https://rseqc.sourceforge.net/#genebody-coverage-py):
76+
the user supplies a curated BED12 (one transcript per line) via `--gene-body-bed`, and each line is treated
77+
independently in the pileup. No transcript is auto-picked from the GTF — supplying a curated BED keeps the
78+
percentile axis aligned with the canonical mRNA species and avoids artifacts from extended-UTR or retained-intron
79+
isoforms. Both plain and gzipped BED12 are accepted.
80+
81+
Common sources for the BED:
82+
83+
- **RSeQC housekeeping BEDs** ([SourceForge](https://sourceforge.net/projects/rseqc/files/BED/)) — pre-curated
84+
single-isoform-per-gene sets for hg38, hg19, mm10, etc. The fastest path to a clean curve.
85+
- **MANE_Select export** — for human, the ~19,000 MANE_Select transcripts converted to BED12 (e.g. via UCSC
86+
`gtfToGenePred` + `genePredToBed`).
87+
- **Custom curated set** — any BED12 the user trusts (e.g. APPRIS principal isoforms, project-specific genes
88+
of interest).
89+
90+
Without `--gene-body-bed`, the gene body coverage plot is omitted from the report (other QC sections are
91+
unaffected).
92+
7293
# Command Line Options
7394

7495
| Option | Default | Description | When to change |
@@ -81,7 +102,8 @@ tranquillyzer qc-metrics \
81102
| `--invalid-file` | auto-detect | Path to invalid annotations parquet | Only if non-standard location |
82103
| `--bam` | None | Coordinate-sorted BAM with CB/UB tags | Provide for saturation and alignment metrics |
83104
| `--counts-matrix` | None | featureCounts counts matrix TSV | Provide for gene-level QC |
84-
| `--gtf` | None | GTF annotation file | Required with `--counts-matrix`; also used for gene body coverage |
105+
| `--gtf` | None | GTF annotation file | Required with `--counts-matrix` |
106+
| `--gene-body-bed` | None | BED12 file (plain or `.gz`) for gene body coverage, RSeQC-style | Provide a curated single-transcript-per-gene BED (e.g. RSeQC `HouseKeepingGenes.bed.gz`, MANE_Select export) to enable the gene body coverage plot |
85107
| `--read-len-bin-width` | 100 | Bin width for read-length histograms | Decrease for finer resolution |
86108

87109
# Output

docs/webpages/pipeline/visualization.qmd

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ without annotation.
2020
# Visualize N random reads
2121
tranquillyzer visualize \
2222
--num-reads 10 \
23-
--model-name 10x3p_sc_ont_013 \
23+
--model-name 10x3p_sc_ont_016 \
2424
--gpu-mem 48 \
2525
OUTPUT_DIR
2626

2727
# Visualize specific reads by name
2828
tranquillyzer visualize \
2929
--read-names read_001,read_002,read_003 \
30-
--model-name 10x3p_sc_ont_013 \
30+
--model-name 10x3p_sc_ont_016 \
3131
--gpu-mem 48 \
3232
OUTPUT_DIR
3333
```
@@ -40,7 +40,7 @@ Either `--num-reads` or `--read-names` must be provided.
4040
|---|:--:|---|
4141
| `OUTPUT_DIR` | required | Directory with preprocessed reads (writes to `plots/`) |
4242
| `--output-file` | `full_read_annots` | PDF filename prefix |
43-
| `--model-name` | `10x3p_sc_ont_013` | Model for inference |
43+
| `--model-name` | `10x3p_sc_ont_016` | Model for inference |
4444
| `--num-reads` | None | Number of random reads to visualize per Parquet file |
4545
| `--read-names` | None | Comma-separated list of specific read names |
4646
| `--gpu-mem` | 12 GB | GPU memory budget |

docs/webpages/quick_start.qmd

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ _Tranquillyzer_ ships with pre-trained models for common 10x Genomics protocols:
2020
|:--|:-:|:-:|
2121
| Batch Size | 128 | 128 |
2222
| Training Fraction | 0.8 | 0.8 |
23-
| Vocab Size | 5 | 5 |
23+
| Vocab Size | 5 | 6 |
2424
| Embedding Dimension | 128 | 128 |
2525
| Conv Layers | 4 | 3 |
26-
| Conv Filters | 128 | 128 |
26+
| Conv Filters | 128 | 64 |
2727
| Conv Kernel Size | 25 | 25 |
28-
| Dilation Rates | [1, 1, 1, 1] | [1, 3, 5] |
28+
| Dilation Rates | [1, 1, 1, 1] | [1, 1, 1] |
2929
| LSTM Layers | 1 | 1 |
30-
| LSTM Units | 96 | 96 |
30+
| LSTM Units | 96 | 32 |
3131
| Bidirectional | True | True |
3232
| CRF Layer | True | True |
3333
| Attention Heads | 0 | 0 |
@@ -51,7 +51,7 @@ tranquillyzer preprocess \
5151

5252
# 2. Annotate reads + correct barcodes + demultiplex (single pass)
5353
tranquillyzer annotate-reads \
54-
--model-name 10x3p_sc_ont_013 \
54+
--model-name 10x3p_sc_ont_016 \
5555
--gpu-mem 48 \
5656
--threads 12 \
5757
--run-barcode-correction \
@@ -92,14 +92,14 @@ tranquillyzer preprocess \
9292

9393
# 2. Annotate reads (no whitelist)
9494
tranquillyzer annotate-reads \
95-
--model-name 10x3p_sc_ont_013 \
95+
--model-name 10x3p_sc_ont_016 \
9696
--gpu-mem 48 \
9797
--threads 12 \
9898
/path/to/output
9999

100100
# 3. Discover cell barcodes via knee-point detection
101101
tranquillyzer generate-whitelist \
102-
--model-name 10x3p_sc_ont_013 \
102+
--model-name 10x3p_sc_ont_016 \
103103
--expected-cells 5000 \
104104
/path/to/output
105105

0 commit comments

Comments
 (0)