Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
> [!IMPORTANT]
> - 📄 <mark>**CBQ-native**</mark>: reads CBQ directly.
> - ⚡<mark>~ 4-8x faster</mark> than the field on typical data (fastp, cutadapt, atropos, trimmomatic), with 📉 <mark>~90% less memory</mark>.
> - 🧬 <mark>**Reference-free sniff adapters**</mark> (curated 234-known adapters) and 👃 <mark>**sniff strandeness**</mark> for RNA against a Salmon index (given or produced on-the-fly through `--transcriptome <PATH>`).
> - 🧬 <mark>**Reference-free sniff adapters**</mark> (curated 234-known adapters) and 👃 <mark>**sniff strandeness**</mark> for RNA against a Salmon index (`bqc sniff index --sequence tx.fa`, or on-the-fly through `--transcriptome <PATH>`).
> - 🔄 <mark>**Everything in one pass**</mark>: 3' adapter removal (incl. `--allow-indels`), quality/positional/homopolymer trim, polyA/G tails, overlap error correction from the mate, internal-adapter split, UMI extraction, filtering — configurable.
> - 🔒 Deterministic + <mark>safe</mark>: single static binary

Expand Down
12 changes: 12 additions & 0 deletions assets/changelog/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@

All notable changes to this project are documented in this file.

## 0.0.4 — 2026-09-10

### Added

- **`sniff index`** — builds a reusable Salmon 2.x transcriptome index from
a FASTA (plain or gzipped) for `sniff strand --index`. Default destination
is `<stem>.index` beside the FASTA; `--output-directory` and `--prefix`
override location and name. `--force` replaces an existing directory;
without it an existing dest is refused before the build. Same optional
`sniff-strand` feature as `sniff strand`. `--transcriptome` on `sniff
strand` remains the throwaway one-shot.

## 0.0.3 — 2026-08-13

### Added
Expand Down
46 changes: 38 additions & 8 deletions assets/docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ bqc workflow reads.cbq -o out.cbq --config illumina.toml -T 8
bqc umi reads.cbq -o out.cbq --umi-location read1 --umi-length 8
bqc dedup reads.cbq -o unique.cbq -T 8
bqc sniff adapters reads.cbq # inspect, never modify
bqc sniff index --sequence transcripts.fa # reusable Salmon index
bqc sniff strand reads.cbq --index salmon-index # RNA-seq orientation
```

Expand All @@ -98,8 +99,8 @@ dataset-level QC reports; `bqc` itself only reads and writes CBQ.
cargo install bqc
```

`bqc sniff strand` is optional and off by default — its mapping engine
pulls in a large dependency tree and needs a C compiler:
`bqc sniff strand` and `bqc sniff index` are optional and off by default —
the Salmon mapper pulls in a large dependency tree and needs a C compiler:

