Jump to content

# Creating a control chart and applying SPC run rules

## Recommended Posts

• Seeq Team

Statistical Process Control (SPC) can give production teams a uniform way to view and interpret data to improve processes and identify and prevent production issues. Control charts and run rule conditions can be created in Seeq to monitor near-real time data and flag when the data indicates abnormal or out of control behavior.

### Creating a Control Chart

1. Find the signal of interest and a signal that can be used to detect the current production grade (ideally a grade code or similar signal - if this does not exist for your product, you can use process set points to stitch together a calculated grade signal). Use .tocondition() in formula to create a condition for each change in the Grade_Code signal.

2. Check data for normalcy and other statistical assumptions prior to proceeding. To check for normalcy, use the Histogram tool in Seeq. Find more information on the Histogram tool in the Seeq Knowledge Base. Note that for this analysis we are using a subgroup size of one and assuming normalcy.

3. Determine the methodology to use to create the average and standard deviation for each grade. In this case, we will identify periods after start-up when the process was in control using Manual Condition, and select these times across each grade.

4. Calculate the mean and standard deviation for each grade, based on the times the process was in-control. Choose a time window that captures all capsules created for the in-control period. To use an unweighted mean, use .toDiscrete() before calculating average.

The same calculation for the mean can be used for the standard deviation, by replacing average() with stddev().

```//Define the time period that contains all in control capsules
\$capsule = capsule('2020-10-16T00:00-00:00', '2021-09-21T00:00-00:00')

//Narrow down data to when process is in control, use keep() to filter the condition by the specific grade code capsule property
\$g101 = \$allgrades.keep('Grade Code',isMatch('Grade 101')).intersect(\$inControl)
\$g102 = \$allgrades.keep('Grade Code',isMatch('Grade 102')).intersect(\$inControl)
\$g103 = \$allgrades.keep('Grade Code',isMatch('Grade 103')).intersect(\$inControl)

//Create average based on the times the product is in control, use .toDiscrete to create an unweighted average
\$g101_ave = \$viscosity.remove(not \$g101).toDiscrete().average(\$capsule)
\$g102_ave = \$viscosity.remove(not \$g102).toDiscrete().average(\$capsule)
\$g103_ave = \$viscosity.remove(not \$g103).toDiscrete().average(\$capsule)

//Create average for all grades in one signal using splice(), use keep() to filter the condition by the specific grade code capsule property
//use within() to show only average only during the condition
0.splice(\$g101_ave, \$allgrades.keep('Grade Code',isMatch('Grade 101')))
.splice(\$g102_ave, \$allgrades.keep('Grade Code',isMatch('Grade 102')))
.splice(\$g103_ave, \$allgrades.keep('Grade Code',isMatch('Grade 103')))
.within(\$allgrades)```

5. Use the mean and standard deviation to create +/- 1 sigma limits, +/-2 sigma limits, and +/-3sigma limits (sometimes called upper and lower control limits). Here is an example of creating the +2 sigma limit:

```//Add 2*standard deviation to the mean to create the \$plus2sd limit, use within() to show limits only during the time periods of interest
(\$mean + (2*\$standardDeviation)).within(\$grade_code)```

6. Overlay the standard deviation limits and mean with the signal of interest by placing on one lane and one y-axis, remove standard deviation.

### Creating Run Rules

Once the control chart is created, run rule conditions can be created to detect instability and the presence of assignable cause in the process. In this example, Western Electric Run Rules are used, but other run rules can be applied using similar principles.

Western Electric Run Rules:

Run Rule 1: Any single data point falls outside the 3sigma-limit from the centerline.

Run Rule 2: Two out of three consecutive points fall beyond the 2sigma-limit, on the same side of the centerline.

Run Rule 3: Four out of five consecutive points fall beyond the 1sigma-limit, on the same side of the centerline.

Run Rule 4: NINE consecutive points fall on the same side of the centerline.

7.  The following formulas can be used to create a condition for each run rule:

#### Run Rule 1:

```//convert to a step signal
\$signalStep = \$signal.toStep()

//find when one data point goes outside the plus3sigma or minus 3sigma limits
(\$signalStep < \$minus3sd or \$signalStep > \$plus3sd)

//set the property on the condition
.setProperty('Run Rule', 'Run Rule 1')
```

#### Run Rule 2:

*Note that the function toCapsulesByCount() is available in Seeq versions R54+

```//Create step-interpolated signal to keep from capturing the linear interpolation between sample points
\$signalStep = \$signal.toStep()

//create capsules for every 3 samples (\$toCapsulesbyCount) and for every sample (\$toCapsules)
\$toCapsulesbyCount = \$signalStep.toCapsulesByCount(3,3*\$maxinterp) //set the maximum interpolation based on the longest time you would expect between samples
\$toCapsules = \$signalStep.toCapsules()

//Create condition for when the signal is not between +/-2 sigma limits
//separate upper and lower to capture when the rule violations occur on the same side of the centerline
\$condLess = (\$signalStep <= \$minus2sd)
\$condGreater = (\$signalStep >= \$plus2sd)

//within 3 data points (\$toCapsulesByCount), count how many sample points are not between +/-2 sigma limits
\$countLess = \$signal.todiscrete().remove(not \$condLess).aggregate(count(),\$toCapsulesbyCount,durationKey())
\$countGreater = \$signal.todiscrete()
.remove(not \$condGreater).aggregate(count(),\$toCapsulesbyCount,durationKey())

//Find when 2+ out of 3 are outside of +/-2 sigma limits
//by setting the count as a property on \$toCapsulesByCount and keeping only capsules greater than or equal to 2
\$RR5below = \$toCapsulesbyCount.setProperty('Run Rule 5 Violations', \$countLess, endvalue())
.keep('Run Rule 5 Violations', isGreaterThanOrEqualto(2))
\$RR5above = \$toCapsulesbyCount.setProperty('Run Rule 5 Violations', \$countGreater, endvalue())
.keep('Run Rule 5 Violations', isGreaterThanOrEqualto(2))

//Find every sample point capsule that touches a run rule violation capsule
//Combine upper and lower into one condition and use merge to combine overlapping capsules and to remove properties
\$toCapsules.touches(\$RR5below or \$RR5above).merge(true)
.setProperty('Run Rule', 'Run Rule 2')```

