processbehavior 0.3.2__tar.gz → 0.3.3__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.
Files changed (209) hide show
  1. {processbehavior-0.3.2 → processbehavior-0.3.3}/CHANGELOG.md +26 -1
  2. {processbehavior-0.3.2 → processbehavior-0.3.3}/PKG-INFO +1 -1
  3. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/__init__.py +1 -1
  4. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/maximum_information.py +4 -7
  5. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/spc_constants.py +21 -20
  6. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/missing_values/X_data.parquet +0 -0
  7. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/missing_values/mR_data.parquet +0 -0
  8. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/missing_values/mR_statistics.json +1 -1
  9. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xmr_r/X_data.parquet +0 -0
  10. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xmr_r/X_statistics.json +1 -1
  11. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xmr_r/mR_data.parquet +0 -0
  12. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/pathological_ordering/X_data.parquet +0 -0
  13. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/pathological_ordering/X_statistics.json +1 -1
  14. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/pathological_ordering/mR_data.parquet +0 -0
  15. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/pathological_ordering/mR_statistics.json +1 -1
  16. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/single_obs_strata/X_data.parquet +0 -0
  17. processbehavior-0.3.3/tests/fixtures/golden_masters/single_obs_strata/X_statistics.json +6 -0
  18. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/single_obs_strata/mR_data.parquet +0 -0
  19. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/single_obs_strata/mR_statistics.json +1 -1
  20. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/unstratified_small/X_data.parquet +0 -0
  21. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/unstratified_small/X_statistics.json +1 -1
  22. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/unstratified_small/mR_data.parquet +0 -0
  23. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/unstratified_small/mR_statistics.json +1 -1
  24. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_spc_constants.py +36 -4
  25. processbehavior-0.3.3/tests/test_vas_chart_constants.py +86 -0
  26. processbehavior-0.3.2/tests/fixtures/golden_masters/single_obs_strata/X_statistics.json +0 -6
  27. {processbehavior-0.3.2 → processbehavior-0.3.3}/.gitignore +0 -0
  28. {processbehavior-0.3.2 → processbehavior-0.3.3}/CITATION.cff +0 -0
  29. {processbehavior-0.3.2 → processbehavior-0.3.3}/CODE_OF_CONDUCT.md +0 -0
  30. {processbehavior-0.3.2 → processbehavior-0.3.3}/CONTRIBUTING.md +0 -0
  31. {processbehavior-0.3.2 → processbehavior-0.3.3}/LICENSE +0 -0
  32. {processbehavior-0.3.2 → processbehavior-0.3.3}/README.md +0 -0
  33. {processbehavior-0.3.2 → processbehavior-0.3.3}/SECURITY.md +0 -0
  34. {processbehavior-0.3.2 → processbehavior-0.3.3}/examples/README.md +0 -0
  35. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/analysis.py +0 -0
  36. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/analysis_dataset.py +0 -0
  37. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/analysis_result.py +0 -0
  38. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/calibration.py +0 -0
  39. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/capability.py +0 -0
  40. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/data_preparation.py +0 -0
  41. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/datasets/__init__.py +0 -0
  42. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/datasets/data/coffee_shop_demo_long.csv +0 -0
  43. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/datasets/loaders.py +0 -0
  44. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/datasets/synthetic.py +0 -0
  45. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/derivations.py +0 -0
  46. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/effects_calculator.py +0 -0
  47. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/exceptions.py +0 -0
  48. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/exporters/__init__.py +0 -0
  49. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/exporters/excel_exporter.py +0 -0
  50. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/focused_result.py +0 -0
  51. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/formulation_spec.py +0 -0
  52. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/loss_function.py +0 -0
  53. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/__init__.py +0 -0
  54. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/_math.py +0 -0
  55. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/capability_chart.py +0 -0
  56. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/contracts.py +0 -0
  57. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/control_chart.py +0 -0
  58. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/effects_charts.py +0 -0
  59. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/lane_boundaries.py +0 -0
  60. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/limits.py +0 -0
  61. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/maximum_information_chart.py +0 -0
  62. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/plotter.py +0 -0
  63. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/renderers.py +0 -0
  64. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/report.py +0 -0
  65. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/residuals.py +0 -0
  66. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/run_rules_viz.py +0 -0
  67. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/stats_box.py +0 -0
  68. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/themes.py +0 -0
  69. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/x_axis_layout.py +0 -0
  70. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/plotting/zones.py +0 -0
  71. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/process_behavior.py +0 -0
  72. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/py.typed +0 -0
  73. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/residual_calculator.py +0 -0
  74. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/result_signals.py +0 -0
  75. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/result_tabular.py +0 -0
  76. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/sds_detector.py +0 -0
  77. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/series_length.py +0 -0
  78. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/signals/__init__.py +0 -0
  79. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/signals/config.py +0 -0
  80. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/signals/detector.py +0 -0
  81. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/signals/detectors.py +0 -0
  82. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/signals/result.py +0 -0
  83. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/study.py +0 -0
  84. {processbehavior-0.3.2 → processbehavior-0.3.3}/processbehavior/types.py +0 -0
  85. {processbehavior-0.3.2 → processbehavior-0.3.3}/pyproject.toml +0 -0
  86. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/__init__.py +0 -0
  87. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/conftest.py +0 -0
  88. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/bishop_analyses/vassds1analysis.json +0 -0
  89. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/bishop_analyses/vassds2analysis.json +0 -0
  90. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/bishop_analyses/vassds3analysis.json +0 -0
  91. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/coffee_capability_full_baseline.json +0 -0
  92. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/data/FILLWEIGHTDATA_800.csv +0 -0
  93. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/data/coffee_shop_demo_long.csv +0 -0
  94. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/missing_values/X_metadata.json +0 -0
  95. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/missing_values/X_statistics.json +0 -0
  96. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/missing_values/mR_metadata.json +0 -0
  97. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xbar_s/S_data.parquet +0 -0
  98. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xbar_s/S_metadata.json +0 -0
  99. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xbar_s/S_statistics.json +0 -0
  100. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xbar_s/Xbar_data.parquet +0 -0
  101. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xbar_s/Xbar_metadata.json +0 -0
  102. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xbar_s/Xbar_statistics.json +0 -0
  103. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xmr_r/X_metadata.json +0 -0
  104. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xmr_r/mR_metadata.json +0 -0
  105. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/paired_xmr_r/mR_statistics.json +0 -0
  106. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/pathological_ordering/X_metadata.json +0 -0
  107. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/pathological_ordering/mR_metadata.json +0 -0
  108. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/residual_chart/S_data.parquet +0 -0
  109. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/residual_chart/S_metadata.json +0 -0
  110. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/residual_chart/S_statistics.json +0 -0
  111. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/single_obs_strata/X_metadata.json +0 -0
  112. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/single_obs_strata/mR_metadata.json +0 -0
  113. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_balanced/S_data.parquet +0 -0
  114. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_balanced/S_metadata.json +0 -0
  115. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_balanced/S_statistics.json +0 -0
  116. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_balanced/Xbar_data.parquet +0 -0
  117. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_balanced/Xbar_metadata.json +0 -0
  118. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_balanced/Xbar_statistics.json +0 -0
  119. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_uneven/S_data.parquet +0 -0
  120. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_uneven/S_metadata.json +0 -0
  121. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_uneven/S_statistics.json +0 -0
  122. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_uneven/Xbar_data.parquet +0 -0
  123. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_uneven/Xbar_metadata.json +0 -0
  124. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/stratified_uneven/Xbar_statistics.json +0 -0
  125. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/unstratified_small/X_metadata.json +0 -0
  126. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/fixtures/golden_masters/unstratified_small/mR_metadata.json +0 -0
  127. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_analysis_bugs.py +0 -0
  128. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_analysis_dataset.py +0 -0
  129. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_analysis_golden_master.py +0 -0
  130. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_analysis_result_contract.py +0 -0
  131. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_analysis_specifications.py +0 -0
  132. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_api_reference.py +0 -0
  133. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_beyond_limits_vectorized.py +0 -0
  134. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_bin_extremes.py +0 -0
  135. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_bishop_reference.py +0 -0
  136. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_by_parameter.py +0 -0
  137. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_by_permutations.py +0 -0
  138. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_calibration.py +0 -0
  139. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_capability.py +0 -0
  140. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_capability_chart.py +0 -0
  141. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_capability_window.py +0 -0
  142. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_chart_availability.py +0 -0
  143. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_chart_column_contract.py +0 -0
  144. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_chart_parsing.py +0 -0
  145. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_control_chart_figure.py +0 -0
  146. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_data_preparation.py +0 -0
  147. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_datasets.py +0 -0
  148. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_derivations.py +0 -0
  149. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_derivations_robustness.py +0 -0
  150. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_design_state_lineage.py +0 -0
  151. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_documented_rule_coverage.py +0 -0
  152. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_edge_cases.py +0 -0
  153. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_effects_calculator.py +0 -0
  154. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_effects_plotting.py +0 -0
  155. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_encode_rsg_vectorized.py +0 -0
  156. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_excel_export.py +0 -0
  157. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_execute_validation.py +0 -0
  158. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_focus.py +0 -0
  159. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_garbage_character_handling.py +0 -0
  160. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_init_cleaning.py +0 -0
  161. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_lane_boundaries.py +0 -0
  162. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_lane_connectors.py +0 -0
  163. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_limits_vectorized.py +0 -0
  164. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_loss_function.py +0 -0
  165. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_maximum_information.py +0 -0
  166. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_na_in_factor_columns.py +0 -0
  167. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_notebook_ergonomics.py +0 -0
  168. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_p0_p2_regressions.py +0 -0
  169. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_performance.py +0 -0
  170. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_phased_limits.py +0 -0
  171. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_plotting.py +0 -0
  172. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_plotting_decorations.py +0 -0
  173. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_plotting_hardening.py +0 -0
  174. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_plotting_xaxis.py +0 -0
  175. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_process_behavior.py +0 -0
  176. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_recentered_mr_fix.py +0 -0
  177. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_reference_integrity.py +0 -0
  178. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_release_gate_0_1_0_checklist.py +0 -0
  179. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_residual_aliases.py +0 -0
  180. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_residual_calculator.py +0 -0
  181. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_residual_labels.py +0 -0
  182. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_residual_scope.py +0 -0
  183. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_resolve_by_grouping.py +0 -0
  184. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_result_signals.py +0 -0
  185. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_result_tabular.py +0 -0
  186. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_sampling_plan.py +0 -0
  187. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_sds.py +0 -0
  188. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_sds_detector.py +0 -0
  189. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_series_length.py +0 -0
  190. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_signal_detectors.py +0 -0
  191. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_signal_result_surface.py +0 -0
  192. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_signals.py +0 -0
  193. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_single_detection.py +0 -0
  194. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_solo_mr_residuals.py +0 -0
  195. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_srp_refactor.py +0 -0
  196. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_strata_companion.py +0 -0
  197. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_strata_sufficiency.py +0 -0
  198. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_stratified_insufficiency.py +0 -0
  199. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_supports_calibration.py +0 -0
  200. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_synthetic.py +0 -0
  201. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_types.py +0 -0
  202. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_validate_by_parameter.py +0 -0
  203. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_weco_integration.py +0 -0
  204. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_why_not.py +0 -0
  205. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_x_axis_layout.py +0 -0
  206. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_xbar_residual_center.py +0 -0
  207. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_xbar_s_options.py +0 -0
  208. {processbehavior-0.3.2 → processbehavior-0.3.3}/tests/test_xbar_stratified.py +0 -0
  209. {processbehavior-0.3.2 → processbehavior-0.3.3}/validation/PBTESTDATABASE_T100.csv +0 -0
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.3.3] - 2026-09-29
11
+
12
+ ### Changed
13
+ - **Individuals and moving-range limits now use the constants exactly as Bishop's VAS manual
14
+ defines them.** The individuals-chart multiplier is 3/1.128 = 2.659574 (previously the
15
+ rounded 2.66) and the moving-range upper limit is 1 + 3(0.8525)/1.128 = 3.267287 (previously
16
+ 3.268), built from the manual's d₂ = 1.128 and d₃ = 0.8525 (Eq 12.4, 12.5, 12.10, 12.11). The
17
+ manual prints the rounded values; Bishop's VAS software computes them without rounding, and PB's
18
+ X and mR limits now match it digit for digit (Medicare first chart: ±3838.32 and 4715.38).
19
+ Limits move by 0.016% and 0.02%, so a signal changes only for a point within that distance of a
20
+ limit. The d₂ used on the calibration path and by the maximum-information chart is now exactly
21
+ 1.128 (it was 3/2.66 = 1.1278), and `MR_SIGMA_INTERVAL_80` was regenerated: five entries move
22
+ by 0.001. New constant `D3_N2` in `processbehavior.spc_constants`.
23
+
24
+ ### Added
25
+ - Docs: the chart-types guide now explains the three views of a study with factors and
26
+ time (the combined ``by=[]`` chart, the ``phased=True`` view, and full stratification),
27
+ how to read a signal at a subgroup boundary on the combined chart (evidence about the
28
+ traversal, kept in the calculation deliberately because it reproduces Bishop's reference
29
+ limits), and which claims survive reordering the lanes, with the R5 chart's limits
30
+ caveat for DS 2 and 3. The ``phased`` view is documented in the user guide for the first
31
+ time. From the #114 discussion with @rabujamra, whose permutation check is
32
+ ``validation/mr_permutation_invariance.py``.
33
+
10
34
  ## [0.3.2] - 2026-09-15
