Design

How genomeblocks works inside: what each table stores, the path data takes through it, and why each step costs what it does. Every page draws the mechanism. The User Guide and API Reference cover how to call it, and the Benchmarks page measures it.

The package at a glance

PLOT matplotlib, lazy signal_draw heatmaps · profiles browserview · view · igv region figures · one-file pages motifs_draw motif heatmaps · logos architecture_draw layouts, any graph backend reads DOMAIN one table per data type signal bigWig → cube bigwig backend Pairs · bedpe BEDPE table · Hi-C pairs tables backend Genes GTF → 3 linked tables tables · intervals motifs Library · hit matrices motifs · fasta backends Atlas bins × tracks, CSR scipy.sparse Architecture vertex + edge tables intervals · graph backends every module builds on Genome · Loci · Locus CORE numpy columns Genome names ↔ int codes · sizes codes[i] → names one per table, re-coded on contact Loci intervals as columns · row number = the join key codes int32 starts int64 ends int64 strands int8 cols {} lookup index built on first use, one per interval backend, dropped when rows change Locus one interval L[i] → LocusView reads the columns BACKENDS one engine per family gb.backends() default first, pip-installable · backend= on a call · with gb.use_backend(...) · a missing engine raises with its install command intervals genomeblocks cgranges · ncls · bioframe pyranges · bedtools bigwig pybigtools pybigwig · python motifs moods else lightmotif biopython fasta genomeblocks pysam · pyfaidx memory · biopython tables polars, else pandas graph graph-tool, else scipy igraph · networkx whole-set work: overlap, signal, scanning, graphs BOUNDARY interop, in and out as_loci(x) every public function calls it on its inputs · columns found by name, lenient on spelling pandas polars pyarrow bioframe pyranges pybedtools AnnData BED · CSV · parquet region strs lists · dicts out: to_pandas · to_polars · to_arrow · to_bioframe · to_pyranges · to_bedtool · to_anndata · to_bed · save · protocols: Arrow C stream · __dataframe__ · narwhals
Five bands, four layers. The core tables are the package: Genome maps names to codes, Loci holds intervals as numpy columns, and a Locus is one row read from them. The domain tables (Genes, Pairs, Architecture, Atlas) and the compute modules (signal, motifs) are built on those columns and return arrays aligned to the rows. Every input enters through the boundary (genomeblocks.interop), so the tables never see pandas or polars. Heavy work runs through one of six backend families, invisible unless you ask for a particular engine. Plot modules read the tables and are never imported by them, so processing never pulls in matplotlib.
import genomeblocks as gb                          # 3 ms; imports no submodule

cre   = gb.Loci.make("atac.narrowPeak", keep=True) # tables
genes = gb.Genes.make("gencode.gtf")
A = (gb.Architecture.make(cre, "loops.bedpe")      # boundary: a path, a Pairs or a frame
       .add_mcool("hic.mcool", resolution=5000)
       .normalize().annotate(genes))
A.components(backend="networkx")                   # backends: same labels on any engine
A.draw("chr8:127.5-128.5 Mb")                      # drawing

Principles

The row number is the join key. Row i of a Loci is row i of the signal cube, the motif matrix, the label vector and every Architecture vertex column computed from it; transcripts['gene'][k] is the row of transcript k’s gene; an edge is (src row, tgt row). Joining a result back to its intervals is array indexing. The uid (chr1:100-200(+)) remains as a name for lookups and exports, not as the key the tables rely on.

One Genome per table, re-coded on contact. Chromosomes are stored as small integer codes into the table’s Genome. Tables built from one another share it; tables read separately each get their own, and an operation between two of them re-codes the second onto the first through a small lookup (Loci._check). There is no session-wide dictionary and no required setup.

Boundary first. Every public function calls as_loci on its interval inputs and the tables convert back out through explicit to_* methods and the Arrow / dataframe protocols. Column names are lenient on input, strict internally. Nothing deep in the package branches on an input type.

Backends are invisible. A call runs on the default engine; backend= or gb.use_backend() picks another; results are normalised to one set of rules so the engine never shows in them. Automatic choice happens only where the candidates are known to give identical answers. A requested engine that is missing raises with its install command rather than switching silently.

Protocols, not adapters. Every container implements __arrow_c_stream__, __dataframe__ and __narwhals_dataframe__ (and Loci __array__), so polars, DuckDB, seaborn, plotly and altair take it as it is. shape, columns, head(), describe() and _repr_html_ make it behave like a frame in a notebook.

Lazy imports. import genomeblocks imports nothing but the names table and resolves gb.Loci, gb.backends and the rest on first use. pandas, pyarrow, narwhals, scipy, matplotlib and every engine are imported inside the function that needs them, so the import costs milliseconds and a pipeline pays only for what it calls.

Processing and drawing are separate modules. signal_draw, motifs_draw, architecture_draw, browserview, view and igv read results; nothing in a processing module imports matplotlib.

Chainable results. Every step returns a table, a numpy array or a frame, and the next step accepts it unchanged.

Module pages

Page What it explains
Tables columns and codes, the shared Genome, the sorted edge table and its views, parquet, short-range HiChIP and super-enhancers
Loci & Locus set algebra on the genome-wide axis, point lookups, the interval backends
Genes GTF / GFF3 → three linked tables, 0-based coordinates, region labels, supported isoforms
Signal bigWig → signal cube, the bigWig backends, process-parallel extraction
Motifs one library, block scanning of many windows × many motifs, three engines
BEDPE & pairs the Pairs table and streaming Hi-C pair counts
Atlas one sparse bins × tracks index and vectorised Fisher tests
Architecture the contact-graph pipeline, weights, genes, hubs and the graph backends
Browser one axis per track, a drawer per track type

The boundary and the engines have their own pages outside this section: Interoperability and Backends.


Copyright © 2024–2026 Umut Berkay Altintas. MIT Licensed.

This site uses Just the Docs, a documentation theme for Jekyll.