7249cb8a8c
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>
96 lines
2.6 KiB
Python
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] = []
|