process-improve 1.83.2__tar.gz → 1.85.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.
Files changed (217) hide show
  1. {process_improve-1.83.2 → process_improve-1.85.1}/PKG-INFO +1 -1
  2. {process_improve-1.83.2 → process_improve-1.85.1}/pyproject.toml +1 -1
  3. {process_improve-1.83.2 → process_improve-1.85.1}/pyproject.toml.orig +1 -1
  4. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/analysis.py +5 -1
  5. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/augment.py +10 -2
  6. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/monitoring/control_charts.py +12 -8
  7. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_diagnostics.py +6 -2
  8. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_mbpls.py +201 -1
  9. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_pca.py +406 -17
  10. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_preprocessing.py +10 -6
  11. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/sensory/mam.py +10 -3
  12. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/univariate/metrics.py +4 -1
  13. {process_improve-1.83.2 → process_improve-1.85.1}/README.md +0 -0
  14. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/__init__.py +0 -0
  15. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/_extras.py +0 -0
  16. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/_linalg.py +0 -0
  17. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/_random.py +0 -0
  18. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/_remote_data.py +0 -0
  19. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/__init__.py +0 -0
  20. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/_batch_monitor.py +0 -0
  21. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/_batch_pca.py +0 -0
  22. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/_batch_plots.py +0 -0
  23. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/_batch_pls.py +0 -0
  24. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/_common.py +0 -0
  25. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/_online.py +0 -0
  26. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/alignment_helpers.py +0 -0
  27. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/control.py +0 -0
  28. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/data_input.py +0 -0
  29. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/datasets.py +0 -0
  30. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/features.py +0 -0
  31. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/plotting.py +0 -0
  32. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/preprocessing.py +0 -0
  33. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/batch/tools.py +0 -0
  34. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/bivariate/__init__.py +0 -0
  35. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/bivariate/_elbow_peak.py +0 -0
  36. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/bivariate/methods.py +0 -0
  37. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/bivariate/tools.py +0 -0
  38. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/chemistry/__init__.py +0 -0
  39. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/chemistry/preprocessing.py +0 -0
  40. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/config.py +0 -0
  41. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/batch/batch-fake-data.csv +0 -0
  42. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/batch/details.txt +0 -0
  43. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/batch/dryer.csv +0 -0
  44. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/batch/nylon.csv +0 -0
  45. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/experiments/boilingpot.csv +0 -0
  46. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/experiments/golf.csv +0 -0
  47. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/experiments/pollutant.csv +0 -0
  48. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/experiments/solar.csv +0 -0
  49. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/experiments/test_doe1.csv +0 -0
  50. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/monitoring/batch-yield-and-purity.csv +0 -0
  51. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/monitoring/rubber-colour.csv +0 -0
  52. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/LDPE/C.csv +0 -0
  53. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/LDPE/Hotellings_T2_A3.csv +0 -0
  54. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/LDPE/Hotellings_T2_A6.csv +0 -0
  55. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/LDPE/LDPE.csv +0 -0
  56. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/LDPE/P.csv +0 -0
  57. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/LDPE/R.csv +0 -0
  58. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/LDPE/T.csv +0 -0
  59. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/LDPE/U.csv +0 -0
  60. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/LDPE/W.csv +0 -0
  61. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/LDPE/Yhat_A6.csv +0 -0
  62. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/cheddar-cheese.csv +0 -0
  63. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/dtu-pectin/NOTICE +0 -0
  64. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/dtu-pectin/extraction1.csv +0 -0
  65. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/dtu-pectin/extraction2.csv +0 -0
  66. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/dtu-pectin/extraction3.csv +0 -0
  67. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/dtu-pectin/ftir1.csv +0 -0
  68. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/dtu-pectin/ftir2.csv +0 -0
  69. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/dtu-pectin/ftir3.csv +0 -0
  70. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/kamyr.csv +0 -0
  71. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/solvents.csv +0 -0
  72. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tablet-spectra.csv +0 -0
  73. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/SOURCE +0 -0
  74. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/formulas_Group1.csv +0 -0
  75. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/formulas_Group2.csv +0 -0
  76. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/formulas_Group3.csv +0 -0
  77. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/formulas_Group4.csv +0 -0
  78. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/formulas_Group5.csv +0 -0
  79. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/process_conditions.csv +0 -0
  80. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/properties_Group1.csv +0 -0
  81. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/properties_Group2.csv +0 -0
  82. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/properties_Group3.csv +0 -0
  83. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/properties_Group4.csv +0 -0
  84. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/properties_Group5.csv +0 -0
  85. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/datasets/multivariate/tpls-pyphi/quality_indicators.csv +0 -0
  86. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/__init__.py +0 -0
  87. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_analyses/__init__.py +0 -0
  88. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_analyses/_shared.py +0 -0
  89. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_analyses/box_cox.py +0 -0
  90. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_analyses/curvature.py +0 -0
  91. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_analyses/diagnostics.py +0 -0
  92. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_analyses/lack_of_fit.py +0 -0
  93. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_analyses/lenth.py +0 -0
  94. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_analyses/model_selection.py +0 -0
  95. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_analyses/ols_extractors.py +0 -0
  96. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_analyses/prediction.py +0 -0
  97. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_desirability.py +0 -0
  98. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_lm.py +0 -0
  99. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_moment_aberration.py +0 -0
  100. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/__init__.py +0 -0
  101. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/analyze_experiment.py +0 -0
  102. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/augment_design.py +0 -0
  103. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/create_factorial_design.py +0 -0
  104. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/doe_knowledge.py +0 -0
  105. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/evaluate_design.py +0 -0
  106. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/fit_linear_model.py +0 -0
  107. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/generate_design.py +0 -0
  108. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/optimize_responses.py +0 -0
  109. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/recommend_strategy.py +0 -0
  110. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/trade_off_table.py +0 -0
  111. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/_tools/visualize_doe.py +0 -0
  112. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/datasets.py +0 -0
  113. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/designs.py +0 -0
  114. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/designs_factorial.py +0 -0
  115. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/designs_mixture.py +0 -0
  116. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/designs_omars.py +0 -0
  117. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/designs_omars_ilp.py +0 -0
  118. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/designs_optimal.py +0 -0
  119. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/designs_response_surface.py +0 -0
  120. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/designs_screening.py +0 -0
  121. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/designs_utils.py +0 -0
  122. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/evaluate.py +0 -0
  123. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/factor.py +0 -0
  124. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/knowledge/__init__.py +0 -0
  125. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/knowledge/api.py +0 -0
  126. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/knowledge/data/concepts.yaml +0 -0
  127. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/knowledge/data/decision_rules.yaml +0 -0
  128. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/knowledge/data/design_types.yaml +0 -0
  129. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/knowledge/data/diagnostics.yaml +0 -0
  130. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/knowledge/engine.py +0 -0
  131. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/knowledge/models.py +0 -0
  132. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/models.py +0 -0
  133. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/omars.py +0 -0
  134. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/omars_trade_off.py +0 -0
  135. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/optimal.py +0 -0
  136. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/optimization.py +0 -0
  137. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/simulations.py +0 -0
  138. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/strategy/__init__.py +0 -0
  139. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/strategy/budget.py +0 -0
  140. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/strategy/domain_templates.py +0 -0
  141. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/strategy/engine.py +0 -0
  142. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/strategy/models.py +0 -0
  143. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/structures.py +0 -0
  144. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/tools.py +0 -0
  145. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/trade_off.py +0 -0
  146. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/__init__.py +0 -0
  147. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/api.py +0 -0
  148. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/plots/__init__.py +0 -0
  149. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/plots/cube_plot.py +0 -0
  150. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/plots/design_quality.py +0 -0
  151. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/plots/diagnostics.py +0 -0
  152. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/plots/effects.py +0 -0
  153. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/plots/optimization_plots.py +0 -0
  154. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/plots/registry.py +0 -0
  155. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/plots/significance.py +0 -0
  156. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/plots/square_plot.py +0 -0
  157. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/experiments/visualization/plots/surfaces.py +0 -0
  158. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/interactions.py +0 -0
  159. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/mcp_server.py +0 -0
  160. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/monitoring/__init__.py +0 -0
  161. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/monitoring/metrics.py +0 -0
  162. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/monitoring/tools.py +0 -0
  163. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/__init__.py +0 -0
  164. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_adaptive.py +0 -0
  165. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_base.py +0 -0
  166. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_common.py +0 -0
  167. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_limits.py +0 -0
  168. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_mbpca.py +0 -0
  169. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_nipals.py +0 -0
  170. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_null.py +0 -0
  171. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_opls.py +0 -0
  172. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_pca_pls.py +0 -0
  173. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_pls.py +0 -0
  174. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_projection.py +0 -0
  175. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_resampling.py +0 -0
  176. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/_tpls.py +0 -0
  177. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/methods.py +0 -0
  178. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/plots.py +0 -0
  179. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/multivariate/tools.py +0 -0
  180. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/py.typed +0 -0
  181. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/recipes.py +0 -0
  182. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/regression/__init__.py +0 -0
  183. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/regression/_robust_regression.py +0 -0
  184. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/regression/methods.py +0 -0
  185. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/regression/tools.py +0 -0
  186. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/sensory/__init__.py +0 -0
  187. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/sensory/analysis.py +0 -0
  188. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/sensory/designed.py +0 -0
  189. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/sensory/diagnostics.py +0 -0
  190. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/sensory/ingest.py +0 -0
  191. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/sensory/panel.py +0 -0
  192. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/sensory/recipes.py +0 -0
  193. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/sensory/tools.py +0 -0
  194. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/sensory/validation.py +0 -0
  195. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/simulation/__init__.py +0 -0
  196. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/simulation/batch.py +0 -0
  197. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/simulation/context.py +0 -0
  198. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/simulation/model.py +0 -0
  199. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/simulation/recipes.py +0 -0
  200. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/simulation/tools.py +0 -0
  201. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/tool_safety.py +0 -0
  202. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/tool_spec.py +0 -0
  203. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/univariate/__init__.py +0 -0
  204. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/univariate/tools.py +0 -0
  205. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/__init__.py +0 -0
  206. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/adapters/__init__.py +0 -0
  207. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/adapters/base.py +0 -0
  208. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/adapters/echarts_adapter.py +0 -0
  209. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/adapters/plotly_adapter.py +0 -0
  210. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/charts/__init__.py +0 -0
  211. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/charts/boxplot.py +0 -0
  212. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/colors.py +0 -0
  213. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/raincloud.py +0 -0
  214. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/spec.py +0 -0
  215. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/themes.py +0 -0
  216. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/tools.py +0 -0
  217. {process_improve-1.83.2 → process_improve-1.85.1}/src/process_improve/visualization/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: process-improve
