Repository navigation
detect_signals() raises TypeError on every phased chart #141
Copy link
Copy link
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
What happens
detect_signals() raises on every chart run with phased=True: X or mR, the combined by=[] chart or a stratified one, called directly or after focus().
import processbehavior as pb
study = pb.formulate(pb.make_design(state=1, seed=42), response='y', time='time',
factors=['factor 1', 'factor 2'])
study.execute(chart='X', by=[], phased=True).detect_signals()
# TypeError: unsupported operand type(s) for -: 'float' and 'NoneType'
r = study.execute(chart='X', by=['factor 1'], phased=True)
r.focus(r.strata[0]).detect_signals() # same TypeErrorWhy
- A phased chart gives each phase its own centre line, so its statistics are
{'N': None, 'center': None, 'lpl': None, 'upl': None, 'limits_vary': True}(the contract since 5c9929c). The per-phase centre and limits are on the rows. SignalDetector.detectsends everylimits_varychart to_calculate_per_row_zones(processbehavior/signals/detector.py, ~337–341), which computesdata['upl'] - stats['center']. That was written for Xbar/S with unequal subgroup sizes, where the limits move but the centre is one number.- Phased charts also set
metadata['run_rules_applicable'] = False(70503be: "zones assume fixed center"). Only the renderer reads it;result_signals._detect_for_chartdoes not, so the detector tries to build zones for rules 2–8 at all. - No test runs signal detection on a phased chart.
Impact
- The chart itself is right: the per-phase limits are correct, and points beyond them are flagged (
beyond_limits, used by the plot,chart_tableandget_signals()). detect_signals()returns nothing. A caller that catches the error, as the processbehavior.com app does, can only report that signal detection failed.
Proposed change
result_signals._detect_for_chartpassesmetadata['run_rules_applicable']toSignalDetector.detect.- When it is False and the rules are the chart-type default, the default set is Rule 1 only. Rules 2–8 are not applicable rather than skipped, so the result is not marked partial on their account. This is how Xbar/S are already Rule-1-only.
- An explicit rule list runs as given (the existing "explicit rules, no filtering" contract in
SignalConfig.get_rules_for_chart). The per-row zones, the run rule and the violation records use each row's own centre when the scalar centre isNone.
Related, not fixed here
Calling detect_signals() at the top level of any stratified result raises ValidationError: Missing required statistics: ['upl', 'lpl', 'center'], followed by the list of strata. result.focus(stratum).detect_signals() works. The message could say so.
Context
Found while scoping phased limits for Xbar/S.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working
Activity
Merge pull request #145 from cnicholas/fix/phased-signals
cnicholas commentedon Oct 14, 2026
Fixed in #145, merged to main with the 0.4.0 stack (e982d32).