68 lines
2.1 KiB
Python
68 lines
2.1 KiB
Python
"""Application service coordinating I/O, validation and prediction."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
|
|
import pandas as pd
|
|
|
|
from .io import FrameReader
|
|
from .model import PredictionModel
|
|
from .validation import FrameValidator
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class DiagnosisResult:
|
|
measurements: pd.DataFrame
|
|
submission: pd.DataFrame
|
|
diagnostics: pd.DataFrame
|
|
warnings: tuple[str, ...] = ()
|
|
|
|
@property
|
|
def engine_ids(self) -> list[str]:
|
|
return self.measurements["engine_id"].drop_duplicates().astype(str).tolist()
|
|
|
|
def engine_measurements(self, engine_id: str) -> pd.DataFrame:
|
|
frame = self.measurements[self.measurements["engine_id"].eq(engine_id)]
|
|
if frame.empty:
|
|
raise KeyError(f"Unknown engine_id={engine_id!r}")
|
|
return frame.reset_index(drop=True)
|
|
|
|
def engine_diagnostics(self, engine_id: str) -> pd.DataFrame:
|
|
frame = self.diagnostics[self.diagnostics["engine_id"].eq(engine_id)]
|
|
if frame.empty:
|
|
raise KeyError(f"Unknown engine_id={engine_id!r}")
|
|
return frame.reset_index(drop=True)
|
|
|
|
|
|
class DiagnosticService:
|
|
"""Constructor-injected use case; no Streamlit or global state dependencies."""
|
|
|
|
def __init__(
|
|
self,
|
|
*,
|
|
reader: FrameReader,
|
|
validator: FrameValidator,
|
|
model: PredictionModel,
|
|
) -> None:
|
|
self._reader = reader
|
|
self._validator = validator
|
|
self._model = model
|
|
|
|
def diagnose_bytes(self, payload: bytes) -> DiagnosisResult:
|
|
return self.diagnose_frame(self._reader.read_bytes(payload))
|
|
|
|
def diagnose_path(self, path: Path) -> DiagnosisResult:
|
|
return self.diagnose_frame(self._reader.read_path(path))
|
|
|
|
def diagnose_frame(self, frame: pd.DataFrame) -> DiagnosisResult:
|
|
validated = self._validator.validate(frame)
|
|
predicted = self._model.predict(validated.frame)
|
|
return DiagnosisResult(
|
|
measurements=validated.frame,
|
|
submission=predicted.submission,
|
|
diagnostics=predicted.diagnostics,
|
|
warnings=validated.warnings,
|
|
)
|