///|
/// Process performance facts for an inspection batch.
pub struct ProcessPerformance {
statistics : SampleStatistics
accepted : Int
rejected : Int
lower_defects : Int
upper_defects : Int
observed_yield : Double
defect_rate : Double
capability : CapabilityReport
} derive(Debug, Eq)
///|
/// Count accepted, lower-side, and upper-side observations.
pub fn process_performance(
values : Array[Double],
window : AcceptanceWindow,
) -> ProcessPerformance {
let statistics = summarize_samples(values)
let capability = capability_report(values, window)
let mut accepted = 0
let mut lower_defects = 0
let mut upper_defects = 0
for value in values {
if value < window.lower {
lower_defects += 1
} else if value > window.upper {
upper_defects += 1
} else {
accepted += 1
}
}
let rejected = lower_defects + upper_defects
{
statistics,
accepted,
rejected,
lower_defects,
upper_defects,
observed_yield: accepted.to_double() / statistics.count.to_double(),
defect_rate: rejected.to_double() / statistics.count.to_double(),
capability,
}
}
///|
/// Return the indices of values outside a closed screening band.
pub fn outlier_indices(
values : Array[Double],
lower : Double,
upper : Double,
) -> Array[Int] {
if upper < lower {
abort("outlier upper bound must not be below lower bound")
}
let result = []
for index in 0.. upper {
result.push(index)
}
}
result
}
///|
/// Convert an observed defect rate to parts per million.
pub fn defects_per_million(report : ProcessPerformance) -> Double {
report.defect_rate * 1_000_000.0
}
///|
/// A least-squares linear trend over equally spaced observations.
pub struct TrendReport {
count : Int
slope : Double
intercept : Double
r_squared : Double
} derive(Debug, Eq)
///|
/// Calculate an equally-spaced least-squares process trend.
pub fn linear_trend(values : Array[Double]) -> TrendReport {
if values.length() < 2 {
abort("a trend requires at least two observations")
}
let count = values.length()
let n = count.to_double()
let mean_x = (n - 1.0) / 2.0
let statistics = summarize_samples(values)
let mean_y = statistics.mean
let mut xx = 0.0
let mut xy = 0.0
let mut yy = 0.0
for index in 0.. Array[Double] {
if window <= 0 {
abort("moving-average window must be positive")
}
if values.length() < window {
[]
} else {
let result = []
for start in 0..<(values.length() - window + 1) {
let mut total = 0.0
for offset in 0.. Double {
let lower = mean - window.lower
let upper = window.upper - mean
if lower < upper {
lower
} else {
upper
}
}