Source code for seqme.metrics.threshold

from collections.abc import Callable
from typing import Literal

import numpy as np

from seqme.core.base import Metric, MetricResult


[docs] class Threshold(Metric): """Fraction of sequences with property within [min, max] a user-defined threshold."""
[docs] def __init__( self, predictor: Callable[[list[str]], np.ndarray], name: str, *, min_value: float | None = None, max_value: float | None = None, ): """ Initialize the metric. Args: predictor: A function that takes a list of sequences and returns a 1D array of scalar values. name: Name of the metric. min_value: Minimum threshold value. max_value: Maximum threshold value. """ self.predictor = predictor self._name = name self.min_value = min_value self.max_value = max_value if (self.min_value is None) and (self.max_value is None): raise ValueError("'min_value' and/or 'max_value' must be set.") if (self.min_value is not None) and (self.max_value is not None) and (self.min_value > self.max_value): raise ValueError(f"Expected min_value ({self.min_value}) <= max_value ({self.max_value}).")
[docs] def __call__(self, sequences: list[str]) -> MetricResult: """ Applies the predictor to the sequences and returns the fraction of sequences within the threshold. Args: sequences: Sequences to evaluate. Returns: MetricResult: Fraction of sequences within the threshold, and the standard error. """ values = self.predictor(sequences) above = values >= self.min_value if self.min_value is not None else True below = values <= self.max_value if self.max_value is not None else True within = above & below p = np.mean(within).item() se = float(np.sqrt(p * (1 - p) / len(within))) return MetricResult(value=p, deviation=se)
@property def name(self) -> str: return self._name @property def objective(self) -> Literal["minimize", "maximize"]: return "maximize"