11
35
 
12
36
  ### Fixed
@@ -929,7 +953,8 @@ and may change between minor versions until 1.0.
929
953
  - `natsort >= 8.0`
930
954
  - `plotly >= 5.18, < 7`
931
955
 
932
- [Unreleased]: https://github.com/cnicholas/processbehavior/compare/v0.3.2...HEAD
956
+ [Unreleased]: https://github.com/cnicholas/processbehavior/compare/v0.3.3...HEAD
957
+ [0.3.3]: https://github.com/cnicholas/processbehavior/compare/v0.3.2...v0.3.3
933
958
  [0.3.2]: https://github.com/cnicholas/processbehavior/compare/v0.3.1...v0.3.2
934
959
  [0.3.1]: https://github.com/cnicholas/processbehavior/compare/v0.3.0...v0.3.1
935
960
  [0.3.0]: https://github.com/cnicholas/processbehavior/compare/v0.2.1...v0.3.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: processbehavior
3
- Version: 0.3.2
3
+ Version: 0.3.3
4
4
  Summary: Python-native Process Behavior & Control Charts (spec-driven SPC with tidy outputs)
5
5
  Project-URL: Homepage, https://github.com/cnicholas/processbehavior
6
6
  Project-URL: Repository, https://github.com/cnicholas/processbehavior
