Metadata-Version: 2.4
Name: fastq-detector
Version: 0.1.0
Summary: Infer sequencing technology and summarize FASTQ read lengths
Author: Iván Bloise Sánchez
License-Expression: MIT
Project-URL: Homepage, https://github.com/ibloise/fastq_detector
Project-URL: Repository, https://github.com/ibloise/fastq_detector
Project-URL: Issues, https://github.com/ibloise/fastq_detector/issues
Project-URL: Changelog, https://github.com/ibloise/fastq_detector/blob/main/CHANGELOG.md
Keywords: bioinformatics,fastq,sequencing,sra
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# fastq-detector

Small Python package for inferring sequencing technology from FASTQ headers and
summarizing read lengths.

It recognizes Illumina, Oxford Nanopore, PacBio, MGI/BGI, Ion Torrent, and
accession-based SRA/GenBank headers. Plain and gzip-compressed FASTQ files are
supported, with analysis over the complete file or the first `N` reads.

## Requirements

- Python 3.11 or newer.
- No runtime dependencies outside the Python standard library.

## Installation

After a release is published, install the package from PyPI:

```bash
python -m pip install fastq-detector
```

To work from a source checkout, install it in editable mode:

```bash
python -m pip install -e .
```

## Usage

The package can be used in two ways: as a command-line application or as an
importable Python package.

### Command-line interface

```bash
fastq-detector reads.fastq
fastq-detector reads_1.fastq reads_2.fastq.gz --reads 1.2M
fastq-detector reads_1.fastq reads_2.fastq --reads 1000 \
  --block-size 250 --output summary.csv
```

The default analyzes every read in every input file. Multiple FASTQ files can
be passed in one invocation; each file is analyzed independently and produces
its own summary. Use `--reads N` (or `-n N`) to analyze the first `N` reads
from **each file**. The value accepts an integer or a case-insensitive `K`, `M`,
or `G` suffix; for example, `12K` means 12,000 reads and `1.2M` means 1,200,000
reads. The CLI reports the detected technology, confidence, number of reads,
and length statistics. Detection requires at least 80% of the analyzed reads to
agree; otherwise the result is `Ambiguous`.

Use `--output FILE.csv` to write one CSV row per input file. The
`--block-size` option controls how many validated reads are held while reading
the input; it defaults to 10,000.

```text
File:                 reads.fastq
Reads analyzed:       1000
Estimated technology: Illumina
Confidence:           100.0%
Minimum:              75 bp
Maximum:              151 bp
Mean:                 149.8 bp
Median:               151.0 bp
25th percentile:      151.0 bp
75th percentile:      151.0 bp
```

### Importable Python package

```python
from fastq_detector import FastqSummary, Technology, summarize_fastq

summary: FastqSummary = summarize_fastq(
    "reads.fastq.gz",
    max_reads=1000,  # Omit to analyze the complete file.
)

print(summary.technology is Technology.ILLUMINA)
print(summary.mean)
print(summary.percentile_25, summary.percentile_75)
```

For multiple files, pass a sequence of paths. `max_reads` is applied
independently to every file:

```python
summary = summarize_fastq(
    ["sample_1.fastq", "sample_2.fastq.gz"],
    max_reads=1000,
)
```

For applications that need to consume records incrementally, use the block
iterator:

```python
from fastq_detector import iter_fastq_blocks

for block in iter_fastq_blocks("reads.fastq.gz", block_size=5000):
    for read in block:
        process(read.sequence, read.quality)
```

The `summarize_fastq` function accepts a string or `pathlib.Path` and supports
both plain FASTQ and `.gz` files. It returns a frozen `FastqSummary` dataclass.
Input is validated from its contents rather than its filename. Empty files,
non-FASTQ content, and malformed or incomplete records raise
`FastqFormatError`, a subclass of `ValueError`. Read-length frequencies are
aggregated as the file is consumed, so memory used for length statistics grows
with the number of distinct lengths rather than the number of reads.

## Public API

### `Technology`

`Technology` is a `StrEnum` containing the normalized technology values used by
the detector:

| Member | Value |
| --- | --- |
| `Technology.SRA_GENBANK` | `"NCBI SRA"` |
| `Technology.ILLUMINA` | `"Illumina"` |
| `Technology.OXFORD_NANOPORE` | `"Oxford Nanopore"` |
| `Technology.PACBIO` | `"PacBio"` |
| `Technology.MGI_BGI` | `"MGI/BGI"` |
| `Technology.ION_TORRENT` | `"Ion Torrent"` |
| `Technology.UNKNOWN` | `"Unknown"` |
| `Technology.AMBIGUOUS` | `"Ambiguous"` |

The detector returns `UNKNOWN` when no registered detector matches. It returns
`AMBIGUOUS` when multiple sampled reads do not provide a sufficiently
consistent technology result. `SRA_GENBANK` identifies accession-based FASTQ
headers emitted by SRA Toolkit for `SRR`, `ERR`, and `DRR` runs; it describes
the archive format. When the SRA accession is followed by the original read
header, the detector unwraps it and reports its sequencing technology instead.
If the embedded header is missing or unknown, it falls back to `SRA_GENBANK`.

### `FastqSummary`

`FastqSummary` is an immutable dataclass with these fields:

| Field | Type | Description |
| --- | --- | --- |
| `technology` | `Technology` | Estimated sequencing technology. |
| `confidence` | `float` | Fraction of analyzed reads matching the winning technology. |
| `reads` | `int` | Number of analyzed reads. |
| `minimum` | `int` | Shortest read length in bases. |
| `maximum` | `int` | Longest read length in bases. |
| `mean` | `float` | Arithmetic mean read length. |
| `median` | `float` | Median read length. |
| `percentile_25` | `float` | 25th percentile of read lengths. |
| `percentile_75` | `float` | 75th percentile of read lengths. |

The length statistics are calculated over the reads selected for analysis,
either the complete file or the first `max_reads` reads.

## Development

Run the test suite from the repository root:

```bash
PYTHONPATH=src python -m unittest discover -v
```

Build the wheel and source distribution:

```bash
python -m pip install build
python -m build
```

## License

Distributed under the MIT License. See the
[LICENSE](https://github.com/ibloise/fastq_detector/blob/main/LICENSE) file.
