Skip to content

Expression data¤

jaxqtl maps genetic variants against molecular phenotypes (e.g. gene expression). Phenotype data is handled as:

  • a sample-by-feature matrix (individuals x genes)
  • a feature metadata table (chromosome, start, end, feature ID)
  • library sizes used to construct offsets for count-based models or normalize counts for expression PCA

See Phenotype data for file formats and coordinates, and Offsets for the unfiltered-input requirement.

Expression container¤

jaxqtl.io.ExpressionData [source] ¤

Expression values, feature metadata, and library sizes aligned by sample.

Attributes:

  • pheno: Sample-by-feature Polars frame. The first column is iid; all remaining columns contain expression values named by phenotype ID.
  • pheno_meta: Feature-level Polars frame with chromosome, start, end, and phenotype_id columns, in that order and matching the expression columns.
  • libsize: Polars frame with iid and libsize columns. Library sizes are computed before optional phenotype filtering.
offset_from_libsize property ¤

Compute log-library-size offsets.

Returns:

A Polars frame with iid and offset columns in the same sample order as libsize. The offset is log(libsize).

from_bedfile(path_or_filename: str | os.PathLike, keep_individuals: list[str] | None = None, drop_individuals: list[str] | None = None, keep_pheno: list[str] | None = None, drop_pheno: list[str] | None = None) classmethod ¤

Load expression data from a BED-like or Parquet table.

The first four columns must be chromosome, start, end, and phenotype ID, using one of the accepted case-insensitive aliases. Remaining columns are sample IDs. Library sizes are computed from all loaded phenotypes before applying keep_pheno or drop_pheno.

Arguments:

  • path_or_filename: .bed, .bed.gz, .parquet, or .parquet.gz input.
  • keep_individuals: Optional sample IDs to retain.
  • drop_individuals: Optional sample IDs to remove.
  • keep_pheno: Optional phenotype IDs to retain.
  • drop_pheno: Optional phenotype IDs to remove.

Returns:

An ExpressionData with samples in rows and phenotypes in columns.

Raises:

  • ValueError: If keep and drop filters are both supplied for the same axis, requested names are missing, required metadata columns are invalid, or the file suffix is unsupported.
to_jax(self) ¤

Convert expression values to a floating-point JAX array.

Returns:

An array with shape (n, g), where rows are samples and columns are phenotypes. The iid column is excluded.

normalize(self, normalization: typing.Literal['none', 'library-size', 'tmm'] = 'library-size') -> ExpressionData ¤

Scale expression to the median library size, without a log transform.

library-size uses stored totals. tmm multiplies totals by TMM factors estimated from this container's current samples and nonzero genes. Estimate normalization before selecting PCA genes. none returns this container unchanged. Original library sizes and metadata are preserved. Invalid counts, sample IDs, or retained library sizes raise ValueError.

validate_values(self, *, require_nonnegative: bool = False) -> None ¤

Reject nonnumeric, missing, or nonfinite expression; optionally require counts >= 0.

filter_genes_by_ids(self, *, keep: list[str] | None = None, drop: list[str] | None = None) -> ExpressionData ¤

Select gene IDs in metadata order, preserving samples and original library sizes.

keep and drop are mutually exclusive. Unknown IDs raise ValueError. With neither selection supplied, return this expression container unchanged.

filter_genes_by_percentage(self, express_percent: float) -> ExpressionData ¤

Keep phenotypes expressed in more than a fraction of samples.

Expression is defined as a value greater than zero. Library sizes are preserved from the unfiltered expression matrix.

Arguments:

  • express_percent: Exclusive lower bound on the expressed-sample fraction, between 0 and 1.

Returns:

A new ExpressionData containing only phenotypes above the threshold.

Raises:

  • ValueError: If express_percent is outside [0, 1].
filter_individuals_by_percentage(self, express_percent: float) -> ExpressionData ¤

Keep samples expressing more than a fraction of phenotypes.

Expression is defined as a value greater than zero. The returned expression and library-size frames contain the same retained samples and order.

Arguments:

  • express_percent: Exclusive lower bound on the expressed-phenotype fraction, between 0 and 1.

Returns:

A new ExpressionData containing only samples above the threshold.

Raises:

  • ValueError: If express_percent is outside [0, 1].
compute_pcs(self, num_pcs: int, rng_key: typing.Union[jaxtyping.Key[jax.Array, ''], jaxtyping.UInt32[jax.Array, 2], jaxtyping.UInt32[jax.Array, 4]], *, normalization: typing.Literal['none', 'library-size', 'tmm'] = 'library-size', transform: typing.Literal['none', 'log1p'] = 'log1p') -> tuple[polars.dataframe.frame.DataFrame, numpy.ndarray] ¤

Compute probabilistic-PCA scores from the expression matrix.

Phenotypes are normalized and optionally log-transformed, constant genes are removed, and remaining genes are standardized across samples before fitting. The randomized initialization is determined by rng_key. A final projected SVD orders the unit-norm sample directions by decreasing explained variance within the fitted subspace.

Arguments:

  • num_pcs: Number of expression principal components to return. It must not exceed min(n_samples - 1, n_variable_genes) after transformation.
  • rng_key: JAX PRNG key controlling the probabilistic-PCA initialization.
  • normalization: "library-size" (default) divides counts by library sizes relative to their median. "tmm" first adjusts sizes using TMM factors estimated from current genes. "none" skips normalization.
  • transform: "log1p" (default) applies log(1 + y) after normalization; "none" skips the log transform. For previously normalized/log-transformed inputs, explicitly disable the stages already applied.

Returns:

A tuple (pcs, explained_variance_ratio). pcs is a Polars frame with iid followed by ExprPC1 through ExprPC{num_pcs}, in decreasing variance order. Rows preserve the input sample order. Components have unit norm rather than being scaled by their singular values. explained_variance_ratio is a NumPy array of shape (num_pcs,) in the same component order. Each value is the squared projected singular value divided by the total sum of squares of the transformed, standardized matrix, including variance outside the fitted subspace.

Raises:

  • ValueError: If there are fewer than two samples, no variable genes, invalid sample IDs, nonnumeric or nonfinite expression, an unsupported transform, negative expression for a log transform, or an invalid component count. Also raised if normalization library sizes are missing, nonnumeric, nonfinite, or nonpositive.