process-improve 2.0.0__tar.gz → 2.2.0__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.
- {process_improve-2.0.0 → process_improve-2.2.0}/PKG-INFO +11 -25
- {process_improve-2.0.0 → process_improve-2.2.0}/README.md +8 -2
- {process_improve-2.0.0 → process_improve-2.2.0}/pyproject.toml +4 -24
- {process_improve-2.0.0 → process_improve-2.2.0}/pyproject.toml.orig +15 -30
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/_batch_plots.py +2 -4
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/control.py +27 -10
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/features.py +28 -11
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/preprocessing.py +34 -5
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/bivariate/_elbow_peak.py +20 -7
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/config.py +1 -1
- process_improve-2.2.0/src/process_improve/datasets/experiments/reference_catalogue/anderson-whitcomb-2007.json +20920 -0
- process_improve-2.2.0/src/process_improve/datasets/experiments/reference_catalogue/box-draper-2007.json +425391 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/box-hunter-hunter-1978.json +1137 -446
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/davies-1956.json +398 -125
- process_improve-2.2.0/src/process_improve/datasets/experiments/reference_catalogue/derringer-suich-1980.json +1653 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/efi-mooc-quizzes.json +429 -217
- process_improve-2.2.0/src/process_improve/datasets/experiments/reference_catalogue/fries-hunter-1980.json +1626 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/goos-2025.json +50 -28
- process_improve-2.2.0/src/process_improve/datasets/experiments/reference_catalogue/goos-jones-2011.json +45443 -0
- process_improve-2.2.0/src/process_improve/datasets/experiments/reference_catalogue/jones-nachtsheim-2011.json +6012 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/jones-nachtsheim-2013.json +101 -51
- process_improve-2.2.0/src/process_improve/datasets/experiments/reference_catalogue/lenth-1989.json +1620 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/montgomery-2013.json +2850 -1169
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/nair-ffd-tutorial-2004.json +14 -10
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/nist-ehandbook-ch5.json +1166 -589
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/nunez-ares-et-al-2023.json +70 -36
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/nunez-ares-goos-2019.json +42 -15
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/nunez-ares-goos-2020.json +241 -121
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/pid-book.json +3170 -1705
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/schmidt-launsby-2000.json +1684 -651
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/ullmann-doe-2012.json +83 -3
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/__init__.py +42 -0
- process_improve-2.2.0/src/process_improve/experiments/_analyses/_shared.py +145 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_analyses/aliasing.py +11 -4
- process_improve-2.2.0/src/process_improve/experiments/_analyses/box_cox.py +230 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_analyses/curvature.py +10 -6
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_analyses/model_selection.py +40 -13
- process_improve-2.2.0/src/process_improve/experiments/_analyses/ols_extractors.py +360 -0
- process_improve-2.2.0/src/process_improve/experiments/_analyses/prediction.py +181 -0
- process_improve-2.2.0/src/process_improve/experiments/_analyses/split_plot.py +936 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_analyses/transforms.py +33 -2
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_blocking.py +90 -10
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_desirability.py +64 -8
- process_improve-2.2.0/src/process_improve/experiments/_expression_text.py +25 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_lm.py +119 -4
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_region_geometry.py +74 -0
- process_improve-2.2.0/src/process_improve/experiments/_region_quadrature.py +305 -0
- process_improve-2.2.0/src/process_improve/experiments/_rules.py +396 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/analyze_experiment.py +17 -4
- process_improve-2.2.0/src/process_improve/experiments/_tools/analyze_omars.py +139 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/augment_design.py +36 -1
- process_improve-2.2.0/src/process_improve/experiments/_tools/compare_designs.py +94 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/evaluate_design.py +15 -1
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/generate_design.py +25 -5
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/optimize_responses.py +34 -2
- process_improve-2.2.0/src/process_improve/experiments/_tools/recommend_next_step.py +159 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/recommend_strategy.py +4 -1
- process_improve-2.2.0/src/process_improve/experiments/_tools/run_sheet.py +159 -0
- process_improve-2.2.0/src/process_improve/experiments/_tools/simulate_design_performance.py +111 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_uniform_sampling.py +67 -14
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/analysis.py +501 -66
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/augment.py +460 -52
- process_improve-2.2.0/src/process_improve/experiments/benchmark.py +356 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/compare.py +186 -17
- process_improve-2.2.0/src/process_improve/experiments/crossed_arrays.py +184 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/design_catalog.py +436 -33
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs.py +347 -45
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_constrained.py +459 -121
- process_improve-2.2.0/src/process_improve/experiments/designs_covariates.py +296 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_mixture.py +20 -11
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_mixture_constrained.py +54 -34
- process_improve-2.2.0/src/process_improve/experiments/designs_mixture_process.py +659 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_optimal.py +139 -71
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_response_surface.py +242 -23
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_screening.py +120 -18
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_space_filling.py +16 -4
- process_improve-2.2.0/src/process_improve/experiments/designs_split_plot.py +586 -0
- process_improve-2.2.0/src/process_improve/experiments/designs_three_level.py +213 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_utils.py +56 -11
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/evaluate.py +663 -65
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/factor.py +7 -0
- process_improve-2.2.0/src/process_improve/experiments/gaussian_process.py +350 -0
- process_improve-2.2.0/src/process_improve/experiments/incomplete_blocks.py +197 -0
- process_improve-2.2.0/src/process_improve/experiments/layouts.py +191 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/least_squares_means.py +36 -2
- process_improve-2.2.0/src/process_improve/experiments/model_comparison.py +199 -0
- process_improve-2.2.0/src/process_improve/experiments/next_step.py +2195 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/omars.py +78 -20
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/optimization.py +369 -161
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/projections.py +27 -9
- process_improve-2.2.0/src/process_improve/experiments/pseudocomponents.py +137 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/random_effects.py +90 -5
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/reference_catalogue.py +604 -107
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/region.py +593 -74
- process_improve-2.2.0/src/process_improve/experiments/run_sheet.py +330 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/separating.py +5 -1
- process_improve-2.2.0/src/process_improve/experiments/sequential.py +308 -0
- process_improve-2.2.0/src/process_improve/experiments/simulate.py +377 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/strategy/domain_templates.py +12 -6
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/strategy/engine.py +274 -69
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/strategy/models.py +16 -1
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/structures.py +20 -4
- process_improve-2.2.0/src/process_improve/experiments/surface_checks.py +180 -0
- process_improve-2.2.0/src/process_improve/experiments/three_level_components.py +162 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/tools.py +13 -0
- process_improve-2.2.0/src/process_improve/experiments/variance_dispersion.py +279 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/plots/optimization_plots.py +3 -3
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/plots/registry.py +10 -3
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/plots/surfaces.py +245 -33
- process_improve-2.2.0/src/process_improve/experiments/yates.py +190 -0
- process_improve-2.2.0/src/process_improve/monitoring/__init__.py +14 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/monitoring/control_charts.py +133 -37
- process_improve-2.2.0/src/process_improve/monitoring/evop.py +237 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/monitoring/metrics.py +16 -1
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_asca.py +11 -8
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_common.py +162 -13
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_diagnostics.py +9 -1
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_mbpca.py +34 -17
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_mbpls.py +117 -27
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_nipals.py +98 -66
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_pca.py +94 -26
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_pls.py +102 -17
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_preprocessing.py +6 -2
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_tpls.py +52 -14
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/plots.py +33 -33
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/recipes.py +36 -13
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/regression/__init__.py +5 -1
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/regression/_robust_regression.py +15 -2
- process_improve-2.2.0/src/process_improve/regression/box_tidwell.py +297 -0
- process_improve-2.2.0/src/process_improve/regression/nonlinear.py +193 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/regression/tools.py +3 -1
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/sensory/analysis.py +10 -3
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/sensory/mam.py +27 -1
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/sensory/panel.py +7 -5
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/simulation/tools.py +2 -2
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/tool_safety.py +73 -8
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/tool_spec.py +57 -2
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/univariate/__init__.py +25 -0
- process_improve-2.2.0/src/process_improve/univariate/classical.py +709 -0
- process_improve-2.2.0/src/process_improve/univariate/error_transmission.py +142 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/univariate/metrics.py +68 -22
- process_improve-2.2.0/src/process_improve/univariate/reference_distribution.py +140 -0
- process_improve-2.2.0/src/process_improve/univariate/serial_correlation.py +190 -0
- process_improve-2.2.0/src/process_improve/univariate/stated_values.py +214 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/univariate/tools.py +8 -3
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/spec.py +5 -3
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/tools.py +13 -3
- process_improve-2.2.0/src/process_improve/workbench/__init__.py +60 -0
- process_improve-2.2.0/src/process_improve/workbench/_expressions.py +245 -0
- process_improve-2.2.0/src/process_improve/workbench/project.py +247 -0
- process_improve-2.2.0/src/process_improve/workbench/recipe.py +601 -0
- process_improve-2.2.0/src/process_improve/workbench/tools.py +583 -0
- process_improve-2.2.0/src/process_improve/workbench/variant.py +465 -0
- process_improve-2.0.0/src/process_improve/experiments/_analyses/_shared.py +0 -54
- process_improve-2.0.0/src/process_improve/experiments/_analyses/box_cox.py +0 -148
- process_improve-2.0.0/src/process_improve/experiments/_analyses/ols_extractors.py +0 -207
- process_improve-2.0.0/src/process_improve/experiments/_analyses/prediction.py +0 -99
- process_improve-2.0.0/src/process_improve/experiments/_analyses/split_plot.py +0 -402
- process_improve-2.0.0/src/process_improve/monitoring/__init__.py +0 -9
- process_improve-2.0.0/src/process_improve/univariate/classical.py +0 -350
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/_extras.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/_linalg.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/_random.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/_remote_data.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/_batch_monitor.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/_batch_pca.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/_batch_pls.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/_common.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/_gaps.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/_online.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/alignment_helpers.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/data_input.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/datasets.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/plotting.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/batch/tools.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/bivariate/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/bivariate/methods.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/bivariate/tools.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/chemistry/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/chemistry/preprocessing.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/batch/batch-fake-data.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/batch/details.txt +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/batch/dryer.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/batch/nylon.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/boilingpot.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/corrosion.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/golf.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/pollutant.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/NOTICE.md +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/reference_catalogue/topics.json +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/solar.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/experiments/test_doe1.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/monitoring/batch-yield-and-purity.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/monitoring/rubber-colour.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/LDPE/C.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/LDPE/Hotellings_T2_A3.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/LDPE/Hotellings_T2_A6.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/LDPE/LDPE.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/LDPE/P.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/LDPE/R.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/LDPE/T.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/LDPE/U.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/LDPE/W.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/LDPE/Yhat_A6.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/cheddar-cheese.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/dtu-pectin/NOTICE +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/dtu-pectin/extraction1.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/dtu-pectin/extraction2.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/dtu-pectin/extraction3.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/dtu-pectin/ftir1.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/dtu-pectin/ftir2.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/dtu-pectin/ftir3.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/kamyr.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/solvents.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tablet-spectra.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/SOURCE +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/formulas_Group1.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/formulas_Group2.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/formulas_Group3.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/formulas_Group4.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/formulas_Group5.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/process_conditions.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/properties_Group1.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/properties_Group2.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/properties_Group3.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/properties_Group4.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/properties_Group5.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/datasets/multivariate/tpls-pyphi/quality_indicators.csv +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_analyses/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_analyses/diagnostics.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_analyses/glm.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_analyses/lack_of_fit.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_analyses/lenth.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_analyses/mixture.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_classical.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_finite_fields.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_moment_aberration.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_orthogonal_arrays.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/create_factorial_design.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/doe_knowledge.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/fit_linear_model.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/search_design_catalog.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/trade_off_table.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/_tools/visualize_doe.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/allocation.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/datasets.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/design_measures.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_factorial.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_omars.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_omars_ilp.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/designs_supersaturated.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/knowledge/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/knowledge/api.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/knowledge/data/concepts.yaml +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/knowledge/data/decision_rules.yaml +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/knowledge/data/design_types.yaml +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/knowledge/data/diagnostics.yaml +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/knowledge/engine.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/knowledge/models.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/marginal_means.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/models.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/multistratum.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/omars_trade_off.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/optimal.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/run_order.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/simulations.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/strategy/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/strategy/budget.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/trade_off.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/true_process.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/api.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/plots/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/plots/cube_plot.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/plots/design_quality.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/plots/diagnostics.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/plots/effects.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/plots/significance.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/experiments/visualization/plots/square_plot.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/interactions.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/mcp_server.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/monitoring/tools.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_adaptive.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_base.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_categorical.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_cv_criteria.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_impute.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_limits.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_null.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_opls.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_pca_pls.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_plsda.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_prm.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_procrustes.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_projection.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_resampling.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/_robust.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/methods.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/multivariate/tools.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/py.typed +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/regression/_variance_components.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/regression/methods.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/sensory/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/sensory/designed.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/sensory/diagnostics.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/sensory/ingest.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/sensory/recipes.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/sensory/tools.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/sensory/validation.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/simulation/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/simulation/batch.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/simulation/context.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/simulation/latent.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/simulation/model.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/simulation/recipes.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/adapters/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/adapters/base.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/adapters/echarts_adapter.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/adapters/plotly_adapter.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/charts/__init__.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/charts/boxplot.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/colors.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/raincloud.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/themes.py +0 -0
- {process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/visualization/types.py +0 -0
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: process-improve
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Designed Experiments; Latent Variables (PCA, PLS, multivariate methods with missing data); Process Monitoring; Batch data analysis.
|
|
5
5
|
Keywords: Designed Experiments,Design of Experiments,DoE,Optimal Design,Response Surface,Latent Variables,PCA,PLS,Multivariate Data Analysis,Chemometrics,Process Monitoring,Batch data analysis
|
|
6
6
|
Author: Kevin Dunn
|
|
7
7
|
Author-email: Kevin Dunn <kgdunn@gmail.com>
|
|
8
8
|
License-Expression: MIT
|
|
9
|
-
Classifier: Development Status ::
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
10
|
Classifier: Intended Audience :: Science/Research
|
|
11
11
|
Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
@@ -40,31 +39,13 @@ Requires-Dist: openpyxl>=3.1.5 ; extra == 'batch'
|
|
|
40
39
|
Requires-Dist: ruptures>=1.1.9 ; extra == 'batch'
|
|
41
40
|
Requires-Dist: scikit-image>=0.25.2 ; extra == 'batch'
|
|
42
41
|
Requires-Dist: osqp>=1.0 ; extra == 'control'
|
|
43
|
-
Requires-Dist: coverage>=7.13.1 ; extra == 'dev'
|
|
44
|
-
Requires-Dist: hypothesis>=6.100 ; extra == 'dev'
|
|
45
|
-
Requires-Dist: matplotlib-stubs>=0.3.11 ; extra == 'dev'
|
|
46
|
-
Requires-Dist: mypy>=1.19.1,<2.5 ; extra == 'dev'
|
|
47
|
-
Requires-Dist: pandas-stubs>=2.3.3.260113 ; extra == 'dev'
|
|
48
|
-
Requires-Dist: plotly-stubs>=0.0.6 ; extra == 'dev'
|
|
49
|
-
Requires-Dist: pre-commit>=4.5.1 ; extra == 'dev'
|
|
50
|
-
Requires-Dist: pytest>=9.0.2 ; extra == 'dev'
|
|
51
|
-
Requires-Dist: pytest-benchmark>=4.0.0 ; extra == 'dev'
|
|
52
|
-
Requires-Dist: pytest-cov>=7.0.0 ; extra == 'dev'
|
|
53
|
-
Requires-Dist: pytest-xdist>=3.8.0 ; extra == 'dev'
|
|
54
|
-
Requires-Dist: pydata-sphinx-theme>=0.16.1 ; extra == 'dev'
|
|
55
|
-
Requires-Dist: ruff>=0.11.0,<0.17 ; extra == 'dev'
|
|
56
|
-
Requires-Dist: sphinx>=8.1.3 ; extra == 'dev'
|
|
57
|
-
Requires-Dist: nbsphinx>=0.9.5 ; extra == 'dev'
|
|
58
|
-
Requires-Dist: ipykernel>=6.29 ; extra == 'dev'
|
|
59
|
-
Requires-Dist: tqdm-stubs>=0.2.1 ; extra == 'dev'
|
|
60
|
-
Requires-Dist: watchdog>=6.0.0 ; extra == 'dev'
|
|
61
42
|
Requires-Dist: numba>=0.63.1 ; extra == 'fast'
|
|
62
43
|
Requires-Dist: mcp>=2.0 ; extra == 'mcp'
|
|
63
44
|
Requires-Dist: matplotlib>=3.10.8 ; extra == 'plotting'
|
|
64
45
|
Requires-Dist: plotly>=6.5.2 ; extra == 'plotting'
|
|
65
46
|
Requires-Dist: ridgeplot>=0.5.0 ; extra == 'plotting'
|
|
66
47
|
Requires-Dist: seaborn>=0.13.2 ; extra == 'plotting'
|
|
67
|
-
Requires-Python: >=3.
|
|
48
|
+
Requires-Python: >=3.11
|
|
68
49
|
Project-URL: Homepage, https://github.com/kgdunn/process-improve
|
|
69
50
|
Project-URL: Documentation, https://kgdunn.github.io/process-improve/
|
|
70
51
|
Project-URL: Try it in your browser, https://kgdunn.github.io/process-improve/app/
|
|
@@ -75,7 +56,6 @@ Project-URL: Changelog, https://github.com/kgdunn/process-improve/blob/main/CHAN
|
|
|
75
56
|
Provides-Extra: all
|
|
76
57
|
Provides-Extra: batch
|
|
77
58
|
Provides-Extra: control
|
|
78
|
-
Provides-Extra: dev
|
|
79
59
|
Provides-Extra: fast
|
|
80
60
|
Provides-Extra: mcp
|
|
81
61
|
Provides-Extra: plotting
|
|
@@ -97,7 +77,7 @@ variable moved, and how sure am I?*
|
|
|
97
77
|
[](https://pypi.org/project/process-improve/)
|
|
98
78
|
[](https://pepy.tech/project/process-improve)
|
|
99
79
|
[](https://pepy.tech/project/process-improve)
|
|
100
|
-
[](https://github.com/kgdunn/process-improve/actions/workflows/run-tests.yml?query=branch%3Amain)
|
|
101
81
|
[](https://codecov.io/gh/kgdunn/process-improve)
|
|
102
82
|
[](https://kgdunn.github.io/process-improve/)
|
|
103
83
|
[](https://github.com/kgdunn/process-improve/blob/main/LICENSE)
|
|
@@ -353,7 +333,7 @@ pip install 'process-improve[fast]' # adds numba (JIT speedups for ba
|
|
|
353
333
|
pip install 'process-improve[all]' # everything above
|
|
354
334
|
```
|
|
355
335
|
|
|
356
|
-
Requires Python 3.
|
|
336
|
+
Requires Python 3.11 or newer. The core install pulls in `numpy`, `pandas`, `scipy`,
|
|
357
337
|
`scikit-learn`, `statsmodels`, `patsy`, `pydantic`, `pyyaml`, `threadpoolctl` and `tqdm`.
|
|
358
338
|
Heavier optional surfaces (plotting, Taguchi arrays, batch IO, batch control, the MCP server, numba JIT)
|
|
359
339
|
live in extras, so a caller who only needs, say, `detect_multivariate_outliers` does not have
|
|
@@ -399,6 +379,12 @@ specific version.
|
|
|
399
379
|
|
|
400
380
|
MIT: see [LICENSE](https://github.com/kgdunn/process-improve/blob/main/LICENSE) for details.
|
|
401
381
|
|
|
382
|
+
## Trademarks
|
|
383
|
+
|
|
384
|
+
OMARS® is a registered trademark of KU Leuven Research & Development. process-improve uses the
|
|
385
|
+
name only for the class of designs defined by Núñez Ares and Goos (2020), and is not affiliated
|
|
386
|
+
with, or endorsed by, KU Leuven, Minitab or Effex.
|
|
387
|
+
|
|
402
388
|
## Contributing
|
|
403
389
|
|
|
404
390
|
Bug reports, feature requests and pull requests are welcome. See
|
|
@@ -14,7 +14,7 @@ variable moved, and how sure am I?*
|
|
|
14
14
|
[](https://pypi.org/project/process-improve/)
|
|
15
15
|
[](https://pepy.tech/project/process-improve)
|
|
16
16
|
[](https://pepy.tech/project/process-improve)
|
|
17
|
-
[](https://github.com/kgdunn/process-improve/actions/workflows/run-tests.yml?query=branch%3Amain)
|
|
18
18
|
[](https://codecov.io/gh/kgdunn/process-improve)
|
|
19
19
|
[](https://kgdunn.github.io/process-improve/)
|
|
20
20
|
[](https://github.com/kgdunn/process-improve/blob/main/LICENSE)
|
|
@@ -270,7 +270,7 @@ pip install 'process-improve[fast]' # adds numba (JIT speedups for ba
|
|
|
270
270
|
pip install 'process-improve[all]' # everything above
|
|
271
271
|
```
|
|
272
272
|
|
|
273
|
-
Requires Python 3.
|
|
273
|
+
Requires Python 3.11 or newer. The core install pulls in `numpy`, `pandas`, `scipy`,
|
|
274
274
|
`scikit-learn`, `statsmodels`, `patsy`, `pydantic`, `pyyaml`, `threadpoolctl` and `tqdm`.
|
|
275
275
|
Heavier optional surfaces (plotting, Taguchi arrays, batch IO, batch control, the MCP server, numba JIT)
|
|
276
276
|
live in extras, so a caller who only needs, say, `detect_multivariate_outliers` does not have
|
|
@@ -316,6 +316,12 @@ specific version.
|
|
|
316
316
|
|
|
317
317
|
MIT: see [LICENSE](https://github.com/kgdunn/process-improve/blob/main/LICENSE) for details.
|
|
318
318
|
|
|
319
|
+
## Trademarks
|
|
320
|
+
|
|
321
|
+
OMARS® is a registered trademark of KU Leuven Research & Development. process-improve uses the
|
|
322
|
+
name only for the class of designs defined by Núñez Ares and Goos (2020), and is not affiliated
|
|
323
|
+
with, or endorsed by, KU Leuven, Minitab or Effex.
|
|
324
|
+
|
|
319
325
|
## Contributing
|
|
320
326
|
|
|
321
327
|
Bug reports, feature requests and pull requests are welcome. See
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "process-improve"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.2.0"
|
|
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"
|
|
7
|
-
requires-python = ">=3.
|
|
7
|
+
requires-python = ">=3.11"
|
|
8
8
|
keywords = [
|
|
9
9
|
"Designed Experiments",
|
|
10
10
|
"Design of Experiments",
|
|
@@ -20,11 +20,10 @@ keywords = [
|
|
|
20
20
|
"Batch data analysis",
|
|
21
21
|
]
|
|
22
22
|
classifiers = [
|
|
23
|
-
"Development Status ::
|
|
23
|
+
"Development Status :: 5 - Production/Stable",
|
|
24
24
|
"Intended Audience :: Science/Research",
|
|
25
25
|
"Operating System :: OS Independent",
|
|
26
26
|
"Programming Language :: Python :: 3",
|
|
27
|
-
"Programming Language :: Python :: 3.10",
|
|
28
27
|
"Programming Language :: Python :: 3.11",
|
|
29
28
|
"Programming Language :: Python :: 3.12",
|
|
30
29
|
"Programming Language :: Python :: 3.13",
|
|
@@ -75,26 +74,6 @@ all = [
|
|
|
75
74
|
"scikit-image>=0.25.2",
|
|
76
75
|
"seaborn>=0.13.2",
|
|
77
76
|
]
|
|
78
|
-
dev = [
|
|
79
|
-
"coverage>=7.13.1",
|
|
80
|
-
"hypothesis>=6.100",
|
|
81
|
-
"matplotlib-stubs>=0.3.11",
|
|
82
|
-
"mypy>=1.19.1,<2.5",
|
|
83
|
-
"pandas-stubs>=2.3.3.260113",
|
|
84
|
-
"plotly-stubs>=0.0.6",
|
|
85
|
-
"pre-commit>=4.5.1",
|
|
86
|
-
"pytest>=9.0.2",
|
|
87
|
-
"pytest-benchmark>=4.0.0",
|
|
88
|
-
"pytest-cov>=7.0.0",
|
|
89
|
-
"pytest-xdist>=3.8.0",
|
|
90
|
-
"pydata-sphinx-theme>=0.16.1",
|
|
91
|
-
"ruff>=0.11.0,<0.17",
|
|
92
|
-
"sphinx>=8.1.3",
|
|
93
|
-
"nbsphinx>=0.9.5",
|
|
94
|
-
"ipykernel>=6.29",
|
|
95
|
-
"tqdm-stubs>=0.2.1",
|
|
96
|
-
"watchdog>=6.0.0",
|
|
97
|
-
]
|
|
98
77
|
|
|
99
78
|
[project.scripts]
|
|
100
79
|
process-improve-mcp = "process_improve.mcp_server:main"
|
|
@@ -168,6 +147,7 @@ select = ["ALL"]
|
|
|
168
147
|
ignore = [
|
|
169
148
|
"CPY001",
|
|
170
149
|
"C408",
|
|
150
|
+
"UP042",
|
|
171
151
|
"ARG001",
|
|
172
152
|
"ANN002",
|
|
173
153
|
"ANN003",
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "process-improve"
|
|
3
|
-
version = "2.
|
|
3
|
+
version = "2.2.0"
|
|
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"
|
|
7
|
-
requires-python = ">=3.
|
|
7
|
+
requires-python = ">=3.11"
|
|
8
8
|
keywords = ["Designed Experiments", "Design of Experiments", "DoE", "Optimal Design", "Response Surface", "Latent Variables", "PCA", "PLS", "Multivariate Data Analysis", "Chemometrics", "Process Monitoring", "Batch data analysis"]
|
|
9
9
|
classifiers = [
|
|
10
|
-
"Development Status ::
|
|
10
|
+
"Development Status :: 5 - Production/Stable",
|
|
11
11
|
"Intended Audience :: Science/Research",
|
|
12
12
|
"Operating System :: OS Independent",
|
|
13
13
|
"Programming Language :: Python :: 3",
|
|
14
|
-
"Programming Language :: Python :: 3.10",
|
|
15
14
|
"Programming Language :: Python :: 3.11",
|
|
16
15
|
"Programming Language :: Python :: 3.12",
|
|
17
16
|
"Programming Language :: Python :: 3.13",
|
|
@@ -28,17 +27,18 @@ dependencies = [
|
|
|
28
27
|
# MCP server, JIT speedups) live in extras; install
|
|
29
28
|
# ``process-improve[all]`` to reproduce the pre-1.24.11 closure.
|
|
30
29
|
"numpy>=2.2.6",
|
|
31
|
-
# Both pandas majors are supported.
|
|
32
|
-
#
|
|
30
|
+
# Both pandas majors are supported. CI's Python 3.11 jobs install the lowest
|
|
31
|
+
# version each dependency allows, so they test pandas 2.3; the newer Pythons
|
|
32
|
+
# test pandas 3.
|
|
33
33
|
"pandas>=2.3.3",
|
|
34
34
|
"patsy>=1.0.2",
|
|
35
35
|
"pydantic>=2.12.5",
|
|
36
36
|
"pyyaml>=6.0",
|
|
37
37
|
"scikit-learn>=1.7.2",
|
|
38
38
|
# Declared directly because generate_omars solves its ILP with
|
|
39
|
-
# scipy.optimize.milp (HiGHS). 1.15 is the oldest release CI runs (
|
|
40
|
-
# 3.
|
|
41
|
-
# node-limited stop differently and is not tested here.
|
|
39
|
+
# scipy.optimize.milp (HiGHS). 1.15 is the oldest release CI runs (the
|
|
40
|
+
# Python 3.11 jobs resolve 1.15.0); older releases bundle HiGHS 1.2, which
|
|
41
|
+
# reports a node-limited stop differently and is not tested here.
|
|
42
42
|
"scipy>=1.15",
|
|
43
43
|
"statsmodels>=0.14.6",
|
|
44
44
|
# Already required by scikit-learn; declared because the REML fits of the
|
|
@@ -108,27 +108,6 @@ all = [
|
|
|
108
108
|
"seaborn>=0.13.2",
|
|
109
109
|
]
|
|
110
110
|
|
|
111
|
-
dev = [
|
|
112
|
-
"coverage>=7.13.1",
|
|
113
|
-
"hypothesis>=6.100",
|
|
114
|
-
"matplotlib-stubs>=0.3.11",
|
|
115
|
-
"mypy>=1.19.1,<2.5",
|
|
116
|
-
"pandas-stubs>=2.3.3.260113",
|
|
117
|
-
"plotly-stubs>=0.0.6",
|
|
118
|
-
"pre-commit>=4.5.1",
|
|
119
|
-
"pytest>=9.0.2",
|
|
120
|
-
"pytest-benchmark>=4.0.0",
|
|
121
|
-
"pytest-cov>=7.0.0",
|
|
122
|
-
"pytest-xdist>=3.8.0",
|
|
123
|
-
"pydata-sphinx-theme>=0.16.1",
|
|
124
|
-
"ruff>=0.11.0,<0.17", # upper-bound so a future ruff release cannot silently break the lint gate (see mypy)
|
|
125
|
-
"sphinx>=8.1.3",
|
|
126
|
-
"nbsphinx>=0.9.5",
|
|
127
|
-
"ipykernel>=6.29",
|
|
128
|
-
"tqdm-stubs>=0.2.1",
|
|
129
|
-
"watchdog>=6.0.0",
|
|
130
|
-
]
|
|
131
|
-
|
|
132
111
|
[project.scripts]
|
|
133
112
|
process-improve-mcp = "process_improve.mcp_server:main"
|
|
134
113
|
|
|
@@ -147,6 +126,8 @@ requires = ["uv_build>=0.7.2,<0.14"]
|
|
|
147
126
|
build-backend = "uv_build"
|
|
148
127
|
|
|
149
128
|
[dependency-groups]
|
|
129
|
+
# The contributors' tools. A dependency group rather than an extra, so the
|
|
130
|
+
# published wheel does not offer them to users (#513).
|
|
150
131
|
dev = [
|
|
151
132
|
"coverage>=7.13.1",
|
|
152
133
|
"hypothesis>=6.100",
|
|
@@ -249,6 +230,10 @@ ignore = [
|
|
|
249
230
|
|
|
250
231
|
"C408", # Unnecessary <dict/list/tuple> call - rewrite as a literal. Disagree with this.
|
|
251
232
|
|
|
233
|
+
# A `(str, Enum)` class turned into `StrEnum` changes what str() and format()
|
|
234
|
+
# return for its members, and these enums are public API.
|
|
235
|
+
"UP042", # Class inherits from both `str` and `enum.Enum`
|
|
236
|
+
|
|
252
237
|
# Arguments
|
|
253
238
|
"ARG001", # Unusued argument
|
|
254
239
|
|
|
@@ -42,8 +42,7 @@ if typing.TYPE_CHECKING:
|
|
|
42
42
|
|
|
43
43
|
_UNFOLDED_INDEX_ERROR = (
|
|
44
44
|
"needs the 2-level (tag, sequence) index that process_improve.batch.dict_to_wide produces. "
|
|
45
|
-
"
|
|
46
|
-
"which drops the multi-level labels."
|
|
45
|
+
"Fit the model to that matrix, or to MCUVScaler's output of it, which keeps the index."
|
|
47
46
|
)
|
|
48
47
|
|
|
49
48
|
|
|
@@ -203,8 +202,7 @@ def unfolded_contribution_plot(
|
|
|
203
202
|
``t2_contributions`` on :class:`process_improve.batch.BatchPCA` or
|
|
204
203
|
:class:`process_improve.batch.BatchPLS`, or of the standalone
|
|
205
204
|
:mod:`process_improve.multivariate` functions on a model fitted to a
|
|
206
|
-
:func:`process_improve.batch.dict_to_wide` matrix
|
|
207
|
-
was re-attached after scaling.
|
|
205
|
+
:func:`process_improve.batch.dict_to_wide` matrix, scaled or not.
|
|
208
206
|
batch_id : Hashable, optional
|
|
209
207
|
Which batch (row) to plot. Defaults to the first row.
|
|
210
208
|
by_tag : bool, default=False
|
|
@@ -528,7 +528,10 @@ def midcourse_correction( # noqa: PLR0913, PLR0912, PLR0915, C901
|
|
|
528
528
|
# bisect each active multiplier down so the achieved statistic lands just
|
|
529
529
|
# inside its cap instead of far below it (the escalation overshoots).
|
|
530
530
|
# Each statistic is non-increasing in its own multiplier for this convex
|
|
531
|
-
# problem, so the per-coordinate bisection is well posed.
|
|
531
|
+
# problem, so the per-coordinate bisection is well posed. Lowering one
|
|
532
|
+
# multiplier can raise the other statistic, so a bisection step is taken
|
|
533
|
+
# only when both caps still hold: every accepted schedule meets both, and
|
|
534
|
+
# an "ok" status means they hold (#681).
|
|
532
535
|
mu_spe = mu_t2 = 0.0
|
|
533
536
|
n_solves = 0
|
|
534
537
|
u_star = _solve(mu_spe, mu_t2)
|
|
@@ -538,6 +541,10 @@ def midcourse_correction( # noqa: PLR0913, PLR0912, PLR0915, C901
|
|
|
538
541
|
spe_cap_value = float("inf") if spe_cap is None else float(spe_cap)
|
|
539
542
|
t2_cap_value = float("inf") if t2_cap is None else float(t2_cap)
|
|
540
543
|
cap_status = "ok"
|
|
544
|
+
|
|
545
|
+
def _within_caps(spe: float, t2: float) -> bool:
|
|
546
|
+
return spe <= spe_cap_value * (1 + _CAP_REL_TOL) and t2 <= t2_cap_value * (1 + _CAP_REL_TOL)
|
|
547
|
+
|
|
541
548
|
for _ in range(30):
|
|
542
549
|
spe_bad = spe_value > spe_cap_value * (1 + _CAP_REL_TOL)
|
|
543
550
|
t2_bad = t2_value > t2_cap_value * (1 + _CAP_REL_TOL)
|
|
@@ -561,12 +568,12 @@ def midcourse_correction( # noqa: PLR0913, PLR0912, PLR0915, C901
|
|
|
561
568
|
mid = 0.5 * (low_mu + high_mu)
|
|
562
569
|
u_try = _solve(mid, mu_t2)
|
|
563
570
|
n_solves += 1
|
|
564
|
-
spe_try,
|
|
565
|
-
if
|
|
571
|
+
spe_try, t2_try = _statistics(u_try)
|
|
572
|
+
if not _within_caps(spe_try, t2_try):
|
|
566
573
|
low_mu = mid
|
|
567
574
|
else:
|
|
568
575
|
high_mu = mid
|
|
569
|
-
u_star, spe_value, t2_value = u_try, spe_try,
|
|
576
|
+
u_star, spe_value, t2_value = u_try, spe_try, t2_try
|
|
570
577
|
if spe_try >= spe_cap_value * (1 - _CAP_REL_TOL):
|
|
571
578
|
break
|
|
572
579
|
mu_spe = high_mu
|
|
@@ -577,7 +584,7 @@ def midcourse_correction( # noqa: PLR0913, PLR0912, PLR0915, C901
|
|
|
577
584
|
u_try = _solve(mu_spe, mid)
|
|
578
585
|
n_solves += 1
|
|
579
586
|
spe_try, t2_try = _statistics(u_try)
|
|
580
|
-
if
|
|
587
|
+
if not _within_caps(spe_try, t2_try):
|
|
581
588
|
low_mu = mid
|
|
582
589
|
else:
|
|
583
590
|
high_mu = mid
|
|
@@ -585,9 +592,7 @@ def midcourse_correction( # noqa: PLR0913, PLR0912, PLR0915, C901
|
|
|
585
592
|
if t2_try >= t2_cap_value * (1 - _CAP_REL_TOL):
|
|
586
593
|
break
|
|
587
594
|
mu_t2 = high_mu
|
|
588
|
-
|
|
589
|
-
t2_ok = t2_value <= t2_cap_value * (1 + _CAP_REL_TOL)
|
|
590
|
-
if spe_ok and t2_ok:
|
|
595
|
+
if _within_caps(spe_value, t2_value):
|
|
591
596
|
break
|
|
592
597
|
|
|
593
598
|
scores = b + A_F @ u_star
|
|
@@ -610,10 +615,22 @@ def midcourse_correction( # noqa: PLR0913, PLR0912, PLR0915, C901
|
|
|
610
615
|
kind = name.split(":", 1)[0]
|
|
611
616
|
key = "bounds" if kind == "bound" else "rate"
|
|
612
617
|
typing.cast("list", active[key]).append(name.split(":", 1)[1])
|
|
618
|
+
|
|
619
|
+
def _binding(statistic: str) -> bool:
|
|
620
|
+
"""Return whether a cap holds its statistic down: with its multiplier at zero, the statistic breaks it."""
|
|
621
|
+
nonlocal n_solves
|
|
622
|
+
n_solves += 1
|
|
623
|
+
if statistic == "spe":
|
|
624
|
+
return _statistics(_solve(0.0, mu_t2))[0] > spe_cap_value * (1 + _CAP_REL_TOL)
|
|
625
|
+
return _statistics(_solve(mu_spe, 0.0))[1] > t2_cap_value * (1 + _CAP_REL_TOL)
|
|
626
|
+
|
|
627
|
+
# A cap is active where its statistic sits at it (within the tolerance), or above it when it
|
|
628
|
+
# could not be met. Below it, a multiplier left over from the bisection is binding only if
|
|
629
|
+
# dropping it would break the cap: one bisected down because its cap is slack is not (#681).
|
|
613
630
|
if spe_cap is not None:
|
|
614
|
-
active["spe_cap"] =
|
|
631
|
+
active["spe_cap"] = spe_value >= spe_cap_value * (1 - _CAP_REL_TOL) or (mu_spe > 0 and _binding("spe"))
|
|
615
632
|
if t2_cap is not None:
|
|
616
|
-
active["t2_cap"] =
|
|
633
|
+
active["t2_cap"] = t2_value >= t2_cap_value * (1 - _CAP_REL_TOL) or (mu_t2 > 0 and _binding("t2"))
|
|
617
634
|
|
|
618
635
|
return Bunch(
|
|
619
636
|
mv=mv,
|
|
@@ -50,10 +50,12 @@ def _prepare_data( # noqa: C901, PLR0912
|
|
|
50
50
|
if phase_col is None:
|
|
51
51
|
phase_col = "__phase_grouper__"
|
|
52
52
|
|
|
53
|
+
# The fake grouping columns are added with `assign`, which returns a new frame: an
|
|
54
|
+
# in-place `insert` added them to the caller's DataFrame as well.
|
|
53
55
|
if phase_col not in df:
|
|
54
56
|
# Cannot use "None" or 'nan'; else it won't group in the
|
|
55
57
|
# groupby([batch_col, phase_col]) statement below.
|
|
56
|
-
df.
|
|
58
|
+
df = df.assign(**{phase_col: "NoPhases"})
|
|
57
59
|
|
|
58
60
|
# If no batch_col: add a fake column with all the same values
|
|
59
61
|
if batch_col not in df or batch_col is None:
|
|
@@ -61,7 +63,7 @@ def _prepare_data( # noqa: C901, PLR0912
|
|
|
61
63
|
if batch_col not in df:
|
|
62
64
|
# Cannot use "None" or 'nan'; else it won't group in the
|
|
63
65
|
# groupby([batch_col, phase_col]) statement below.
|
|
64
|
-
df.
|
|
66
|
+
df = df.assign(**{batch_col: 1})
|
|
65
67
|
|
|
66
68
|
if tags is None:
|
|
67
69
|
tags = list(df.columns)
|
|
@@ -226,12 +228,18 @@ def f_iqr(
|
|
|
226
228
|
The difference between the 75th percentile and the 25th percentile of a
|
|
227
229
|
sample this is the 25 % trimmed range, an example of an L - estimator.
|
|
228
230
|
|
|
229
|
-
|
|
231
|
+
Missing values are omitted, as ``f_std`` and ``f_robust_mad`` omit them.
|
|
232
|
+
|
|
233
|
+
See also: f_std, f_robust_mad
|
|
230
234
|
"""
|
|
231
235
|
base_name = "iqr"
|
|
236
|
+
|
|
237
|
+
def _iqr(col: pd.Series) -> float:
|
|
238
|
+
return float(iqr(col, nan_policy="omit"))
|
|
239
|
+
|
|
232
240
|
prepared, tags, output, _ = _prepare_data(data, tags, batch_col, phase_col)
|
|
233
241
|
f_names = [(tag + "_" + base_name) for tag in tags]
|
|
234
|
-
output = prepared.agg(
|
|
242
|
+
output = prepared.agg(_iqr)
|
|
235
243
|
return output.rename(columns=dict(zip(tags, f_names, strict=False)))
|
|
236
244
|
|
|
237
245
|
|
|
@@ -282,8 +290,6 @@ def f_sum(
|
|
|
282
290
|
|
|
283
291
|
If the x-axis (time) data are evenly-spaced, then this is directly
|
|
284
292
|
proportional to the area under the trace (curve/trajectory).
|
|
285
|
-
|
|
286
|
-
See also: f_cumsum
|
|
287
293
|
"""
|
|
288
294
|
base_name = "sum"
|
|
289
295
|
prepared, tags, output, _ = _prepare_data(data, tags, batch_col, phase_col)
|
|
@@ -310,6 +316,9 @@ def f_area(
|
|
|
310
316
|
The spacing of the x-axis is taken into account, so, this will produce
|
|
311
317
|
accurate areas if the data are not evenly-spaced in time along the x-axis.
|
|
312
318
|
|
|
319
|
+
A datetime or timedelta time axis is measured in seconds, so the area is in the tag's
|
|
320
|
+
units multiplied by seconds. A numeric time axis is used in its own units.
|
|
321
|
+
|
|
313
322
|
The area is calculated using the trapezoidal rule.
|
|
314
323
|
|
|
315
324
|
See also: f_sum, f_cumsum
|
|
@@ -323,7 +332,13 @@ def f_area(
|
|
|
323
332
|
for batch_id, this_batch in prepared:
|
|
324
333
|
# Average width of the base * height. For time series, the average width of the base is
|
|
325
334
|
# the same as the sampling intervals. Therefore the diff of the index.
|
|
326
|
-
|
|
335
|
+
time_axis = this_batch.index
|
|
336
|
+
if isinstance(time_axis, pd.DatetimeIndex | pd.TimedeltaIndex):
|
|
337
|
+
# A plain diff gives timedelta64 widths, which made the area a timedelta that a
|
|
338
|
+
# float column cannot hold. Seconds keep it a number in a stated unit.
|
|
339
|
+
half_base_factor = np.asarray(pd.TimedeltaIndex(time_axis[1:] - time_axis[:-1]).total_seconds())
|
|
340
|
+
else:
|
|
341
|
+
half_base_factor = np.diff(time_axis)
|
|
327
342
|
for tag in tags:
|
|
328
343
|
# Now the sum makes sense: gets the area under the curve by adding
|
|
329
344
|
# up the smaller trapezoids: consider the trapezoids as rotated by 90 degrees.
|
|
@@ -433,7 +448,7 @@ def f_rupture(
|
|
|
433
448
|
``display`` helper that uses matplotlib; plotting belongs to the caller, and the rest
|
|
434
449
|
of this project plots with plotly.
|
|
435
450
|
|
|
436
|
-
See also: f_elbow,
|
|
451
|
+
See also: f_elbow, f_crossing
|
|
437
452
|
"""
|
|
438
453
|
default_settings: dict = {"model": "rbf", "penalty": None, "min_size": 2, "jump": 5}
|
|
439
454
|
if settings:
|
|
@@ -779,8 +794,10 @@ def f_crossing( # noqa: PLR0913
|
|
|
779
794
|
|
|
780
795
|
f_name = tag + "_" + base_name
|
|
781
796
|
|
|
782
|
-
def _cross_first(x: pd.DataFrame) -> np.ndarray | list:
|
|
783
|
-
|
|
797
|
+
def _cross_first(x: pd.DataFrame) -> np.ndarray | list | float:
|
|
798
|
+
crossing = cross(x[tag], threshold, direction, only_index=only_index, first_point_only=True)
|
|
799
|
+
# `cross` returns an empty array when there is no crossing; the documented feature is NaN.
|
|
800
|
+
return np.nan if np.size(crossing) == 0 else crossing
|
|
784
801
|
|
|
785
802
|
# pandas-stubs' DFCallable1 protocol does not include ``np.ndarray`` among the allowed
|
|
786
803
|
# return types, although groupby.apply accepts array-returning callables at runtime.
|
|
@@ -806,7 +823,7 @@ def f_elbow( # noqa: PLR0913
|
|
|
806
823
|
The elbow is calculated against whichever variable is given by `x_axis_tag` (usually a time-
|
|
807
824
|
based tag).
|
|
808
825
|
|
|
809
|
-
The function returns the *value* on the x-axis where the
|
|
826
|
+
The function returns the *value* on the x-axis where the elbow occurs. Sometimes you might
|
|
810
827
|
want the *index* of the value, so you can also find the corresponding y-axis value. Use
|
|
811
828
|
`only_index=True` for such cases.
|
|
812
829
|
"""
|
|
@@ -582,6 +582,10 @@ _HUBER_CUTOFF = 1.345
|
|
|
582
582
|
#: Smallest batch weight :func:`_batch_weights` will return, so no batch is ever silenced.
|
|
583
583
|
_MIN_BATCH_WEIGHT = 1e-3
|
|
584
584
|
|
|
585
|
+
#: Iterations of :func:`batch_dtw` that align every batch to the ``reference_batch``. Each later
|
|
586
|
+
#: iteration aligns to the average trajectory of the iteration before it.
|
|
587
|
+
_ITERATIONS_ON_THE_REFERENCE_BATCH = 3
|
|
588
|
+
|
|
585
589
|
|
|
586
590
|
def _batch_weights(aligned_batches: dict, batch_weighting: str) -> np.ndarray:
|
|
587
591
|
"""
|
|
@@ -721,7 +725,7 @@ def one_iteration_dtw(
|
|
|
721
725
|
aligned_batches[batch_id] = result
|
|
722
726
|
successful_alignments += 1
|
|
723
727
|
|
|
724
|
-
except ValueError as exc:
|
|
728
|
+
except ValueError as exc:
|
|
725
729
|
# Chain the cause: a band constraint that is too narrow explains itself, and
|
|
726
730
|
# that explanation is the actionable part. `from None` discarded it.
|
|
727
731
|
raise ValueError(f"Failed on batch {batch_id}: {exc}") from exc
|
|
@@ -818,6 +822,11 @@ def batch_dtw( # noqa: PLR0915
|
|
|
818
822
|
"interpolate_method": "cubic", # any scipy.interpolate.interp1d method
|
|
819
823
|
}
|
|
820
824
|
|
|
825
|
+
Every batch is aligned to ``reference_batch`` in the first three iterations. From
|
|
826
|
+
the fourth iteration on, the reference is the average trajectory of the iteration
|
|
827
|
+
before, so the result depends less on which batch was chosen as the reference. The
|
|
828
|
+
number three is fixed, not a setting.
|
|
829
|
+
|
|
821
830
|
The default settings resample the time axis to 100 points, starting at 0 and ending
|
|
822
831
|
at 99, so each point is one percent of the batch's duration however long the batch
|
|
823
832
|
actually ran. Lower the delta for a finer axis (``0.5`` gives 200 points, ``0.25``
|
|
@@ -932,7 +941,12 @@ def batch_dtw( # noqa: PLR0915
|
|
|
932
941
|
average_batch = None
|
|
933
942
|
delta_weight: np.floating | np.ndarray = np.linalg.norm(weight_vector)
|
|
934
943
|
iter_step = 0
|
|
935
|
-
|
|
944
|
+
# The first iteration runs whatever the tolerance: it is the one that aligns the batches,
|
|
945
|
+
# and everything after the loop reads its results. A tolerance at or above the norm of
|
|
946
|
+
# the unit weights (the square root of the number of columns) used to skip it entirely.
|
|
947
|
+
while iter_step == 0 or (
|
|
948
|
+
(np.linalg.norm(delta_weight) > settings["tolerance"]) and (iter_step <= settings["maximum_iterations"])
|
|
949
|
+
):
|
|
936
950
|
if settings["show_progress"]:
|
|
937
951
|
print(f"Iter = {iter_step} and norm = {np.linalg.norm(delta_weight)}") # noqa: T201
|
|
938
952
|
|
|
@@ -946,7 +960,7 @@ def batch_dtw( # noqa: PLR0915
|
|
|
946
960
|
weight_matrix = np.diag(weight_vector)
|
|
947
961
|
weight_history = np.vstack((weight_history, weight_vector.copy()))
|
|
948
962
|
|
|
949
|
-
if iter_step >
|
|
963
|
+
if iter_step > _ITERATIONS_ON_THE_REFERENCE_BATCH:
|
|
950
964
|
refbatch_sc = average_batch
|
|
951
965
|
|
|
952
966
|
aligned_batches, average_batch = one_iteration_dtw(
|
|
@@ -1029,9 +1043,10 @@ def batch_dtw( # noqa: PLR0915
|
|
|
1029
1043
|
result.synced = synced_interpolated
|
|
1030
1044
|
aligned_df_collection.append(synced_interpolated)
|
|
1031
1045
|
|
|
1032
|
-
#
|
|
1046
|
+
# Each frame's batch_id column already holds its own dictionary key. Casting the whole
|
|
1047
|
+
# column to the type of the last key turned an integer key into a string one whenever
|
|
1048
|
+
# the keys were of mixed types, so the caller could no longer look its batch up.
|
|
1033
1049
|
aligned_df = pd.concat(aligned_df_collection)
|
|
1034
|
-
aligned_df["batch_id"] = aligned_df["batch_id"].astype(type(batch_id))
|
|
1035
1050
|
|
|
1036
1051
|
last_average_batch = reverse_scaling(dict(avg=cast("pd.DataFrame", average_batch)), scale_df)["avg"]
|
|
1037
1052
|
aligned_batch_dfdict = melted_to_dict(aligned_df, batch_id_col="batch_id")
|
|
@@ -1083,6 +1098,12 @@ def resample_to_reference(
|
|
|
1083
1098
|
-------
|
|
1084
1099
|
dict
|
|
1085
1100
|
Batch data, in the standard format.
|
|
1101
|
+
|
|
1102
|
+
Raises
|
|
1103
|
+
------
|
|
1104
|
+
ValueError
|
|
1105
|
+
If a batch, the reference among them, has fewer than 2 rows: there is nothing to
|
|
1106
|
+
interpolate between.
|
|
1086
1107
|
"""
|
|
1087
1108
|
default_settings = {
|
|
1088
1109
|
"interpolate_kind": "cubic", # must be a valid "scipy.interpolate.interp1d" `kind`
|
|
@@ -1090,6 +1111,14 @@ def resample_to_reference(
|
|
|
1090
1111
|
if settings:
|
|
1091
1112
|
default_settings.update(settings)
|
|
1092
1113
|
settings = default_settings
|
|
1114
|
+
# Each batch's time axis is scaled to [0, 1] by dividing by its last row number, which is
|
|
1115
|
+
# 0 for a single row: the division gave NaN and scipy then refused an "all-nan" axis.
|
|
1116
|
+
too_short = {batch_id: batch.shape[0] for batch_id, batch in batches.items() if batch.shape[0] < 2}
|
|
1117
|
+
if too_short:
|
|
1118
|
+
raise ValueError(
|
|
1119
|
+
f"resample_to_reference needs at least 2 rows in every batch, to interpolate between; "
|
|
1120
|
+
f"these batches have fewer (batch: rows): {too_short}."
|
|
1121
|
+
)
|
|
1093
1122
|
out = {}
|
|
1094
1123
|
target_time = np.arange(0, batches[reference_batch].shape[0])
|
|
1095
1124
|
target_time = target_time / target_time[-1]
|
{process_improve-2.0.0 → process_improve-2.2.0}/src/process_improve/bivariate/_elbow_peak.py
RENAMED
|
@@ -26,6 +26,10 @@ def find_elbow_point(x: np.ndarray, y: np.ndarray, max_iter: int = 41) -> int |
|
|
|
26
26
|
the median of the accumulated intersection points; the median location is
|
|
27
27
|
where the intersections should stabilise.
|
|
28
28
|
|
|
29
|
+
Both axes are first scaled to span 0 to 1, so that "closest" does not add up
|
|
30
|
+
distances in two different units. The elbow is therefore the same whatever
|
|
31
|
+
units `x` and `y` are in: time in seconds or in hours gives the same index.
|
|
32
|
+
|
|
29
33
|
Will probably not work well on few data points. If so, try fitting a spline
|
|
30
34
|
to the raw data and then repeat with the interpolated data.
|
|
31
35
|
|
|
@@ -81,19 +85,22 @@ def find_elbow_point(x: np.ndarray, y: np.ndarray, max_iter: int = 41) -> int |
|
|
|
81
85
|
if len(x) <= 10:
|
|
82
86
|
raise ValueError("Requires more than 10 values in the vectors (not including missing data).")
|
|
83
87
|
idx_sort = x.argsort()
|
|
84
|
-
x = x[idx_sort]
|
|
85
|
-
y = y[idx_sort]
|
|
88
|
+
x = _scale_to_unit_range(x[idx_sort])
|
|
89
|
+
y = _scale_to_unit_range(y[idx_sort])
|
|
86
90
|
N = x.size
|
|
87
91
|
|
|
88
92
|
int_x_list: list[float] = []
|
|
89
93
|
int_y_list: list[float] = []
|
|
94
|
+
# On fewer than about 2 * max_iter points the floored window sizes repeat, so each size is
|
|
95
|
+
# fitted once. A repeat still adds its intersection again, which keeps the median unchanged.
|
|
96
|
+
intersections: dict[int, tuple] = {}
|
|
90
97
|
for i in np.floor(np.linspace(0, int(N / 2 - start) + 1, max_iter)):
|
|
91
98
|
idx = int(start + i)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
int_x, int_y =
|
|
99
|
+
if idx not in intersections:
|
|
100
|
+
lft = fit_robust_lm(x[0:idx], y[0:idx])
|
|
101
|
+
rgt = fit_robust_lm(x[-idx:], y[-idx:])
|
|
102
|
+
intersections[idx] = find_line_intersection(lft[1], lft[0], rgt[1], rgt[0])
|
|
103
|
+
int_x, int_y = intersections[idx]
|
|
97
104
|
int_x_list.append(int_x)
|
|
98
105
|
int_y_list.append(int_y)
|
|
99
106
|
|
|
@@ -110,6 +117,12 @@ def find_elbow_point(x: np.ndarray, y: np.ndarray, max_iter: int = 41) -> int |
|
|
|
110
117
|
return int(np.argmin(calculate_line_length(mid_x, mid_y, x, y)))
|
|
111
118
|
|
|
112
119
|
|
|
120
|
+
def _scale_to_unit_range(values: np.ndarray) -> np.ndarray:
|
|
121
|
+
"""Shift and scale ``values`` to span 0 to 1; a constant vector is only shifted, to 0."""
|
|
122
|
+
span = float(np.ptp(values))
|
|
123
|
+
return (values - values.min()) / (span if span > 0 else 1.0)
|
|
124
|
+
|
|
125
|
+
|
|
113
126
|
def find_line_intersection(m1: float, b1: float, m2: float, b2: float) -> tuple:
|
|
114
127
|
"""
|
|
115
128
|
Find the intersection point of two lines.
|
|
@@ -251,7 +251,7 @@ class Settings:
|
|
|
251
251
|
|
|
252
252
|
@property
|
|
253
253
|
def max_memory_mb(self) -> int:
|
|
254
|
-
"""
|
|
254
|
+
"""Address space a tool's subprocess may map beyond what its imports mapped (MiB)."""
|
|
255
255
|
return self._get("max_memory_mb", _read_env_int)
|
|
256
256
|
|
|
257
257
|
@max_memory_mb.setter
|