#### Run Rule 3:

*Note that the function toCapsulesByCount() is available in Seeq versions R54+

```//Create step-interpolated signal to keep from capturing the linear interpolation between sample points
\$signalStep = \$signal.toStep()

//create capsules for every 5 samples (\$toCapsulesbyCount) and for every sample (\$toCapsules)
\$toCapsulesbyCount = \$signalStep.toCapsulesByCount(5,5*\$maxinterp) //set the maximum interpolation based on the longest time you would expect between samples
\$toCapsules = \$signalStep.toCapsules()

//Create condition for when the signal is not between +/-1 sigma limits
//separate upper and lower to capture when the rule violations occur on the same side of the centerline
\$condLess = (\$signalStep <= \$minus1sd)
\$condGreater = (\$signalStep >= \$plus1sd)

//within 5 data points (\$toCapsulesByCount), count how many sample points (\$toCapsules) are not between +/-1 sigma limits
\$countLess = \$signal.toDiscrete().remove(not \$condLess).aggregate(count(),\$toCapsulesbyCount, durationkey())
\$countGreater = \$signal.toDiscrete()
.remove(not \$condGreater).aggregate(count(),\$toCapsulesbyCount,durationkey())

//Find when 4+ out of 5 are outside of +/-1 sigma limits
//by setting the count as a property on \$toCapsulesByCount and keeping only capsules greater than or equal to 4
\$RR6below = \$toCapsulesbyCount.setProperty('Run Rule 6 Violations', \$countLess, endvalue())
.keep('Run Rule 6 Violations', isGreaterThanOrEqualto(4))
\$RR6above = \$toCapsulesbyCount.setProperty('Run Rule 6 Violations', \$countGreater, endvalue())
.keep('Run Rule 6 Violations', isGreaterThanOrEqualto(4))

//Find every sample point capsule (\$toCapsules) that touches a run rule violation capsule
//Combine upper and lower into one condition and use merge to combine overlapping capsules and to remove properties
\$toCapsules.touches(\$RR6below or \$RR6above).merge(true)
.setproperty('Run Rule', 'Run Rule 3')```

#### Run Rule 4:

```//Create step-interpolated signal to keep from capturing the linear interpolation between sample points
\$signalStep = \$signal.toStep()

//create capsules for every 9 samples (\$toCapsulesbyCount) and for every sample (\$toCapsules)
\$toCapsulesbyCount = \$signalStep.toCapsulesByCount(9,9*\$maxinterp) //set the maximum interpolation based on the longest time you would expect between samples
\$toCapsules = \$signalStep.toCapsules()

//Create condition for when the signal is either greater than or less than the mean
//separate upper and lower to capture when the rule violations occur on the same side of the centerline
\$condLess = \$signalStep.isLessThan(\$mean)
\$condGreater = \$signalStep.isGreaterThan(\$mean)

//Find when the last 9 samples are fuly within the greater than or less than the mean
//use merge to combine overlapping capsules and remove properties
\$toCapsules.touches(combinewith(\$toCapsulesbyCount.inside(\$condLess), \$toCapsulesbyCount.inside(\$condGreater))).merge(true)
.setproperty('Run Rule', 'Run Rule 4')
```

**To make it easier to use these run rules in Seeq, custom formula functions can be created for each run rule using the User Defined Formula Function Editor Add-on which can be found in Seeq’s Open Source Gallery along with user guides and instructions for installation. For example, Run Rule 2 can be simplified to the following formula using the User-Defined Formula Functions Add-on with Seeq Data Lab:

`\$signal.WesternElectric_runRule2(\$minus2sd, \$plus2sd)`

9. If desired, all run rules can be combined into one condition in formula using .combinewith():

`combineWith(\$runRule1,\$runRule2,\$runRule3, \$runRule4)`

10. As a final step, a table can be created detailing the run rule violations in the trend view. Here, the header column is set as ‘Capsule Property’ >> ‘Run Rule’ and the capsule properties, start, end, and duration were added as columns. The last value of the signal ‘Grade_Code’ was also added as a column to the table. For more information on Tables, see the Seeq Knowledge Base.

Edited by Katie Pintar
Update the run rule formulas.
• 2
• 1

## Create an account or sign in to comment

You need to be a member in order to leave a comment

## Create an account

Sign up for a new account in our community. It's easy!

Register a new account

## Sign in

Already have an account? Sign in here.

Sign In Now
×
×
• Create New...