API reference¶
- class vsparse.VCSCArray(shape, major_ptr, values, value_ptr, indices)[source]¶
Bases:
_VCSBaseValue-Compressed Sparse Column array. Values are deduplicated per column.
- Parameters:
- property T: _VCSBase¶
shares buffers and swaps the VCSC/VCSR dual class.
- Type:
Transpose. Free
- astype(dtype, copy=True)¶
Cast the stored values to
dtype. Structural zeros stay zero implicitly.
- copy()¶
- count_nonzero()¶
Count of stored elements that are actually nonzero (unlike
nnz/getnnz).- Return type:
- classmethod from_scipy(mat)¶
Build from any scipy sparse array/matrix (converted internally).
- Return type:
_VCSBase
- getnnz(axis=None)¶
Count of stored elements along
axis, or overall ifNone.
- indices¶
- log1p()¶
Elementwise
log1p. Structural zeros stay zero implicitly.- Return type:
_VCSBase
- major_ptr¶
- max(axis=None)¶
Maximum value (including implicit zeros) along
axis, or overall ifNone.
- mean(axis=None)¶
Mean of (structural + implicit-zero) values along
axis, or overall ifNone.
- min(axis=None)¶
Minimum value (including implicit zeros) along
axis, or overall ifNone.
- multiply(other)¶
Elementwise multiplication (matches scipy’s sparse-array
.multiply).- Return type:
_VCSBase|ndarray
- normalized(view='parafac2', *, recalculate=True)¶
A normalized view of this array – see
vsparse._vcs_norm/vsparse._norm_common.- Parameters:
view (
str|Recipe) – Which normalization recipe to apply: the name of one ofvsparse._norm_common.RECIPES("raw","cp10k_log1p","parafac2"(the default),"scanpy","pearson"), or aRecipebuilt by the caller.recalculate (
bool) – IfTrue(the default), (re)compute the recipe’s statistics fresh from this array. IfFalse, reuse a previously computed view forviewon this same array, if one exists (from an earlier.normalized(view, ...)call, with any value ofrecalculate) – this is how switching between recipes avoids recomputing each one every time. If no such view has been computed yet, one is still computed (there is nothing to reuse). The cache holds at mostNORM_CACHE_MAXSIZErecipes, and holds each view weakly – see_NormCache.
- Return type:
- shape¶
- property stats: VCSStats¶
Per-row/per-column totals and nonzero counts – see
vsparse._stats.Computed on first access (
O(nnz)) and kept, or restored from the sidecar of a file written bywrite_h5ad()/write_zarr(). Normalization reads its per-cell/per-gene scales (a/b) from here.
- sum(axis=None)¶
Sum of (structural) values along
axis(0=rows, 1=columns), or overall ifNone.
- to_scipy()¶
Decompress to the equivalent scipy
csc_array/csr_array.
- transpose()¶
- Return type:
_VCSBase
- value_ptr¶
- values¶
- class vsparse.VCSRArray(shape, major_ptr, values, value_ptr, indices)[source]¶
Bases:
_VCSBaseValue-Compressed Sparse Row array. Values are deduplicated per row.
- Parameters:
- property T: _VCSBase¶
shares buffers and swaps the VCSC/VCSR dual class.
- Type:
Transpose. Free
- astype(dtype, copy=True)¶
Cast the stored values to
dtype. Structural zeros stay zero implicitly.
- copy()¶
- count_nonzero()¶
Count of stored elements that are actually nonzero (unlike
nnz/getnnz).- Return type:
- classmethod from_scipy(mat)¶
Build from any scipy sparse array/matrix (converted internally).
- Return type:
_VCSBase
- getnnz(axis=None)¶
Count of stored elements along
axis, or overall ifNone.
- indices¶
- log1p()¶
Elementwise
log1p. Structural zeros stay zero implicitly.- Return type:
_VCSBase
- major_ptr¶
- max(axis=None)¶
Maximum value (including implicit zeros) along
axis, or overall ifNone.
- mean(axis=None)¶
Mean of (structural + implicit-zero) values along
axis, or overall ifNone.
- min(axis=None)¶
Minimum value (including implicit zeros) along
axis, or overall ifNone.
- multiply(other)¶
Elementwise multiplication (matches scipy’s sparse-array
.multiply).- Return type:
_VCSBase|ndarray
- normalized(view='parafac2', *, recalculate=True)¶
A normalized view of this array – see
vsparse._vcs_norm/vsparse._norm_common.- Parameters:
view (
str|Recipe) – Which normalization recipe to apply: the name of one ofvsparse._norm_common.RECIPES("raw","cp10k_log1p","parafac2"(the default),"scanpy","pearson"), or aRecipebuilt by the caller.recalculate (
bool) – IfTrue(the default), (re)compute the recipe’s statistics fresh from this array. IfFalse, reuse a previously computed view forviewon this same array, if one exists (from an earlier.normalized(view, ...)call, with any value ofrecalculate) – this is how switching between recipes avoids recomputing each one every time. If no such view has been computed yet, one is still computed (there is nothing to reuse). The cache holds at mostNORM_CACHE_MAXSIZErecipes, and holds each view weakly – see_NormCache.
- Return type:
- shape¶
- property stats: VCSStats¶
Per-row/per-column totals and nonzero counts – see
vsparse._stats.Computed on first access (
O(nnz)) and kept, or restored from the sidecar of a file written bywrite_h5ad()/write_zarr(). Normalization reads its per-cell/per-gene scales (a/b) from here.
- sum(axis=None)¶
Sum of (structural) values along
axis(0=rows, 1=columns), or overall ifNone.
- to_scipy()¶
Decompress to the equivalent scipy
csc_array/csr_array.
- transpose()¶
- Return type:
_VCSBase
- value_ptr¶
- values¶
- class vsparse.VCSStats(row_sums, row_nnz, col_sums, col_nnz, col_depth_sums)[source]¶
Per-row/per-column statistics of one VCS array – see
vsparse._stats.The arrays are read-only, since a
VCSStatsis shared between an array and its copies.- Parameters:
- vsparse.from_anndata(adata, layer=None, use_raw=False, format='csc')[source]¶
Convert
adata.X(or a layer /raw.X) into a VCSC/VCSR array.- Parameters:
- Return type:
_VCSBase- Returns:
- vsparse.to_layer(adata, arr, key)[source]¶
Decompress
arrand store it asadata.layers[key].AnnData does not natively understand the VCSC/VCSR layout, so this stores the equivalent scipy sparse array.
- class vsparse.CudaNormalizedView(view)[source]¶
Bases:
objectA
NormalizedViewBaseresident on a CUDA device.Built by
to_gpu(), not directly. Holds the wrapped array’s value-compressed structure and the recipe’s statistics as CuPy arrays, and computesself @ B/B @ selfwith the kernels in this module. All floating-point state isDEVICE_DTYPE(float32).The object pins its device memory for as long as it is alive; drop the reference (and, if you need the memory back immediately,
cupy.get_default_memory_pool().free_all_blocks()) to release it.- Parameters:
view (NormalizedViewBase)
- shape¶
- recipe¶
- major_ptr¶
- value_ptr¶
- indices¶
- values¶
- row_scale¶
- gene_scale¶
- col_mean¶
- col_post_scale¶
- to_cupy_sparse(format=None, *, sort_indices=True)[source]¶
The uncentered
Deltaterm as a CuPy CSR/CSC matrix, one float per nonzero.The device-side counterpart of
to_scipy_sparse(), and the baseline the kernels are benchmarked against: it hands the product to cuSPARSE, at the cost of expanding every value-compressed run and so giving up the layout’s whole memory advantage.meansis left to subtract externally, exactly as on the host.- Parameters:
format (
str|None) – Sparse format to build. Defaults to whichever one matches the wrapped array’s own major axis, which is the one that costs nothing to assemble. Worth overriding: cuSPARSE is markedly faster with a CSR operand in both directions – measurably so fordense @ sparse, where CSC ran ~5x slower inbenchmarks/cases.py– so a caller multiplying repeatedly should pay the one-time conversion and pass"csr".sort_indices (
bool) – Whether to sort each slice’s indices ascending before returning. A VCS slice stores its indices grouped by the value they share, never in index order, so the expanded matrix is not canonical unless this sorts it – and cuSPARSE measured ~6x slower on the unsorted form. That penalty is why this defaults toTruewhere the host’sto_scipy_sparse(), whose result usually goes somewhere less picky, returns the unsorted order. PassFalseto skip the sort when the result is used once, or by something that does not care.
- Return type:
- vsparse.cuda_is_available()[source]¶
Whether CuPy is importable and a CUDA device is actually present.
- Return type:
- class vsparse.VCSCAnnData(X=None, *, raw_X=None, **kwargs)[source]¶
Bases:
AnnDataAn
AnnDatawhoseXis a VCSCArray/VCSRArray.Standard
AnnDatavalidates every array assigned toX/layers/etc. against a fixed allowlist of types (dense/sparse/ dask), so a plainAnnDatacannot hold aVCSCArraydirectly. This subclass overrides theXproperty to store one without going through that validation. A “raw” VCSC/VCSR matrix, if any, is kept as.raw_X– a plain attribute, not wired into anndata’s own.raw/Rawmachinery, which has the same restriction.Because of this, most operations that need anndata’s normal per-element type dispatch on
X– concatenation, most of scanpy/anndata’s ecosystem – are not supported whileXis VCSC/VCSR-backed. Callto_anndata()first to get a fully-featured, ordinaryAnnData. Indexing (adata[obs_idx, var_idx]) is supported (see__getitem__()), but always as an eager copy, not a lazy view – anndata’s view machinery bypasses theX/raw_Xoverrides here.Persist with
write_h5ad()/write_zarr()andread_h5ad()/read_zarr()(not the top-levelanndata.read_h5ad/read_zarr, which always reconstruct a plainAnnDataand would fail validating a VCSC-typedX).- Parameters:
X (_AnyVCS | None)
raw_X (_AnyVCS | None)
kwargs (Any)
- copy()[source]¶
A deep copy, preserving the VCSC/VCSR-backed
X/raw_X.The inherited
anndata.AnnData.copy()only knows how to copy the standard private_Xattribute, which this class never sets (see the class docstring:X/raw_Xlive in_vcs_X/_vcs_raw_Xinstead) – so it silently drops them (Xcomes backNone) and returns a plainAnnDatarather than this class. This copies every field explicitly instead, including a realVCSCArray/VCSRArraycopy ofX/raw_X, and returnstype(self)so a subclass (e.g. one overriding theXproperty) round-trips too.- Return type:
- to_memory(*, copy=False)[source]¶
Return this object with its data loaded into memory.
The inherited
anndata.AnnData.to_memory()has the same problem as the inheritedcopy()(see above): it iterates the object’s standard attributes, which never includes this class’sX/raw_X(held in_vcs_X/_vcs_raw_Xinstead), and reconstructs a plainAnnData– soXsilently comes backNone.This class never actually supports a lazily backed
X/raw_X(they’re always eagerly-heldVCSCArray/VCSRArrayinstances), so there is never anything to load – this always returns a fullcopy()instead, regardless ofcopy(unlike plainAnnData, wherecopy=Falsecan skip copying arrays already in memory; here everything already is, so the distinction doesn’t apply).- Return type:
- Parameters:
copy (bool)
- normalized(view='parafac2', *, recalculate=True)[source]¶
A normalized view of
X– seevsparse._base._VCSBase.normalized().Also records the recipe’s statistics – per-cell
ainobs["vsparse_a"], per-geneb/c/sinvarm["vsparse_b"]/["vsparse_c"]/["vsparse_s"], and the active recipe name plus astaleflag inuns["vsparse"]– so they persist acrosswrite_h5ad()/write_zarr()and can be reused instead of recomputed.recalculate=Falsereuses whatever is already recorded forview: first an in-memory view already built this session (however it was built), else what’s stored inobs/varm/uns(built fresh, but skipping theO(nnz)statistics passes) if it matchesviewand the current shape.uns["vsparse"]["stale"]is set toTrueafter indexing (see__getitem__()), since population statistics like a depth median or a per-gene mean no longer reflect the subset –recalculate=Falsereuses them anyway; the defaultrecalculate=Truealways recomputes fresh (and clearsstale).
- classmethod from_anndata(adata, format='csc', raw_format=None, *, include_raw=True)[source]¶
Build from a regular
AnnData, compressing X (and raw.X).- Return type:
- Parameters:
- write_h5ad(filename, *, convert_strings_to_categoricals=True, dataset_kwargs=None, **_kwargs)[source]¶
Write to
.h5ad. Read back withread_h5ad().X/raw_Xare always stored as IVCSC (from VCSC) or IVCSR (from VCSR): the minor-axis indices are byte-packed (delta + varint encoding), at the cost of extra work on write/read. They come back fromread_h5ad()as ordinary VCSCArray/VCSRArray objects – IVCSC/IVCSR is purely an on-disk storage format.- Parameters:
convert_strings_to_categoricals (
bool) – Convertobs/varstring columns to categorical in place before writing, asanndata’s own writers do. Only columns with fewer categories than rows are converted.dataset_kwargs (
Mapping[str,Any] |None) – Passed toh5py.Group.create_datasetfor every array written. Defaults to zstd (level 1) compression, whichread_h5ad()decodes in parallel; pass{}to store uncompressed. Either way, compression is only ever applied to numeric arrays – seevsparse._compression.numeric_only_compression()._kwargs (Any)
- Return type:
- classmethod read_h5ad(filename)[source]¶
Read a file written by
write_h5ad().Reads files compressed with the current zstd default and with the Blosc2 default of earlier versions alike.
- Return type:
- Parameters:
- write_zarr(store, *, convert_strings_to_categoricals=True, dataset_kwargs=None, **_kwargs)[source]¶
Write to a zarr store. Read back with
read_zarr().See
write_h5ad()for the IVCSC/IVCSR storage format andconvert_strings_to_categoricals/dataset_kwargs(including the numeric-only compression behavior); the default compression here is zstd (level 1) vianumcodecs.
- classmethod read_zarr(store)[source]¶
Read a store written by
write_zarr().- Return type:
- Parameters:
store (Any)