Skip to content

Commit 404d2b8

Browse files
authored
Dev/2.0.0 (#29)
* feat(report): add reads extracted per taxon to output report * refactor(cli): make CLI arg names more explicit * docs(readme): update CLI arg descriptions + clarity * fix(logging): remove duplicate log message * fix: clippy * docs(changelog): update for version 2.0.0 release * docs(changelog): update for version 2.0.0 release * build: update kractor version to 2.0.0 in Cargo.toml and Cargo.lock * docs: minor changes * style: cargo fmt * style: allow clippy type complexity warning
1 parent 4e21045 commit 404d2b8

9 files changed

Lines changed: 324 additions & 274 deletions

File tree

CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [2.0.0] - 2025-08-12
9+
10+
### Added
11+
- Added a `reads_extracted_per_taxon` field to to summary report (#28)
12+
- Added a `proportion_extracted` field to summary report (#28)
13+
- Added the version to summary report (#28)
14+
- Added an output format (`fasta` or `fastq`) field to the summary report (#28)
15+
- Added a `--verbose` flag (in addition to the existing `-v`)
16+
17+
### Changed
18+
- Removed `-O` for compression type, now uses `--compression-format` for clarity.
19+
- Removed `-l` for compression level, now uses `--compression-level` for clarity.
20+
- Renamed `--json-report` to `--summary`
21+
- Improved the JSON report format to make it easier to read by removing `Paired` and `Single` fields and instead having a simple `total_reads_in` and `total_reads_out` field.
22+
23+
### Fixed
24+
- Removed duplicate log message for taxon IDs identified
25+
- Clippy warnings
26+
827
## [1.0.1] - 2025-06-28
928

1029
### Fixed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "kractor"
3-
version = "1.0.1"
3+
version = "2.0.0"
44
edition = "2021"
55
authors = ["Samuel Sims"]
66
description = "Extract reads from a FASTQ file based on taxonomic classification via Kraken2."

README.md

Lines changed: 79 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,25 @@
1010

1111
**kra**ken extr**actor**
1212

13-
Kractor extracts sequencing reads based on taxonomic classifications obtained
14-
via [Kraken2](https://github.com/DerrickWood/kraken2). It consumes paired or unpaired `fastq[.gz/.bz]` files as input
15-
alongisde a Kraken2 standard output. It can optionally consume a Kraken2 report to extract all taxonomic parents and
16-
children of a given taxid. Fast and multithreaded by default, it outputs `fast[q/a]` files, that can optionally be
17-
compressed. Memory usage
18-
is minimal, averaging ~4.5MB while processing a 17GB fastq file.
13+
Kractor extracts sequencing reads from fastq `[.gz/.bz2]` files using taxonomic classifications obtained via Kraken2.
14+
It supports single or paired-end reads, can optionally include taxonomic parents or children, and uses minimal memory (~4.5 MB for a 17 GB FASTQ file).
1915

20-
The end result is a `fast[q/a]` file containing all reads classified as the specified taxon.
16+
The end result is a `fast[q/a]` file containing all reads classified as the specified taxon(s).
2117

22-
Kractor significantly enhances processing speed compared to KrakenTools for both paired and unpaired reads. Paired reads
23-
are processed approximately 21x quicker for compressed fastqs and 10x quicker for uncompressed. Unpaired reads are
24-
approximately 4x faster for both compressed and uncompressed inputs.
18+
Kractor significantly enhances processing speed compared to KrakenTools for both paired and unpaired reads.
19+
20+
*Performance vs KrakenTools:*
21+
- Paired compressed FASTQ: ~21× faster
22+
- Paired uncompressed FASTQ: ~10× faster
23+
- Unpaired: ~4× faster (compressed or uncompressed)
2524

2625
For additional details, refer to the [benchmarks](benchmarks/benchmarks.md)
2726

2827
## Motivation
2928

30-
Inspired by [KrakenTools](https://github.com/jenniferlu717/KrakenTools).
29+
Provides similar functionality to the [KrakenTools](https://github.com/jenniferlu717/KrakenTools) `extract_kraken_reads` python script.
3130

32-
The main motivation was to enchance speed when parsing, extracting, and writing a large volume of reads - and also to
33-
learn rust.
31+
However the main motivation was to enhance speed when processing multiple, large FASTQ files - and as a way to learn Rust.
3432

3533
## Installation
3634

@@ -43,11 +41,8 @@ release.
4341

4442
![](https://anaconda.org/bioconda/kractor/badges/platforms.svg)
4543

46-
47-
With conda installed, and bioconda channel correctly setup:
48-
4944
```
50-
conda install kractor
45+
conda install -c bioconda kractor
5146
```
5247

5348
### Docker:
@@ -96,21 +91,36 @@ Extract reads from a FASTQ file based on taxonomic classification via Kraken2.
9691
Usage: kractor [OPTIONS] --input [<INPUT>...] --output [<OUTPUT>...] --kraken <KRAKEN> --taxid <TAXID>...
9792

9893
Options:
99-
-i, --input [<INPUT>...] Input file path(s). Accepts up to 2 files (for paired-end reads)
100-
-o, --output [<OUTPUT>...] Output file path(s). Accepts up to 2 files (for paired-end reads)
101-
-k, --kraken <KRAKEN> Kraken2 stdout file path
102-
-r, --report <REPORT> Kraken2 report file path (Optional). Required when using --parents or --children
103-
-t, --taxid <TAXID>... Taxonomic IDs to extract reads for. Can specify multiple
104-
-O, --compression-type <OUTPUT_TYPE> Compression format for output files. Overides the inferred format
105-
-l, --level <COMPRESSION_LEVEL> Compression level [default: 2]
106-
--parents Include all parent taxon IDs in the output
107-
--children Include all child taxon IDs in the output
108-
--exclude Exclude specified taxon IDs from the output
109-
--output-fasta Output results in FASTA format
110-
--json-report Enable a JSON summary output written to stdout
111-
-v Enable verbose output
112-
-h, --help Print help
113-
-V, --version Print version
94+
-i, --input [<INPUT>...]
95+
Input file path(s). Accepts up to 2 files (for paired-end reads)
96+
-o, --output [<OUTPUT>...]
97+
Output file path(s). Accepts up to 2 files (for paired-end reads)
98+
-k, --kraken <KRAKEN>
99+
Kraken2 stdout file path
100+
-r, --report <REPORT>
101+
Kraken2 report file path
102+
-t, --taxid <TAXID>...
103+
One or more taxon IDs to extract reads for
104+
-p, --parents
105+
Include all parent taxon IDs in the output. Requires a Kraken2 report file
106+
-c, --children
107+
Include all child taxon IDs in the output. Requires a Kraken2 report file
108+
--compression-format <OUTPUT_TYPE>
109+
Compression format for output files (gz, bz2). Overides the inferred format
110+
--compression-level <COMPRESSION_LEVEL>
111+
Compression level (1-9) [default: 2]
112+
--exclude
113+
Exclude specified taxon IDs from the output
114+
--output-fasta
115+
Output results in FASTA format
116+
--summary
117+
Enable a JSON summary output written to stdout
118+
-v, --verbose
119+
Enable verbose output
120+
-h, --help
121+
Print help
122+
-V, --version
123+
Print version
114124
```
115125

116126
### Examples:
@@ -139,25 +149,17 @@ kractor -i sample.fastq -o extracted.fasta -k kraken_output.txt -t 562 --output-
139149
Use `--json-report` to get summary statistics (output to stdout on completion)
140150
```json
141151
{
142-
"taxon_count": 1,
143-
"taxon_ids": [
144-
1
145-
],
146-
"reads_in": {
147-
"Paired": {
148-
"total": 107053222,
149-
"read1": 53526611,
150-
"read2": 53526611
151-
}
152+
"total_taxon_count": 2,
153+
"reads_extracted_per_taxon": {
154+
"0": 745591,
155+
"1": 1646
152156
},
153-
"reads_out": {
154-
"Paired": {
155-
"total": 185410,
156-
"read1": 92705,
157-
"read2": 92705
158-
}
159-
},
160-
"input_format": "paired"
157+
"total_reads_in": 3491078,
158+
"total_reads_out": 747237,
159+
"proportion_extracted": 0.2140419091180432,
160+
"input_format": "single",
161+
"output_format": "fastq",
162+
"kractor_version": "2.0.0"
161163
}
162164
```
163165

@@ -169,105 +171,94 @@ Use `--json-report` to get summary statistics (output to stdout on completion)
169171

170172
`-i, --input`
171173

172-
This option will specify the input files containing the reads you want to extract from. They can be compressed - (`gz`,
173-
`bz2`). Paired end reads can be specified by:
174+
Specifies one or two input FASTQ files to extract reads from. Files may be uncompressed or compressed (`gz`, `bz2`).
175+
Paired end reads can be specified by:
174176

175177
Using `--input` twice: `-i <R1_fastq_file> -i <R2_fastq_file>`
176178

177179
Using `--input` once but passing both files: `-i <R1_fastq_file> <R2_fastq_file>`
178180

179-
This means that bash wildcard expansion works: `-i *.fastq`
180-
181181
#### Output
182182

183183
`-o, --output`
184184

185-
This option will specify the output files containing the extracted reads. The order of the output files is assumed to be
186-
the same as the input.
187-
188-
By default the compression will be inferred from the output file extension for supported file types (`gz`, `bz`). If the
189-
output type cannot be inferred, plaintext will be output.
185+
Specifies the output file(s) for extracted reads, matching the order of the input files.
186+
Compression type is inferred from the file extension (.gz, .bz2). If not recognised, output will be uncompressed.
190187

191188
#### Kraken Output
192189

193190
`-k, --kraken`
194191

195-
This option will specify the path to the [Standard Kraken Output Format file](https://github.com/DerrickWood/kraken2/wiki/Manual#standard-kraken-output-format), containing taxonomic classification of read IDs.
192+
Path to the [Standard Kraken Output Format file](https://github.com/DerrickWood/kraken2/wiki/Manual#standard-kraken-output-format), containing taxonomic classification of read IDs.
196193

197194
#### Taxid
198195

199196
`-t, --taxid`
200197

201-
This option will specify the taxon ID for reads you want to extract.
198+
One or more taxonomic IDs to extract.
202199

203-
Multiple taxids can be specified:
204-
`-t 1 2 10`.
200+
For example: `-t 1 2 10`
205201

206-
Each taxid will adhere to `--exclude` `--parents` and `--children`
202+
Each taxid is affected by `--exclude`, `--parents`, and `--children` if those options are used.
207203

208204
### Optional:
209205

210206
#### Output type
211207

212-
`-O, --output-type`
213-
214-
This option will manually set the compression mode used for the output file and will override the type inferred from the
215-
output path.
208+
`--compression-format`
216209

217-
Valid values are:
210+
Manually set output compression format, overriding what is inferred from file names.
218211

219-
- `gz` to output gz
220-
- `bz2` to output bz2
221-
- `none` to not apply compresison
212+
Valid values:
213+
- `gz` – gzip compression
214+
- `bz2` – bzip2 compression
215+
- `none` – no compression
222216

223217
#### Compression level
224218

225-
`-l, --level`
219+
`--compression-level`
220+
221+
Set compression level (1–9).
222+
- 1 = fastest, largest file
223+
- 9 = slowest, smallest file
226224

227-
This option will set the compression level to use if compressing the output. Should be a value between 1-9 with 1 being
228-
the fastest but largest file size and 9 is for slowest, but best file size. By default this is set at 2 as it is a good
229-
trade off for speed/filesize.
225+
Default: 2 (balance of speed and size)
230226

231227
#### Output fasta
232228

233229
`--output-fasta`
234230

235-
This option will output a fasta file, with read ids as headers.
231+
Output sequences in FASTA format instead of FASTQ.
236232

237233
#### Kraken Report
238234

239235
`-r, --report`
240236

241-
This option specifies the path to the [Kraken2 report file](https://github.com/DerrickWood/kraken2/wiki/Manual#sample-report-output-format). If you want to use `--parents` or `--children`
242-
then is argument is required.
237+
Path to the [Kraken2 report file](https://github.com/DerrickWood/kraken2/wiki/Manual#sample-report-output-format). Required if using `--parents` or `--children`.
243238

244239
#### Parents
245240

246241
`--parents`
247242

248-
This will extract reads classified at all taxons between the root and the specified `--taxid`.
243+
Include reads classified between the root and the specified `--taxid`. Requires `--report`.
249244

250245
#### Children
251246

252247
`--children`
253248

254-
This will extract all the reads classified as decendents or subtaxa of `--taxid` (Including the taxid).
249+
Include reads classified at the given taxid and all its descendant taxa. Requires `--report`.
255250

256251
#### Exclude
257252

258253
`--exclude`
259254

260-
This will output every read except those matching the taxid. Works with `--parents` and `--children`
255+
Extract all reads except those matching the given taxids. Can be combined with `--parents` or `--children`.
261256

262257
#### JSON report
263258

264-
`--json-report`
265-
266-
This will output a json report that to stdout upon programme completion.
267-
268-
## Version
259+
`--summary`
269260

270-
- 1.0.1
261+
Write a JSON report to stdout after processing.
271262

272263
## Citation
273264
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.15761838.svg)](https://doi.org/10.5281/zenodo.15761838)

src/cli.rs

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,44 +17,39 @@ pub struct Cli {
1717
/// Kraken2 stdout file path.
1818
#[arg(short = 'k', long = "kraken", required = true)]
1919
pub kraken: PathBuf,
20-
/// Kraken2 report file path (Optional). Required when using --parents or --children.
20+
/// Kraken2 report file path.
2121
#[arg(short = 'r', long = "report", required_if_eq_any([("parents", "true"), ("children", "true")]))]
2222
pub report: Option<PathBuf>,
23-
/// Taxonomic IDs to extract reads for. Use multiple times for multiple IDs.
23+
/// One or more taxon IDs to extract reads for.
2424
#[arg(short = 't', long = "taxid", required = true, num_args(1..))]
2525
pub taxid: Vec<i32>,
26-
/// Compression format for output files. Overides the inferred format.
27-
#[arg(
28-
short = 'O',
29-
long = "compression-type",
30-
value_parser(validate_compression)
31-
)]
26+
/// Include all parent taxon IDs in the output. Requires a Kraken2 report file.
27+
#[arg(short = 'p', long, action)]
28+
pub parents: bool,
29+
/// Include all child taxon IDs in the output. Requires a Kraken2 report file.
30+
#[arg(short = 'c', long, action)]
31+
pub children: bool,
32+
/// Compression format for output files (gz, bz2). Overides the inferred format.
33+
#[arg(long = "compression-format", value_parser(validate_compression))]
3234
pub output_type: Option<niffler::compression::Format>,
33-
/// Compression level
35+
/// Compression level (1-9).
3436
#[arg(
35-
short = 'l',
36-
long = "level",
37+
long = "compression-level",
3738
default_value = "2",
3839
value_parser(validate_compression_level)
3940
)]
4041
pub compression_level: niffler::Level,
41-
/// Include all parent taxon IDs in the output.
42-
#[arg(long, action)]
43-
pub parents: bool,
44-
/// Include all child taxon IDs in the output.
45-
#[arg(long, action)]
46-
pub children: bool,
4742
/// Exclude specified taxon IDs from the output.
4843
#[arg(long)]
4944
pub exclude: bool,
5045
/// Output results in FASTA format
5146
#[arg(long, action)]
5247
pub output_fasta: bool,
5348
/// Enable a JSON summary output written to stdout.
54-
#[arg(long = "json-report")]
55-
pub json: bool,
49+
#[arg(long = "summary")]
50+
pub summary: bool,
5651
/// Enable verbose output.
57-
#[arg(short)]
52+
#[arg(short, long)]
5853
pub verbose: bool,
5954
}
6055

@@ -63,7 +58,7 @@ fn validate_compression(s: &str) -> Result<niffler::compression::Format, String>
6358
"gz" => Ok(niffler::compression::Format::Gzip),
6459
"bz2" => Ok(niffler::compression::Format::Bzip),
6560
"none" => Ok(niffler::compression::Format::No),
66-
_ => Err(format!("Unknown compression type: {}", s)),
61+
_ => Err(format!("Unknown compression type: {s}")),
6762
}
6863
}
6964

@@ -79,8 +74,7 @@ fn validate_compression_level(s: &str) -> Result<niffler::Level, String> {
7974
Ok(8) => Ok(niffler::Level::Eight),
8075
Ok(9) => Ok(niffler::Level::Nine),
8176
_ => Err(format!(
82-
"Unknown compression level: {} Try a value between 1-9",
83-
s
77+
"Unknown compression level: {s} Try a value between 1-9"
8478
)),
8579
}
8680
}

0 commit comments

Comments
 (0)