Files
TieMeasureFlow/src/backend/models/api/statistics.py
T
Adriano 7249cb8a8c fix(spc): Cp/Cpk usa sigma within (MRbar/1.128), Pp/Ppk la stdev campionaria (#19)
Prima Cp/Cpk usava stdev campionaria e Pp/Ppk la population stdev: stesso
indice due volte, proporzionale. Ora Cp/Cpk (capability a breve termine)
usa sigma_within dalla moving range dei valori consecutivi in ordine
cronologico; Pp/Ppk (performance complessiva) resta sulla stdev campionaria
(n-1). MRbar == 0 -> Cp/Cpk None. Stessa sigma_within per UCL/LCL della
carta di controllo a valori individuali (mean +/- 2.66*MRbar), non piu la
stdev globale che allargava i limiti e nascondeva la deriva.

Aggiunto campo opzionale std_dev_within a CapabilityData.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 22:27:06 +02:00

96 lines
2.6 KiB
Python

"""Pydantic schemas for SPC statistics responses."""
from datetime import datetime
from typing import Optional
from pydantic import BaseModel, Field
class StatisticsQuery(BaseModel):
"""Common query parameters for statistics endpoints."""
recipe_id: int
version_id: Optional[int] = None
subtask_id: Optional[int] = None
date_from: Optional[datetime] = None
date_to: Optional[datetime] = None
operator_id: Optional[int] = None
lot_number: Optional[str] = None
serial_number: Optional[str] = None
class ControlChartData(BaseModel):
"""Data for X-bar/R control chart."""
values: list[float]
timestamps: list[datetime]
mean: float
ucl: float # Upper Control Limit
lcl: float # Lower Control Limit
utl: Optional[float] = None
uwl: Optional[float] = None
lwl: Optional[float] = None
ltl: Optional[float] = None
nominal: Optional[float] = None
out_of_control: list[int] = [] # Indices of OOC points
class HistogramData(BaseModel):
"""Data for histogram with normal curve."""
bins: list[float]
counts: list[int]
normal_x: list[float]
normal_y: list[float]
mean: float
std_dev: float
n: int
class CapabilityData(BaseModel):
"""Capability indices."""
cp: Optional[float] = None
cpk: Optional[float] = None
pp: Optional[float] = None
ppk: Optional[float] = None
mean: float
std_dev: float # overall sample std dev (n-1), used for Pp/Ppk
std_dev_within: Optional[float] = None # MRbar/1.128, used for Cp/Cpk
n: int
utl: Optional[float] = None
ltl: Optional[float] = None
nominal: Optional[float] = None
class TrendData(BaseModel):
"""Temporal trend data for capability indices."""
dates: list[datetime]
cpk_values: list[Optional[float]]
ppk_values: list[Optional[float]]
n_per_period: list[int]
class SummaryData(BaseModel):
"""Pass/fail/warning summary counts."""
total: int
pass_count: int
warning_count: int
fail_count: int
pass_rate: float
warning_rate: float
fail_rate: float
class AlertData(BaseModel):
"""Western Electric rules violations."""
rule: str
description: str
points: list[int] # Indices of violating points
severity: str = Field(..., pattern="^(info|warning|critical)$")
class StatisticsResponse(BaseModel):
"""Combined statistics response."""
summary: SummaryData
capability: Optional[CapabilityData] = None
control_chart: Optional[ControlChartData] = None
histogram: Optional[HistogramData] = None
trend: Optional[TrendData] = None
alerts: list[AlertData] = []