diff --git a/spec/montgomery_spec.rb b/spec/montgomery_spec.rb index 1745b8e..c781b41 100644 --- a/spec/montgomery_spec.rb +++ b/spec/montgomery_spec.rb @@ -190,10 +190,27 @@ class MontgomerySpec < SpcSpec describe "Cusum with fixed target" do subject do DB.from( - Sequel.lit('spc_reports.cusum_rules(?)', 10) # target mean = 10 + Sequel.lit('spc_reports.cusum_rules(?, ?)', + 0.5, # allowance + 10 # target mean + ) ).where(instrument_id:).order_by(:sample_id) end + + describe "Calculating net deviation" do + it_has_correct_values(column: :deviation, values: [ + # @formatter:off + -0.55, -2.01, -0.71, 1.66, 2.16, + 0.18, -1.96, 1.46, -0.8, 0.34, + -0.97, 1.47, 0.51, -0.6, 0.08, + -0.63, 0.62, 0.31, -1.48, 0.84, + 0.9, -0.67, 2.29, 1.5, 0.6, + 1.08, 0.38, 1.62, 1.31, 0.52 + # @formatter:on + ]) + end + describe "Calculating Cₙ" do it_has_correct_values(column: :c_n, values: [ # @formatter:off @@ -206,6 +223,58 @@ class MontgomerySpec < SpcSpec # @formatter:on ]) end + + describe "Calculating positive deviation" do + it_has_correct_values(column: :deviation_plus, values: [ + # @formatter:off + -1.05, -2.51, -1.21, 1.16, 1.66, + -0.32, -2.46, 0.96, -1.3, -0.16, + -1.47, 0.97, 0.01, -1.1, -0.42, + -1.13, 0.12, -0.19, -1.98, 0.34, + 0.4, -1.17, 1.79, 1.0, 0.1, + 0.58, -0.12, 1.12, 0.81, 0.02 + # @formatter:on + ]) + end + + describe "Calculating C⁺" do + it_has_correct_values(column: :c_plus, values: [ + # @formatter:off + 0, 0, 0, 1.16, 2.82, + 2.50, 0.04, 1.00, 0, 0, + 0, 0.97, 0.98, 0, 0, + 0, 0.12, 0, 0, 0.34, + 0.74, 0, 1.79, 2.79, 2.89, + 3.47, 3.35, 4.47, 5.28, 5.30 + # @formatter:on + ]) + end + + describe "Calculating negative deviation" do + it_has_correct_values(column: :deviation_minus, values: [ + # @formatter:off + -0.05, -1.51, -0.21, 2.16, 2.66, + 0.68, -1.46, 1.96, -0.3, 0.84, + -0.47, 1.97, 1.01, -0.1, 0.58, + -0.13, 1.12, 0.81, -0.98, 1.34, + 1.4, -0.17, 2.79, 2.0, 1.1, + 1.58, 0.88, 2.12, 1.81, 1.02 + # @formatter:on + ]) + end + + describe "Calculating C⁻" do + it_has_correct_values(column: :c_minus, values: [ + # @formatter:off + -0.05, -1.56, -1.77, 0, 0, + 0, -1.46, 0, -0.3, 0, + -0.47, 0, 0, -0.1, 0, + -0.13, 0, 0, -0.98, 0, + 0, -0.17, 0, 0, 0, + 0, 0, 0, 0, 0 + # @formatter:on + ]) + end end end end \ No newline at end of file diff --git a/sql/02-spc-intermediates-schema.sql b/sql/02-spc-intermediates-schema.sql index cd800c0..6e12707 100644 --- a/sql/02-spc-intermediates-schema.sql +++ b/sql/02-spc-intermediates-schema.sql @@ -508,3 +508,40 @@ $$; -- Cumulative Sum, aka Cusum +create function spc_intermediates.cusum_c_plus_step( + last_c_plus decimal + , measurement decimal + , allowance decimal + , target_mean decimal +) returns decimal immutable language sql as +$$ + select greatest(coalesce(last_c_plus, 0) + (measurement - target_mean - allowance), 0); +$$; + +create aggregate spc_intermediates.cusum_c_plus( + measurement decimal + , allowance decimal + , target_mean decimal +) ( + sfunc = spc_intermediates.cusum_c_plus_step, + stype = decimal +); + +create function spc_intermediates.cusum_c_minus_step( + last_c_minus decimal + , measurement decimal + , allowance decimal + , target_mean decimal +) returns decimal immutable language sql as +$$ + select least(coalesce(last_c_minus, 0) + (measurement - target_mean + allowance), 0); +$$; + +create aggregate spc_intermediates.cusum_c_minus( + measurement decimal + , allowance decimal + , target_mean decimal +) ( + sfunc = spc_intermediates.cusum_c_minus_step, + stype = decimal +); diff --git a/sql/03-spc-reports-schema.sql b/sql/03-spc-reports-schema.sql index 4abbb6c..d3e2aa9 100644 --- a/sql/03-spc-reports-schema.sql +++ b/sql/03-spc-reports-schema.sql @@ -395,7 +395,8 @@ $$; -- Cumulative Sum aka Cusum create function spc_reports.cusum_rules( - p_target_mean decimal default null + p_allowance decimal + , p_target_mean decimal default null ) returns table ( measurement_id bigint, @@ -403,22 +404,33 @@ returns table ( window_id bigint, instrument_id bigint, measured_value decimal, - error decimal, - C_n decimal + deviation decimal, + deviation_plus decimal, + deviation_minus decimal, + C_n decimal, + C_plus decimal, + C_minus decimal ) immutable language sql as $$ select m.id as measurement_id , m.sample_id - , w.id as window_id + , w.id as window_id , s.instrument_id , m.measured_value - , m.measured_value - coalesce(p_target_mean, mean_measured_value) as error + , m.measured_value - coalesce(p_target_mean, mean_measured_value) as deviation + , m.measured_value - coalesce(p_target_mean, mean_measured_value) - p_allowance as deviation_plus + , m.measured_value - coalesce(p_target_mean, mean_measured_value) + p_allowance as deviation_plus , sum(m.measured_value - coalesce(p_target_mean, mean_measured_value)) - over (partition by w.id order by m.id) as C_n + over (partition by w.id order by m.id) as C_n + , spc_intermediates.cusum_c_plus(m.measured_value, p_allowance, coalesce(p_target_mean, mean_measured_value)) + over window_sample as C_plus + , spc_intermediates.cusum_c_minus(m.measured_value, p_allowance, coalesce(p_target_mean, mean_measured_value)) + over window_sample as C_minus from spc_data.measurements m join spc_data.samples s on s.id = m.sample_id join spc_data.instruments i on i.id = s.instrument_id join spc_data.windows w on i.id = w.instrument_id - join spc_intermediates.individual_measurement_statistics_ewma imse on w.id = imse.window_id; + join spc_intermediates.individual_measurement_statistics_ewma imse on w.id = imse.window_id +window window_sample as (partition by w.id order by m.sample_id); $$; \ No newline at end of file