gunz_cm.structs package#

Module contents#

Data structures module.

This module is the home for typed data shapes that the DOP campaign (v2.18.0 → v2.25.0) populated. It is the canonical surface for DOP Principle 1 (separate code from data) and Principle 4 (illegal states unrepresentable): data shapes live here as frozen Pydantic models, NamedTuples, and Annotated type aliases, while the code that operates on them lives in loaders/, converters/, reconstructions/, etc.

Public exports#

Annotated type aliases (Phase 1):

  • BinSizeBPint with Field(gt=0) for bin sizes in bp

  • DownsampleRatioint with Field(gt=0) for downsampling factors

  • BinCountint with ge=1, le=10_000_000 for bin counts

  • ChromNamestr with regex ^(chr)?[A-Za-z0-9_.-]+$ for chrom names

  • RegionSpecstr with min_length=1, max_length=128 for region specs

Frozen Pydantic models:

Value types:

  • LazyMatrixView — NamedTuple holding a loader + kwargs for deferred materialization

  • materialize() — free function: invoke view.loader(**view.kwargs)

Conflict policy (Phase 7):

  • ConflictPolicyLiteral["error", "overwrite", "skip"]

  • from_legacy_flags() — migrate legacy (overwrite, exist_ok) pair

DOP alignment#

Phase 1 establishes DOP Principles 1 and 3. Phases 2/6/7 extend the module with conversion functions (Phase 2), loader config (Phase 6), and conflict policy (Phase 7). See the release notes at docs/release-notes/v2.{18..25}.0.md for per-phase detail.

Examples

Canonical import path for users:

from gunz_cm.structs import (
    LoaderConfig, RegionSpec, ConflictPolicy, from_legacy_flags,
    CmFrameSchema, LazyMatrixView, materialize,
)
class gunz_cm.structs.CmFrameSchema(*, row_col: str, col_col: str, count_col: str, raw_count_col: str | None = None)[source]#

Bases: BaseModel

Canonical column contract for a contact-matrix DataFrame.

Parameters:
  • row_col (str) – Column name holding the row bin index (0-based, local to the loaded region).

  • col_col (str) – Column name holding the column bin index (0-based, local to the loaded region).

  • count_col (str) – Column name holding the count (raw or balanced, depending on the loader’s balancing argument).

  • raw_count_col (str or None) – Optional column name holding raw (unbalanced) counts. Present only when the loader is invoked with return_raw_counts=True.

Examples

col_col: str#
count_col: str#
has_raw_count() bool[source]#

Return True if this schema carries a separate raw-count column.

Examples

