# -*- coding: ascii -*-
"""Comprehensive classification report over multiple runs."""
__author__ = "Danil Totmyanin"
__copyright__ = "Copyright (c) 2026 PySATL project"
__license__ = "SPDX-License-Identifier: MIT"
from collections.abc import Mapping
from typing import Any
from pysatl_cpd.analysis.metrics.multiple_run.classification.base import TotalFN, TotalFP, TotalTP
from pysatl_cpd.analysis.metrics.multiple_run.classification.fmeasure import FScoreMetric
from pysatl_cpd.analysis.metrics.multiple_run.classification.precision import PrecisionMetric
from pysatl_cpd.analysis.metrics.multiple_run.classification.recall import RecallMetric
from pysatl_cpd.analysis.metrics.multiple_run.derived_metric import DerivedMetric
from pysatl_cpd.core.detection_trace import DetectionTrace
from pysatl_cpd.data.providers.labeled.labeled_data import LabeledData as LabeledData
from pysatl_cpd.typedefs import Number
[docs]
class ClassificationReport[TraceT: DetectionTrace, ProviderT: LabeledData[Any, Any]](
DerivedMetric[TraceT, ProviderT, Number, dict[str, Number]]
):
"""Configure the classification report with an error margin.
Parameters
----------
error_margin
Allowed (left, right) margin around each true change point for
matching detections.
"""
[docs]
def __init__(self, error_margin: tuple[int, int]) -> None:
self._bases = {
"tp": TotalTP[TraceT, ProviderT](error_margin),
"fp": TotalFP[TraceT, ProviderT](error_margin),
"fn": TotalFN[TraceT, ProviderT](error_margin),
"precision": PrecisionMetric[TraceT, ProviderT](error_margin),
"recall": RecallMetric[TraceT, ProviderT](error_margin),
"f1": FScoreMetric[TraceT, ProviderT](error_margin),
}
@property
def bases(self) -> Mapping[str, Any]:
"""Underlying classification metrics.
Returns
-------
Mapping[str, Any]
"""
return self._bases
[docs]
def compute(self, values: Mapping[str, Number]) -> dict[str, Number]:
"""Return the computed metric values as a plain dictionary.
Parameters
----------
values
Named metric values from the underlying source metrics.
Returns
-------
dict[str, Number]
The same values in a new dictionary.
"""
return dict(values)