3
- Version: 1.83.2
3
+ Version: 1.85.1
4
4
  Summary: Designed Experiments; Latent Variables (PCA, PLS, multivariate methods with missing data); Process Monitoring; Batch data analysis.
5
5
  Keywords: Designed Experiments,Latent Variables,PCA,PLS,Multivariate Data Analysis,Batch data analysis
6
6
  Author: Kevin Dunn
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "process-improve"
3
- version = "1.83.2"
3
+ version = "1.85.1"
4
4
  description = "Designed Experiments; Latent Variables (PCA, PLS, multivariate methods with missing data); Process Monitoring; Batch data analysis."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "process-improve"
3
- version = "1.83.2"
3
+ version = "1.85.1"
4
4
  description = 'Designed Experiments; Latent Variables (PCA, PLS, multivariate methods with missing data); Process Monitoring; Batch data analysis.'
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -165,7 +165,11 @@ def analyze_experiment( # noqa: PLR0912, PLR0913, PLR0915, C901
165
165
  Factor settings per run. May also contain the response column(s).
166
166
  responses : DataFrame, Series, or None
167
167
  Response column(s). If *None*, ``response_column`` must name a
168
- column already present in *design_matrix*.
168
+ column already present in *design_matrix*. When a DataFrame with
169
+ more than one column is passed, only the first column is analysed;
170
+ the rest are added to the working frame but ignored by every
171
+ subsequent step. Use ``response_column`` to pick a specific column
172
+ explicitly.
169
173
  model : str or None
170
174
  ``"main_effects"``, ``"interactions"``, ``"quadratic"``, an explicit
171
175
  formula, or *None* (defaults to ``"interactions"``).
@@ -326,7 +326,12 @@ def _augment_add_center_points(ctx: _AugmentContext) -> dict[str, Any]:
326
326
 
327
327
 
328
328
  def _augment_replicate(ctx: _AugmentContext) -> dict[str, Any]:
329
- """Append one or more complete copies of the existing design."""
329
+ """Append zero or more complete copies of the existing design.
330
+
331
+ The number of copies is ``ctx.n_additional_runs`` (default 1 when
332
+ ``ctx.n_additional_runs`` is ``None``); passing 0 leaves the design
333
+ unchanged.
334
+ """
330
335
  df = ctx.existing_design[ctx.factor_names].copy()
331
336
  n_copies = ctx.n_additional_runs if ctx.n_additional_runs is not None else 1
332
337
 
@@ -722,7 +727,10 @@ def augment_design( # noqa: PLR0913
722
727
  n_additional_runs : int or None
723
728
  Budget for additional runs. Interpretation depends on the
724
729
  augmentation type (number of center points, number of D-optimal
725
- runs, number of replicates, or number of blocks).
730
+ runs, number of blocks, ...). For ``"replicate"``, this is the
731
+ number of complete copies of the existing design that are appended
732
+ (each copy adds ``len(existing_design)`` runs); the default of
733
+ ``None`` becomes 1 complete copy.
726
734
  fold_on : str or None
727
735
  For ``"semifold"`` only: which factor to fold on. If ``None``,
728
736
  the best factor is auto-selected.
@@ -42,7 +42,7 @@ def rho(x: float, k: float = 2.52) -> float:
42
42
 
43
43
  def psi(x: float, k: float = 2.0) -> float:
44
44
  """
45
- Pre-clean based on the Huber y-function.
45
+ Pre-clean based on the Huber psi function.
46
46
 
47
47
  Can be interpreted as replacing unexpected high or low values by a more likely value.
48
48
  From p 288 of the paper
@@ -63,24 +63,28 @@ class ControlChart:
63
63
  Other choice is 'regular' (i.e. not-robust) calculations. User should then ensure that
64
64
  no outliers are present in the data.
65
65
 
66
- variant (str, optional): Many variants of control charts are available. The variant
67
- string is compared case-insensitively (it is normalised via ``.strip().lower()``
68
- on assignment), so ``'HW'``, ``'hw'``, and ``'Hw'`` are all equivalent.
66
+ variant (str, optional): Only two variants are currently accepted:
67
+ ``'hw'`` (the default) and ``'xbar.no.subgroup'``. Any other value,
68
+ including ``'cusum'``, raises ``ValueError`` at construction time.
69
+ The variant string is compared case-insensitively (it is normalised
70
+ via ``.strip().lower()`` on assignment), so ``'HW'``, ``'hw'``, and
71
+ ``'Hw'`` are all equivalent.
69
72
 
70
73
  The default is a Holt-Winters (`'hw'`) chart, with automatic determination of
71
74
  control chart parameters. This chart is a blend of infinite history (CUSUM)
72
75
  charts, and an instantaneous (no history taken into account) Shewhart chart. The
73
76
  exact blend is specified by parameters `ld_1` (lambda 1) and `ld_2` (lambda 2).
74
77
 
75
- Other variants are:
78
+ The other accepted variant is:
76
79
 
77
80
  'xbar.no.subgroup' [Shewhart chart, with no subgroups]. In other words, each
78
81
  observation is independently plotted on the control chart.
79
82
 
80
83
  A pure 'cusum' (CUmulative SUM) chart is a planned future variant but
81
- is not currently implemented; the Holt-Winters ('hw') default already
82
- blends CUSUM-style infinite history with Shewhart-style
83
- instantaneous behaviour via its lambda parameters.
84
+ is not currently implemented; passing ``variant='cusum'`` raises
85
+ ``ValueError``. The Holt-Winters ('hw') default already blends
86
+ CUSUM-style infinite history with Shewhart-style instantaneous
87
+ behaviour via its lambda parameters.
84
88
  """
85
89
  self.style = style.strip()
86
90
  self.variant = variant.strip().lower()
@@ -457,7 +457,10 @@ def observation_contributions(model: BaseEstimator, n_components: int | None = N
457
457
 
458
458
  Values lie between 0 and 1 and each column sums to 1, so a contribution
459
459
  well above the average :math:`1/N` flags an observation that strongly
460
- shapes that component.
460
+ shapes that component. The exception is a component whose score column
461
+ has zero variance (``sum(t_{ia}^2) = 0``): the division cannot be
462
+ computed, so the column is returned as zeros rather than NaN, and its
463
+ sum is 0 rather than 1.
461
464
 
462
465
  Note that this is *not* the same diagnostic as the ``score_contributions``
463
466
  method, despite the similar name. ``score_contributions`` is *per-variable*
@@ -480,7 +483,8 @@ def observation_contributions(model: BaseEstimator, n_components: int | None = N
480
483
  -------
481
484
  pd.DataFrame
482
485
  Contributions of shape (n_samples, n_components), indexed by sample.
483
- Each column sums to 1.
486
+ Each column sums to 1 except columns for components whose score has
487
+ zero variance, which are returned as zeros and sum to 0.
484
488
 
485
489
  Raises
486
490
  ------
@@ -17,12 +17,20 @@ from collections.abc import Sequence
17
17
  import numpy as np
18
18
  import pandas as pd
19
19
  from sklearn.base import BaseEstimator, RegressorMixin, _fit_context
20
+ from sklearn.model_selection import BaseCrossValidator, KFold, RepeatedKFold
20
21
  from sklearn.utils import Bunch
21
22
  from sklearn.utils.validation import check_is_fitted
22
23
 
23
24
  from ..visualization.themes import REFERENCE_LINE_COLOR
24
25
  from ._base import _HotellingsT2LimitMixin
25
- from ._common import SpecificationWarning, _nz, _scale_block_contributions, epsqrt
26
+ from ._common import (
27
+ SelectionRule,
28
+ SpecificationWarning,
29
+ _nz,
30
+ _scale_block_contributions,
31
+ _select_n_components,
32
+ epsqrt,
33
+ )
26
34
  from ._diagnostics import _select_rows
27
35
  from ._limits import spe_calculation
28
36
  from ._nipals import quick_regress, ssq
@@ -1025,6 +1033,198 @@ class MBPLS(_HotellingsT2LimitMixin, RegressorMixin, BaseEstimator):
1025
1033
  check_is_fitted(self, "super_weights_")
1026
1034
  return self._project(X)
1027
1035
 
1036
+ @classmethod
1037
+ def select_n_components( # noqa: PLR0913, PLR0915
1038
+ cls,
1039
+ X: dict[str, pd.DataFrame],
1040
+ y: pd.DataFrame,
1041
+ *,
1042
+ max_components: int | None = None,
1043
+ cv: int | BaseCrossValidator = 5,
1044
+ n_repeats: int | None = None,
1045
+ random_state: int | None = None,
1046
+ selection_rule: SelectionRule = "1se",
1047
+ **mbpls_kwargs,
1048
+ ) -> Bunch:
1049
+ """Select the number of multi-block PLS components by cross-validation.
1050
+
1051
+ Whole rows are held out. The super score of a held-out row is computed
1052
+ from its X-blocks alone and its Y is what the model predicts, so the
1053
+ value being predicted never enters its own prediction. That is the same
1054
+ argument that makes row-wise cross-validation sound for a single-block
1055
+ :meth:`PLS.select_n_components`, and it is unaffected by there being
1056
+ several X-blocks.
1057
+
1058
+ Each block is centred and scaled inside :meth:`fit`, on the training
1059
+ rows only, so the fold statistics never see the held-out rows.
1060
+
1061
+ One model is fitted per fold **and** per component count, because the
1062
+ hierarchical NIPALS deflation means an ``a``-component model is not
1063
+ recoverable from an ``A``-component one. The cost is
1064
+ ``cv * n_repeats * max_components`` fits.
1065
+
1066
+ Parameters
1067
+ ----------
1068
+ X : dict[str, pd.DataFrame]
1069
+ X-blocks, keyed by block name, all sharing ``y``'s row index.
1070
+ y : pd.DataFrame
1071
+ Y-block, one row per observation.
1072
+ max_components : int, optional
1073
+ Largest component count to evaluate. Defaults to the largest the
1074
+ smallest training fold supports, capped at the total width of the
1075
+ X-blocks.
1076
+ cv : int or sklearn CV splitter, default 5
1077
+ An integer is used as the ``n_splits`` of a shuffled
1078
+ :class:`~sklearn.model_selection.KFold`, or of a
1079
+ :class:`~sklearn.model_selection.RepeatedKFold` when
1080
+ ``n_repeats > 1``. A splitter object is used as given, and
1081
+ ``n_repeats`` is then ignored.
1082
+ n_repeats : int, optional
1083
+ How many times to repeat the split with a fresh shuffle. Resolved
1084
+ to 10 when ``cv`` is an integer; pass 1 to disable repeats.
1085
+ random_state : int, optional
1086
+ Seed for the shuffling. Ignored when ``cv`` is a splitter.
1087
+ selection_rule : {"1se", "min", "q2_increment"}, default "1se"
1088
+ How ``n_components`` is chosen from the curve. See
1089
+ :data:`~process_improve.multivariate._common.SelectionRule`.
1090
+ ``"randomization"`` is not offered here.
1091
+ **mbpls_kwargs
1092
+ Passed to every :class:`MBPLS` fitted, for instance ``tol`` or
1093
+ ``algorithm``.
1094
+
1095
+ Returns
1096
+ -------
1097
+ sklearn.utils.Bunch
1098
+ With ``n_components`` (int), ``rmsecv`` and ``se_rmsecv`` (Series
1099
+ indexed ``1..A``), ``per_fold_rmsecv`` (DataFrame, components by
1100
+ fold), ``press`` (Series), ``r2y_validated`` (DataFrame with one
1101
+ column per target plus ``"total"``), ``cv_predictions`` (DataFrame
1102
+ of the held-out predictions of the recommended model, averaged
1103
+ over repeats) and ``selection_rule``.
1104
+
1105
+ Raises
1106
+ ------
1107
+ ValueError
1108
+ If ``X`` is not a non-empty dict of frames sharing ``y``'s index,
1109
+ or if no component count could be evaluated.
1110
+
1111
+ Examples
1112
+ --------
1113
+ >>> import numpy as np, pandas as pd
1114
+ >>> from process_improve.multivariate.methods import MBPLS
1115
+ >>> rng = np.random.default_rng(0)
1116
+ >>> t = rng.standard_normal((40, 2))
1117
+ >>> blocks = {
1118
+ ... "a": pd.DataFrame(t @ rng.standard_normal((2, 5)) + rng.standard_normal((40, 5)) * 0.3),
1119
+ ... "b": pd.DataFrame(t @ rng.standard_normal((2, 4)) + rng.standard_normal((40, 4)) * 0.3),
1120
+ ... }
1121
+ >>> Y = pd.DataFrame(t @ rng.standard_normal((2, 2)) + rng.standard_normal((40, 2)) * 0.3)
1122
+ >>> out = MBPLS.select_n_components(blocks, Y, max_components=3, cv=5, n_repeats=2, random_state=0)
1123
+ >>> 1 <= out.n_components <= 3
1124
+ True
1125
+ """
1126
+ if not isinstance(X, dict):
1127
+ raise TypeError(f"X must be a dict of DataFrames, one per block; got {type(X).__name__}.")
1128
+ if not X:
1129
+ raise ValueError("X must hold at least one block.")
1130
+ y = pd.DataFrame(y)
1131
+ for name, block in X.items():
1132
+ if not isinstance(block, pd.DataFrame):
1133
+ raise TypeError(f"Block {name!r} must be a pandas DataFrame; got {type(block).__name__}.")
1134
+ if len(block) != len(y):
1135
+ raise ValueError(f"Block {name!r} has {len(block)} rows; y has {len(y)}.")
1136
+ n_samples = len(y)
1137
+ total_width = sum(block.shape[1] for block in X.values())
1138
+
1139
+ if isinstance(cv, int):
1140
+ repeats = 10 if n_repeats is None else int(n_repeats)
1141
+ splitter: BaseCrossValidator = (
1142
+ KFold(cv, shuffle=True, random_state=random_state)
1143
+ if repeats == 1
1144
+ else RepeatedKFold(n_splits=cv, n_repeats=repeats, random_state=random_state)
1145
+ )
1146
+ n_splits = cv
1147
+ else:
1148
+ splitter, repeats, n_splits = cv, 1, cv.get_n_splits(y)
1149
+
1150
+ if max_components is not None and int(max_components) < 1:
1151
+ raise ValueError(f"max_components must be at least 1; got {max_components}.")
1152
+
1153
+ splits = list(splitter.split(y))
1154
+ smallest_train = min(len(train) for train, _ in splits)
1155
+ # At least one component is always evaluated: a fold too small to support more
1156
+ # still supports one, and reporting nothing would hide that from the caller.
1157
+ ceiling = max(1, min(smallest_train - 1, total_width))
1158
+ A = ceiling if max_components is None else min(int(max_components), ceiling)
1159
+
1160
+ component_index = pd.Index(range(1, A + 1), name="n_components")
1161
+ targets = list(y.columns)
1162
+ press = np.zeros((A, len(targets)))
1163
+ per_fold = np.full((A, len(splits)), np.nan)
1164
+ gathered: dict[int, list[pd.DataFrame]] = {a: [] for a in component_index}
1165
+ tested = np.zeros(n_samples) # how often each row is held out, which need not be uniform
1166
+
1167
+ for fold, (train, test) in enumerate(splits):
1168
+ tested[test] += 1.0
1169
+ tr, te = y.index[train], y.index[test]
1170
+ train_blocks = {name: block.iloc[train] for name, block in X.items()}
1171
+ test_blocks = {name: block.iloc[test] for name, block in X.items()}
1172
+ for a in component_index:
1173
+ with warnings.catch_warnings():
1174
+ warnings.simplefilter("ignore", SpecificationWarning)
1175
+ model = cls(n_components=a, **mbpls_kwargs).fit(train_blocks, y.loc[tr])
1176
+ predicted = model.diagnose(test_blocks).predictions
1177
+ residual = y.loc[te].to_numpy(dtype=float) - np.asarray(predicted, dtype=float)
1178
+ press[a - 1] += np.nansum(residual**2, axis=0)
1179
+ per_fold[a - 1, fold] = float(np.sqrt(np.nanmean(residual**2)))
1180
+ gathered[a].append(pd.DataFrame(predicted, index=te, columns=targets))
1181
+
1182
+ # Weight the "predict the mean" reference by the same per-row coverage that
1183
+ # built PRESS, so each row counts in the denominator exactly as often as it
1184
+ # counted in the numerator. A splitter that tests some rows more than others,
1185
+ # or not at all, is then handled exactly rather than by a flat repeat count.
1186
+ # This is what PLS.select_n_components does, and both sides are on the
1187
+ # original Y scale, so the two are directly comparable.
1188
+ values = y.to_numpy(dtype=float)
1189
+ centred_sq = (values - np.nanmean(values, axis=0)) ** 2
1190
+ tss = np.nansum(tested[:, None] * centred_sq, axis=0)
1191
+ per_target = np.where(tss > 0, 1.0 - press / np.where(tss > 0, tss, 1.0), np.nan)
1192
+ total = np.where(tss.sum() > 0, 1.0 - press.sum(axis=1) / tss.sum(), np.nan)
1193
+
1194
+ n_predicted = float(tested.sum())
1195
+ rmsecv = pd.Series(
1196
+ np.sqrt(press.sum(axis=1) / max(n_predicted * len(targets), 1.0)), index=component_index, name="RMSECV"
1197
+ )
1198
+ with warnings.catch_warnings():
1199
+ warnings.simplefilter("ignore", RuntimeWarning)
1200
+ se = np.nanstd(per_fold, axis=1, ddof=1) / np.sqrt(np.maximum(1, np.sum(~np.isnan(per_fold), axis=1)))
1201
+ se_rmsecv = pd.Series(se, index=component_index, name="SE of RMSECV")
1202
+ r2y_validated = pd.DataFrame(
1203
+ np.column_stack([per_target, total]), index=component_index, columns=[*targets, "total"]
1204
+ )
1205
+
1206
+ recommended = _select_n_components(
1207
+ selection_rule,
1208
+ mean_error=rmsecv.to_numpy(),
1209
+ se_error=se_rmsecv.to_numpy(),
1210
+ q2_cumulative=r2y_validated["total"].to_numpy(),
1211
+ )
1212
+ held_out = pd.concat(gathered[recommended]).groupby(level=0).mean().reindex(y.index)
1213
+
1214
+ return Bunch(
1215
+ n_components=int(recommended),
1216
+ rmsecv=rmsecv,
1217
+ se_rmsecv=se_rmsecv,
1218
+ per_fold_rmsecv=pd.DataFrame(
1219
+ per_fold, index=component_index, columns=[f"fold_{i + 1}" for i in range(len(splits))]
1220
+ ),
1221
+ press=pd.Series(press.sum(axis=1), index=component_index, name="PRESS"),
1222
+ r2y_validated=r2y_validated,
1223
+ cv_predictions=held_out,
1224
+ selection_rule=selection_rule,
1225
+ n_splits=n_splits,
1226
+ )
1227
+
1028
1228
  def predict(self, X: dict[str, pd.DataFrame]) -> Bunch:
1029
1229
  """Forward to :meth:`diagnose`; emits a :class:`DeprecationWarning`.
1030
1230