>>> CmFrameSchema(row_col="r", col_col="c", count_col="v").has_raw_count()
False
>>> CmFrameSchema(row_col="r", col_col="c", count_col="v", raw_count_col="raw_v").has_raw_count()
True
model_config: ClassVar[ConfigDict] = {'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

raw_count_col: str | None#
row_col: str#
class gunz_cm.structs.LazyMatrixView(loader: t.Callable[..., t.Any], kwargs: dict[str, t.Any])[source]#

Bases: NamedTuple

Immutable recipe for materializing a contact matrix on demand.

Parameters:
  • loader (Callable[..., t.Any]) – Zero-argument-callable that, when invoked, returns the materialized contact matrix (typically a scipy.sparse.csr_matrix or numpy.ndarray). The loader is invoked by materialize(), passing self.kwargs.

  • kwargs (dict[str, t.Any]) – Keyword arguments to pass to loader at materialize time. Stored as a plain dict (not a MappingProxyType) for ergonomic view.kwargs["path"] = "x.hic" updates prior to materialization, since NamedTuples are immutable and we do not want to break the ergonomic “configure then load” pattern.

Examples

kwargs: dict[str, Any]#

Alias for field number 1

loader: Callable[[...], Any]#

Alias for field number 0

class gunz_cm.structs.LoaderConfig(*, fpath: Path, bin_size_bp: Optional[int] = None, region1: Optional[str] = None, region2: Optional[str] = None, balancing: Optional[Union[Balancing, List[Balancing]]] = None, output_format: DataStructure = DataStructure.DF, fformat: Optional[Format] = None, backend: Optional[Backend] = None, return_raw_counts: bool = False, chunksize: Optional[int] = None)[source]#

Bases: BaseModel

Canonical loader configuration consumed by every format-specific loader.

Frozen, immutable, and validated at construction. The fields mirror the union of all keyword arguments accepted by _load_cooler_data, _load_hic_data, _load_csv_data, _load_memmap_data, and _load_gzcm_data.

fpath#

Path to the contact-matrix file. Required.

Type:

pathlib.Path

bin_size_bp#

Bin size in base pairs. Uses BinSizeBP (positive int). None is allowed because some loaders (CSV, GZCM, PICKLE) do not require an explicit bin size — the value is inferred from the file header.

Type:

Optional[int]

region1, region2

Genomic regions to load. region2=None means “intra-chromosomal of region1”. Both default to None so format-specific loaders that don’t support regions (NPY, PICKLE) can still construct a valid LoaderConfig. Accepts chromosome names (“chr1”), region ranges (“chr1:1-10000”), or the whole-chromosome alias (“ALL”). The strict ChromName regex from _types is intentionally not used here because loaders accept a broader range of region formats.

balancing#

Balancing (normalization) method(s). None means “no balancing”; some formats also accept a list of methods to return multiple normalised columns in one call.

Type:

Optional[Union[gunz_cm.consts.Balancing, List[gunz_cm.consts.Balancing]]]

output_format#

In-memory representation of the loaded data. Defaults to DataStructure.DF (DataFrame).

Type:

gunz_cm.consts.DataStructure

fformat#

Explicit file format. None triggers extension-based inference.

Type:

Optional[gunz_cm.consts.Format]

backend#

Loader backend. None selects the format’s default backend. This is the resolved representation — the legacy use_fast_hic parameter is translated to backend=Backend.STRAW upstream.

Type:

Optional[gunz_cm.consts.Backend]

return_raw_counts#

If True, the loader returns raw counts alongside balanced counts. Not supported by every format; loaders that don’t support it raise NotImplementedError at runtime.

Type:

bool

chunksize#

Optional chunked-streaming parameter. None means “load the full region in one go”. Used by COOLER and HIC loaders.

Type:

Optional[int]

Examples

>>> cfg = LoaderConfig(
...     fpath=pathlib.Path("data.hic"),
...     bin_size_bp=50_000,
...     region1="chr1",
...     backend=Backend.STRAW,
... )
>>> cfg.model_dump()
{'fpath': PosixPath('data.hic'), 'bin_size_bp': 50000, ...}
backend: t.Optional[Backend]#
balancing: t.Optional[t.Union[Balancing, t.List[Balancing]]]#
bin_size_bp: t.Optional[BinSizeBP]#
chunksize: t.Optional[int]#
fformat: t.Optional[Format]#
fpath: pathlib.Path#
model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}#

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

output_format: DataStructure#
region1: t.Optional[RegionSpec]#
region2: t.Optional[RegionSpec]#
return_raw_counts: bool#
gunz_cm.structs.from_legacy_flags(*, overwrite: bool, exist_ok: bool) Literal['error', 'overwrite', 'skip'][source]#

Translate the legacy (overwrite, exist_ok) pair to a ConflictPolicy.

This is the single point of conversion during the v2.24.0 deprecation window. It exists so that:

  1. The four legal (overwrite, exist_ok) combinations map to exactly one of the three named modes.

  2. The illegal (True, True) combination produces a clear ValueError rather than silently falling through to one of the other branches.

Mapping#

  • (False, False)"error" (raise on conflict)

  • (True, False)"overwrite" (replace existing)

  • (False, True)"skip" (log + return)

  • (True, True)ValueError (ambiguous — prefer the new on_conflict parameter for clarity)

param overwrite:

The legacy overwrite flag.

param exist_ok:

The legacy exist_ok flag.

returns:

The corresponding named mode.

rtype:

ConflictPolicy

raises ValueError:

If both flags are True — the combination is ambiguous.

Examples

>>> from_legacy_flags(overwrite=False, exist_ok=False)
'error'
>>> from_legacy_flags(overwrite=True, exist_ok=False)
'overwrite'
>>> from_legacy_flags(overwrite=False, exist_ok=True)
'skip'
gunz_cm.structs.materialize(view: LazyMatrixView) Any[source]#

Materialize a LazyMatrixView by invoking its loader.

This is the canonical way to convert a lazy view into concrete data. Free function (not a method on LazyMatrixView) so the caller can substitute their own materialization strategy.

Parameters:

view (LazyMatrixView) – The lazy view to materialize.

Returns:

Whatever view.loader(**view.kwargs) returns.

Return type:

t.Any

Examples

>>> def fake(**kw): return kw
>>> v = LazyMatrixView(loader=fake, kwargs={"x": 1})
>>> materialize(v) == {"x": 1}
True