Readers¶
Driven adapters that read genomic data from external file formats and produce immutable domain objects. Readers sit at the boundary between the domain and the filesystem — they own all format-specific parsing and coordinate conversion.
Overview¶
Taxonomy¶
| Reader | Format | Output type |
|---|---|---|
VcfReader |
VCF / BCF | VariantAnnotation per ALT allele |
VcfCohortReader |
Multi-sample VCF / BCF | Variant + GenotypeCount per allele |
BedRegionReader |
BED 3–6 | GenomicPosition |
GtfReader |
GTF / GFF3 | GtfRecord (low-level) |
GencodeGeneRepository |
GENCODE GTF / GFF3 | GeneAnnotation (implements GeneRepository) |
TabixReader |
bgzipped + tabix-indexed (base) | dict rows — used internally by annotators |
ZarrVariantReader |
vcf2zarr Zarr stores | VariantAnnotation |
NirvanaReader |
Nirvana JSON | VariantAnnotation with transcripts, classifications, and scores |
EmedgeneReader |
Emedgene (Illumina) Excel report | VariantAnnotation |
TabixReader — shared foundation¶
TabixReader is the base class behind every bgzipped file reader and all tabix-based
annotators. It provides two access patterns:
_query(path, targets)— point lookups by(chrom, pos, ref, alt)key._query_region(path, regions)— interval scans overGenomicPositionranges.
Both patterns handle chromosome alias normalization automatically. For parallel
workloads, each worker must open its own TabixFile; handles are never shared
across threads.
VCF readers¶
VcfReader handles single-sample and joint-genotyped VCFs. When a sample_id is
provided it returns only ALT alleles present in that sample and infers zygosity
from the GT field. Without a sample, all ALT alleles in every record are yielded.
store_info=True serializes all INFO fields into Metadata.data.
VcfCohortReader is the population-level counterpart. It reads a multi-sample
VCF for a defined sample subset and computes per-variant GenotypeCount statistics
(ref/ref, ref/alt, alt/alt counts). Two API levels are available: iter_region_counts
for raw counts, and a higher-level method that returns VariantAnnotation objects
with inline frequency annotations.
Coordinate convention¶
All readers convert to 1-based inclusive before constructing GenomicPosition:
- BED (0-based half-open) →
start + 1;endstays as-is - pysam
.fetch()(0-based half-open) →start + 1 - GTF / GENCODE — already 1-based inclusive, no conversion needed
- Zarr
variant_position— already 1-based
GENCODE provider¶
GencodeGeneRepository implements the GeneRepository port directly, making it
drop-in compatible with any service that depends on that interface. It parses a
GENCODE GTF (or GFF3) and builds GeneAnnotation objects with full transcript
structure. Filtering options: transcript support level, MANE Select tag, and
specific biotypes.
Optional dependency¶
All readers backed by pysam use a lazy import with a clear error message if the package is absent:
try:
import pysam
except ImportError as exc:
raise ImportError("pysam is required: uv pip install 'iris[genomics]'") from exc
VCF¶
iris.adapters.driven.readers.vcf
¶
VCF/BCF file reader using pysam, producing VariantAnnotation objects.
VcfReader
¶
Reads VCF/BCF files (.vcf, .vcf.gz, .bcf) using pysam.
When sample_id is provided, only ALT alleles called in that sample are returned and zygosity is inferred from the GT field. When omitted, all ALT alleles in every record are returned without genotype filtering.
With store_info=True, all INFO fields are serialized into Metadata.data. QUAL and non-PASS FILTER values are always stored when present.
read
¶
Read a VCF/BCF file and return a list of VariantAnnotation objects.
Source code in src/iris/adapters/driven/readers/vcf.py
VCF Cohort¶
iris.adapters.driven.readers.vcf_cohort
¶
Multi-sample VCF/BCF cohort reader for population-level statistics.
VcfCohortReader
¶
Reads a multi-sample VCF/BCF for a defined sample subset, computing population-level statistics per variant and genomic region.
Two levels of API are provided:
iter_region_counts
Low-level: yields list[tuple[Variant, GenotypeCount]] per region.
Each entry is one ALT allele. Use this when you need raw counts for
downstream analyses (HWE, missingness, stratified AF, etc.).
iter_regions
High-level convenience: yields list[VariantAnnotation] per region,
with a single AlleleFrequency per variant populated from the counts.
The BCF file is opened once per iter_region_counts / iter_regions
call regardless of the number of regions, and sample indices are resolved
once from the header.
| ATTRIBUTE | DESCRIPTION |
|---|---|
sample_ids |
Frozenset of sample identifiers to include in the cohort. All IDs must be present in the VCF header.
TYPE:
|
population |
Label written to
TYPE:
|
min_an |
Minimum allele number required to emit a variant. Variants
where all cohort samples are missing are dropped (default
TYPE:
|
assembly |
Assembly name written to
TYPE:
|
Example
from iris.domain.genomics.utils import chrom_blocks
from iris.adapters.driven.readers.vcf_cohort import VcfCohortReader
reader = VcfCohortReader(sample_ids=frozenset(my_79k_ids), population="cohort_79k")
blocks = chrom_blocks("1", 248_956_422, block_size=10_000_000)
for block_vas in reader.iter_regions("cohort.bcf", blocks):
exporter.export(block_vas, fh)
iter_region_counts
¶
Yield raw genotype counts per region block.
Each yielded list contains one (Variant, GenotypeCount) tuple per
ALT allele that passes min_an. Multiallelic records produce one
tuple per ALT. Blocks with no passing variants yield an empty list.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
Path to a bgzipped, tabix/CSI-indexed VCF or BCF file.
TYPE:
|
regions
|
Genomic regions defining the blocks. Regions spanning multiple chromosomes are handled efficiently (one file open, grouped internally by chromosome).
TYPE:
|
| YIELDS | DESCRIPTION |
|---|---|
list[tuple[Variant, GenotypeCount]]
|
One list of |
Source code in src/iris/adapters/driven/readers/vcf_cohort.py
iter_regions
¶
Yield VariantAnnotation objects with AlleleFrequency per region block.
Convenience wrapper around iter_region_counts. Each variant
carries one AlleleFrequency entry for self.population.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
Path to a bgzipped, tabix/CSI-indexed VCF or BCF file.
TYPE:
|
regions
|
Genomic regions defining the blocks.
TYPE:
|
| YIELDS | DESCRIPTION |
|---|---|
list[VariantAnnotation]
|
One list of |
Source code in src/iris/adapters/driven/readers/vcf_cohort.py
BED¶
iris.adapters.driven.readers.bed
¶
BED file reader producing GenomicPosition objects.
BedRegionReader
¶
Bases: RegionReader
Reads BED files (BED3–BED6) and produces GenomicPosition objects.
BED coordinates are 0-based half-open [start, end); they are converted to 1-based inclusive as stored by GenomicPosition.
read
¶
Read BED records from handle and return them as GenomicPosition objects.
Source code in src/iris/adapters/driven/readers/bed.py
GTF¶
iris.adapters.driven.readers.gtf
¶
Low-level streaming parser for GTF and GFF3 annotation files.
GtfRecord
¶
A single parsed record from a GTF or GFF3 file.
Coordinates are 1-based inclusive (GENCODE/GTF native).
Multi-value GTF attributes (e.g. tag) are stored as frozenset[str].
GtfReader
¶
Streaming parser for GTF and GFF3 files (plain text or gzip-compressed).
Both GENCODE GTF and GFF3 formats are supported. Format detection is based
on file extension (.gff / .gff3 → GFF3; everything else → GTF).
Compressed files must end in .gz.
Usage::
reader = GtfReader()
for record in reader.read("gencode.v46.annotation.gtf.gz"):
if record.feature == "gene":
print(record.get("gene_name"))
read
¶
Yield one :class:GtfRecord per data line, skipping comment lines.
Source code in src/iris/adapters/driven/readers/gtf.py
Tabix¶
iris.adapters.driven.readers.tabix
¶
Tabix query primitives: point lookups and region scans over bgzipped indexed files.
TabixReader
¶
Base class for reading bgzipped, tabix-indexed files via pysam.
Provides point-lookup and region-scan methods with automatic chromosome prefix resolution and duplicate-line suppression.
The workers parameter (available on all query methods) enables
chromosome-partitioned parallel fetching via ThreadPoolExecutor.
Each worker opens its own TabixFile; handles are never shared across
threads. workers=1 (the default) preserves the original sequential,
lazy-iterator behaviour.
Zarr¶
iris.adapters.driven.readers.zarr
¶
Zarr store reader for vcf2zarr-formatted variant stores.
ZarrVariantReader
¶
Reads a vcf2zarr Zarr store and returns VariantAnnotation objects.
When sample_id is provided, only ALT alleles called in that sample are returned and zygosity is inferred from call_genotype. When omitted, all ALT alleles in every record are returned without genotype filtering.
ClinVar annotations (variant_CLNSIG, variant_CLNREVSTAT) and allele frequencies (variant_AF, variant_AC, variant_AN) are parsed automatically when present. With store_info=True, all remaining variant_* INFO fields are serialized into Metadata.data.
variant_position is assumed 0-based (the vcf2zarr default). Set zero_based=False for stores built with 1-based positions.
read
¶
Read a vcf2zarr Zarr store and return VariantAnnotation objects.
Source code in src/iris/adapters/driven/readers/zarr.py
GENCODE¶
iris.adapters.driven.readers.providers.gencode
¶
GENCODE gene annotation reader backed by a GTF or GFF3 file.
Implements :class:~iris.domain.genomics.repositories.GeneRepository so the
adapter is drop-in compatible with any port that depends on that interface.
Typical usage::
from pathlib import Path
from iris.adapters.driven.readers.providers.gencode import GencodeGeneRepository
repo = GencodeGeneRepository(
"gencode.v46.annotation.gtf.gz",
assembly="GRCh38",
version="v46",
tags={"MANE_Select"}, # only MANE Select transcripts
min_transcript_support_level=2, # TSL 1 or 2
)
# Single gene (by Ensembl ID or gene name)
ann = repo.get_annotation("BRCA1")
# Subset of genes
anns = repo.find_annotations(["BRCA1", "BRCA2", "TP53"])
# All genes
all_anns = repo.find_all_annotations()
GencodeGeneRepository
¶
GencodeGeneRepository(
path,
*,
assembly=None,
version=None,
annotation_sources=None,
tags=None,
min_transcript_support_level=None,
)
Bases: GeneRepository
Read-only gene repository backed by a GENCODE GTF or GFF3 annotation file.
All data is loaded lazily on the first access and cached for the lifetime of the instance. Filters are applied during the initial scan so the in-memory cache only contains transcripts that pass them.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
Path to the annotation file (
TYPE:
|
assembly
|
Genome assembly identifier stored in every
:class:
TYPE:
|
version
|
GENCODE release label stored in
:class:
TYPE:
|
annotation_sources
|
If provided, only include transcripts whose GTF
source column (second column) is in this set. Typical values are
TYPE:
|
tags
|
If provided, only include transcripts that carry at least one
of these tags (e.g.
TYPE:
|
min_transcript_support_level
|
If provided, only include transcripts
whose
TYPE:
|
Source code in src/iris/adapters/driven/readers/providers/gencode.py
from_registry
classmethod
¶
from_registry(
source="gencode",
registry=None,
*,
assembly=None,
version=None,
tags=None,
min_transcript_support_level=None,
)
Build a GencodeGeneRepository resolving source from the iris DataRegistry.
Source code in src/iris/adapters/driven/readers/providers/gencode.py
get
¶
Return the :class:~iris.domain.genomics.entities.Gene for identifier.
identifier may be a versioned Ensembl ID (ENSG00000012048.23),
an unversioned Ensembl ID (ENSG00000012048), or a gene symbol
(BRCA1).
Source code in src/iris/adapters/driven/readers/providers/gencode.py
get_annotation
¶
Return a fully annotated gene for identifier, or None.
Source code in src/iris/adapters/driven/readers/providers/gencode.py
find_by_position
¶
Return all genes whose genomic span overlaps position.
Source code in src/iris/adapters/driven/readers/providers/gencode.py
find_by_phenotype
¶
Not supported by GTF annotation files; always returns an empty list.
find_all_annotations
¶
Return all :class:~iris.domain.genomics.entities.GeneAnnotation objects.
Source code in src/iris/adapters/driven/readers/providers/gencode.py
find_annotations
¶
Return annotations for the given gene identifiers.
Identifiers may be versioned/unversioned Ensembl IDs or gene symbols. Unknown identifiers are silently skipped.
Source code in src/iris/adapters/driven/readers/providers/gencode.py
Nirvana¶
iris.adapters.driven.readers.providers.nirvana
¶
Nirvana JSON annotation file reader producing VariantAnnotation objects.
NirvanaReader
¶
Reads a Nirvana JSON annotation file and yields VariantAnnotation objects for one sample.
read
¶
Parse the Nirvana JSON file and return VariantAnnotation objects.
Source code in src/iris/adapters/driven/readers/providers/nirvana.py
Emedgene¶
iris.adapters.driven.readers.providers.emedgene
¶
Emedgene (Illumina) Excel report reader producing VariantAnnotation objects.
Reads the main variant sheet (Sheet1 / first sheet) and the optional 'Applied Filters' sheet, capturing all 59 columns exported by Emedgene.
EmedgeneReader
¶
Reads an Emedgene (Illumina) Excel report and yields VariantAnnotation objects.
Reads the main variant sheet and the 'Applied Filters' sheet (when present). Applied filter metadata is attached to every row so callers can inspect what filters were active when the report was exported.
Requires openpyxl (uv pip install openpyxl).
read
¶
Read an Emedgene Excel report and return VariantAnnotation objects.