Signal detection identifies out-of-control conditions in your process using the Western Electric (WECO) rules. These rules detect patterns that indicate special cause variation.
What You’ll Learn¶
Understand all 8 Western Electric rules
Configure which rules to apply
Interpret signal detection results
Visualize rule violations on charts
Setup¶
import numpy as np
import pandas as pd
from processbehavior import ProcessBehaviorCreate Data with Various Patterns¶
We’ll create data that exhibits different out-of-control patterns to demonstrate each rule:
np.random.seed(42)
n = 50
values = np.random.normal(100, 2, n)
# Rule 1: Point beyond limits (index 10)
values[10] = 112 # Beyond 3-sigma
# Rule 4: Run (8 consecutive same side) (indices 20-27)
values[20:28] = np.random.normal(103, 0.5, 8) # All above center
# Rule 5: Trend (6 consecutive increasing) (indices 35-40)
values[35:41] = [98, 99, 100, 101, 102, 103]
df = pd.DataFrame({
'day': range(1, n + 1),
'measurement': np.round(values, 2)
})
print(f"Dataset: {len(df)} observations")
df.head()Dataset: 50 observations
Create Analysis¶
pb = ProcessBehavior(df)
study = pb.formulate(
response=pb.cols.measurement,
time=pb.cols.day
)
result = study.execute() # single stream over time -> recommended chart is XThe 8 Western Electric Rules¶
Zone Definitions¶
The rules reference three zones on each side of the centerline:
Zone C: Within 1 sigma of centerline
Zone B: Between 1 and 2 sigma
Zone A: Between 2 and 3 sigma
The Rules¶
| Rule | Name | Pattern | Interpretation |
|---|---|---|---|
| 1 | Beyond Limits | 1 point > 3σ from center | Obvious special cause |
| 2 | Zone A | 2 of 3 consecutive in Zone A | Likely shift |
| 3 | Zone B | 4 of 5 consecutive in Zone B+ | Process shifting |
| 4 | Run | 8+ consecutive same side | Sustained shift |
| 5 | Trend | 6+ consecutive increasing/decreasing | Drift |
| 6 | Oscillation | 14+ consecutive alternating | Overcontrol |
| 7 | Hugging Center | 15+ consecutive in Zone C | Reduced variation |
| 8 | Avoiding Center | 8+ consecutive not in Zone C | Bimodal distribution |
Standard vs. Extended Rules¶
ProcessBehavior offers three rule sets:
'standard': Rules 1-4 (most common, lower false alarm rate)'extended': Rules 1-8 (more sensitive, higher false alarm rate)'all': Same as extended
# Default rules (chart-appropriate: all 8 for an X chart)
signals = result.detect_signals(chart='X')
print(f"Signals found: {signals.count}")
# The documented presets:
std = result.detect_signals(chart='X', rules='standard') # rules 1-4
ext = result.detect_signals(chart='X', rules='extended') # rules 1-8
print(f"standard (1-4): {std.count} | extended (1-8): {ext.count}")Signals found: 11
standard (1-4): 8 | extended (1-8): 11
Examining Signal Results¶
signals = result.detect_signals(chart='X')
print(f"Has signals: {signals.has_signals}")
print(f"Total count: {signals.count}")
print(f"\nFlagged observations: {signals.flagged_observations}")Has signals: True
Total count: 11
Flagged observations: {np.int64(10), np.int64(23), np.int64(24), np.int64(25), np.int64(26), np.int64(27), np.int64(28)}
# View all violations
print("All Violations:")
signals.violationsAll Violations:
# Summary by rule
print(signals.summary)
======================================================================
Signal Detection Summary: X
======================================================================
Total violations: 11
Flagged observations: 7
Violations by rule:
rule_3: 6
rule_8: 3
rule_1: 1
rule_4: 1
First violations:
• Obs 10: Point beyond control limits (value=112.000)
• Obs 23: 4 of 5 consecutive points in Zone B or beyond (value=103.310)
• Obs 24: 4 of 5 consecutive points in Zone B or beyond (value=103.520)
• Obs 25: 4 of 5 consecutive points in Zone B or beyond (value=103.470)
• Obs 25: 8+ consecutive points avoiding Zone C (value=103.470)
... and 6 more
======================================================================
# Violations grouped by rule
print("\nViolations by Rule:")
for rule, violations in signals.by_rule.items():
print(f" {rule}: {len(violations)} violation(s)")
Violations by Rule:
rule_1: 1 violation(s)
rule_3: 6 violation(s)
rule_4: 1 violation(s)
rule_8: 3 violation(s)
Visualize with Rule Violations¶
fig = result.plot(
show_zones=True,
show_rules=True, # Shows all rule violations
highlight_signals=True
)
fig.show()Custom Rule Configuration¶
Pass an explicit list of rule names, or build a RuleSet for precise control:
# Custom rule configuration using a list of rule names
signals_custom = result.detect_signals(
chart='X',
rules=['rule_1', 'rule_4'] # Beyond limits and runs
)
print(f"Custom rules found: {signals_custom.count} signals")Custom rules found: 2 signals
# Specific rules - just Rule 1 (beyond limits)
signals_rule1 = result.detect_signals(
chart='X',
rules=['rule_1']
)
print(f"Rule 1 only: {signals_rule1.count} signals")Rule 1 only: 1 signals
# The RuleSet builder: compose exactly the rules you want
from processbehavior.signals import RuleSet
rules = RuleSet().beyond_limits().run(length=8).trend(length=6)
signals_rs = result.detect_signals(chart='X', rules=rules)
print(f"Rules applied: {rules.get_rules()}")
print(f"Signals found: {signals_rs.count}")Rules applied: ['rule_1', 'rule_4', 'rule_5']
Signals found: 2
Rule Applicability by Chart Type¶
Not all rules apply to all chart types:
| Chart Type | Applicable Rules |
|---|---|
| X | All 8 rules |
| mR | All 8 rules |
| Xbar | Rule 1 only |
| S | Rule 1 only |
Why the Difference?¶
X and mR charts are time-ordered, so sequential patterns (runs, trends) are meaningful
Xbar/S charts compare subgroups, which may not be time-ordered
For Xbar/S, only points beyond limits indicate special causes
Understanding Each Rule¶
Rule 1: Beyond Limits¶
Pattern: Single point beyond 3σ limits
Interpretation: Almost certainly a special cause. In a stable process, the chance of a point beyond 3σ is about 0.27%.
Action: Investigate immediately. What changed?
# Our data point at index 10 (day 11) should trigger Rule 1
print(f"Value at day 11: {df.loc[10, 'measurement']}")
stats = result.get_statistics('X')
print(f"UPL: {stats['upl']:.2f}")Value at day 11: 112.0
UPL: 106.56
Rule 4: Run¶
Pattern: 8+ consecutive points on same side of centerline
Interpretation: The process has shifted. Even small shifts (< 1σ) will eventually produce runs.
Action: Look for what caused the sustained change.
# Days 21-28 should all be above centerline
print("Values at days 21-28:")
print(df.loc[20:27, ['day', 'measurement']])
print(f"\nCenterline: {stats['center']:.2f}")Values at days 21-28:
day measurement
20 21 103.16
21 22 102.81
22 23 102.66
23 24 103.31
24 25 103.52
25 26 103.47
26 27 102.58
27 28 102.85
Centerline: 100.54
Rule 5: Trend¶
Pattern: 6+ consecutive points increasing or decreasing
Interpretation: Process is drifting. Common causes: tool wear, temperature changes, material degradation.
Action: Identify and address the source of drift.
# Days 36-41 have increasing trend
print("Values at days 36-41:")
print(df.loc[35:40, ['day', 'measurement']])Values at days 36-41:
day measurement
35 36 98.0
36 37 99.0
37 38 100.0
38 39 101.0
39 40 102.0
40 41 103.0
False Alarm Rates¶
More rules = more sensitivity = more false alarms
| Rule Set | Approx. False Alarm Rate |
|---|---|
| Rule 1 only | 0.27% per point |
| Rules 1-4 | ~1-2% per point |
| Rules 1-8 | ~3-5% per point |
Recommendation: Start with standard rules (1-4). Only use extended rules when you have enough data and can investigate false alarms.
Summary¶
In this tutorial, you learned:
The 8 Western Electric rules detect different patterns
Use
'standard'(rules 1-4) for most applicationsUse
'extended'(rules 1-8) for more sensitive detectionUse
RuleSet()builder for custom configurationsOnly Rule 1 applies to Xbar/S charts; all 8 apply to X and mR
More rules = more sensitivity = more false alarms
Next Steps¶
Western Electric Rules - Complete rule reference
Plotting & Themes - Visualization options
Excel Export - Export results