@@ -47,7 +47,7 @@ its ``.sds`` field. Internally some modules still use the legacy "SDS"
47
47
  prefix (e.g. ``sds_detector.py``); the model itself is three-state.
48
48
  """
49
49
 
50
- __version__ = '0.3.2'
50
+ __version__ = '0.3.3'
51
51
 
52
52
  # Result object
53
53
  from processbehavior.analysis_result import AnalysisResult
@@ -21,7 +21,7 @@ import numpy as np
21
21
  import pandas as pd
22
22
 
23
23
  from .exceptions import ValidationError
24
- from .spc_constants import R_UPPER_LIMIT_MULTIPLIER, XMR_LIMIT_MULTIPLIER
24
+ from .spc_constants import D2_N2, R_UPPER_LIMIT_MULTIPLIER, XMR_LIMIT_MULTIPLIER
25
25
 
26
26
  if TYPE_CHECKING:
27
27
  from .analysis_dataset import AnalysisDataSet
@@ -48,9 +48,9 @@ class MaximumInformationResult:
48
48
  sigma_hat : float
49
49
  mR / d2 — noise floor sigma estimate.
50
50
  upl : float
51
- Upper natural process limit (R2 mean + 2.66 * mR).
51
+ Upper natural process limit (R2 mean + E2 * mR, E2 = 3/1.128 ≈ 2.66).
52
52
  lpl : float
53
- Lower natural process limit (R2 mean - 2.66 * mR).
53
+ Lower natural process limit (R2 mean - E2 * mR).
54
54
  n_signals : int
55
55
  Points beyond limits on XmR.
56
56
  round_to : int
@@ -159,9 +159,6 @@ class MaximumInformationResult:
159
159
  # Pure Function
160
160
  # ============================================================================
161
161
 
162
- # d2 for n=2 (moving range of consecutive pairs)
163
- _D2 = 1.128
164
-
165
162
 
166
163
  def assess_maximum_information(
167
164
  ads: AnalysisDataSet,
@@ -204,7 +201,7 @@ def assess_maximum_information(
204
201
  r2_mean = float(np.mean(r2_values))
205
202
  mr_values = np.abs(np.diff(r2_values))
206
203
  r2_mR = float(np.mean(mr_values))
207
- sigma_hat = r2_mR / _D2
204
+ sigma_hat = r2_mR / D2_N2
208
205
 
209
206
  # Limits: mean ± E2 * mR
210
207
  upl = r2_mean + XMR_LIMIT_MULTIPLIER * r2_mR
@@ -29,15 +29,19 @@ from .exceptions import ValidationError
29
29
  # Control limit multiplier (3-sigma limits are standard in SPC)
30
30
  SIGMA_MULTIPLIER = 3
31
31
 
32
- # E2 constant for XmR charts (n=2, moving range of 2 consecutive observations)
33
- # Used for calculating control limits on individual values
34
- # E2 = d2 / d3 for n=2, where d2 = 1.128 and d3 = 0.8525
35
- XMR_LIMIT_MULTIPLIER = 2.66
32
+ # Moving-range constants for n = 2 (consecutive pairs), as in Bishop's VAS manual:
33
+ # sigma = mR / d2 (Eq 12.4), X limits = X ± 3·mR/d2 (Eq 12.10-12.11), and the
34
+ # moving-range upper limit = (1 + 3·d3/d2)·mR (Eq 12.5). The manual prints the
35
+ # rounded values 2.66 and 3.268; Bishop's VAS software computes them from d2 and
36
+ # d3 without rounding, and so does this library.
37
+ D2_N2 = 1.128
38
+ D3_N2 = 0.8525
36
39
 
37
- # D4 constant for R charts (n=2, range of 2 consecutive observations)
38
- # Used for upper control limit on moving range
39
- # D4 = 1 + 3(d3/d2) for n=2
40
- R_UPPER_LIMIT_MULTIPLIER = 3.268
40
+ # E2 for XmR charts: X ± E2·mR, E2 = 3/d2 (≈ 2.66)
41
+ XMR_LIMIT_MULTIPLIER = SIGMA_MULTIPLIER / D2_N2
42
+
43
+ # D4 for the moving-range chart: upper limit = D4·mR, D4 = 1 + 3·d3/d2 (≈ 3.267)
44
+ R_UPPER_LIMIT_MULTIPLIER = 1 + SIGMA_MULTIPLIER * D3_N2 / D2_N2
41
45
 
42
46
 
43
47
  # ============================================================================
@@ -260,8 +264,8 @@ def calculate_limits(
260
264
  -----
261
265
  Xbar limits: X̄ ± (3 * Wd) / sqrt(n), where Wd = S / c4(n)
262
266
  S limits: S * b3(n) to S * b4(n)
263
- XmR limits: X̄ ± (E2 * mR), where E2 = 2.66
264
- R limits: 0 to mR * D4, where D4 = 3.268
267
+ XmR limits: X̄ ± (E2 * mR), where E2 = 3/d2 = 3/1.128 (≈ 2.66)
268
+ R limits: 0 to mR * D4, where D4 = 1 + 3·d3/d2 = 1 + 3(0.8525)/1.128 (≈ 3.267)
265
269
 
266
270
  References
267
271
  ----------
@@ -414,11 +418,8 @@ def calculate_limits_vectorized(
414
418
  return pd.DataFrame({'lpl': lpl, 'upl': upl}, index=index)
415
419
 
416
420
 
417
- # d2 bias constant for the n=2 moving range, derived from the library's own E2
418
- # (E2 = sigma_multiplier / d2 at n=2, with the default 3-sigma multiplier). Used
419
- # only on the calibration path so calibrated X/mR limits stay internally
420
- # consistent with the data-path XmR/R constants.
421
- D2_N2 = 3.0 / XMR_LIMIT_MULTIPLIER
421
+ # calibrated_limits uses D2_N2 (defined with the XmR constants above), so
422
+ # calibrated X/mR limits stay consistent with the data-path XmR/R constants.
422
423
 
423
424
 
424
425
  def calibrated_limits(
@@ -714,12 +715,12 @@ MR_SIGMA_INTERVAL_80: dict[int, tuple[float, float]] = {
714
715
  9: (0.618, 1.418),
715
716
  10: (0.637, 1.396),
716
717
  11: (0.656, 1.375),
717
- 12: (0.670, 1.360),
718
+ 12: (0.670, 1.359),
718
719
  13: (0.680, 1.344),
719
- 14: (0.694, 1.330),
720
+ 14: (0.694, 1.329),
720
721
  15: (0.703, 1.315),
721
722
  16: (0.714, 1.310),
722
- 17: (0.722, 1.300),
723
+ 17: (0.721, 1.300),
723
724
  18: (0.730, 1.288),
724
725
  19: (0.739, 1.280),
725
726
  20: (0.745, 1.274),
@@ -728,9 +729,9 @@ MR_SIGMA_INTERVAL_80: dict[int, tuple[float, float]] = {
728
729
  23: (0.761, 1.253),
729
730
  24: (0.766, 1.249),
730
731
  25: (0.771, 1.243),
731
- 26: (0.775, 1.238),
732
+ 26: (0.774, 1.238),
732
733
  27: (0.780, 1.234),
733
734
  28: (0.784, 1.229),
734
- 29: (0.787, 1.224),
735
+ 29: (0.787, 1.223),
735
736
  30: (0.790, 1.220),
736
737
  }
@@ -2,5 +2,5 @@
2
2
  "N": 2,
3
3
  "center": 0.707,
4
4
  "lpl": 0.0,
5
- "upl": 2.312
5
+ "upl": 2.311
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "N": 1,
3
3
  "center": 49.085,
4
- "lpl": 46.738,
4
+ "lpl": 46.739,
5
5
  "upl": 51.432
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "N": 1,
3
3
  "center": 49.774,
4
- "lpl": 47.548,
4
+ "lpl": 47.549,
5
5
  "upl": 52.0
6
6
  }
@@ -2,5 +2,5 @@
2
2
  "N": 2,
3
3
  "center": 0.837,
4
4
  "lpl": 0.0,
5
- "upl": 2.735
5
+ "upl": 2.734
6
6
  }
@@ -0,0 +1,6 @@
1
+ {
2
+ "N": 1,
3
+ "center": 48.991,
4
+ "lpl": 45.23,
5
+ "upl": 52.753
6
+ }
@@ -2,5 +2,5 @@
2
2
  "N": 2,
3
3
  "center": 1.414,
4
4
  "lpl": 0.0,
5
- "upl": 4.622
5
+ "upl": 4.621
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "N": 1,
3
3
  "center": 49.213,
4
- "lpl": 46.364,
4
+ "lpl": 46.365,
5
5
  "upl": 52.061
6
6
  }
@@ -2,5 +2,5 @@
2
2
  "N": 2,
3
3
  "center": 1.071,
4
4
  "lpl": 0.0,
5
- "upl": 3.5
5
+ "upl": 3.499
6
6
  }
@@ -12,6 +12,10 @@ import pandas as pd
12
12
  import pytest
13
13
 
14
14
  from processbehavior.spc_constants import (
15
+ D2_N2,
16
+ D3_N2,
17
+ R_UPPER_LIMIT_MULTIPLIER,
18
+ XMR_LIMIT_MULTIPLIER,
15
19
  b3,
16
20
  b4,
17
21
  c4,
@@ -121,6 +125,34 @@ def test_b3_b4_raises_on_invalid_n(func):
121
125
  func(1)
122
126
 
123
127
 
128
+ # ============================================================================
129
+ # Test: moving-range constants (n = 2)
130
+ # ============================================================================
131
+
132
+
133
+ class TestMovingRangeConstants:
134
+ """The XmR and mR constants follow Bishop's VAS manual (Eq 12.4, 12.5, 12.10, 12.11)
135
+ and are computed from d2 = 1.128 and d3 = 0.8525 without rounding, as VAS does."""
136
+
137
+ def test_building_blocks_are_the_manuals(self):
138
+ assert D2_N2 == 1.128
139
+ assert D3_N2 == 0.8525
140
+
141
+ def test_multipliers_are_the_manuals_formulas(self):
142
+ assert XMR_LIMIT_MULTIPLIER == 3 / D2_N2
143
+ assert R_UPPER_LIMIT_MULTIPLIER == 1 + 3 * D3_N2 / D2_N2
144
+
145
+ def test_multipliers_match_the_vas_software(self):
146
+ # Measured from Bishop's VAS charts: Medicare 3838.32 / 1443.21 and 4715.38 / 1443.21.
147
+ assert abs(XMR_LIMIT_MULTIPLIER - 2.659574) < 1e-6
148
+ assert abs(R_UPPER_LIMIT_MULTIPLIER - 3.267287) < 1e-6
149
+
150
+ def test_multipliers_round_to_the_manuals_printed_values(self):
151
+ # The manual prints 2.66 and 3.268 (3.686/1.128, with 3.686 itself rounded).
152
+ assert round(XMR_LIMIT_MULTIPLIER, 2) == 2.66
153
+ assert abs(R_UPPER_LIMIT_MULTIPLIER - 3.268) < 0.001
154
+
155
+
124
156
  # ============================================================================
125
157
  # Test: calculate_limits
126
158
  # ============================================================================
@@ -133,10 +165,10 @@ def test_b3_b4_raises_on_invalid_n(func):
133
165
  ('Xbar', dict(mean=10.0, sd=0.5, N=5), 9.286, 10.714, 0.01, 0.01),
134
166
  # S: sd=0.5, N=5 → LPL=0.5*b3(5)=0, UPL=0.5*b4(5)≈1.044
135
167
  ('S', dict(sd=0.5, N=5), 0.0, 1.044, 0.001, 0.01),
136
- # XmR: mean=10, mR=0.3 → 10±2.66*0.3=10±0.798
137
- ('XmR', dict(mean=10.0, mR=0.3), 10.0 - 2.66 * 0.3, 10.0 + 2.66 * 0.3, 0.001, 0.001),
138
- # R: mR=0.3 → LPL=0, UPL=0.3*3.268
139
- ('R', dict(mR=0.3), 0.0, 0.3 * 3.268, 0.001, 0.001),
168
+ # XmR: mean=10, mR=0.3 → 10 ± (3/1.128)·0.3 = 10 ± 0.7979
169
+ ('XmR', dict(mean=10.0, mR=0.3), 10.0 - 3 / 1.128 * 0.3, 10.0 + 3 / 1.128 * 0.3, 1e-12, 1e-12),
170
+ # R: mR=0.3 → LPL=0, UPL = (1 + 3·0.8525/1.128)·0.3
171
+ ('R', dict(mR=0.3), 0.0, (1 + 3 * 0.8525 / 1.128) * 0.3, 1e-12, 1e-12),
140
172
  ],
141
173
  ids=['Xbar', 'S', 'XmR', 'R'],
142
174
  )
@@ -0,0 +1,86 @@
1
+ """Individuals and moving-range chart limits match Bishop's VAS software.
2
+
3
+ The expected values are read from Bishop's VAS output decks of 29 September 2026 (Medicare and
4
+ PM SDS 2), at the precision the charts print. They pin the XmR constants E2 = 3/1.128 and
5
+ D4 = 1 + 3(0.8525)/1.128 from the manual (Eq 12.4, 12.5, 12.10, 12.11): with the rounded 2.66 and
6
+ 3.268 the Medicare limits miss by 0.6 and 1.0, and the PM SDS 2 moving-range limit prints 2.84.
7
+ """
8
+
9
+ from pathlib import Path
10
+
11
+ import pandas as pd
12
+ import pytest
13
+
14
+ import processbehavior as pb
15
+
16
+ VALIDATION = Path(__file__).resolve().parent.parent / 'validation'
17
+ MEDICARE_CSV = VALIDATION / 'aco_per_capita_expenditure.csv'
18
+ T100_CSV = VALIDATION / 'PBTESTDATABASE_T100.csv'
19
+
20
+
21
+ # precision=6 so the comparison rounds once, at the precision VAS prints.
22
+ @pytest.fixture(scope='module')
23
+ def medicare():
24
+ df = pd.read_csv(MEDICARE_CSV)
25
+ return pb.formulate(df, response='PER CAPITA EXPENDITURE', factors=['ACO'], time='YEAR', precision=6)
26
+
27
+
28
+ @pytest.fixture(scope='module')
29
+ def pm_sds_2():
30
+ df = pd.read_csv(T100_CSV, na_values=['*'])
31
+ return pb.formulate(df, response='PM SDS 2', factors=['FACTOR 1', 'FACTOR 2'], time='PRODUCTION TIME', precision=6)
32
+
33
+
34
+ class TestMedicareFirstChart:
35
+ """VAS MEDICARE ANALYSIS, slides 1-2: individuals chart ±3838.32, moving range 1443.21 / 4715.38."""
36
+
37
+ def test_individuals_half_width(self, medicare):
38
+ s = medicare.execute(chart='X', by=[]).get_statistics('X')
39
+ assert s['upl'] - s['center'] == pytest.approx(3838.32, abs=0.005)
40
+ assert s['center'] - s['lpl'] == pytest.approx(3838.32, abs=0.005)
41
+
42
+ def test_moving_range_limits(self, medicare):
43
+ s = medicare.execute(chart='mR', by=[]).get_statistics('mR')
44
+ assert s['center'] == pytest.approx(1443.21, abs=0.005)
45
+ assert s['upl'] == pytest.approx(4715.38, abs=0.005)
46
+
47
+
48
+ class TestMedicarePerOrganisationCharts:
49
+ """VAS MEDICARE ANALYSIS, slides 3-6: the per-organisation individuals and moving-range charts.
50
+
51
+ VAS prints six significant figures and appears to place the printed limits about a centre line
52
+ already rounded to that precision (ACO-002: 12637.4 + 2169.97 = 14807.37, printed 14807.4; the exact
53
+ limit is 14807.346), so one-decimal values allow 0.1.
54
+ """
55
+
56
+ @pytest.mark.parametrize(
57
+ 'aco, lpl, upl, lpl_tol, upl_tol',
58
+ [('ACO-001', 7503.91, 11991.3, 0.005, 0.05), ('ACO-002', 10467.4, 14807.4, 0.1, 0.1)],
59
+ )
60
+ def test_individuals_limits(self, medicare, aco, lpl, upl, lpl_tol, upl_tol):
61
+ t = medicare.execute(chart='X', by=['ACO']).chart_table()
62
+ row = t[t['subgroup'] == aco].iloc[0]
63
+ assert row['lpl'] == pytest.approx(lpl, abs=lpl_tol)
64
+ assert row['upl'] == pytest.approx(upl, abs=upl_tol)
65
+
66
+ @pytest.mark.parametrize('aco, center, upl', [('ACO-001', 843.62, 2756.36), ('ACO-002', 815.91, 2665.81)])
67
+ def test_moving_range_limits(self, medicare, aco, center, upl):
68
+ t = medicare.execute(chart='mR', by=['ACO']).chart_table()
69
+ row = t[t['subgroup'] == aco].iloc[0]
70
+ assert row['center'] == pytest.approx(center, abs=0.005)
71
+ assert row['upl'] == pytest.approx(upl, abs=0.005)
72
+
73
+
74
+ class TestPmSds2FirstChart:
75
+ """VAS PM SDS 2 ANALYSIS, slides 1-2: 237.78 (235.47 / 240.09), moving range 0.87 / 2.83."""
76
+
77
+ def test_individuals_limits(self, pm_sds_2):
78
+ s = pm_sds_2.execute(chart='X', by=[]).get_statistics('X')
79
+ assert round(s['center'], 2) == 237.78
80
+ assert round(s['lpl'], 2) == 235.47
81
+ assert round(s['upl'], 2) == 240.09
82
+
83
+ def test_moving_range_limits(self, pm_sds_2):
84
+ s = pm_sds_2.execute(chart='mR', by=[]).get_statistics('mR')
85
+ assert round(s['center'], 2) == 0.87
86
+ assert round(s['upl'], 2) == 2.83
@@ -1,6 +0,0 @@
1
- {
2
- "N": 1,
3
- "center": 48.991,
4
- "lpl": 45.229,
5
- "upl": 52.754
6
- }
File without changes