API Reference¶
parafac2
¶
Main exports.
CompressedData
dataclass
¶
Compressed representation of a multi-condition single-cell dataset.
Stores the small dense per-condition cores and the orthonormal bases for
the gene mode (Q) and cell mode (Q_k), enabling fast rank sweeps
without touching the raw data again.
Source code in parafac2/compress.py
L_g
property
¶
Gene compression dimension.
Q
instance-attribute
¶
Gene projection basis of shape (n_genes, L_g) with orthonormal columns.
Q_k
instance-attribute
¶
Per-condition cell projection bases (n_cells_k, L_c_k) or None.
adata = None
class-attribute
instance-attribute
¶
Reference to original AnnData object if available.
condition_unique_idxs
instance-attribute
¶
Integer condition indices for each cell.
cores
instance-attribute
¶
List of length n_cond with dense cores Y_k of shape (L_c_k, L_g).
lost_var
instance-attribute
¶
Variance discarded by the compression projectors.
max_cell_dim
property
¶
Maximum cell dimension across cores.
means = None
class-attribute
instance-attribute
¶
Per-gene means subtracted during compression.
n_cond
instance-attribute
¶
Number of conditions.
n_genes
instance-attribute
¶
Number of genes in the uncompressed dataset.
norm_tensor
instance-attribute
¶
Total squared Frobenius norm of the original mean-centered dataset.
slice_weights = None
class-attribute
instance-attribute
¶
Optional per-condition slice weights for normalized ALS.
total_cells
instance-attribute
¶
Total number of cells across all conditions.
GPUMatrix
¶
Wrapper for a single matrix (csr_array or np.ndarray) stored on GPU memory (CuPy or MLX) or CPU. Evaluates matrix products on the device and returns results as NumPy ndarrays.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mat
|
ndarray | csr_array
|
The matrix to wrap and transfer to the selected device. |
required |
backend
|
str
|
One of |
None
|
Source code in parafac2/backend.py
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 | |
__init__(mat, backend=None)
¶
Transfer mat to the resolved backend's device memory.
Source code in parafac2/backend.py
__matmul__(rhs)
¶
__rmatmul__(lhs)
¶
matmul(rhs)
¶
Compute self @ rhs on the wrapped device.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rhs
|
ndarray
|
The right-hand operand. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The product, as a NumPy array. |
Source code in parafac2/backend.py
rmatmul(lhs)
¶
Compute lhs @ self on the wrapped device.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
ndarray
|
The left-hand operand. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The product, as a NumPy array. |
Source code in parafac2/backend.py
compress_dataset(X_in, L='auto', rank=None, n_power_iter=2, random_state=None, normalize_slices=False, backend=None)
¶
Compress an AnnData dataset in gene and cell modes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X_in
|
AnnData
|
Input dataset with data in |
required |
L
|
int | tuple[int, int | None] | str
|
Compression dimension(s). If |
"auto"
|
rank
|
int | None
|
Expected maximum rank to fit on the compressed data. Used when
|
None
|
n_power_iter
|
int
|
Number of power iterations for randomized SVD. |
2
|
random_state
|
int | Generator | None
|
Random seed or generator. |
None
|
normalize_slices
|
bool
|
Whether to precalculate slice weights for normalized ALS. |
False
|
backend
|
str | None
|
Compute backend for raw matrix products. |
None
|
Returns:
| Type | Description |
|---|---|
CompressedData
|
The compressed dataset ready for fast PARAFAC2 fitting. |
Source code in parafac2/compress.py
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | |
get_backend(backend=None)
¶
Return the requested backend, or auto-detect the first available one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
str
|
One of |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The resolved backend name: |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in parafac2/backend.py
parafac2_init(X, condition_unique_idxs, rank=3, means=None, random_state=None, n_oversamples=10, n_iter=2, norm_tensor=None)
¶
Compute initial factors using randomized SVD.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
Any
|
The (optionally sparse or GPU-backed) data matrix, stacked across
all conditions, with shape |
required |
condition_unique_idxs
|
ndarray
|
Integer array of length |
required |
rank
|
int
|
The number of components to compute. |
3
|
means
|
ndarray | None
|
Per-gene means to mean-center |
None
|
random_state
|
int | Generator | None
|
Seed or generator controlling the random projection used by the randomized SVD. |
None
|
n_oversamples
|
int
|
Extra dimensions added to |
10
|
n_iter
|
int
|
Number of power iterations used to refine the random projection. |
2
|
norm_tensor
|
float | None
|
Precomputed squared Frobenius norm of the mean-centered |
None
|
Returns:
| Type | Description |
|---|---|
tuple[list[ndarray], float]
|
The initial |
Source code in parafac2/parafac2.py
parafac2_nd(X_in, rank, n_iter_max=100, tol=1e-06, random_state=None, callback=None, backend=None, normalize_slices=False, n_inner=1, compress=None)
¶
The same interface as regular PARAFAC2 with optional CANDELINC compression.
If compress is specified (or if X_in is already a
:class:~parafac2.compress.CompressedData), PARAFAC2 is fit in the
compressed subspace (Bro's "compress-then-fit"), eliminating per-sweep raw
data passes.
If normalize_slices is True, each condition's contribution to the
factor updates is rescaled by the inverse of its (mean-centered)
Frobenius norm. This prevents conditions with many more cells (or much
higher variance) from dominating the shared factors, e.g. the A
matrix. The weighting is computed from small per-condition summary
statistics and applied to per-condition intermediates only, so X is
never copied or modified. The reported error/R2X are unaffected, since
they are still computed from the unweighted fit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X_in
|
AnnData | CompressedData
|
Input dataset with the (optionally sparse) data matrix in |
required |
rank
|
int
|
The number of components to fit. |
required |
n_iter_max
|
int
|
Maximum number of ALS iterations. |
100
|
tol
|
float
|
Convergence tolerance: iteration stops once the (non-negative) decrease in relative error between successive iterations drops below this value. |
1e-6
|
random_state
|
int | None
|
Seed controlling the randomized SVD initialization. |
None
|
callback
|
Callable[[int, float, list[ndarray]], None] | None
|
Optional callback invoked after each iteration with the iteration index, the relative error, and the current factor matrices. |
None
|
backend
|
str | None
|
Compute backend to run matrix products on: one of |
None
|
normalize_slices
|
bool
|
Whether to rescale each condition's contribution to the factor updates by the inverse of its Frobenius norm, as described above. |
False
|
n_inner
|
int
|
Number of |
1
|
compress
|
int | tuple[int, int | None] | str | bool | None
|
Compression mode. If |
None
|
Returns:
| Type | Description |
|---|---|
tuple[tuple[ndarray, list[ndarray], list[ndarray]], float]
|
A |
Source code in parafac2/parafac2.py
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 | |
prepare_dataset(X, condition_name, geneThreshold)
¶
Preprocess and normalize an AnnData dataset for PARAFAC2 factorization.
Performs quality control filtering of low-count cells and low-expression genes, normalizes total cell counts and gene sums, applies a log10 transformation, and computes metadata required by PARAFAC2 (condition indices and gene means).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
AnnData
|
Input single-cell dataset with raw count matrix stored in |
required |
condition_name
|
str
|
Column name in |
required |
geneThreshold
|
float
|
Minimum threshold fraction for gene inclusion. Genes with total counts
less than |
required |
Returns:
| Type | Description |
|---|---|
AnnData
|
A filtered and normalized copy of the AnnData object. Contains the
log-transformed normalized counts in |
Source code in parafac2/normalize.py
store_pf2(X, parafac2_output)
¶
Store the Pf2 results into the anndata object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
AnnData | CompressedData
|
The dataset the factorization was fit on. Must have
|
required |
parafac2_output
|
tuple[ndarray, list[ndarray], list[ndarray]]
|
The |
required |
Returns:
| Type | Description |
|---|---|
AnnData
|
The target AnnData object, mutated in place, with the weights in
|
Source code in parafac2/parafac2.py
to_gpu(mat, backend=None)
¶
Transfer matrix to GPU memory if CuPy or MLX is requested/available, returning a GPUMatrix wrapper. Otherwise returns the CPU matrix as-is.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mat
|
ndarray | csr_array
|
The matrix to (optionally) transfer. |
required |
backend
|
str
|
One of |
None
|
Returns:
| Type | Description |
|---|---|
GPUMatrix | ndarray | csr_array
|
A :class: |
Source code in parafac2/backend.py
parafac2.parafac2¶
parafac2.parafac2
¶
Core PARAFAC2 decomposition routines.
Implements PARAFAC2 initialization (randomized SVD), the alternating-least- squares fitting loop, CANDELINC-style compression, and standardization/storage of the fitted factors and per-condition projections. Operates directly on a single (optionally sparse) data matrix held in an AnnData object, avoiding per-condition copies.
parafac2_init(X, condition_unique_idxs, rank=3, means=None, random_state=None, n_oversamples=10, n_iter=2, norm_tensor=None)
¶
Compute initial factors using randomized SVD.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
Any
|
The (optionally sparse or GPU-backed) data matrix, stacked across
all conditions, with shape |
required |
condition_unique_idxs
|
ndarray
|
Integer array of length |
required |
rank
|
int
|
The number of components to compute. |
3
|
means
|
ndarray | None
|
Per-gene means to mean-center |
None
|
random_state
|
int | Generator | None
|
Seed or generator controlling the random projection used by the randomized SVD. |
None
|
n_oversamples
|
int
|
Extra dimensions added to |
10
|
n_iter
|
int
|
Number of power iterations used to refine the random projection. |
2
|
norm_tensor
|
float | None
|
Precomputed squared Frobenius norm of the mean-centered |
None
|
Returns:
| Type | Description |
|---|---|
tuple[list[ndarray], float]
|
The initial |
Source code in parafac2/parafac2.py
parafac2_nd(X_in, rank, n_iter_max=100, tol=1e-06, random_state=None, callback=None, backend=None, normalize_slices=False, n_inner=1, compress=None)
¶
The same interface as regular PARAFAC2 with optional CANDELINC compression.
If compress is specified (or if X_in is already a
:class:~parafac2.compress.CompressedData), PARAFAC2 is fit in the
compressed subspace (Bro's "compress-then-fit"), eliminating per-sweep raw
data passes.
If normalize_slices is True, each condition's contribution to the
factor updates is rescaled by the inverse of its (mean-centered)
Frobenius norm. This prevents conditions with many more cells (or much
higher variance) from dominating the shared factors, e.g. the A
matrix. The weighting is computed from small per-condition summary
statistics and applied to per-condition intermediates only, so X is
never copied or modified. The reported error/R2X are unaffected, since
they are still computed from the unweighted fit.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X_in
|
AnnData | CompressedData
|
Input dataset with the (optionally sparse) data matrix in |
required |
rank
|
int
|
The number of components to fit. |
required |
n_iter_max
|
int
|
Maximum number of ALS iterations. |
100
|
tol
|
float
|
Convergence tolerance: iteration stops once the (non-negative) decrease in relative error between successive iterations drops below this value. |
1e-6
|
random_state
|
int | None
|
Seed controlling the randomized SVD initialization. |
None
|
callback
|
Callable[[int, float, list[ndarray]], None] | None
|
Optional callback invoked after each iteration with the iteration index, the relative error, and the current factor matrices. |
None
|
backend
|
str | None
|
Compute backend to run matrix products on: one of |
None
|
normalize_slices
|
bool
|
Whether to rescale each condition's contribution to the factor updates by the inverse of its Frobenius norm, as described above. |
False
|
n_inner
|
int
|
Number of |
1
|
compress
|
int | tuple[int, int | None] | str | bool | None
|
Compression mode. If |
None
|
Returns:
| Type | Description |
|---|---|
tuple[tuple[ndarray, list[ndarray], list[ndarray]], float]
|
A |
Source code in parafac2/parafac2.py
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 | |
store_pf2(X, parafac2_output)
¶
Store the Pf2 results into the anndata object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
AnnData | CompressedData
|
The dataset the factorization was fit on. Must have
|
required |
parafac2_output
|
tuple[ndarray, list[ndarray], list[ndarray]]
|
The |
required |
Returns:
| Type | Description |
|---|---|
AnnData
|
The target AnnData object, mutated in place, with the weights in
|
Source code in parafac2/parafac2.py
parafac2.normalize¶
parafac2.normalize
¶
Dataset preprocessing and normalization utilities for PARAFAC2 analysis.
This module provides functions to filter, normalize, and annotate single-cell gene expression datasets stored in AnnData objects prior to PARAFAC2 matrix factorization.
prepare_dataset(X, condition_name, geneThreshold)
¶
Preprocess and normalize an AnnData dataset for PARAFAC2 factorization.
Performs quality control filtering of low-count cells and low-expression genes, normalizes total cell counts and gene sums, applies a log10 transformation, and computes metadata required by PARAFAC2 (condition indices and gene means).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
AnnData
|
Input single-cell dataset with raw count matrix stored in |
required |
condition_name
|
str
|
Column name in |
required |
geneThreshold
|
float
|
Minimum threshold fraction for gene inclusion. Genes with total counts
less than |
required |
Returns:
| Type | Description |
|---|---|
AnnData
|
A filtered and normalized copy of the AnnData object. Contains the
log-transformed normalized counts in |
Source code in parafac2/normalize.py
parafac2.compress¶
parafac2.compress
¶
CANDELINC compression for PARAFAC2.
Compresses the gene and cell modes of single-cell datasets prior to PARAFAC2 factorization, collapsing the problem to small dense per-condition cores.
CompressedData
dataclass
¶
Compressed representation of a multi-condition single-cell dataset.
Stores the small dense per-condition cores and the orthonormal bases for
the gene mode (Q) and cell mode (Q_k), enabling fast rank sweeps
without touching the raw data again.
Source code in parafac2/compress.py
L_g
property
¶
Gene compression dimension.
Q
instance-attribute
¶
Gene projection basis of shape (n_genes, L_g) with orthonormal columns.
Q_k
instance-attribute
¶
Per-condition cell projection bases (n_cells_k, L_c_k) or None.
adata = None
class-attribute
instance-attribute
¶
Reference to original AnnData object if available.
condition_unique_idxs
instance-attribute
¶
Integer condition indices for each cell.
cores
instance-attribute
¶
List of length n_cond with dense cores Y_k of shape (L_c_k, L_g).
lost_var
instance-attribute
¶
Variance discarded by the compression projectors.
max_cell_dim
property
¶
Maximum cell dimension across cores.
means = None
class-attribute
instance-attribute
¶
Per-gene means subtracted during compression.
n_cond
instance-attribute
¶
Number of conditions.
n_genes
instance-attribute
¶
Number of genes in the uncompressed dataset.
norm_tensor
instance-attribute
¶
Total squared Frobenius norm of the original mean-centered dataset.
slice_weights = None
class-attribute
instance-attribute
¶
Optional per-condition slice weights for normalized ALS.
total_cells
instance-attribute
¶
Total number of cells across all conditions.
compress_cells(X_c, condition_unique_idxs, L_c=None)
¶
Compute per-condition cell-mode compression projectors Q_k and cores Y_k.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X_c
|
ndarray
|
Gene-compressed data matrix of shape |
required |
condition_unique_idxs
|
ndarray
|
Integer condition index for each cell. |
required |
L_c
|
int | None
|
Target cell subspace dimension per condition. If |
None
|
Returns:
| Type | Description |
|---|---|
tuple[list[ndarray], list[ndarray | None] | None, float]
|
|
Source code in parafac2/compress.py
compress_dataset(X_in, L='auto', rank=None, n_power_iter=2, random_state=None, normalize_slices=False, backend=None)
¶
Compress an AnnData dataset in gene and cell modes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X_in
|
AnnData
|
Input dataset with data in |
required |
L
|
int | tuple[int, int | None] | str
|
Compression dimension(s). If |
"auto"
|
rank
|
int | None
|
Expected maximum rank to fit on the compressed data. Used when
|
None
|
n_power_iter
|
int
|
Number of power iterations for randomized SVD. |
2
|
random_state
|
int | Generator | None
|
Random seed or generator. |
None
|
normalize_slices
|
bool
|
Whether to precalculate slice weights for normalized ALS. |
False
|
backend
|
str | None
|
Compute backend for raw matrix products. |
None
|
Returns:
| Type | Description |
|---|---|
CompressedData
|
The compressed dataset ready for fast PARAFAC2 fitting. |
Source code in parafac2/compress.py
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 | |
compress_genes(X, means, L_g, n_power_iter=2, random_state=None)
¶
Compute gene-mode compression projector Q and compressed matrix Xc.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
Any
|
Stacked data matrix of shape |
required |
means
|
ndarray | None
|
Per-gene means for centering. |
required |
L_g
|
int
|
Target gene subspace dimension. |
required |
n_power_iter
|
int
|
Number of power iterations for randomized SVD. |
2
|
random_state
|
int | Generator | None
|
Random seed or generator. |
None
|
Returns:
| Type | Description |
|---|---|
tuple[ndarray, ndarray, float]
|
|
Source code in parafac2/compress.py
init_compressed_factors(cores, rank, random_state=None)
¶
Initialize factor matrices [A, B, C_L] directly on compressed cores.
Source code in parafac2/compress.py
project_data_compressed(cores, factors, norm_tensor, mode, return_projections=False, slice_weights=None)
¶
Project compressed per-condition cores and accumulate MTTKRP and error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
cores
|
list[ndarray]
|
List of per-condition core matrices |
required |
factors
|
list[ndarray]
|
Current factor matrices |
required |
norm_tensor
|
float
|
Squared Frobenius norm of the original mean-centered tensor. |
required |
mode
|
int
|
Mode to update (0, 1, or 2). |
required |
return_projections
|
bool
|
Whether to return the list of projection matrices |
False
|
slice_weights
|
ndarray | None
|
Optional per-condition slice weights. |
None
|
Returns:
| Type | Description |
|---|---|
tuple[ndarray, float] | list[ndarray]
|
|
Source code in parafac2/compress.py
parafac2.utils¶
parafac2.utils
¶
Low-level numerical routines supporting the PARAFAC2 fit.
Provides norm computation over (optionally mean-centered, optionally sparse) data, the per-condition projection step, the per-mode ALS factor update (which forms its own MTTKRP), and post-fit standardization of the factors and projections.
The fit touches the raw data through exactly two products, which together dominate runtime on single-cell-sized inputs:
W = (X - 1 mu^T) @ C(:func:calc_W), which depends only onC.X^T @ Hfor the mode-2 MTTKRP (inside :func:parafac_update).
Everything else flows through the compressed per-condition slices
S_k = P_k^T W_k, an (n_cond, rank, rank) array small enough to keep
resident. In particular the mode-0 and mode-1 MTTKRPs and the reconstruction
error are all functions of S alone, so the projections and both of those
factor updates can be recomputed from a cached W without re-reading the
data.
calc_W(X, means, C)
¶
Compute W = (X - 1 mu^T) @ C, the first of the two raw-data products.
W depends only on C, so it stays valid across the A and B
updates and only has to be recomputed once C changes.
The product is taken in X's own dtype. That matters: handing a
float64 C to a float32 sparse X makes SciPy upcast the entire
sparse matrix, doubling both the memory traffic that dominates this step
and the peak memory. The result is widened to float64 afterwards, which
is O(n_cells * rank) and so negligible beside the product itself.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
Any
|
The (optionally sparse or GPU-backed) data matrix, stacked across all
conditions, with shape |
required |
means
|
ndarray | None
|
Per-gene means to mean-center |
required |
C
|
ndarray
|
The current gene factor matrix, shape |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The float64 array |
Source code in parafac2/utils.py
calc_err(S, factors, norm_X_sq)
¶
Return the squared reconstruction error from the compressed slices.
Uses the expansion ||X||^2 + Tr(A^T A * B^T B * C^T C) - 2 <A, diag(B^T
S_k)>, so no raw-data pass is needed and the error is free to evaluate
as often as desired (e.g. to monitor an inner iteration).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
S
|
ndarray
|
The stacked compressed slices from :func: |
required |
factors
|
list[ndarray]
|
The current |
required |
norm_X_sq
|
float
|
The squared Frobenius norm of the mean-centered |
required |
Returns:
| Type | Description |
|---|---|
float
|
The squared reconstruction error. |
Source code in parafac2/utils.py
calc_norm_sq(X, means=None)
¶
Return the squared Frobenius norm of the mean-centered matrix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray | csr_array
|
The (dense or sparse) matrix to compute the norm of. |
required |
means
|
ndarray | None
|
Per-column means to subtract before computing the norm. If |
None
|
Returns:
| Type | Description |
|---|---|
float
|
|
Source code in parafac2/utils.py
calc_slice_norms(X, means, condition_unique_idxs, n_cond)
¶
Return the per-condition Frobenius norm of the mean-centered slices.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
ndarray | csr_array
|
The (dense or sparse) matrix stacked across all conditions. |
required |
means
|
ndarray | None
|
Per-column means to subtract before computing each slice's norm, or
|
required |
condition_unique_idxs
|
ndarray
|
Integer array assigning each row of |
required |
n_cond
|
int
|
The total number of conditions. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of length |
Source code in parafac2/utils.py
condition_slices(condition_unique_idxs, n_cond)
¶
Return a per-condition row selector for each condition.
Computing condition_unique_idxs == i inside the per-condition loop
costs O(n_cells) per condition, i.e. O(n_cells * n_cond) per pass
over the data, plus a fancy-indexed copy each time. Precomputing the
selectors once drops that to O(n_cells), and when the rows are
already grouped by condition (the usual case, since conditions are
concatenated) the selectors are plain slice objects, making
W[sel] a zero-copy view.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
condition_unique_idxs
|
ndarray
|
Integer array assigning each row to a condition in |
required |
n_cond
|
int
|
The total number of conditions. |
required |
Returns:
| Type | Description |
|---|---|
list[slice | ndarray]
|
One selector per condition: a |
Source code in parafac2/utils.py
extract_dataset_info(X_in, normalize_slices=False)
¶
Extract matrix, condition indices, gene means, norm_sq, and optional slice weights.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X_in
|
AnnData
|
Input single-cell AnnData dataset. |
required |
normalize_slices
|
bool
|
Whether to calculate per-condition slice inverse-norm weights. |
False
|
Returns:
| Type | Description |
|---|---|
tuple[ndarray | csr_array, ndarray, ndarray, float, ndarray | None]
|
The |
Source code in parafac2/utils.py
parafac_update(factors, mode, S, projections=None, *, X=None, means=None, cond_slices=None, slice_weights=None)
¶
Form the MTTKRP for the requested mode and update that factor.
Modes 0 and 1 are built from the compressed slices S alone and cost
O(n_cond * rank^2). Mode 2 is the only update that has to revisit the
raw data, via X^T @ H with H_k = P_k B diag(a_k).
slice_weights, if given, is a per-condition scalar (e.g. an inverse
Frobenius norm) applied only to the MTTKRP contributions. This rebalances
how much each slice contributes to the factor updates without touching or
copying X, and without affecting the reported error (which
:func:calc_err computes from the unweighted S).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factors
|
list[ndarray]
|
The current |
required |
mode
|
int
|
Which factor to update (index into |
required |
S
|
ndarray
|
The stacked compressed slices from :func: |
required |
projections
|
list[ndarray] | None
|
The per-condition projections. Required for |
None
|
X
|
(Any, keyword - only)
|
The raw data matrix. Required for |
None
|
means
|
(ndarray | None, keyword - only)
|
Per-gene means to mean-center |
None
|
cond_slices
|
(list[slice | ndarray] | None, keyword - only)
|
Per-condition row selectors from :func: |
None
|
slice_weights
|
(ndarray | None, keyword - only)
|
Optional per-condition scalar weights, as described above. |
None
|
Returns:
| Type | Description |
|---|---|
list[ndarray]
|
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in parafac2/utils.py
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 | |
polar_factor(M)
¶
Compute the nearest orthonormal matrix to M via polar decomposition.
Source code in parafac2/utils.py
project_data(W, factors, cond_slices)
¶
Compute each condition's projection matrix and compressed slice.
For condition k the projection P_k is the orthonormal polar
factor of W_k diag(a_k) B^T, and the compressed slice is
S_k = P_k^T W_k. Costs O(n_cells * rank^2) and touches no raw
data, so it is roughly two orders of magnitude cheaper than
:func:calc_W and can be repeated freely while W is cached.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
W
|
ndarray
|
The cached |
required |
factors
|
list[ndarray]
|
The current |
required |
cond_slices
|
list[slice | ndarray]
|
Per-condition row selectors from :func: |
required |
Returns:
| Type | Description |
|---|---|
tuple[list[ndarray], ndarray]
|
The per-condition projections |
Source code in parafac2/utils.py
randomized_svd_right(X, means, n_components, n_oversamples=0, n_power_iter=2, random_state=None)
¶
Compute the top right-singular vectors of the mean-centered matrix (X - 1 mu^T).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
X
|
Any
|
The (optionally sparse or GPU-backed) data matrix of shape
|
required |
means
|
ndarray | None
|
Per-gene means for implicit centering, or |
required |
n_components
|
int
|
Number of right-singular vectors to return. |
required |
n_oversamples
|
int
|
Additional random test vectors for randomized SVD projection. |
0
|
n_power_iter
|
int
|
Number of power iterations for subspace refinement. |
2
|
random_state
|
int | Generator | None
|
Random seed or NumPy generator. |
None
|
Returns:
| Type | Description |
|---|---|
ndarray
|
Array of shape |
Source code in parafac2/utils.py
solve_factors(factors, mttkrp, mode)
¶
ALS factor update for a single mode using its precomputed MTTKRP.
Source code in parafac2/utils.py
standardize_pf2(factors, projections)
¶
Put a fitted PARAFAC2 model into a canonical, comparable form.
Reorders components by condition variance-to-mean ratio, normalizes and
sign-flips the factors (via TensorLy's cp_normalize/cp_flip_sign),
permutes components to maximize the diagonal of B (via linear-sum
assignment), and flips signs so that B's diagonal is non-negative.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
factors
|
list[ndarray]
|
The fitted |
required |
projections
|
list[ndarray]
|
The fitted per-condition projection matrices |
required |
Returns:
| Type | Description |
|---|---|
tuple[ndarray, list[ndarray], list[ndarray]]
|
The |
Source code in parafac2/utils.py
parafac2.backend¶
parafac2.backend
¶
GPU/CPU backend abstraction for matrix operations.
Provides a unified interface for performing dense and sparse (CSR) matrix multiplications on CPU (NumPy), Apple GPUs (MLX), or NVIDIA GPUs (CuPy). This lets the PARAFAC2 fit run its matrix products on whichever accelerator is available without copying data through an intermediate common format.
GPUMatrix
¶
Wrapper for a single matrix (csr_array or np.ndarray) stored on GPU memory (CuPy or MLX) or CPU. Evaluates matrix products on the device and returns results as NumPy ndarrays.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mat
|
ndarray | csr_array
|
The matrix to wrap and transfer to the selected device. |
required |
backend
|
str
|
One of |
None
|
Source code in parafac2/backend.py
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 | |
__init__(mat, backend=None)
¶
Transfer mat to the resolved backend's device memory.
Source code in parafac2/backend.py
__matmul__(rhs)
¶
__rmatmul__(lhs)
¶
matmul(rhs)
¶
Compute self @ rhs on the wrapped device.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rhs
|
ndarray
|
The right-hand operand. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The product, as a NumPy array. |
Source code in parafac2/backend.py
rmatmul(lhs)
¶
Compute lhs @ self on the wrapped device.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
ndarray
|
The left-hand operand. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The product, as a NumPy array. |
Source code in parafac2/backend.py
get_backend(backend=None)
¶
Return the requested backend, or auto-detect the first available one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
str
|
One of |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The resolved backend name: |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in parafac2/backend.py
matmul(mat, rhs)
¶
Compute mat @ rhs, dispatching to the fastest available kernel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mat
|
Any
|
A :class: |
required |
rhs
|
ndarray
|
The dense right-hand operand. |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The product |
Notes
rhs should already share mat's dtype. Handing a float64 rhs
to a float32 sparse mat makes SciPy upcast the whole sparse matrix,
which for single-cell-sized data is both slow and memory-hostile; see
:func:~parafac2.utils.calc_W.
Source code in parafac2/backend.py
matrix_dtype(mat)
¶
rmatmul(lhs, mat)
¶
Compute lhs @ mat, dispatching to the fastest available kernel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lhs
|
ndarray
|
The dense left-hand operand. |
required |
mat
|
Any
|
A :class: |
required |
Returns:
| Type | Description |
|---|---|
ndarray
|
The product |
Source code in parafac2/backend.py
to_gpu(mat, backend=None)
¶
Transfer matrix to GPU memory if CuPy or MLX is requested/available, returning a GPUMatrix wrapper. Otherwise returns the CPU matrix as-is.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mat
|
ndarray | csr_array
|
The matrix to (optionally) transfer. |
required |
backend
|
str
|
One of |
None
|
Returns:
| Type | Description |
|---|---|
GPUMatrix | ndarray | csr_array
|
A :class: |