Source code for pysatl_cpd.benchmark.online.noreset.thresholds.ranges

# -*- coding: ascii -*-
"""Threshold range definitions for no-reset benchmark campaigns."""

from __future__ import annotations

__author__ = "Mikhail Mikhailov, Andrey Isakov"
__copyright__ = "Copyright (c) 2026 PySATL project"
__license__ = "SPDX-License-Identifier: MIT"

from abc import ABC, abstractmethod
from collections.abc import Sequence
from dataclasses import dataclass, field

import numpy as np

from pysatl_cpd.typedefs import Number


[docs] @dataclass class ThresholdsRange(ABC): """Base class for threshold range strategies. Subclasses fill ``thresholds_range`` at initialisation (or defer it). Attributes ---------- thresholds_range Sequence of threshold values, populated by ``__post_init__``. """ thresholds_range: Sequence[Number] = field(default_factory=tuple)
[docs] @abstractmethod def __post_init__(self) -> None: # pragma: no cover """Generate a linearly spaced threshold grid. Raises ------ NotImplementedError Subclasses must implement this method. """ raise NotImplementedError("Subclasses must implement this method")
[docs] @dataclass class ManualThresholdsRange(ThresholdsRange): """A threshold range defined by an explicit list of values.""" _values: Sequence[Number] = ()
[docs] def __post_init__(self) -> None: """Populate the thresholds range from the explicit value list.""" self.thresholds_range = tuple(self._values)
[docs] @dataclass class LinearThresholdsRange(ThresholdsRange): """A threshold range generated by linear interpolation. Attributes ---------- start Start of the range. end End of the range. count Number of thresholds. """ start: Number = 0.0 end: Number = 1.0 count: int = 10
[docs] def __post_init__(self) -> None: """Generate a linearly spaced threshold grid. Raises ------ ValueError If *count* is less than 1. """ if self.count < 1: msg = "count must be >= 1" raise ValueError(msg) self.thresholds_range = tuple(np.linspace(self.start, self.end, self.count, dtype=np.float64))
[docs] @dataclass class AutoThresholdsRange(ThresholdsRange): """Threshold range resolved later by an external analyzer. Attributes ---------- count Desired number of thresholds. """ count: int = 2
[docs] def __post_init__(self) -> None: """Validate count and leave thresholds empty for later resolution.""" if self.count < 1: msg = "count must be >= 1" raise ValueError(msg) self.thresholds_range = ()