Getting Started with Gunz-CM#
version: 1.0.0 status: active
Install#
pip install gunz-cm
Requires Python 3.11 or later. For GPU-accelerated 3D reconstruction and super-resolution, also install the optional extras:
pip install gunz-cm[3dr] # CPU PyTorch
pip install gunz-cm[3dr-gpu] # CUDA PyTorch
pip install gunz-cm[ren] # CPU super-resolution
pip install gunz-cm[ren-gpu] # CUDA super-resolution
Load your first contact matrix#
A Hi-C contact matrix lives in one of several file formats. gunz-cm’s
unified load_cm_data(...) function reads any of them and returns a
matrix in your preferred format:
from gunz_cm import load_cm_data
from gunz_cm.consts import Balancing, DataStructure
# Replace with your file path. The function infers the format from
# the extension (.hic, .cool, .mcool, .csv, .coo, .gzcm, .pkl, .npy).
fpath = "data/sample.mcool"
cm = load_cm_data(
fpath=fpath,
bin_size_bp=1_000_000, # 1 Mb resolution
region1="chr1", # chromosome
region2="chr1", # same-chromosome contact matrix
balancing=Balancing.NONE, # raw counts; or KR, VC, VC_SQRT
output_format=DataStructure.COO, # sparse SciPy matrix
)
print(f"Shape: {cm.shape}, Non-zero entries: {cm.nnz}")
The output is a scipy.sparse.coo_matrix. Convert to a dense array
with the standard scipy method:
dense = cm.toarray() # 2D numpy array
Inspect a file before loading#
Before loading, probe a file to see what’s inside. For multi-resolution
.mcool files, list the available zoom levels; for any cooler file, list
the chromosome names and lengths:
from gunz_cm.loaders import get_chrom_infos
import cooler
# Chromosome names and lengths (works for any cooler file)
chrom_info = get_chrom_infos(fpath)
# {'chr1': {'name': 'chr1', 'length': 248956422}, ...}
# Resolution (read directly from the file attribute)
binsize = cooler.Cooler(fpath).binsize
print(f"Resolution: {binsize:,} bp")
Run with synthetic data (no files required)#
If you don’t have a Hi-C file handy, the tutorials generate synthetic data inline. Here’s the same load call against a synthetic 3x3 contact matrix:
import tempfile
from pathlib import Path
import cooler
import numpy as np
import pandas as pd
from gunz_cm import load_cm_data
from gunz_cm.consts import Balancing, DataStructure
# Create a 3x3 synthetic .cool file
tmpdir = Path(tempfile.mkdtemp(prefix="gunz_cm_demo_"))
fpath = str(tmpdir / "synthetic.cool")
bins = pd.DataFrame({
"chrom": ["chr1"] * 3,
"start": [0, 1_000_000, 2_000_000],
"end": [1_000_000, 2_000_000, 3_000_000],
})
rows, cols, counts = [], [], []
for i in range(3):
for j in range(i, 3):
# Distance-decaying contacts
weight = 100.0 * np.exp(-abs(bins["start"].iloc[i] - bins["start"].iloc[j]) / 1_000_000)
rows.append(i); cols.append(j); counts.append(weight)
pixels = pd.DataFrame({"bin1_id": rows, "bin2_id": cols, "count": counts})
cooler.create_cooler(fpath, bins, pixels, symmetric_upper=True, mode="w")
# Load as a DataFrame
df = load_cm_data(
fpath=fpath, bin_size_bp=1_000_000, region1="chr1",
balancing=Balancing.NONE, output_format=DataStructure.DF,
)
print(df)
Filter and balance the matrix#
Raw counts have visibility and mappability biases. Drop empty rows/columns and apply Knight-Ruiz (KR) matrix balancing:
import numpy as np
from gunz_cm.preprocs import filter_empty_rowcols
# Load as a sparse COO matrix
cm = load_cm_data(
fpath=fpath, bin_size_bp=1_000_000, region1="chr1",
balancing=Balancing.NONE, output_format=DataStructure.COO,
)
sparse_matrix = filter_empty_rowcols(cm) # drop empty bins
# Knight-Ruiz matrix balancing: a Sinkhorn-style loop that finds
# per-bin weights w such that diag(w) @ A @ diag(w) has uniform
# row sums. This teaching version operates in-memory on a small
# matrix; for large datasets use the streaming
# `gunz_cm.normalization.kr_normalize_chunked` instead.
A = sparse_matrix.toarray().astype(float)
w = np.ones(A.shape[0])
for _ in range(200):
row_sums = A @ w
row_sums = np.where(row_sums == 0, 1.0, row_sums)
w_new = w / np.sqrt(row_sums)
if np.max(np.abs(w_new - w)) < 1e-5:
break
w = w_new
balanced = (A * w[:, None]) * w[None, :]
print(f"Row sums after KR: {balanced.sum(axis=1).round(4)}")
# Row sums are now equal across rows (uniform marginals)
Convert to another format#
Convert to COO text, GZCM v3 (compressed tiles), or MEMMAP for archival or downstream tooling:
from gunz_cm.converters import convert_to_cm_coo
from pathlib import Path
# Write a COO text file (tab-delimited: row, col, count)
convert_to_cm_coo(
input_fpath=fpath,
output_fpath=Path(tmpdir / "chr1.coo"),
region1="chr1",
bin_size_bp=1_000_000,
balancing=Balancing.NONE, # synthetic data has no KR weights
on_conflict="overwrite", # v2.25.0: replaces deprecated overwrite=True
)
# Read it back
df = load_cm_data(
fpath=str(tmpdir / "chr1.coo"),
bin_size_bp=1_000_000,
region1="chr1",
balancing=Balancing.NONE,
output_format=DataStructure.DF,
)
print(f"Round-trip pixels: {len(df)}")
Visualize the result#
Render the matrix as a heatmap with the visualizations module:
import matplotlib
matplotlib.use("Agg") # non-interactive backend
import matplotlib.pyplot as plt
import numpy as np
from gunz_cm import load_cm_data
from gunz_cm.consts import Balancing, DataStructure
# Load and visualize
cm = load_cm_data(
fpath=fpath, bin_size_bp=1_000_000, region1="chr1",
balancing=Balancing.NONE, output_format=DataStructure.COO,
)
matrix = cm.toarray().astype(float)
# Direct matplotlib: log-scaled heatmap
fig, ax = plt.subplots(figsize=(6, 5))
im = ax.imshow(
np.log1p(matrix),
cmap="hot_r",
aspect="equal",
interpolation="nearest",
)
ax.set_title("log(1 + count) contact matrix")
fig.colorbar(im, ax=ax, label="log(counts)")
plt.savefig(tmpdir / "matrix.png", dpi=150, bbox_inches="tight")
What’s next?#
This page covered a minimal end-to-end session: install → load → inspect → balance → convert → visualize. To go deeper on any of these stages, read the dedicated user-guide pages:
Load more formats (HIC, COOL, MCOOL, GZCM, PICKLE, NPY): see the :doc:
user_guide/loaderspage and the :doc:tutorials/generated/01_core_operations/01_load_hictutorial.Filter and balance: see :doc:
user_guide/preprocsand :doc:user_guide/normalization, plus the :doc:tutorials/generated/02_preprocessing_normalization/02_balance_krtutorial.Convert and archive: see :doc:
user_guide/convertersand the :doc:tutorials/generated/01_core_operations/03_converttutorial.3D reconstruction and metrics: see :doc:
user_guide/reconstructionsand :doc:user_guide/metrics, plus the :doc:tutorials/generated/prototypes/tutorial_3d_reconstructiontutorial.All tutorials (load → convert → visualize → random downsample): see the :doc:
tutorials/indexpage.
For full API reference, see :doc:gunz_cm or the per-module pages in
:doc:user_guide/index. For a 5-minute overview of the library’s
mental model, see :doc:quickstart.
To report bugs or request features, open an issue on GitHub at https://github.com/sXperfect/gunz-cm/issues.