Source code for pysatl_cpd.benchmark.online.noreset.tooling.bisegment_cut

# -*- coding: ascii -*-
"""Shared no-reset bisegment crop model and validation helpers."""

from __future__ import annotations

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

from dataclasses import dataclass


[docs] @dataclass(frozen=True, kw_only=True) class BisegmentCut: """Validated crop margins in sample points.""" left_trim: int right_trim: int def __post_init__(self) -> None: if self.left_trim < 0 or self.right_trim < 0: raise ValueError("bisegment_cut margins must be non-negative") @property def is_noop(self) -> bool: """Return True when crop does not trim any points.""" return self.left_trim == 0 and self.right_trim == 0 @property def as_tuple(self) -> tuple[int, int]: """Return a tuple representation for hashing/serialization.""" return (self.left_trim, self.right_trim)
[docs] def validate_for_length(self, length: int) -> None: """Validate that the crop leaves at least one sample.""" if self.left_trim + self.right_trim >= length: raise ValueError( "bisegment_cut trims the provider entirely: " f"left={self.left_trim}, right={self.right_trim}, len={length}" )
[docs] @classmethod def parse(cls, value: BisegmentCut | tuple[int, int] | None) -> BisegmentCut: """Parse tuple/None input into a validated `BisegmentCut`.""" if value is None: return NOOP_BISEGMENT_CUT if isinstance(value, cls): return value if isinstance(value, tuple): left_trim, right_trim = value return cls(left_trim=left_trim, right_trim=right_trim) if hasattr(value, "left_trim") and hasattr(value, "right_trim"): return cls(left_trim=value.left_trim, right_trim=value.right_trim) raise TypeError( f"bisegment_cut must be None, BisegmentCut, or (left_trim, right_trim); got {type(value).__name__!r}" )
NOOP_BISEGMENT_CUT = BisegmentCut(left_trim=0, right_trim=0)