abspc 0.2.1__tar.gz
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.
- abspc-0.2.1/LICENSE +21 -0
- abspc-0.2.1/MANIFEST.in +5 -0
- abspc-0.2.1/PKG-INFO +571 -0
- abspc-0.2.1/README.md +230 -0
- abspc-0.2.1/abspc/README.md +514 -0
- abspc-0.2.1/abspc/__init__.py +58 -0
- abspc-0.2.1/abspc/icons/assurance_fail.png +0 -0
- abspc-0.2.1/abspc/icons/assurance_hit_or_miss.png +0 -0
- abspc-0.2.1/abspc/icons/assurance_pass.png +0 -0
- abspc-0.2.1/abspc/icons/icon_empty.png +0 -0
- abspc-0.2.1/abspc/icons/improvement_direction_high.png +0 -0
- abspc-0.2.1/abspc/icons/improvement_direction_low.png +0 -0
- abspc-0.2.1/abspc/icons/variation_common_cause.png +0 -0
- abspc-0.2.1/abspc/icons/variation_concern_high.png +0 -0
- abspc-0.2.1/abspc/icons/variation_concern_low.png +0 -0
- abspc-0.2.1/abspc/icons/variation_improvement_high.png +0 -0
- abspc-0.2.1/abspc/icons/variation_improvement_low.png +0 -0
- abspc-0.2.1/abspc/plot.py +1193 -0
- abspc-0.2.1/abspc/spc.py +1230 -0
- abspc-0.2.1/abspc/utils.py +484 -0
- abspc-0.2.1/abspc.egg-info/PKG-INFO +571 -0
- abspc-0.2.1/abspc.egg-info/SOURCES.txt +30 -0
- abspc-0.2.1/abspc.egg-info/dependency_links.txt +1 -0
- abspc-0.2.1/abspc.egg-info/requires.txt +9 -0
- abspc-0.2.1/abspc.egg-info/top_level.txt +1 -0
- abspc-0.2.1/pyproject.toml +58 -0
- abspc-0.2.1/setup.cfg +4 -0
- abspc-0.2.1/setup.py +32 -0
- abspc-0.2.1/tests/test_plot.py +594 -0
- abspc-0.2.1/tests/test_spc.py +653 -0
- abspc-0.2.1/tests/test_summary.py +60 -0
- abspc-0.2.1/tests/test_utils.py +302 -0
abspc-0.2.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Aneurin Bevan University Health Board
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
abspc-0.2.1/MANIFEST.in
ADDED
abspc-0.2.1/PKG-INFO
ADDED
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: abspc
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: SPC chart visuals using the NHS Making Data Count methodology — Python, Looker & Looker Studio
|
|
5
|
+
Author: Aneurin Bevan University Health Board
|
|
6
|
+
Author-email: Daniel Westwood <daniel.westwood@wales.nhs.uk>
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2024-2026 Aneurin Bevan University Health Board
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
|
|
29
|
+
Project-URL: Documentation, https://github.com/Aneurin-Bevan-University-Health-Board/biu_Making_Data_Count_CustomVisuals#readme
|
|
30
|
+
Project-URL: Issues, https://github.com/Aneurin-Bevan-University-Health-Board/biu_Making_Data_Count_CustomVisuals/issues
|
|
31
|
+
Project-URL: Homepage, https://github.com/Aneurin-Bevan-University-Health-Board/biu_Making_Data_Count_CustomVisuals
|
|
32
|
+
Project-URL: Repository, https://github.com/Aneurin-Bevan-University-Health-Board/biu_Making_Data_Count_CustomVisuals
|
|
33
|
+
Keywords: spc,statistical process control,nhs,making data count,quality improvement,looker,looker studio
|
|
34
|
+
Classifier: Development Status :: 3 - Alpha
|
|
35
|
+
Classifier: Intended Audience :: Healthcare Industry
|
|
36
|
+
Classifier: Intended Audience :: Science/Research
|
|
37
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
38
|
+
Classifier: Programming Language :: Python :: 3
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
43
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
44
|
+
Requires-Python: >=3.9
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
License-File: LICENSE
|
|
47
|
+
Requires-Dist: numpy>=1.23
|
|
48
|
+
Requires-Dist: pandas>=1.5
|
|
49
|
+
Requires-Dist: matplotlib>=3.6
|
|
50
|
+
Provides-Extra: dev
|
|
51
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
52
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
53
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
54
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
55
|
+
Dynamic: license-file
|
|
56
|
+
Dynamic: requires-python
|
|
57
|
+
|
|
58
|
+
# abspc — Python SPC Charts
|
|
59
|
+
|
|
60
|
+
The `abspc` Python package provides publication-ready Statistical Process
|
|
61
|
+
Control (SPC) charts following the NHS
|
|
62
|
+
[Making Data Count](https://www.england.nhs.uk/publication/making-data-count/)
|
|
63
|
+
methodology.
|
|
64
|
+
|
|
65
|
+
Built on **matplotlib**, it produces high-quality static images suitable for
|
|
66
|
+
board reports, dashboards, and quality-improvement publications.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Installation
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
pip install abspc
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Or install the development version from source:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
git clone https://github.com/Aneurin-Bevan-University-Health-Board/biu_Making_Data_Count_CustomVisuals
|
|
80
|
+
cd biu_Making_Data_Count_CustomVisuals
|
|
81
|
+
pip install -e ".[dev]"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Quick Start
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
import pandas as pd
|
|
90
|
+
from abspc import plot_spc_chart, plot_run_chart
|
|
91
|
+
|
|
92
|
+
# Minimal XmR chart
|
|
93
|
+
data = pd.DataFrame({"value": [48, 52, 49, 55, 47, 51, 53, 50, 48, 54]})
|
|
94
|
+
fig, ax = plot_spc_chart(data, chart_type="XmR")
|
|
95
|
+
fig.savefig("my_xmr_chart.png")
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Chart Types
|
|
101
|
+
|
|
102
|
+
### XmR Chart
|
|
103
|
+
|
|
104
|
+
The XmR (individuals / moving-range) chart is the most common SPC chart type.
|
|
105
|
+
It is suitable for individual measurements collected over time.
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
import numpy as np
|
|
109
|
+
import pandas as pd
|
|
110
|
+
from abspc import plot_spc_chart
|
|
111
|
+
|
|
112
|
+
data = pd.DataFrame({"value": np.random.normal(50, 3, 24)})
|
|
113
|
+
|
|
114
|
+
fig, ax = plot_spc_chart(
|
|
115
|
+
data,
|
|
116
|
+
chart_type="XmR",
|
|
117
|
+
title="XmR Chart – Individual Measurements",
|
|
118
|
+
xlabel="Month",
|
|
119
|
+
ylabel="Value",
|
|
120
|
+
shade_band=True,
|
|
121
|
+
improvement_direction="high",
|
|
122
|
+
)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+

|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
### p Chart
|
|
130
|
+
|
|
131
|
+
The p chart is for proportion data (e.g., percentage of patients waiting
|
|
132
|
+
> 4 hours). It requires a `subgroup_size` column containing the denominator.
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
data = pd.DataFrame({
|
|
136
|
+
"value": [0.10, 0.12, 0.08, 0.15, 0.09, 0.11, 0.10, 0.13, 0.07, 0.12,
|
|
137
|
+
0.09, 0.11, 0.10, 0.08, 0.14, 0.12, 0.09, 0.11, 0.08, 0.10,
|
|
138
|
+
0.12, 0.09, 0.11, 0.10],
|
|
139
|
+
"subgroup_size": [200] * 24,
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
fig, ax = plot_spc_chart(
|
|
143
|
+
data,
|
|
144
|
+
chart_type="p",
|
|
145
|
+
title="p Chart – Proportion",
|
|
146
|
+
xlabel="Month",
|
|
147
|
+
ylabel="Proportion",
|
|
148
|
+
improvement_direction="low",
|
|
149
|
+
)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+

|
|
153
|
+
|
|
154
|
+
You can also pass a **numerator column** and a **denominator column**:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
data = pd.DataFrame({
|
|
158
|
+
"events": [20, 24, 16, 30, 18],
|
|
159
|
+
"population": [200, 200, 200, 200, 200],
|
|
160
|
+
})
|
|
161
|
+
fig, ax = plot_spc_chart(
|
|
162
|
+
data,
|
|
163
|
+
chart_type="p",
|
|
164
|
+
value_col="population",
|
|
165
|
+
numerator_col="events",
|
|
166
|
+
improvement_direction="low",
|
|
167
|
+
)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### c Chart
|
|
173
|
+
|
|
174
|
+
The c chart is for counts of events in a fixed sample size (e.g., adverse
|
|
175
|
+
events per ward per month).
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
data = pd.DataFrame({"value": [3, 5, 2, 6, 4, 3, 7, 5, 4, 6,
|
|
179
|
+
5, 3, 4, 6, 5, 4, 3, 5, 6, 4,
|
|
180
|
+
3, 5, 4, 6]})
|
|
181
|
+
|
|
182
|
+
fig, ax = plot_spc_chart(
|
|
183
|
+
data,
|
|
184
|
+
chart_type="c",
|
|
185
|
+
title="c Chart – Count of Events",
|
|
186
|
+
xlabel="Month",
|
|
187
|
+
ylabel="Count",
|
|
188
|
+
improvement_direction="low",
|
|
189
|
+
)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+

|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### Run Chart
|
|
197
|
+
|
|
198
|
+
The run chart plots data against time with a **median** centre line and no
|
|
199
|
+
control limits. It uses run-chart rules to detect signals (8-point shift and
|
|
200
|
+
6-point trend).
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from abspc import plot_run_chart
|
|
204
|
+
|
|
205
|
+
data = pd.DataFrame({"value": np.random.normal(40, 4, 24)})
|
|
206
|
+
|
|
207
|
+
fig, ax = plot_run_chart(
|
|
208
|
+
data,
|
|
209
|
+
title="Run Chart – Median Centre Line",
|
|
210
|
+
xlabel="Month",
|
|
211
|
+
ylabel="Value",
|
|
212
|
+
improvement_direction="high",
|
|
213
|
+
)
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+

|
|
217
|
+
|
|
218
|
+
`plot_spc_chart` also accepts `chart_type="run"` and will automatically
|
|
219
|
+
delegate to `plot_run_chart`:
|
|
220
|
+
|
|
221
|
+
```python
|
|
222
|
+
fig, ax = plot_spc_chart(data, chart_type="run")
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Features
|
|
228
|
+
|
|
229
|
+
### Logo Placement
|
|
230
|
+
|
|
231
|
+
Pass any image (PNG, JPEG, etc.) via `logo_path` to display your
|
|
232
|
+
organisation's logo at the **top-right of the chart, level with the title**.
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
fig, ax = plot_spc_chart(
|
|
236
|
+
data,
|
|
237
|
+
chart_type="XmR",
|
|
238
|
+
title="A&E 4-Hour Waits – Aneurin Bevan UHB",
|
|
239
|
+
logo_path="path/to/logo.png",
|
|
240
|
+
logo_zoom=0.08,
|
|
241
|
+
)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+

|
|
245
|
+
|
|
246
|
+
> **Note:** `logo_path` places the logo in the title margin (top-right).
|
|
247
|
+
> The legacy `nhs_logo_path` parameter places an image inside the plot area.
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
### Date Axis
|
|
252
|
+
|
|
253
|
+
All chart functions automatically detect datetime data on the x-axis and
|
|
254
|
+
apply smart date tick formatting.
|
|
255
|
+
|
|
256
|
+
**Option 1 — `DatetimeIndex` (auto-detected):**
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
dates = pd.date_range("2022-01-01", periods=30, freq="MS")
|
|
260
|
+
data = pd.DataFrame({"value": np.random.normal(75, 6, 30)}, index=dates)
|
|
261
|
+
|
|
262
|
+
fig, ax = plot_spc_chart(data, chart_type="XmR", title="Monthly Date Axis")
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+

|
|
266
|
+
|
|
267
|
+
**Option 2 — Explicit date column:**
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
fig, ax = plot_run_chart(data, x_col="period", date_format="%b %Y")
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
| `date_format` | Example output |
|
|
274
|
+
|---------------|----------------|
|
|
275
|
+
| `"%b %Y"` | Jan 2024 |
|
|
276
|
+
| `"%Y-%m"` | 2024-01 |
|
|
277
|
+
| `"%d/%m/%Y"` | 01/01/2024 |
|
|
278
|
+
| `None` *(default)* | Auto (ConciseDateFormatter) |
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
### Change-Point Annotations
|
|
283
|
+
|
|
284
|
+
Mark known process changes with vertical lines and labels:
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
fig, ax = plot_spc_chart(
|
|
288
|
+
data,
|
|
289
|
+
chart_type="XmR",
|
|
290
|
+
change_points=[
|
|
291
|
+
{"x": 9, "label": "New protocol"},
|
|
292
|
+
{"x": 20, "label": "Staff training"},
|
|
293
|
+
],
|
|
294
|
+
)
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+

|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
### Auto-Rebase on Sustained Improvement
|
|
302
|
+
|
|
303
|
+
When ≥ 8 consecutive points show sustained improvement, control limits can be
|
|
304
|
+
automatically recalculated for the new phase:
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
fig, ax = plot_spc_chart(
|
|
308
|
+
data,
|
|
309
|
+
chart_type="XmR",
|
|
310
|
+
improvement_direction="high",
|
|
311
|
+
auto_rebase=True,
|
|
312
|
+
)
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+

|
|
316
|
+
|
|
317
|
+
Use `rebase_control_limits` for programmatic access without plotting:
|
|
318
|
+
|
|
319
|
+
```python
|
|
320
|
+
from abspc import rebase_control_limits
|
|
321
|
+
|
|
322
|
+
result = rebase_control_limits(data, chart_type="XmR", improvement_direction="high")
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
> Auto-rebase is supported for XmR, p, u, and c charts (not run charts).
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
### MDC Variation & Assurance Icons
|
|
330
|
+
|
|
331
|
+
Set `show_icons=True` to display the official Making Data Count variation and
|
|
332
|
+
assurance icons at the top-left of the chart:
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
fig, ax = plot_spc_chart(
|
|
336
|
+
data,
|
|
337
|
+
chart_type="XmR",
|
|
338
|
+
improvement_direction="high",
|
|
339
|
+
target=60,
|
|
340
|
+
show_target=True,
|
|
341
|
+
show_icons=True,
|
|
342
|
+
)
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
**Programmatic access:**
|
|
346
|
+
|
|
347
|
+
```python
|
|
348
|
+
from abspc import (
|
|
349
|
+
calculate_control_limits,
|
|
350
|
+
detect_special_causes,
|
|
351
|
+
determine_variation_type,
|
|
352
|
+
determine_assurance_type,
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
result = detect_special_causes(calculate_control_limits(data, chart_type="XmR"))
|
|
356
|
+
variation = determine_variation_type(result, value_col="value", improvement_direction="high")
|
|
357
|
+
assurance = determine_assurance_type(result, target=60, improvement_direction="high")
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
> For run charts only the variation icon is shown (no control limits means
|
|
361
|
+
> assurance cannot be calculated).
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
### MDC Summary Table
|
|
366
|
+
|
|
367
|
+
`plot_mdc_summary_table` renders an NHS MDC-style summary table showing
|
|
368
|
+
multiple measures at a glance:
|
|
369
|
+
|
|
370
|
+
```python
|
|
371
|
+
from abspc import plot_mdc_summary_table
|
|
372
|
+
|
|
373
|
+
fig, ax = plot_mdc_summary_table(
|
|
374
|
+
[
|
|
375
|
+
{
|
|
376
|
+
"data": df,
|
|
377
|
+
"chart_type": "XmR",
|
|
378
|
+
"measure": "A&E 4-Hour Waits",
|
|
379
|
+
"description": "% patients seen within 4 hours",
|
|
380
|
+
"value_col": "value",
|
|
381
|
+
"improvement_direction": "high",
|
|
382
|
+
"target": 95,
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
"data": df_infections,
|
|
386
|
+
"chart_type": "p",
|
|
387
|
+
"measure": "Infection Rate",
|
|
388
|
+
"description": "Proportion of infections per month",
|
|
389
|
+
"value_col": "value",
|
|
390
|
+
"improvement_direction": "low",
|
|
391
|
+
"target": 0.05,
|
|
392
|
+
"subgroup_col": "subgroup_size",
|
|
393
|
+
},
|
|
394
|
+
],
|
|
395
|
+
title="MDC Summary — Board Report",
|
|
396
|
+
)
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## Special-Cause Rules
|
|
402
|
+
|
|
403
|
+
Four NHS MDC rules (aligned with NHSRplotthedots):
|
|
404
|
+
|
|
405
|
+
| Rule | Name | Description |
|
|
406
|
+
|------|------|-------------|
|
|
407
|
+
| **1** | Astronomical point | Single value outside 3σ limits |
|
|
408
|
+
| **2** | Shift | ≥ 8 consecutive points above or below the mean |
|
|
409
|
+
| **3** | Trend | ≥ 6 consecutive points all rising or all falling |
|
|
410
|
+
| **4** | Two-in-three | 2 of 3 consecutive points in the warning zone |
|
|
411
|
+
|
|
412
|
+
Use the detection functions directly:
|
|
413
|
+
|
|
414
|
+
```python
|
|
415
|
+
from abspc import calculate_control_limits, detect_special_causes
|
|
416
|
+
|
|
417
|
+
result = calculate_control_limits(data, chart_type="XmR")
|
|
418
|
+
flags = detect_special_causes(result)
|
|
419
|
+
print(flags[["value", "mean", "ucl", "lcl", "rule1", "rule2", "rule3", "rule4", "special_cause"]])
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## API Reference
|
|
425
|
+
|
|
426
|
+
### `plot_spc_chart`
|
|
427
|
+
|
|
428
|
+
```python
|
|
429
|
+
fig, ax = plot_spc_chart(
|
|
430
|
+
data,
|
|
431
|
+
chart_type, # "XmR" | "p" | "u" | "c" | "run"
|
|
432
|
+
value_col="value",
|
|
433
|
+
subgroup_col="subgroup_size",
|
|
434
|
+
numerator_col=None,
|
|
435
|
+
x_col=None,
|
|
436
|
+
title=None,
|
|
437
|
+
xlabel="Observation",
|
|
438
|
+
ylabel="Value",
|
|
439
|
+
improvement_direction="high",
|
|
440
|
+
target=None,
|
|
441
|
+
show_target=False,
|
|
442
|
+
shade_band=False,
|
|
443
|
+
shade_color="#41B6E6",
|
|
444
|
+
nhs_logo_path=None,
|
|
445
|
+
ax=None,
|
|
446
|
+
figsize=(12, 5),
|
|
447
|
+
show_legend=True,
|
|
448
|
+
change_points=None,
|
|
449
|
+
auto_rebase=False,
|
|
450
|
+
date_format=None,
|
|
451
|
+
logo_path=None,
|
|
452
|
+
logo_zoom=0.07,
|
|
453
|
+
show_icons=False,
|
|
454
|
+
icon_zoom=0.06,
|
|
455
|
+
)
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
| Parameter | Type | Default | Description |
|
|
459
|
+
|-----------|------|---------|-------------|
|
|
460
|
+
| `data` | `pd.DataFrame` | *(required)* | Input DataFrame with at least the `value_col` column. |
|
|
461
|
+
| `chart_type` | `str` | *(required)* | `"XmR"`, `"p"`, `"u"`, `"c"`, or `"run"` (case-insensitive). |
|
|
462
|
+
| `value_col` | `str` | `"value"` | Column containing the measured values. |
|
|
463
|
+
| `subgroup_col` | `str \| None` | `"subgroup_size"` | Column with subgroup sizes. Required for `"p"` and `"u"`. |
|
|
464
|
+
| `numerator_col` | `str \| None` | `None` | For `"p"` charts: column with event counts when `value_col` holds the denominator. |
|
|
465
|
+
| `x_col` | `str \| None` | `None` | Column for the x-axis. Auto-detects `DatetimeIndex` if `None`. |
|
|
466
|
+
| `title` | `str \| None` | `None` | Chart title. Auto-generated if omitted. |
|
|
467
|
+
| `xlabel` | `str` | `"Observation"` | X-axis label. |
|
|
468
|
+
| `ylabel` | `str` | `"Value"` | Y-axis label. |
|
|
469
|
+
| `improvement_direction` | `str` | `"high"` | `"high"` or `"low"`. Controls point colouring. |
|
|
470
|
+
| `target` | `float \| None` | `None` | Optional target value for the target line and assurance calculation. |
|
|
471
|
+
| `show_target` | `bool` | `False` | Draw a dashed target line at `target`. |
|
|
472
|
+
| `shade_band` | `bool` | `False` | Fill between UCL and LCL with a translucent band. |
|
|
473
|
+
| `shade_color` | `str` | `"#41B6E6"` | Colour for tolerance-band shading. |
|
|
474
|
+
| `nhs_logo_path` | `str \| None` | `None` | Logo inside the axes (legacy). Use `logo_path` instead. |
|
|
475
|
+
| `ax` | `Axes \| None` | `None` | Existing axes to draw on. Creates a new figure when `None`. |
|
|
476
|
+
| `figsize` | `tuple` | `(12, 5)` | Figure size in inches. Ignored when `ax` is provided. |
|
|
477
|
+
| `show_legend` | `bool` | `True` | Add a colour legend. |
|
|
478
|
+
| `change_points` | `list[dict] \| None` | `None` | Vertical annotation lines. Each dict needs `"x"` and `"label"`. |
|
|
479
|
+
| `auto_rebase` | `bool` | `False` | Auto-detect sustained improvement and recalculate limits. |
|
|
480
|
+
| `date_format` | `str \| None` | `None` | `strftime`-style format for datetime x-axis. |
|
|
481
|
+
| `logo_path` | `str \| None` | `None` | Logo image at top-right of figure. |
|
|
482
|
+
| `logo_zoom` | `float` | `0.07` | Logo height as fraction of figure height. |
|
|
483
|
+
| `show_icons` | `bool` | `False` | Display MDC variation & assurance icons. |
|
|
484
|
+
| `icon_zoom` | `float` | `0.06` | Icon height as fraction of figure height. |
|
|
485
|
+
|
|
486
|
+
**Returns:** `(fig, ax)` — `matplotlib.figure.Figure` and `matplotlib.axes.Axes`.
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
490
|
+
### `plot_run_chart`
|
|
491
|
+
|
|
492
|
+
```python
|
|
493
|
+
fig, ax = plot_run_chart(
|
|
494
|
+
data,
|
|
495
|
+
value_col="value",
|
|
496
|
+
x_col=None,
|
|
497
|
+
title=None,
|
|
498
|
+
xlabel="Observation",
|
|
499
|
+
ylabel="Value",
|
|
500
|
+
improvement_direction="high",
|
|
501
|
+
target=None,
|
|
502
|
+
show_target=False,
|
|
503
|
+
nhs_logo_path=None,
|
|
504
|
+
ax=None,
|
|
505
|
+
figsize=(12, 5),
|
|
506
|
+
show_legend=True,
|
|
507
|
+
change_points=None,
|
|
508
|
+
date_format=None,
|
|
509
|
+
logo_path=None,
|
|
510
|
+
logo_zoom=0.07,
|
|
511
|
+
show_icons=False,
|
|
512
|
+
icon_zoom=0.06,
|
|
513
|
+
)
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
Same parameter semantics as `plot_spc_chart` (without `chart_type`,
|
|
517
|
+
`subgroup_col`, `numerator_col`, `shade_band`, `shade_color`, `auto_rebase`).
|
|
518
|
+
|
|
519
|
+
**Returns:** `(fig, ax)`.
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
### `calculate_control_limits`
|
|
524
|
+
|
|
525
|
+
Returns the input DataFrame extended with `mean`, `ucl`, `lcl`, `uwl`, `lwl`
|
|
526
|
+
columns (or just `mean` for run charts).
|
|
527
|
+
|
|
528
|
+
### `detect_special_causes`
|
|
529
|
+
|
|
530
|
+
Returns the DataFrame extended with boolean columns `rule1`, `rule2`, `rule3`,
|
|
531
|
+
`rule4`, and `special_cause`.
|
|
532
|
+
|
|
533
|
+
### `detect_run_chart_signals`
|
|
534
|
+
|
|
535
|
+
Returns the DataFrame extended with `run_shift`, `run_trend`, and `run_signal`.
|
|
536
|
+
|
|
537
|
+
### `rebase_control_limits`
|
|
538
|
+
|
|
539
|
+
Returns the DataFrame with limits recalculated per improvement phase and a
|
|
540
|
+
`rebase_phase` integer column.
|
|
541
|
+
|
|
542
|
+
### `show_summary`
|
|
543
|
+
|
|
544
|
+
Generates a programmatic summary dictionary for a chart, including variation
|
|
545
|
+
type, assurance status, descriptive statistics, triggered SPC rules, and a
|
|
546
|
+
list of signal points. Pass `show_summary=True` to `plot_spc_chart` or
|
|
547
|
+
`plot_run_chart` to render the summary as an additional figure.
|
|
548
|
+
|
|
549
|
+
```python
|
|
550
|
+
from abspc import show_summary
|
|
551
|
+
|
|
552
|
+
summary = show_summary(data, chart_type="XmR", improvement_direction="high", target=60)
|
|
553
|
+
print(summary["variation"], summary["assurance"])
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### `plot_mdc_summary_table`
|
|
557
|
+
|
|
558
|
+
Renders an NHS MDC-style summary table for one or more measures (see the
|
|
559
|
+
[MDC Summary Table](#mdc-summary-table) section above).
|
|
560
|
+
|
|
561
|
+
---
|
|
562
|
+
|
|
563
|
+
## Running Tests
|
|
564
|
+
|
|
565
|
+
```bash
|
|
566
|
+
pip install -e ".[dev]"
|
|
567
|
+
pytest
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
160 unit tests covering all chart types, SPC rules, run-chart signals,
|
|
571
|
+
auto-rebase, change-point annotations, summary generation, and plotting.
|