```bash
cargo install bqc --features sniff-strand
Expand Down Expand Up @@ -605,10 +606,9 @@ bqc sniff strand reads.cbq --transcriptome transcripts.fa # index built on the
`--index` and `--transcriptome` are mutually exclusive; exactly one is
required. **`--transcriptome`** takes a transcriptome FASTA instead of a ready
index and builds a Salmon index from it on the fly in a temporary directory,
discarded when the run ends. There is no persistent index cache — the index is
rebuilt on every run — so reach for `--index` when the same reference is used
repeatedly. The file must exist and be a FASTA; a missing path is a
configuration error.
discarded when the run ends. For a reusable index, run `bqc sniff index`
once and pass the directory to `--index`. The file must exist and be a FASTA;
a missing path is a configuration error.

Two related results are reported:

Expand Down Expand Up @@ -666,10 +666,39 @@ The report also records index provenance — reference count, k-mer length,
decoy state and content hashes — so a result can be matched back to the
index that produced it.

### 5.11 `bqc sniff index`

Builds a reusable Salmon 2.x transcriptome index from a FASTA (plain or
gzipped). Same feature as `sniff strand`. The output is a directory, suitable
as `bqc sniff strand --index`.

```bash
bqc sniff index --sequence transcripts.fa
bqc sniff index --sequence transcripts.fa.gz --output-directory /idx --prefix hg38
idx=$(bqc sniff index --sequence transcripts.fa)
bqc sniff strand reads.cbq --index "$idx"
```

```text
--sequence <FASTA> transcriptome FASTA, optionally gzipped
--output-directory <PATH> parent directory of the index [FASTA's directory]
--prefix <NAME> index directory name [<fasta-stem>.index]
-T, --threads <INT> worker threads; 0 uses every core
--force replace an existing index directory
```

Default name: strip a trailing `.gz`, then `.fa` / `.fasta` / `.fna`
(any case), and append `.index`. `--prefix` is that last path component as
given — it does not add `.index`. It is a name, not a path; use
`--output-directory` to choose the location. The destination path is printed
to stdout. Without `--force`, an existing directory is refused before the
index is built.

## 6. Sniff reports

Both sniff commands accept `--format text` (default), `json` or `tsv`, and
`-o` writes the report atomically (stdout otherwise).
`sniff adapters` and `sniff strand` accept `--format text` (default), `json`
or `tsv`, and `-o` writes the report atomically (stdout otherwise). `sniff
index` prints the index directory path to stdout and has no report.

* **JSON** is the stable pipeline interface. It carries a `schema_version`
and a common envelope: `tool`, `input` (path, records, schema flags),
Expand Down Expand Up @@ -818,6 +847,7 @@ cardinality.
bqc sniff adapters sample.cbq --require-confident \
--emit-config sample.adapters.toml --format json -o sample.adapters.json
# 2. Is the library stranded? (needs a Salmon index)
bqc sniff index --sequence transcripts.fa --prefix reference.salmon
bqc sniff strand sample.cbq --index reference.salmon \
--require-confident --format json -o sample.strand.json
# 3. Clean the data in one pass using the detected adapters.
Expand Down
2 changes: 1 addition & 1 deletion bqc/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions bqc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bqc"
version = "0.0.3"
version = "0.0.4"
edition = "2024"
description = "CBQ-native all-in-one quality control tool"
license = "MIT"
Expand All @@ -13,10 +13,11 @@ rust-version = "1.91"

[features]
default = []
# `bqc sniff strand`. Opt-in: the Salmon mapper pulls in roughly 330 crates
# and needs a C compiler, which is a large cost to impose on every build for one
# subcommand. This gates optional compilation, not a choice of backend — there
# is one implementation, and no subprocess or FASTQ fallback exists.
# `bqc sniff strand` and `bqc sniff index`. Opt-in: the Salmon mapper pulls in
# roughly 330 crates and needs a C compiler, which is a large cost to impose on
# every build for one pair of subcommands. This gates optional compilation, not
# a choice of backend — there is one implementation, and no subprocess or FASTQ
# fallback exists.
sniff-strand = [
"dep:piscem-rs",
"dep:salmon-core",
Expand Down
21 changes: 14 additions & 7 deletions bqc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ bqc filter reads.cbq -o out.cbq --min-length 30 --failed rejected.cbq
bqc correct pairs.cbq -o out.cbq --correction-log corrections.tsv
bqc workflow reads.cbq -o out.cbq --config illumina.toml -T 8
bqc sniff adapters reads.cbq # inspect, never modify
bqc sniff index --sequence transcripts.fa # reusable Salmon index
bqc sniff strand reads.cbq --index salmon-index # RNA-seq orientation
```

Expand All @@ -31,6 +32,7 @@ bqc sniff strand reads.cbq --index salmon-index # RNA-seq orientation
| Split reads at internal adapters into separate records | `bqc segment` |
| All of the above fused into one pass | `bqc workflow` |
| Non-destructive inspection: which adapters are in this file? | `bqc sniff adapters` |
| Reusable Salmon transcriptome index from a FASTA | `bqc sniff index` |
| RNA-seq library strandedness, against a transcriptome | `bqc sniff strand` |

`bqtools qc` describes a dataset; `bqc filter` decides whether an individual
Expand Down Expand Up @@ -303,9 +305,11 @@ three_prime = "GGATCCTAAGCC"

## Sniffing

`bqc sniff` inspects a file without changing it. It never trims, filters,
reorders or rewrites anything; the input is opened read-only and is
byte-identical afterwards.
`bqc sniff adapters` and `bqc sniff strand` inspect a file without changing
it. They never trim, filter, reorder or rewrite anything; the input is opened
read-only and is byte-identical afterwards. `bqc sniff index` builds a reusable
Salmon transcriptome index from a FASTA so `sniff strand --index` does not
rebuild one on every run.

```bash
bqc sniff adapters reads.cbq # human-readable summary
Expand Down Expand Up @@ -430,6 +434,7 @@ bqc workflow sample.cbq --config sample.toml -o sample.clean.cbq
### Strandedness

```bash
bqc sniff index --sequence transcripts.fa # reusable index
bqc sniff strand reads.cbq --index salmon-index --format json -o strand.json
```

Expand Down Expand Up @@ -477,10 +482,12 @@ Pair orientation is reported as measured. An outward or matching library is
surfaced with a warning rather than collapsed into inward, because that is
exactly the finding worth seeing.

**The index must be a Salmon 2.x index.** An index built by salmon 1.x uses the
pufferfish format and cannot be read; `bqc` says so and gives the rebuild
command. Its reference count, k, decoy state and content hashes are recorded with
the result, so a report can be matched back to the index that produced it.
**The index must be a Salmon 2.x index.** `bqc sniff index --sequence tx.fa`
builds one. An index built by salmon 1.x uses the pufferfish format and cannot
be read; `bqc` says so and gives the rebuild command. `--transcriptome` on
`sniff strand` still builds a throwaway index for a one-shot run. Its reference
count, k, decoy state and content hashes are recorded with the result, so a
report can be matched back to the index that produced it.

Sampling stops at a batch boundary once `--target-informative` (50000)
observations have accumulated, so a high mapping rate does not cost a full pass —
Expand Down
Loading
Loading