Skip to content

Expose the received-order X/mR chart: formulate(response=...) with no time or factors #129

Description

@cnicholas

Summary

formulate(response=...) with no time, factors or plan is refused. A bare list of values charted in the order received is the most common individuals chart there is, and it is the app's most common input (pasted values). The machinery to produce it already exists in the library; it is reachable through an undocumented side door and mislabels its own sigma source when it gets there. This issue is to expose it at the front door, make the spellings agree, and document it.

Current behaviour

Front door refuses.

pb.ProcessBehavior(df).formulate(response="value")
# ValidationError: A study needs either a time order or a grouping structure — this has neither.

Side door accepts. factors=[] with no time bypasses the check. DataPreparation.build_keys gives every row an empty cell key, the canonical sort collapses to received order, and sort_key is stamped 0..N−1. The X/mR chart that results is correct: N points in received order, N−1 moving ranges.

study = pb.ProcessBehavior(df).formulate(response="value", factors=[])
study.execute(chart="X", by=[], companion=True)   # works

But the side door mislabels itself. With no time variable and no factors, the series-length assessment sees one big cell and reports Sigma rests on within-cell replication. For an X/mR chart whose sigma comes from N−1 moving ranges, that line is wrong. The design report also shows Min cell size: N | K: 0 | T: None, which does not describe what was charted.

The refusal message does not mention the side door, so the two spellings of "no factors" diverge in exactly the way d0fdc17 (Aug 2026) was written to remove. That commit reopened response + time and left response alone closed.

History

  • Before e429205 (Jan 2026) response-only was accepted and documented ("response-only analysis … classified as SDS 4 with implicit single condition"). e429205 removed it as a breaking change to keep design-state classification on a factor × time grid, deleting the single-stream detector path and 41 tests.
  • d0fdc17 (Aug 2026) reopened formulate(response, time) with no factors as an ordinary ADS 2 study, and kept the refusal only when time, factors and plan are all absent.

Proposal

Treat a bare response as a single stream whose time order is the row order. This is the same study d0fdc17 already accepts when a time column is named: one observation per time point, no factors, ADS 2 (no replication), sigma from N−1 moving ranges. No new design state and no special case in the detector; the grid is 1 × N.

  1. Accept formulate(response=...). When time, factors and plan are all absent, stamp received order (obs_id) as the time order. Record on FormulationSpec that the sequence is implicit (e.g. time_var=None plus an implicit_sequence flag, or a synthetic time column name that the report knows how to describe).
  2. Say so in the design report. A line such as Time: received order (no time column given). The series-length line then reads correctly: T=N. Sigma for X/mR rests on N−1 moving ranges. The existing series-length wording is settled and does not change; this just routes the case to the right branch.
  3. Make factors=[] with no time take the same path, so the two spellings produce byte-identical studies. Finish what d0fdc17 started.
  4. Xbar / S stay unavailable. ADS 2 has no replication; that is already the correct answer and preserves the e429205 principle.
  5. Document it as the first example in the getting-started path: a list of values → X/mR chart in the order received. read_clipboard is the natural companion.

Not proposed

  • No warning on this path. The risk the old docstring named (values not actually in time order) is real, but a warning would fire on the single most common use case. The design report states the assumption; the analyst owns it. Same posture as the series-length line.
  • No change to the detector, residuals, or any existing formulation with a time column or factors.

Invariants to preserve

  • Every existing formulation (time given, or factors/plan given) is byte-identical.
  • factors=[] with a time column (the d0fdc17 path) is unchanged.
  • ODS/ADS detection still runs on raw data; the implicit sequence is assigned before detection so the 1 × N grid is what it sees.
  • 280 Bishop reference assertions untouched (validation/e2e_bishop_report.py).

Test strategy

  • formulate(response), formulate(response, factors=[]) and formulate(response, time=<explicit 1..N column>) produce identical AnalysisResult frames and statistics on the same data.
  • Design report on the bare-response study carries the received-order line and the correct series-length text.
  • Shuffled input produces a different chart (proves received order is what is charted, not any hidden sort).
  • Xbar/S on the bare-response study raise the existing no-replication error and why_not agrees.

Files to touch

  • processbehavior/process_behavior.py_validate_factors_or_plan_args (drop the all-absent refusal or narrow it), formulate assigns the implicit sequence.
  • processbehavior/data_preparation.pybuild_keys already handles the empty case; confirm the implicit sequence flows into cell_key.
  • processbehavior/series_length.py / study.py — route the implicit-sequence case to the moving-range branch; design report line.
  • processbehavior/formulation_spec.py (or wherever FormulationSpec lives) — the implicit-sequence marker.
  • Docs: getting-started first example; read_clipboard docstring example.
  • Tests as above; the existing test at tests/test_process_behavior.py:~1024 documents the spelling inconsistency and should become the equality test.

Context

Surfaced while investigating #114: checking what a "standard" X chart of the ACO data would be showed that response-only is refused at the front door and reachable via factors=[], with the wrong sigma-source line. The app supports pasted lists of values, and a chart in the order received is the everyday case.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions