processbehavior 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- processbehavior/__init__.py +133 -0
- processbehavior/analysis.py +2944 -0
- processbehavior/analysis_dataset.py +361 -0
- processbehavior/analysis_result.py +1276 -0
- processbehavior/calibration.py +70 -0
- processbehavior/capability.py +720 -0
- processbehavior/data_preparation.py +792 -0
- processbehavior/datasets/__init__.py +37 -0
- processbehavior/datasets/data/coffee_shop_demo_long.csv +385 -0
- processbehavior/datasets/loaders.py +66 -0
- processbehavior/datasets/synthetic.py +1711 -0
- processbehavior/derivations.py +602 -0
- processbehavior/effects_calculator.py +603 -0
- processbehavior/exceptions.py +216 -0
- processbehavior/exporters/__init__.py +5 -0
- processbehavior/exporters/excel_exporter.py +708 -0
- processbehavior/focused_result.py +329 -0
- processbehavior/formulation_spec.py +144 -0
- processbehavior/loss_function.py +517 -0
- processbehavior/maximum_information.py +285 -0
- processbehavior/plotting/__init__.py +46 -0
- processbehavior/plotting/_math.py +121 -0
- processbehavior/plotting/capability_chart.py +858 -0
- processbehavior/plotting/contracts.py +176 -0
- processbehavior/plotting/control_chart.py +206 -0
- processbehavior/plotting/effects_charts.py +640 -0
- processbehavior/plotting/lane_boundaries.py +78 -0
- processbehavior/plotting/limits.py +157 -0
- processbehavior/plotting/maximum_information_chart.py +395 -0
- processbehavior/plotting/plotter.py +1469 -0
- processbehavior/plotting/renderers.py +660 -0
- processbehavior/plotting/report.py +211 -0
- processbehavior/plotting/residuals.py +282 -0
- processbehavior/plotting/run_rules_viz.py +150 -0
- processbehavior/plotting/stats_box.py +183 -0
- processbehavior/plotting/themes.py +544 -0
- processbehavior/plotting/x_axis_layout.py +474 -0
- processbehavior/plotting/zones.py +127 -0
- processbehavior/process_behavior.py +1290 -0
- processbehavior/py.typed +0 -0
- processbehavior/residual_calculator.py +572 -0
- processbehavior/result_signals.py +149 -0
- processbehavior/result_tabular.py +296 -0
- processbehavior/sds_detector.py +1432 -0
- processbehavior/signals/__init__.py +14 -0
- processbehavior/signals/config.py +435 -0
- processbehavior/signals/detector.py +328 -0
- processbehavior/signals/detectors.py +368 -0
- processbehavior/signals/result.py +232 -0
- processbehavior/spc_constants.py +692 -0
- processbehavior/study.py +2733 -0
- processbehavior/types.py +154 -0
- processbehavior-0.2.0.dist-info/METADATA +279 -0
- processbehavior-0.2.0.dist-info/RECORD +56 -0
- processbehavior-0.2.0.dist-info/WHEEL +4 -0
- processbehavior-0.2.0.dist-info/licenses/LICENSE +201 -0
processbehavior/types.py
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"""TypedDict definitions for the chart-info payload shape.
|
|
2
|
+
|
|
3
|
+
Every entry under ``AnalysisResult.charts`` is structurally a
|
|
4
|
+
:class:`ChartPayload` — a dict carrying the chart's data, statistics,
|
|
5
|
+
metadata, and (for stratified results) its strata list. Until this
|
|
6
|
+
module existed, the shape was an informal ``dict[str, Any]``; producer
|
|
7
|
+
sites in :mod:`processbehavior.analysis` and consumer sites in
|
|
8
|
+
:mod:`processbehavior.plotting` could disagree about keys silently. The
|
|
9
|
+
strata-list bug (commit ``f938fdf``) and the Xbar dead-branch bug
|
|
10
|
+
(commit ``1444b63``) were both producer/consumer disagreements about
|
|
11
|
+
this contract.
|
|
12
|
+
|
|
13
|
+
Typing the contract lets mypy catch the next drift at edit time.
|
|
14
|
+
|
|
15
|
+
Usage
|
|
16
|
+
-----
|
|
17
|
+
At a producer site::
|
|
18
|
+
|
|
19
|
+
from processbehavior.types import ChartPayload, ChartMetadata
|
|
20
|
+
|
|
21
|
+
def _calculate_my_chart(self, ...) -> dict[str, ChartPayload]:
|
|
22
|
+
return {
|
|
23
|
+
'Xbar': ChartPayload(
|
|
24
|
+
data=df,
|
|
25
|
+
statistics={'N': 30, 'center': 100.0, 'lpl': 95.0, 'upl': 105.0},
|
|
26
|
+
metadata=ChartMetadata(chart_type='Xbar', value_col='y'),
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
At a consumer site::
|
|
31
|
+
|
|
32
|
+
from processbehavior.types import ChartPayload
|
|
33
|
+
|
|
34
|
+
def render(info: ChartPayload) -> Figure:
|
|
35
|
+
df = info['data'] # mypy: pd.DataFrame
|
|
36
|
+
stats = info['statistics'] # mypy: ChartStatistics | nested dict
|
|
37
|
+
metadata = info['metadata'] # mypy: ChartMetadata
|
|
38
|
+
...
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
from __future__ import annotations
|
|
42
|
+
|
|
43
|
+
from typing import TYPE_CHECKING, TypedDict
|
|
44
|
+
|
|
45
|
+
try: # Python 3.11+
|
|
46
|
+
from typing import NotRequired
|
|
47
|
+
except ImportError: # Python 3.9-3.10
|
|
48
|
+
from typing_extensions import NotRequired
|
|
49
|
+
|
|
50
|
+
if TYPE_CHECKING:
|
|
51
|
+
import pandas as pd
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class ChartStatistics(TypedDict):
|
|
55
|
+
"""Statistics for one chart (unstratified) or one stratum (stratified).
|
|
56
|
+
|
|
57
|
+
Every control chart (X, mR, Xbar, S) and the Histogram emit this
|
|
58
|
+
same shape from ``get_statistics()``. Histogram additionally carries
|
|
59
|
+
:class:`HistogramExtras` keys.
|
|
60
|
+
|
|
61
|
+
When the control limits and/or subgroup size vary across subgroups
|
|
62
|
+
(e.g. Xbar/S with ``n_mode='actual'`` on unbalanced data),
|
|
63
|
+
``N``, ``lpl``, and ``upl`` are ``None`` and the optional
|
|
64
|
+
``limits_vary`` flag is ``True``. ``center`` remains a single scalar.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
N: int | None
|
|
68
|
+
center: float | None
|
|
69
|
+
lpl: float | None
|
|
70
|
+
upl: float | None
|
|
71
|
+
limits_vary: NotRequired[bool]
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class HistogramExtras(TypedDict, total=False):
|
|
75
|
+
"""Additional keys present in Histogram statistics dicts.
|
|
76
|
+
|
|
77
|
+
``mean`` is an alias for :attr:`ChartStatistics.center`; ``n`` is an
|
|
78
|
+
alias for :attr:`ChartStatistics.N`. ``std`` is the sample standard
|
|
79
|
+
deviation. These keys exist for historical / convenience reasons.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
mean: float | None
|
|
83
|
+
std: float | None
|
|
84
|
+
n: int
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class ChartMetadata(TypedDict, total=False):
|
|
88
|
+
"""Per-chart metadata keys.
|
|
89
|
+
|
|
90
|
+
All keys are optional (``total=False``). Different chart variants
|
|
91
|
+
populate different subsets:
|
|
92
|
+
|
|
93
|
+
- ``chart_type`` / ``value_col`` / ``center_col``: every chart.
|
|
94
|
+
- ``stratified`` / ``stratify_col`` / ``stratify_by``: stratified
|
|
95
|
+
charts only.
|
|
96
|
+
- ``lane_boundaries``: stratified X/mR charts with collapsed factors.
|
|
97
|
+
- ``insufficient_strata``: mR/r charts that dropped first-per-stratum.
|
|
98
|
+
- ``phased`` / ``single_point_phases``: charts run with
|
|
99
|
+
``phased=True``.
|
|
100
|
+
- ``run_rules_applicable``: present on charts where Western Electric
|
|
101
|
+
rules apply (or explicitly don't).
|
|
102
|
+
- ``limits_source`` / ``calibration``: reserved for the standards-
|
|
103
|
+
given charts feature (see issue #79).
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
chart_type: str
|
|
107
|
+
value_col: str
|
|
108
|
+
center_col: str
|
|
109
|
+
stratified: bool
|
|
110
|
+
stratify_col: str | None
|
|
111
|
+
stratify_by: list[str]
|
|
112
|
+
lane_boundaries: dict[str, list[float]] | None
|
|
113
|
+
insufficient_strata: list[str] | None
|
|
114
|
+
phased: bool
|
|
115
|
+
single_point_phases: int
|
|
116
|
+
run_rules_applicable: bool
|
|
117
|
+
bins: int # Histogram only
|
|
118
|
+
focused_stratum: str # After AnalysisResult.focus()
|
|
119
|
+
stratum_display: str # Pretty-printed stratum label
|
|
120
|
+
residual_type: str # 'R1'..'R6' for residual charts
|
|
121
|
+
recentered: bool # Recentered residual charts
|
|
122
|
+
limits_source: str # 'data' | 'calibration' (issue #79)
|
|
123
|
+
calibration: dict | None # Mean/sd payload (issue #79)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
# Statistics can be flat (unstratified) or nested-by-stratum (stratified).
|
|
127
|
+
ChartStatisticsValue = ChartStatistics | dict[str, ChartStatistics]
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class ChartPayload(TypedDict):
|
|
131
|
+
"""The dict structure stored in ``AnalysisResult.charts[name]``.
|
|
132
|
+
|
|
133
|
+
Required: ``data``, ``statistics``, ``metadata``.
|
|
134
|
+
Optional: ``strata`` (present on stratified charts).
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
data: pd.DataFrame
|
|
138
|
+
statistics: ChartStatisticsValue
|
|
139
|
+
metadata: ChartMetadata
|
|
140
|
+
strata: NotRequired[list[str]]
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
# Type alias for the full charts dict on AnalysisResult.
|
|
144
|
+
Charts = dict[str, ChartPayload]
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
__all__ = [
|
|
148
|
+
'ChartStatistics',
|
|
149
|
+
'HistogramExtras',
|
|
150
|
+
'ChartMetadata',
|
|
151
|
+
'ChartStatisticsValue',
|
|
152
|
+
'ChartPayload',
|
|
153
|
+
'Charts',
|
|
154
|
+
]
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: processbehavior
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python-native Process Behavior & Control Charts (spec-driven SPC with tidy outputs)
|
|
5
|
+
Project-URL: Homepage, https://github.com/cnicholas/processbehavior
|
|
6
|
+
Project-URL: Repository, https://github.com/cnicholas/processbehavior
|
|
7
|
+
Project-URL: Issues, https://github.com/cnicholas/processbehavior/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/cnicholas/processbehavior/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Documentation, https://cnicholas.github.io/processbehavior/
|
|
10
|
+
Author: cnicholas
|
|
11
|
+
License-Expression: Apache-2.0
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: bishop-vas,control-chart,control-charts,design-of-experiments,process-behavior,process-behavior-chart,quality-control,shewhart,spc,variance-analysis,wheeler,xmr
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Manufacturing
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Requires-Dist: natsort>=8.0.0
|
|
29
|
+
Requires-Dist: numpy>=1.23
|
|
30
|
+
Requires-Dist: pandas<3,>=2.0
|
|
31
|
+
Requires-Dist: plotly<7,>=5.18
|
|
32
|
+
Requires-Dist: typing-extensions>=4.0; python_version < '3.11'
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: filelock>=3.20.3; extra == 'dev'
|
|
35
|
+
Requires-Dist: ipykernel; extra == 'dev'
|
|
36
|
+
Requires-Dist: jupyter-book>=2.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: kaleido>=0.2; extra == 'dev'
|
|
38
|
+
Requires-Dist: lxml>=6.1.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
40
|
+
Requires-Dist: nbconvert>=7.17.1; extra == 'dev'
|
|
41
|
+
Requires-Dist: nbmake>=1.5; extra == 'dev'
|
|
42
|
+
Requires-Dist: openpyxl>=3.1; extra == 'dev'
|
|
43
|
+
Requires-Dist: orjson>=3.11.6; extra == 'dev'
|
|
44
|
+
Requires-Dist: pillow>=12.2.0; extra == 'dev'
|
|
45
|
+
Requires-Dist: pre-commit>=3.7; extra == 'dev'
|
|
46
|
+
Requires-Dist: pyarrow>=14.0; extra == 'dev'
|
|
47
|
+
Requires-Dist: pygments>=2.20.0; extra == 'dev'
|
|
48
|
+
Requires-Dist: pytest-cov>=5; extra == 'dev'
|
|
49
|
+
Requires-Dist: pytest-timeout>=2.4; extra == 'dev'
|
|
50
|
+
Requires-Dist: pytest>=9.0.3; extra == 'dev'
|
|
51
|
+
Requires-Dist: requests>=2.33.0; extra == 'dev'
|
|
52
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
53
|
+
Requires-Dist: tornado>=6.5.5; extra == 'dev'
|
|
54
|
+
Requires-Dist: virtualenv>=20.36.1; extra == 'dev'
|
|
55
|
+
Provides-Extra: docs
|
|
56
|
+
Requires-Dist: ipykernel; extra == 'docs'
|
|
57
|
+
Requires-Dist: jupyter-book>=2.0; extra == 'docs'
|
|
58
|
+
Requires-Dist: lxml>=6.1.0; extra == 'docs'
|
|
59
|
+
Requires-Dist: nbconvert>=7.17.1; extra == 'docs'
|
|
60
|
+
Requires-Dist: orjson>=3.11.6; extra == 'docs'
|
|
61
|
+
Requires-Dist: pillow>=12.2.0; extra == 'docs'
|
|
62
|
+
Requires-Dist: pygments>=2.20.0; extra == 'docs'
|
|
63
|
+
Requires-Dist: requests>=2.33.0; extra == 'docs'
|
|
64
|
+
Requires-Dist: tornado>=6.5.5; extra == 'docs'
|
|
65
|
+
Provides-Extra: excel
|
|
66
|
+
Requires-Dist: openpyxl>=3.1; extra == 'excel'
|
|
67
|
+
Provides-Extra: images
|
|
68
|
+
Requires-Dist: kaleido>=0.2; extra == 'images'
|
|
69
|
+
Provides-Extra: lint
|
|
70
|
+
Requires-Dist: filelock>=3.20.3; extra == 'lint'
|
|
71
|
+
Requires-Dist: mypy>=1.10; extra == 'lint'
|
|
72
|
+
Requires-Dist: pre-commit>=3.7; extra == 'lint'
|
|
73
|
+
Requires-Dist: ruff>=0.5; extra == 'lint'
|
|
74
|
+
Requires-Dist: virtualenv>=20.36.1; extra == 'lint'
|
|
75
|
+
Provides-Extra: test
|
|
76
|
+
Requires-Dist: nbmake>=1.5; extra == 'test'
|
|
77
|
+
Requires-Dist: openpyxl>=3.1; extra == 'test'
|
|
78
|
+
Requires-Dist: pyarrow>=14.0; extra == 'test'
|
|
79
|
+
Requires-Dist: pytest-cov>=5; extra == 'test'
|
|
80
|
+
Requires-Dist: pytest-timeout>=2.4; extra == 'test'
|
|
81
|
+
Requires-Dist: pytest>=9.0.3; extra == 'test'
|
|
82
|
+
Description-Content-Type: text/markdown
|
|
83
|
+
|
|
84
|
+
# processbehavior
|
|
85
|
+
|
|
86
|
+
[](https://pypi.org/project/processbehavior/)
|
|
87
|
+
[](https://pypi.org/project/processbehavior/)
|
|
88
|
+
[](https://github.com/cnicholas/processbehavior/actions/workflows/ci.yml)
|
|
89
|
+
[](https://github.com/cnicholas/processbehavior/blob/main/LICENSE)
|
|
90
|
+
|
|
91
|
+
A Python library for **Process Behavior Analysis** following Thomas A. Bishop's Variance Analysis System (VAS) methodology.
|
|
92
|
+
|
|
93
|
+
Unlike traditional SPC packages, processbehavior faithfully implements Bishop's VAS equation-by-equation: automatic detection of the three-state design lineage (PDS / ODS / ADS), variance decomposition via R1-R6 residuals, and chart selection routed by the data your study can actually analyze.
|
|
94
|
+
|
|
95
|
+
## Installation
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pip install processbehavior
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Plotting (plotly) is included. For Excel export and static image export, install the corresponding extras:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install "processbehavior[excel]" # openpyxl, for result.to_excel(...)
|
|
105
|
+
pip install "processbehavior[images]" # kaleido, for static plot images
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Quickstart
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
import processbehavior as pb
|
|
112
|
+
|
|
113
|
+
# Generate a sample dataset (replace with your own DataFrame)
|
|
114
|
+
df = pb.make_design(state=1, seed=42)
|
|
115
|
+
# Columns: 'time', 'factor 1', 'factor 2', 'y'
|
|
116
|
+
|
|
117
|
+
# Formulate — detects PDS / ODS / ADS and builds the analysis dataset
|
|
118
|
+
study = pb.formulate(
|
|
119
|
+
df,
|
|
120
|
+
response='y',
|
|
121
|
+
time='time',
|
|
122
|
+
factors=['factor 1', 'factor 2'],
|
|
123
|
+
)
|
|
124
|
+
print(f"Observed: ODS {study.observed_design_state.sds}")
|
|
125
|
+
print(f"Analytical: ADS {study.analytical_design_state.sds}")
|
|
126
|
+
print(f"Recommended chart: {study.recommended_chart}")
|
|
127
|
+
|
|
128
|
+
# Execute analysis (routes by ADS)
|
|
129
|
+
result = study.execute() # uses the recommended chart
|
|
130
|
+
stats = result.statistics('Xbar') # always {'N', 'center', 'lpl', 'upl'}
|
|
131
|
+
print(f"Center: {stats['center']}")
|
|
132
|
+
|
|
133
|
+
# When subgroup sizes differ the limits differ per subgroup, so the scalar
|
|
134
|
+
# 'lpl'/'upl' are None and stats['limits_vary'] is True. The per-subgroup
|
|
135
|
+
# limits live in the chart table:
|
|
136
|
+
print(result.get_chart('Xbar')[['center', 'lpl', 'upl']].head())
|
|
137
|
+
|
|
138
|
+
# Plot (interactive plotly figure)
|
|
139
|
+
result.plot()
|
|
140
|
+
|
|
141
|
+
# Export to Excel (requires the [excel] extra)
|
|
142
|
+
result.to_excel('analysis.xlsx')
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The whole pipeline is one expression when you don't need the intermediate objects:
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
pb.formulate(df, response='y', factors=['factor 1'], time='time').execute().plot()
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Use `pb.ProcessBehavior(df)` directly when you want the fluent derived-variable verbs
|
|
152
|
+
(`.transform(...)`, `.bin(...)`), which attach before formulating. With that object in hand,
|
|
153
|
+
`pbd.cols.<column_name>` provides IDE auto-completion for column references.
|
|
154
|
+
|
|
155
|
+
## Key Concepts
|
|
156
|
+
|
|
157
|
+
### Two-Step Workflow
|
|
158
|
+
|
|
159
|
+
The API mirrors how analysts think:
|
|
160
|
+
|
|
161
|
+
1. **`formulate()`** - Understand your data structure. Detects PDS / ODS / ADS, identifies valid charts, and computes residuals. This is the expensive step.
|
|
162
|
+
2. **`execute()`** - Run analysis. Produces charts from the pre-computed data. This is cheap and can be called multiple times for different charts from the same study.
|
|
163
|
+
|
|
164
|
+
### Design-State Lineage (PDS / ODS / ADS)
|
|
165
|
+
|
|
166
|
+
processbehavior reports three design states at three points in the analysis lifecycle:
|
|
167
|
+
|
|
168
|
+
| State | Computed from | Codomain | Meaning |
|
|
169
|
+
|-------|---------------|----------|---------|
|
|
170
|
+
| **PDS** — Planned | Your declared `factors` and `time` (or an explicit `plan=`) | {1, 2} | What you intended to collect |
|
|
171
|
+
| **ODS** — Observed | Raw data, before NA filtering | {1..6} | What was actually collected (cells with all-NA responses count as "attempted but empty") |
|
|
172
|
+
| **ADS** — Analytical | Tidy data, after NA filtering | {0, 1, 2, 3} | What survives tidying; **drives chart selection, residual availability, and variance decomposition** |
|
|
173
|
+
|
|
174
|
+
The integer codes are Bishop's reference scale ("Bishop Table 1"):
|
|
175
|
+
|
|
176
|
+
| Code | Cell Sizes (N_kt) |
|
|
177
|
+
|------|--------------------|
|
|
178
|
+
| 1 | Complete grid, all N_kt >= 2 (full replication) |
|
|
179
|
+
| 2 | Complete grid, all N_kt = 1 (no replication) |
|
|
180
|
+
| 3 | Complete grid, mix of N_kt = 1 and N_kt >= 2 |
|
|
181
|
+
| 4 | Incomplete grid, occupied cells N_kt >= 2 |
|
|
182
|
+
| 5 | Incomplete grid, occupied cells N_kt = 1 |
|
|
183
|
+
| 6 | Incomplete grid, mixed N_kt |
|
|
184
|
+
|
|
185
|
+
ODS values in {4, 5, 6} collapse to ADS values in {1, 2, 3} during tidying (empty cells drop and the surviving subset becomes the analytical grid).
|
|
186
|
+
|
|
187
|
+
Access the lineage on a formulated study:
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
study.plan_design_state # PDS (when a plan was supplied)
|
|
191
|
+
study.observed_design_state # ODS — what the raw data showed
|
|
192
|
+
study.analytical_design_state # ADS — what the analysis is fit for
|
|
193
|
+
study.design() # DesignReport: full lineage in one object
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Residual System (R1-R6)
|
|
197
|
+
|
|
198
|
+
For factorial designs (ADS 1-3), processbehavior decomposes variation into diagnostic residuals:
|
|
199
|
+
|
|
200
|
+
- **R1** - The response centered at 0 (Bishop §13.1); the building block for the rest
|
|
201
|
+
- **R2** - Within-cell noise (measurement error, short-term fluctuation)
|
|
202
|
+
- **R3** - Interaction between design conditions and time
|
|
203
|
+
- **R4** - Time main effects (trends, seasonality, batch effects)
|
|
204
|
+
- **R5** - Design condition main effects, all factors combined
|
|
205
|
+
- **R6** - A single design factor's main effect (machine-to-machine, operator bias)
|
|
206
|
+
|
|
207
|
+
```python
|
|
208
|
+
# Chart any residual
|
|
209
|
+
result = study.execute(chart='Xbar', value='R4') # Time main effects
|
|
210
|
+
result = study.execute(chart='Xbar', value='R5') # Design condition main effects
|
|
211
|
+
result = study.execute(chart='Xbar', value='R6', by=['machine']) # One factor's effect
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Not every chart pairs with every residual — the valid pairs depend on the ADS.
|
|
215
|
+
`study.residual_charts` lists them, and `study.why_not('X', value='R4')` explains
|
|
216
|
+
any pair it refuses.
|
|
217
|
+
|
|
218
|
+
### Stratified Analysis
|
|
219
|
+
|
|
220
|
+
For X/mR charts with grouping factors, processbehavior produces a single combined chart with per-stratum limits:
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
result = study.execute(chart='X', by=['machine'])
|
|
224
|
+
|
|
225
|
+
# Drill into a specific stratum
|
|
226
|
+
for stratum in result.strata:
|
|
227
|
+
focused = result.focus(stratum)
|
|
228
|
+
focused.plot()
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Validation
|
|
232
|
+
|
|
233
|
+
processbehavior's analytical outputs are continuously verified against Dr. Thomas A. Bishop's Minitab reference results. The validator at `validation/e2e_bishop_report.py` runs **280 numerical assertions** through the full formulate → execute → capability / loss / maximum-information pipeline:
|
|
234
|
+
|
|
235
|
+
| Analytical Design State | Datasets validated | Assertions | Status |
|
|
236
|
+
|---|---|---|---|
|
|
237
|
+
| ADS 1 (full replication) | `PM SDS 1` from `PBTESTDATABASE_T100.csv` | 102 | ✅ all pass |
|
|
238
|
+
| ADS 2 (no replication) | `PM SDS 2` | 89 | ✅ all pass |
|
|
239
|
+
| ADS 3 (partial replication) | `PM SDS 3` | 89 | ✅ all pass |
|
|
240
|
+
|
|
241
|
+
Reference data is Bishop's published Minitab golden output. The library matches every chart center, control limit, signal classification, capability index, and loss-function value to within the precision Bishop reports.
|
|
242
|
+
|
|
243
|
+
ODS 4–6 (incomplete-grid scenarios) are detected and routed correctly but their end-to-end Bishop-reference coverage is pending. The synthetic generators in `make_design(state=4|5|6)` produce data with the structural shape Bishop's Table 1 specifies; full numerical validation against Bishop's incomplete-grid Minitab output is on the roadmap (issue #109).
|
|
244
|
+
|
|
245
|
+
The full report renders to `validation/e2e_bishop_report.html`.
|
|
246
|
+
|
|
247
|
+
## Features
|
|
248
|
+
|
|
249
|
+
- **Three-state lineage**: PDS / ODS / ADS detected automatically; chart selection routes by ADS
|
|
250
|
+
- **Correct charts**: Xbar-S, X (Individual), mR (Moving Range), Histogram with proper limit calculations
|
|
251
|
+
- **Variance decomposition**: R1-R6 residuals for factorial designs
|
|
252
|
+
- **Effects analysis**: Main effects, time effects, and interaction effects
|
|
253
|
+
- **Stratified charts**: Automatic per-stratum limits for grouped individual data
|
|
254
|
+
- **Signal detection**: all eight Western Electric rules on X/mR; Rule 1 (3-sigma) on Xbar/S, where the run- and zone-based rules need a time order that subgroup comparisons don't have
|
|
255
|
+
- **Beyond the charts**: capability indices (Cp/Cpk/Pp/Ppk), Taguchi loss decomposition, and maximum-information analysis — validated in the same Bishop-reference CI gate
|
|
256
|
+
- **IDE support**: Column auto-completion via `ProcessBehavior(df).cols`
|
|
257
|
+
- **Self-diagnostic errors**: Helpful messages that say what's available and how to fix it
|
|
258
|
+
- **Excel export**: Publication-ready workbooks with charts and statistics
|
|
259
|
+
- **Interactive plots**: Plotly-based charts with hover details
|
|
260
|
+
|
|
261
|
+
## Scope
|
|
262
|
+
|
|
263
|
+
processbehavior is the **computational engine** for Bishop's VAS methodology. It handles data ingestion, design-state lineage detection (PDS / ODS / ADS), residual computation, chart generation, and export.
|
|
264
|
+
|
|
265
|
+
For the **curated analyst experience** — guided workflows, interactive dashboards, and collaboration features — see [processbehavior.com](https://processbehavior.com).
|
|
266
|
+
|
|
267
|
+
For the **methodological foundation** — the theory behind VAS, design-state classification, and residual interpretation — see Bishop's published book below and the forthcoming book by Dr. Thomas A. Bishop and Chris Nicholas.
|
|
268
|
+
|
|
269
|
+
## References
|
|
270
|
+
|
|
271
|
+
The methodology this library implements:
|
|
272
|
+
|
|
273
|
+
> Bishop, Thomas A. (2021). *[The Scientific Basis for Modern Analytic Practice](https://www.lulu.com/shop/thomas-bishop/the-scientific-basis-for-modern-analytic-practice/paperback/product-k7e8dk.html)*. Lulu Press. 279 pp.
|
|
274
|
+
|
|
275
|
+
To cite the software itself, see [`CITATION.cff`](CITATION.cff).
|
|
276
|
+
|
|
277
|
+
## License
|
|
278
|
+
|
|
279
|
+
Apache 2.0
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
processbehavior/__init__.py,sha256=t0ESK8AXsRqRavP_7hZqD6Has5jIAX21sS90t5EFgeU,4097
|
|
2
|
+
processbehavior/analysis.py,sha256=huEz6DxbAqgduuVYZKnijnJtrhLkvqmtOYClZX3iIJo,117738
|
|
3
|
+
processbehavior/analysis_dataset.py,sha256=YBAKCh87dU9xNh89q33YVeZ_rT3bHG3iO6J1zhgyoH4,15040
|
|
4
|
+
processbehavior/analysis_result.py,sha256=TCAOFT8De6wjIxALirIqbPFsnwgm6E1rDYQeLHCJjqI,46141
|
|
5
|
+
processbehavior/calibration.py,sha256=0vZ6XxezPjk8hfDNf8p4TBt5XynnceSFMEH-F_REWpI,2841
|
|
6
|
+
processbehavior/capability.py,sha256=xlPnPxhrzlKpRbi_ikTzvEPF5ceLjce9tgAlx5-ZzUw,24639
|
|
7
|
+
processbehavior/data_preparation.py,sha256=XOBi3Kpdq_h2-pSHl5YhZyE57BCAVYv--hQN7DioILo,30808
|
|
8
|
+
processbehavior/derivations.py,sha256=YJSy97GqR7khjlv4TU8TOAfr5K97NHbXm0LgvSt_3Oo,23684
|
|
9
|
+
processbehavior/effects_calculator.py,sha256=D75tEY5IprLHUfgQpMAJT_zcqn9w7bVTLTvS8kzV_Mw,19234
|
|
10
|
+
processbehavior/exceptions.py,sha256=Xxe_CMGcl7-B7tqfCpzrSc72RgixBTeXYK181-8arBg,6944
|
|
11
|
+
processbehavior/focused_result.py,sha256=0IAUXvp1iD_uQy_ol4LnxeYu9yGO67IWsUYwLJdpHFE,12637
|
|
12
|
+
processbehavior/formulation_spec.py,sha256=rnwxpy5Ms10NDuQbim4GUtsmjkdhaWMC_TzYT7T-nbw,4725
|
|
13
|
+
processbehavior/loss_function.py,sha256=2z-xvE1UomxSRdh3HQ01D2_GC_cSAr9HkquVKkuEO04,16621
|
|
14
|
+
processbehavior/maximum_information.py,sha256=UWj_Nw34XN1CuUF8OwbrbykSRtaz_aSL4EXoiRxs_Vo,7964
|
|
15
|
+
processbehavior/process_behavior.py,sha256=YV_XJtZyUQZw9Y5wBa5CXAGpDr9wvbkHOEr3W0fYm24,51327
|
|
16
|
+
processbehavior/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
processbehavior/residual_calculator.py,sha256=OlBq3717rHANeb_AsiZXYu1rFRbBnXatO1RAyrtoN64,18546
|
|
18
|
+
processbehavior/result_signals.py,sha256=i4FI5VWkVREU-tEzX-JVoDinpf009MKq41GwALUnMPM,5000
|
|
19
|
+
processbehavior/result_tabular.py,sha256=DQdvAqEjTY8v4cSP3xpeLcczL9DH32wW7s99qfnPe8c,10796
|
|
20
|
+
processbehavior/sds_detector.py,sha256=BE5k9KDgNd-IMTFbTPOqt-Ln4kRLzyo5FyApjAWQr8k,55861
|
|
21
|
+
processbehavior/spc_constants.py,sha256=puWrLDe9FrLnBqAKbzPHM8uDv4TZUySj1F_aIHQWjkU,24498
|
|
22
|
+
processbehavior/study.py,sha256=ZpjMrCzM68d6ha1ZxcZgNAFyJQ-5ErlcYTqj_bE7mJo,107611
|
|
23
|
+
processbehavior/types.py,sha256=WjDDSQMrH6SzZfQwgXIWdvpb823DXQ_HsTQz_8Sw-g4,5015
|
|
24
|
+
processbehavior/datasets/__init__.py,sha256=tRHsamUxYQU1lbFQSynPO3e7dBOmeOrRJdNrzB1OMTw,694
|
|
25
|
+
processbehavior/datasets/loaders.py,sha256=9HuK2kdbjYWFtaZG5xhRXhUQqoVR3Y6XAZgl7CJ0_vg,2945
|
|
26
|
+
processbehavior/datasets/synthetic.py,sha256=tt6Cq66yHz8YSqzZK5U_6qrN69YLuc1vWLjgxpeuS54,63910
|
|
27
|
+
processbehavior/datasets/data/coffee_shop_demo_long.csv,sha256=0NdPqhs_TqodFoCYKCICprpuDwv9yNw_c0aUWDi6EHM,15486
|
|
28
|
+
processbehavior/exporters/__init__.py,sha256=Mqr4EaLtz7ILkMUijZ19uxa8indyiR-fwCxh6ZHhwus,110
|
|
29
|
+
processbehavior/exporters/excel_exporter.py,sha256=W060uld632sAGXZwtMYAyu_i6ysock18T2YGzWHoGHw,29884
|
|
30
|
+
processbehavior/plotting/__init__.py,sha256=b0qEpYUIZFNXY8wX1MXZN5Lq_Gt2PnIQPdkfy6OlcgA,1506
|
|
31
|
+
processbehavior/plotting/_math.py,sha256=jAnMadBVt58L5LnYN96ZDLUnEv8TjFnYCFz3aIaxgOU,3311
|
|
32
|
+
processbehavior/plotting/capability_chart.py,sha256=BXQ_yNBb03z65Ar6a9T1G-zOvruelZcLhAmVSePI7lE,27572
|
|
33
|
+
processbehavior/plotting/contracts.py,sha256=D5PF3GLCp8K8y9FQbo8etVK7HsngsxdqiVoOJ46FSBE,5130
|
|
34
|
+
processbehavior/plotting/control_chart.py,sha256=0y1QY18K3wKXXiETSjiFpSpiwt6nISuOd1q6tN-JycY,7455
|
|
35
|
+
processbehavior/plotting/effects_charts.py,sha256=DPH_frTjp9w-bugeKQrMLwee1hjWBXHmCGr1Qt8aKfs,19495
|
|
36
|
+
processbehavior/plotting/lane_boundaries.py,sha256=AkiDB2FWYfFfgkN-dxEIWijSNnzBIiwKHnqV-ODHe_E,2309
|
|
37
|
+
processbehavior/plotting/limits.py,sha256=2Fu6qTV3-7GedDeR_sXxA4SRvw-5RwMi40ud5PWhxv0,4211
|
|
38
|
+
processbehavior/plotting/maximum_information_chart.py,sha256=vCfgnyZkN8pG_K0t_xiYAxX6i40tFpuu5a8kYM0em_0,11157
|
|
39
|
+
processbehavior/plotting/plotter.py,sha256=PUO8L-lK-Lr7Ys8RhITgW666LcM2tEC7hzHVZa82hgQ,52853
|
|
40
|
+
processbehavior/plotting/renderers.py,sha256=l-5fKgBYyOkZbDcin_VglhhnO9oZ2qZ0FcLznXcXOik,20651
|
|
41
|
+
processbehavior/plotting/report.py,sha256=y3d0Zwfr1p9w1Dm02KV1-qhKcV6GeUJi8VhCzGukaw8,6725
|
|
42
|
+
processbehavior/plotting/residuals.py,sha256=4V2oBFV8yi1H2kpoC0irouOQNvE2mHQNd828b3cKg2Q,8573
|
|
43
|
+
processbehavior/plotting/run_rules_viz.py,sha256=gsAMIql9-fXp4VxDthB8V1pEBlGm3N63GBy5wH9__AE,4428
|
|
44
|
+
processbehavior/plotting/stats_box.py,sha256=tuJZkMh6KFkfRX7WdLM76O-dw-QuxHxBuQia5qot-1E,5450
|
|
45
|
+
processbehavior/plotting/themes.py,sha256=z1Pvxvfb28ZB1Wcvu98mRYvR7QvAetqGdL7URBzN1lc,16090
|
|
46
|
+
processbehavior/plotting/x_axis_layout.py,sha256=B3TG65vndWPqaNLJKjxkZgxRXJE86I9_BbKgvRuWZj8,17310
|
|
47
|
+
processbehavior/plotting/zones.py,sha256=i7bHGkPT6rGV4z3xn8Pmm3pUdEHQDJayYM5OeD7tD_E,3793
|
|
48
|
+
processbehavior/signals/__init__.py,sha256=CK07shlXxUFUzeo57qIiyMxGgi72Sq87sN3pOWbOYTU,430
|
|
49
|
+
processbehavior/signals/config.py,sha256=x2enUInz9_n_-1F5lAuJExQEr_m1iNlEHGWEpl1P0x4,12728
|
|
50
|
+
processbehavior/signals/detector.py,sha256=nMQ1EMs1C2uNQRS-v1Y174QBGBW2cO-Z1a-Oxx4rNsY,12097
|
|
51
|
+
processbehavior/signals/detectors.py,sha256=ia-LHfS4fKkN4DZ2kZBvc_Z04em-FoVGu9xB09VuMVU,10203
|
|
52
|
+
processbehavior/signals/result.py,sha256=wN2PIG_ASYFvLQlPrDwujm9lBfWWRsLSLfTyzEgeCIc,6875
|
|
53
|
+
processbehavior-0.2.0.dist-info/METADATA,sha256=hsrVC4c1DwG5qbfjm5REhUhXor-YN-zEEMBgCKwPrjA,13388
|
|
54
|
+
processbehavior-0.2.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
55
|
+
processbehavior-0.2.0.dist-info/licenses/LICENSE,sha256=GgI9nWoMCj2vWn2iisJHcHK_uYHWZ76s9jRsedoO_Wc,11281
|
|
56
|
+
processbehavior-0.2.0.dist-info/RECORD,,
|