Files
cmm-report-analyzer/app/analysis/charts.py
chrisryn 9abf9b4b58 Initial commit: CMM Report Analyzer
FastAPI app that parses CMM inspection reports (PDF/Excel/CSV),
computes SPC metrics (Cp/Cpk/Pp/Ppk, control limits, Shapiro-Wilk),
generates interactive Plotly charts, and provides AI-powered quality
summaries via Azure OpenAI with graceful fallback.

Includes 21 passing tests covering parsers, SPC calculations, and
API endpoints.
2026-02-19 10:38:51 -06:00

87 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from __future__ import annotations
import plotly.graph_objects as go
from app.analysis.spc import SPCResult
def histogram(result: SPCResult) -> dict:
"""Distribution histogram with spec limits overlay."""
fig = go.Figure()
fig.add_trace(go.Histogram(x=result.values, name="Measurements", nbinsx=20))
fig.add_vline(x=result.usl, line_dash="dash", line_color="red",
annotation_text="USL")
fig.add_vline(x=result.lsl, line_dash="dash", line_color="red",
annotation_text="LSL")
fig.add_vline(x=result.nominal, line_dash="dot", line_color="green",
annotation_text="Nominal")
fig.update_layout(
title=f"Distribution {result.feature_name}",
xaxis_title="Value", yaxis_title="Count",
template="plotly_white", height=350,
)
return fig.to_plotly_json()
def control_chart(result: SPCResult) -> dict:
"""Individual values control chart (I-chart)."""
x_axis = list(range(1, result.n + 1))
fig = go.Figure()
fig.add_trace(go.Scatter(
x=x_axis, y=result.values, mode="lines+markers", name="Value",
))
fig.add_hline(y=result.mean, line_color="green", annotation_text="Mean")
fig.add_hline(y=result.ucl, line_dash="dash", line_color="red",
annotation_text="UCL")
fig.add_hline(y=result.lcl, line_dash="dash", line_color="red",
annotation_text="LCL")
fig.add_hline(y=result.usl, line_dash="dot", line_color="orange",
annotation_text="USL")
fig.add_hline(y=result.lsl, line_dash="dot", line_color="orange",
annotation_text="LSL")
fig.update_layout(
title=f"Control Chart {result.feature_name}",
xaxis_title="Sample #", yaxis_title="Value",
template="plotly_white", height=350,
)
return fig.to_plotly_json()
def capability_bar(results: list[SPCResult]) -> dict:
"""Capability index bar chart comparing all features."""
names = [r.feature_name for r in results]
cpk_vals = [r.cpk if r.cpk is not None else 0.0 for r in results]
ppk_vals = [r.ppk if r.ppk is not None else 0.0 for r in results]
colors = ["#2ecc71" if v >= 1.33 else "#f39c12" if v >= 1.0 else "#e74c3c"
for v in cpk_vals]
fig = go.Figure()
fig.add_trace(go.Bar(x=names, y=cpk_vals, name="Cpk", marker_color=colors))
fig.add_trace(go.Bar(x=names, y=ppk_vals, name="Ppk", marker_color="rgba(52,152,219,0.6)"))
fig.add_hline(y=1.33, line_dash="dash", line_color="green",
annotation_text="Cpk=1.33")
fig.add_hline(y=1.0, line_dash="dot", line_color="orange",
annotation_text="Cpk=1.0")
fig.update_layout(
title="Process Capability Summary",
xaxis_title="Feature", yaxis_title="Index",
barmode="group", template="plotly_white", height=400,
)
return fig.to_plotly_json()
def generate_charts(results: list[SPCResult]) -> dict:
"""Generate all charts for a set of SPC results."""
charts: dict[str, list[dict] | dict] = {
"histograms": [],
"control_charts": [],
}
for r in results:
if r.n >= 2:
charts["histograms"].append(histogram(r))
charts["control_charts"].append(control_chart(r))
if results:
charts["capability_bar"] = capability_bar(results)
return charts