Skip to content

Color Space

Color mapping from gene set scores to RGB (pipeline steps 2–3).

Blending (2–3 gene sets)

blend_to_rgb

blend_to_rgb(
    scores: DataFrame,
    *,
    colors: list[tuple[float, float, float]] | None = None,
) -> NDArray

Map gene set scores to RGB via multiplicative blending from white.

Parameters:

Name Type Description Default
scores DataFrame

DataFrame returned by :func:score_gene_sets. Only columns whose names start with score- are used.

required
colors list[tuple[float, float, float]] | None

One (R, G, B) tuple per gene set. If None, defaults are chosen based on the number of gene sets (2 → blue/red, 3 → RGB).

None

Returns:

Type Description
ndarray

(n_cells, 3) RGB array with values in [0, 1].

Raises:

Type Description
ValueError

If fewer than 2 or more than 3 gene sets are present, or if the number of supplied colours does not match expectations.

Source code in src/multiscoresplot/_colorspace.py
def blend_to_rgb(
    scores: DataFrame,
    *,
    colors: list[tuple[float, float, float]] | None = None,
) -> NDArray:
    """Map gene set scores to RGB via multiplicative blending from white.

    Parameters
    ----------
    scores
        DataFrame returned by :func:`score_gene_sets`.  Only columns whose
        names start with ``score-`` are used.
    colors
        One ``(R, G, B)`` tuple per gene set.  If *None*, defaults are chosen
        based on the number of gene sets (2 → blue/red, 3 → RGB).

    Returns
    -------
    numpy.ndarray
        ``(n_cells, 3)`` RGB array with values in [0, 1].

    Raises
    ------
    ValueError
        If fewer than 2 or more than 3 gene sets are present, or if the
        number of supplied colours does not match expectations.
    """
    score_cols = _validate_score_columns(scores)
    n_sets = len(score_cols)

    if n_sets < 2:
        raise ValueError("At least 2 gene sets are required.")
    if n_sets > 3:
        raise ValueError(
            f"Direct projection supports at most 3 gene sets (got {n_sets}). "
            "Use reduce_to_rgb() for higher dimensions."
        )

    mat = scores[score_cols].to_numpy(dtype=np.float64)

    default = DEFAULT_COLORS_2 if n_sets == 2 else DEFAULT_COLORS_3
    if colors is None:
        colors = default
    if len(colors) != n_sets:
        raise ValueError(f"Expected {n_sets} colors for {n_sets} gene sets, got {len(colors)}.")
    return _multiplicative_blend(mat, colors)

Dimensionality Reduction (2+ gene sets)

reduce_to_rgb

reduce_to_rgb(
    scores: DataFrame,
    *,
    method: str = "pca",
    n_components: int = 3,
    **kwargs: object,
) -> NDArray

Map gene set scores to RGB via dimensionality reduction.

Parameters:

Name Type Description Default
scores DataFrame

DataFrame returned by :func:score_gene_sets.

required
method str

Reduction method: "pca" (default), "nmf", "ica", or any method registered via :func:register_reducer.

'pca'
n_components int

Number of components to retain (max 3 for RGB).

3
**kwargs object

Extra keyword arguments forwarded to the reducer function.

{}

Returns:

Type Description
ndarray

(n_cells, 3) RGB array with values in [0, 1].

Raises:

Type Description
ValueError

If fewer than 2 gene sets are present or method is unknown.

Source code in src/multiscoresplot/_colorspace.py
def reduce_to_rgb(
    scores: DataFrame,
    *,
    method: str = "pca",
    n_components: int = 3,
    **kwargs: object,
) -> NDArray:
    """Map gene set scores to RGB via dimensionality reduction.

    Parameters
    ----------
    scores
        DataFrame returned by :func:`score_gene_sets`.
    method
        Reduction method: ``"pca"`` (default), ``"nmf"``, ``"ica"``, or any
        method registered via :func:`register_reducer`.
    n_components
        Number of components to retain (max 3 for RGB).
    **kwargs
        Extra keyword arguments forwarded to the reducer function.

    Returns
    -------
    numpy.ndarray
        ``(n_cells, 3)`` RGB array with values in [0, 1].

    Raises
    ------
    ValueError
        If fewer than 2 gene sets are present or *method* is unknown.
    """
    if method not in _REDUCERS:
        available = ", ".join(sorted(_REDUCERS))
        raise ValueError(f"Unknown reduction method '{method}'. Available: {available}.")

    score_cols = _validate_score_columns(scores)
    if len(score_cols) < 2:
        raise ValueError("At least 2 gene sets are required.")

    mat = scores[score_cols].to_numpy(dtype=np.float64)
    k = min(n_components, 3)
    return _REDUCERS[method](mat, k, **kwargs)

Custom Reducers

register_reducer

register_reducer(
    name: str,
    fn: Callable[..., NDArray],
    *,
    component_prefix: str | None = None,
) -> None

Register a dimensionality reduction method for use with reduce_to_rgb.

Parameters:

Name Type Description Default
name str

Short identifier (e.g. "pca", "nmf").

required
fn Callable[..., NDArray]

Callable with signature (X, n_components, **kwargs) -> NDArray returning an (n_cells, 3) array with values in [0, 1].

required
component_prefix str | None

Label prefix for legend axes (e.g. "PC" → PC1, PC2, PC3).

None
Source code in src/multiscoresplot/_colorspace.py
def register_reducer(
    name: str,
    fn: Callable[..., NDArray],
    *,
    component_prefix: str | None = None,
) -> None:
    """Register a dimensionality reduction method for use with ``reduce_to_rgb``.

    Parameters
    ----------
    name
        Short identifier (e.g. ``"pca"``, ``"nmf"``).
    fn
        Callable with signature ``(X, n_components, **kwargs) -> NDArray``
        returning an ``(n_cells, 3)`` array with values in [0, 1].
    component_prefix
        Label prefix for legend axes (e.g. ``"PC"`` → PC1, PC2, PC3).
    """
    _REDUCERS[name] = fn
    if component_prefix is not None:
        _COMPONENT_PREFIXES[name] = component_prefix

Utility

get_component_labels

get_component_labels(method: str) -> list[str]

Return ["<prefix>1", "<prefix>2", "<prefix>3"] for a registered method.

Source code in src/multiscoresplot/_colorspace.py
def get_component_labels(method: str) -> list[str]:
    """Return ``["<prefix>1", "<prefix>2", "<prefix>3"]`` for a registered method."""
    prefix = _COMPONENT_PREFIXES.get(method, "C")
    return [f"{prefix}{i + 1}" for i in range(3)]