gage-rr-analyzer
You are gage-rr-analyzer - a specialized skill for conducting Measurement System Analysis (MSA) and Gage R&R studies.
Overview
This skill enables AI-powered MSA including:
- Gage R&R study design (crossed, nested)
- ANOVA variance decomposition
- Repeatability (equipment variation) calculation
- Reproducibility (appraiser variation) calculation
- Part-to-part variation analysis
- %GRR and %Contribution metrics
- Number of distinct categories (ndc)
- Measurement decision analysis
- Acceptance criteria evaluation (< 10%, 10-30%, > 30%)
Prerequisites
- Python 3.8+ with numpy, scipy, pandas
- Measurement data from designed study
- Understanding of MSA principles
Capabilities
1. Gage R&R Study Design
from dataclasses import dataclass
from typing import List
import numpy as np
@dataclass
class GageRRStudyDesign:
"""
Design parameters for Gage R&R study
"""
num_parts: int = 10 # Typically 10
num_operators: int = 3 # Typically 2-3
num_trials: int = 3 # Typically 2-3 measurements per part per operator
def total_measurements(self):
return self.num_parts * self.num_operators * self.num_trials
def randomized_run_order(self):
"""Generate randomized measurement order"""
runs = []
for part in range(1, self.num_parts + 1):
for operator in range(1, self.num_operators + 1):
for trial in range(1, self.num_trials + 1):
runs.append({
"part": part,
"operator": operator,
"trial": trial
})
np.random.shuffle(runs)
return runs
def create_study_worksheet(design: GageRRStudyDesign):
"""
Create data collection worksheet
"""
runs = design.randomized_run_order()
worksheet = {
"study_info": {
"gage_name": "",
"gage_number": "",
"study_date": "",
"characteristic": "",
"specification": "",
"resolution": ""
},
"operators": [f"Operator_{i}" for i in range(1, design.num_operators + 1)],
"parts": [f"Part_{i}" for i in range(1, design.num_parts + 1)],
"run_order": runs,
"data_entry": []
}
return worksheet
2. ANOVA Method (Crossed Study)
import pandas as pd
from scipy import stats
def gage_rr_anova(data, parts_col='Part', operators_col='Operator', measurement_col='Measurement'):
"""
Gage R&R analysis using ANOVA method
data: DataFrame with Part, Operator, and Measurement columns
"""
df = pd.DataFrame(data)
# Get design parameters
n_parts = df[parts_col].nunique()
n_operators = df[operators_col].nunique()
n_trials = len(df) // (n_parts * n_operators)
# Calculate means
grand_mean = df[measurement_col].mean()
part_means = df.groupby(parts_col)[measurement_col].mean()
operator_means = df.groupby(operators_col)[measurement_col].mean()
cell_means = df.groupby([parts_col, operators_col])[measurement_col].mean()
# Sum of Squares
SS_total = ((df[measurement_col] - grand_mean) ** 2).sum()
SS_part = n_operators * n_trials * ((part_means - grand_mean) ** 2).sum()
SS_operator = n_parts * n_trials * ((operator_means - grand_mean) ** 2).sum()
# SS Interaction
SS_cell = n_trials * ((cell_means - grand_mean) ** 2).sum()
SS_interaction = SS_cell - SS_part - SS_operator
# SS Error (repeatability)
SS_error = SS_total - SS_part - SS_operator - SS_interaction
# Degrees of freedom
df_part = n_parts - 1
df_operator = n_operators - 1
df_interaction = df_part * df_operator
df_error = n_parts * n_operators * (n_trials - 1)
df_total = len(df) - 1
# Mean Squares
MS_part = SS_part / df_part
MS_operator = SS_operator / df_operator
MS_interaction = SS_interaction / df_interaction if df_interaction > 0 else 0
MS_error = SS_error / df_error
# F-statistics
F_part = MS_part / MS_interaction if MS_interaction > 0 else MS_part / MS_error
F_operator = MS_operator / MS_interaction if MS_interaction > 0 else MS_operator / MS_error
F_interaction = MS_interaction / MS_error if MS_interaction > 0 else 0
# p-values
p_part = 1 - stats.f.cdf(F_part, df_part, df_interaction if MS_interaction > 0 else df_error)
p_operator = 1 - stats.f.cdf(F_operator, df_operator, df_interaction if MS_interaction > 0 else df_error)
p_interaction = 1 - stats.f.cdf(F_interaction, df_interaction, df_error) if F_interaction > 0 else 1
anova_table = {
"Part": {"SS": SS_part, "df": df_part, "MS": MS_part, "F": F_part, "p": p_part},
"Operator": {"SS": SS_operator, "df": df_operator, "MS": MS_operator, "F": F_operator, "p": p_operator},
"Part*Operator": {"SS": SS_interaction, "df": df_interaction, "MS": MS_interaction, "F": F_interaction, "p": p_interaction},
"Repeatability": {"SS": SS_error, "df": df_error, "MS": MS_error},
"Total": {"SS": SS_total, "df": df_total}
}
return anova_table, {
"n_parts": n_parts,
"n_operators": n_operators,
"n_trials": n_trials,
"grand_mean": grand_mean
}
3. Variance Components Calculation
def calculate_variance_components(anova_table, design_params):
"""
Extract variance components from ANOVA
"""
n = design_params['n_trials']
k = design_params['n_operators']
p = design_params['n_parts']
MS_part = anova_table['Part']['MS']
MS_operator = anova_table['Operator']['MS']
MS_interaction = anova_table['Part*Operator']['MS']
MS_error = anova_table['Repeatability']['MS']
# Variance components
var_repeatability = MS_error
# Check if interaction is significant (p < 0.25 typically)
if anova_table['Part*Operator']['p'] < 0.25:
var_interaction = max(0, (MS_interaction - MS_error) / n)
var_operator = max(0, (MS_operator - MS_interaction) / (n * p))
else:
# Pool interaction with error
var_interaction = 0
pooled_ms = (anova_table['Part*Operator']['SS'] + anova_table['Repeatability']['SS']) / \
(anova_table['Part*Operator']['df'] + anova_table['Repeatability']['df'])
var_operator = max(0, (MS_operator - pooled_ms) / (n * p))
var_repeatability = pooled_ms
var_part = max(0, (MS_part - MS_operator) / (n * k)) if MS_part > MS_operator else \
max(0, (MS_part - MS_error) / (n * k))
# Reproducibility = Operator + Interaction
var_reproducibility = var_operator + var_interaction
# Gage R&R = Repeatability + Reproducibility
var_grr = var_repeatability + var_reproducibility
# Total variation
var_total = var_grr + var_part
return {
"repeatability": var_repeatability,
"reproducibility": var_reproducibility,
"operator": var_operator,
"interaction": var_interaction,
"gage_rr": var_grr,
"part_to_part": var_part,
"total": var_total
}
4. %GRR and Metrics Calculation
def calculate_grr_metrics(variance_components, tolerance=None):
"""
Calculate Gage R&R metrics
tolerance: specification range (USL - LSL) for %Tolerance calculation
"""
vc = variance_components
# Standard deviations (6*sigma for 99.73% spread)
std_repeatability = np.sqrt(vc['repeatability'])
std_reproducibility = np.sqrt(vc['reproducibility'])
std_grr = np.sqrt(vc['gage_rr'])
std_part = np.sqrt(vc['part_to_part'])
std_total = np.sqrt(vc['total'])
# Study variation (6 * sigma)
sv_repeatability = 6 * std_repeatability
sv_reproducibility = 6 * std_reproducibility
sv_grr = 6 * std_grr
sv_part = 6 * std_part
sv_total = 6 * std_total
metrics = {
"study_variation": {
"repeatability": sv_repeatability,
"reproduc