File readers and I/O#
Single-pass readers for the common genomic formats, random-access FASTA, the format detector, and the record/flag types they yield. See the User Guide for the iteration contract and grove-loading workflows.
Readers#
- class pygenogrove.BedReader#
Bases:
pybind11_objectA single-pass iterator over the records of a BED file.
Iterate it directly to get BedEntry objects:
for entry in pygenogrove.BedReader("peaks.bed"): ...
Plain and BGZF/gzip-compressed (.gz) files are both accepted (the format is auto-detected). The reader owns an htslib file handle and is single-pass — it cannot be restarted or iterated twice.
- Parameters:
path (str) – Path to the BED file. A missing/unreadable file raises an exception.
skip_invalid_lines (bool, optional) – Controls handling of malformed records after the first. If False (default) such a line raises RuntimeError mid-iteration; if True it is skipped silently. NOTE: the first data record is validated when the reader is constructed, so a malformed first record raises immediately at construction regardless of this flag.
region (str, optional) – A tabix region string (“chr”, “chr:start-end”) in tabix query coordinates (1-based, inclusive) — note this differs from BED’s own 0-based half-open convention. When set, only records overlapping the region are yielded; requires a bgzip-compressed, tabix-indexed file. Empty (default) streams the whole file.
- get_current_line(self: pygenogrove.BedReader) int#
1-based physical line number consumed so far (comments/blanks count); 0 before the first read.
- get_error_message(self: pygenogrove.BedReader) str#
Error message from the most recent read; empty on clean EOF.
- class pygenogrove.GffReader#
Bases:
pybind11_objectA single-pass iterator over the records of a GFF3/GTF file.
Iterate it directly to get GffEntry objects:
for entry in pygenogrove.GffReader("genes.gff3"): ...
The GFF3 vs GTF format is auto-detected per record (see GffEntry.format). Plain and BGZF/gzip-compressed (.gz) files are both accepted. The reader owns an htslib file handle and is single-pass.
- Parameters:
path (str) – Path to the GFF/GTF file. A missing/unreadable file raises an exception.
skip_invalid_lines (bool, optional) – Controls handling of malformed records after the first. If False (default) such a line raises RuntimeError mid-iteration; if True it is skipped silently. NOTE: the first data record is validated when the reader is constructed, so a malformed first record raises immediately at construction regardless of this flag.
validate_gtf (bool, optional) – If True, validate the mandatory GTF2 attributes (gene_id, transcript_id).
region (str, optional) – A tabix region string (“chr”, “chr:start-end”) in tabix query coordinates (1-based, inclusive). When set, only records overlapping the region are yielded; requires a bgzip-compressed, tabix-indexed file. Empty (default) streams the whole file.
- get_current_line(self: pygenogrove.GffReader) int#
1-based physical line number consumed so far (comments/blanks count); 0 before the first read.
- get_error_message(self: pygenogrove.GffReader) str#
Error message from the most recent read; empty on clean EOF.
- class pygenogrove.BamReader#
Bases:
pybind11_objectA single-pass iterator over the alignments of a SAM/BAM file.
Iterate it directly to get SamEntry objects:
for aln in pygenogrove.BamReader("reads.bam"): ...
SAM/BAM are auto-detected by htslib. The reader owns an htslib handle and is single-pass — it cannot be restarted or iterated twice.
- Parameters:
path (str) – Path to the SAM/BAM file. A missing/unreadable file raises.
skip_unmapped (bool, optional) – Skip unmapped reads (default True).
skip_secondary (bool, optional) – Skip the corresponding alignment categories (default False).
skip_supplementary (bool, optional) – Skip the corresponding alignment categories (default False).
skip_qc_fail (bool, optional) – Skip the corresponding alignment categories (default False).
skip_duplicates (bool, optional) – Skip the corresponding alignment categories (default False).
min_mapq (int, optional) – Minimum mapping quality; reads below it are skipped (0 = no filter).
- get_current_line(self: pygenogrove.BamReader) int#
Records consumed so far (advances on skipped/filtered records too).
- get_error_message(self: pygenogrove.BamReader) str#
Error message from the most recent read; empty on clean EOF.
- class pygenogrove.VcfReader#
Bases:
pybind11_objectSingle-pass iterator over a VCF/BCF file (plain, bgzip-ed, or binary BCF; htslib auto-detects). Yields VcfEntry. Not thread-safe — drive one reader per thread.
- for v in pygenogrove.VcfReader(“calls.vcf”, skip_filtered=True):
…
- get_contigs(self: pygenogrove.VcfReader) list[str]#
Contig names declared in the header.
- get_current_line(self: pygenogrove.VcfReader) int#
1-based index of the most recently consumed record (counts records dropped by skip_filtered too); 0 before the first read.
- get_error_message(self: pygenogrove.VcfReader) str#
Error message from the most recent read; empty on clean EOF.
- get_header(self: pygenogrove.VcfReader) str#
Full VCF header text (## meta lines + the #CHROM column line).
- get_sample_names(self: pygenogrove.VcfReader) list[str]#
Sample names in column order (empty for sites-only VCFs).
- class pygenogrove.FastaReader#
Bases:
pybind11_objectA single-pass iterator over the records of a FASTA or FASTQ file.
Iterate it directly to get FastaEntry objects:
for rec in pygenogrove.FastaReader("genome.fa"): print(rec.name, len(rec))
FASTA (>) and FASTQ (@) are auto-detected, and plain or gzip/BGZF-compressed (.gz) inputs are accepted. The reader owns an htslib handle and is single-pass — it cannot be restarted or iterated twice.
- Parameters:
path (str) – Path to the FASTA/FASTQ file. A missing/unreadable file raises.
skip_empty_sequences (bool, optional) – Skip records whose sequence is empty (default False).
- get_current_line(self: pygenogrove.FastaReader) int#
1-based physical line number consumed so far; 0 before the first read.
- get_error_message(self: pygenogrove.FastaReader) str#
Error message from the most recent read; empty on clean EOF.
- class pygenogrove.FastaIndex#
Bases:
pybind11_objectRandom-access reader for a FASTA file, backed by an .fai index.
Opening builds the index if it is missing (this writes a sibling
.faifile, so the FASTA’s directory must be writable on first open). Region coordinates are 0-based half-open[start, end)— to fetch the bases of a GenomicCoordinate (0-based closed[start, end]), callidx.fetch(index, gc.start, gc.end + 1).Non-copyable; the underlying htslib handle is closed when the object is garbage-collected.
- fetch(*args, **kwargs)#
Overloaded function.
fetch(self: pygenogrove.FastaIndex, name: str, start: int, end: int) -> str
fetch(name, start, end) -> str
Bases of sequence name over the 0-based half-open region [start, end). Raises IndexError if name is unknown or the region is invalid (start >= end, or beyond htslib’s limit).
fetch(self: pygenogrove.FastaIndex, name: str) -> str
fetch(name) -> str
The entire sequence named name. Raises IndexError if unknown.
- has_sequence(self: pygenogrove.FastaIndex, name: str) bool#
Whether name is present in the index.
- names(self: pygenogrove.FastaIndex) list[str]#
List of all sequence names, in index order.
- sequence_count(self: pygenogrove.FastaIndex) int#
Number of sequences in the index.
- sequence_length(self: pygenogrove.FastaIndex, name: str) int#
Length in bases of sequence name. Raises IndexError if unknown.
- sequence_name(self: pygenogrove.FastaIndex, index: int) str#
Name of the i-th sequence (0-based). Raises IndexError if out of range.
Record types#
- class pygenogrove.SamEntry#
Bases:
pybind11_objectA single SAM/BAM alignment record (htslib-native coordinates: start is 0-based, end is 0-based exclusive).
Load alignments into the universal Grove as JSON, deriving the strand-aware key from the record:
g = pygenogrove.Grove() for aln in pygenogrove.BamReader("reads.bam"): g.insert(aln.chrom, aln.to_coordinate(), aln.to_dict())
- property chrom#
Reference name (RNAME)
- property cigar#
CIGAR string form, e.g. ‘100M’ (‘*’ if none).
- consumes_reference(self: pygenogrove.SamEntry) bool#
Covers >= 1 reference base (False for unmapped / pure soft-clip).
- property end#
0-based exclusive end (POS + CIGAR ref length)
- property flags#
The AlignmentFlags (FLAG)
- get_strand(self: pygenogrove.SamEntry) str#
Strand char from the FLAG: ‘+’ forward, ‘-’ reverse, ‘.’ unmapped.
- is_mapped(self: pygenogrove.SamEntry) bool#
The read is mapped.
- is_primary(self: pygenogrove.SamEntry) bool#
Not secondary and not supplementary.
- property mapq#
Mapping quality (0-255)
- property qname#
Query/read name (QNAME)
- property quality#
ASCII quality scores (QUAL)
- property sequence#
Read sequence (SEQ)
- property start#
0-based start (htslib-native, from POS)
- to_coordinate(self: pygenogrove.SamEntry) pygenogrove.GenomicCoordinate#
Derive the strand-aware GenomicCoordinate key for this alignment (strand from the FLAG; 0-based half-open [start, end) -> closed [start, end-1]). Raises ValueError if the read covers no reference bases (unmapped or a zero-ref-consuming CIGAR).
- to_dict(self: pygenogrove.SamEntry) dict#
A dict of the core alignment fields (qname, mapq, strand, cigar, flags, is_primary, is_mapped) — convenient as a Grove JSON payload.
- class pygenogrove.FastaEntry#
Bases:
pybind11_objectA single FASTA/FASTQ record: a named nucleotide sequence.
For FASTQ records, quality holds the per-base quality string; for FASTA it is None. name is the header text up to the first whitespace, and comment is the rest of the header line.
- property comment#
Optional description (rest of the header line).
- is_fastq(self: pygenogrove.FastaEntry) bool#
Whether this record carries quality scores (i.e. came from FASTQ).
- property name#
Sequence name (header text up to the first whitespace).
- property quality#
Per-base quality string (FASTQ only; None for FASTA).
- property sequence#
Nucleotide sequence.
- class pygenogrove.VcfEntry#
Bases:
pybind11_objectA single VCF/BCF variant record (0-based half-open start/end, decoupled from any grove key type).
Load variants into the universal Grove as JSON, deriving the key from the record:
g = pygenogrove.Grove() for v in pygenogrove.VcfReader("calls.vcf"): g.insert(v.chrom, v.to_coordinate(), v.to_dict())
- property alt#
ALT alleles (empty for monomorphic records).
- property chrom#
CHROM (contig name).
- property end#
0-based exclusive end (start + len(REF)).
- property filter#
FILTER entries; [‘PASS’] when passed, empty when ‘.’.
- property format#
FORMAT keys in column order (incl. ‘GT’); empty unless parse_samples.
- property id#
ID, empty when ‘.’.
- property info#
name -> bool / list[int] / list[float] / str.
- Type:
INFO fields (when parse_info)
- is_indel(self: pygenogrove.VcfEntry) bool#
True if any sequence ALT differs in length from REF.
- is_snp(self: pygenogrove.VcfEntry) bool#
True for a simple biallelic single-base SNP.
- passed_filter(self: pygenogrove.VcfEntry) bool#
True if FILTER is PASS or unset (‘.’).
- property qual#
QUAL score (only valid when qual_missing is False).
- property qual_missing#
True when QUAL is ‘.’ (missing).
- property ref#
REF allele.
- property samples#
Per-sample SampleGenotype list, parallel to VcfReader.get_sample_names().
- property start#
0-based start (htslib position; VCF POS - 1).
- to_coordinate(self: pygenogrove.VcfEntry) pygenogrove.GenomicCoordinate#
Derive the GenomicCoordinate key for this variant (unstranded ‘.’; 0-based half-open [start, end) -> closed [start, end-1]). Raises ValueError if the record spans no reference bases.
- to_dict(self: pygenogrove.VcfEntry) dict#
A JSON-serializable dict of the core variant fields (id, ref, alt, qual, filter, is_snp, is_indel) — convenient as a Grove payload.
- class pygenogrove.SampleGenotype#
Bases:
pybind11_objectGenotype and FORMAT data for one sample at one variant record.
- property fields#
Other FORMAT fields keyed by tag (e.g. ‘DP’, ‘GQ’), excluding GT. Values are list[int] / list[float] / str.
- property gt_alleles#
Decoded GT allele indices (0 = REF, 1.. = ALT index, -1 = missing ‘.’); empty when no GT field.
- gt_string(self: pygenogrove.SampleGenotype) str#
GT as a VCF-style string (‘0/1’, ‘0|1’, ‘./.’, ‘’ if no GT).
- property has_gt#
True if a GT field was present for this sample.
- is_hom_ref(self: pygenogrove.SampleGenotype) bool#
True if every called allele is the reference (all 0); a missing genotype is not hom-ref.
- property phased#
Whether the genotype is phased (the ‘|’ separator).
Note
VcfEntry.is_symbolic_allele(allele) (static) — returns True when allele
is a symbolic / non-reference placeholder such as <*>, <NON_REF>, or *.
It is documented here manually and excluded from autodoc above because its
binding docstring contains an unescaped * that the RST parser misreads;
re-include it once that is fixed upstream in pygenogrove.
Alignment flags#
- class pygenogrove.SamFlags#
Bases:
pybind11_objectSAM/BAM FLAG bit constants (for has_flag()).
- DUPLICATE = 1024#
- MATE_REVERSE = 32#
- MATE_UNMAPPED = 8#
- PAIRED = 1#
- PROPER_PAIR = 2#
- QCFAIL = 512#
- READ1 = 64#
- READ2 = 128#
- REVERSE = 16#
- SECONDARY = 256#
- SUPPLEMENTARY = 2048#
- UNMAPPED = 4#
- class pygenogrove.AlignmentFlags#
Bases:
pybind11_objectThe SAM/BAM bitwise FLAG, with convenience accessors.
- has_flag(self: pygenogrove.AlignmentFlags, flag: int) bool#
Whether a specific FLAG bit (see SamFlags) is set.
- is_duplicate(self: pygenogrove.AlignmentFlags) bool#
- is_mate_reverse(self: pygenogrove.AlignmentFlags) bool#
- is_mate_unmapped(self: pygenogrove.AlignmentFlags) bool#
- is_paired(self: pygenogrove.AlignmentFlags) bool#
- is_proper_pair(self: pygenogrove.AlignmentFlags) bool#
- is_qc_fail(self: pygenogrove.AlignmentFlags) bool#
- is_read1(self: pygenogrove.AlignmentFlags) bool#
- is_read2(self: pygenogrove.AlignmentFlags) bool#
- is_reverse(self: pygenogrove.AlignmentFlags) bool#
- is_secondary(self: pygenogrove.AlignmentFlags) bool#
- is_supplementary(self: pygenogrove.AlignmentFlags) bool#
- is_unmapped(self: pygenogrove.AlignmentFlags) bool#
- value(self: pygenogrove.AlignmentFlags) int#
Raw 16-bit FLAG value.
Format detection#
- class pygenogrove.FiletypeDetector#
Bases:
pybind11_objectDetects a file’s format and compression from its extension + magic bytes.
- detect_filetype(self: pygenogrove.FiletypeDetector, path: str) tuple[pygenogrove.Filetype, pygenogrove.CompressionType]#
detect_filetype(path) -> (Filetype, CompressionType)
Infer the file format and compression of path. Returns a tuple, e.g. (Filetype.BED, CompressionType.GZIP) for “peaks.bed.gz”. Unrecognized inputs yield Filetype.UNKNOWN / CompressionType.UNKNOWN.
- class pygenogrove.Filetype#
Bases:
pybind11_objectDetected file format.
Members:
BED
BEDGRAPH
GFF
GTF
VCF
SAM
BAM
FASTA
FASTQ
GG
UNKNOWN
- BAM = <Filetype.BAM: 6>#
- BED = <Filetype.BED: 0>#
- BEDGRAPH = <Filetype.BEDGRAPH: 1>#
- FASTA = <Filetype.FASTA: 7>#
- FASTQ = <Filetype.FASTQ: 8>#
- GFF = <Filetype.GFF: 2>#
- GG = <Filetype.GG: 9>#
- GTF = <Filetype.GTF: 3>#
- SAM = <Filetype.SAM: 5>#
- UNKNOWN = <Filetype.UNKNOWN: 10>#
- VCF = <Filetype.VCF: 4>#
- property name#
- property value#
- class pygenogrove.CompressionType#
Bases:
pybind11_objectDetected compression.
Members:
NONE
GZIP
BZIP2
XZ
ZSTD
LZ4
UNKNOWN
- BZIP2 = <CompressionType.BZIP2: 2>#
- GZIP = <CompressionType.GZIP: 1>#
- LZ4 = <CompressionType.LZ4: 5>#
- NONE = <CompressionType.NONE: 0>#
- UNKNOWN = <CompressionType.UNKNOWN: 6>#
- XZ = <CompressionType.XZ: 3>#
- ZSTD = <CompressionType.ZSTD: 4>#
- property name#
- property value#