DaSPi 2.5.0__tar.gz → 2.7.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.
Files changed (186) hide show
  1. {daspi-2.5.0 → daspi-2.7.0}/PKG-INFO +1 -1
  2. {daspi-2.5.0 → daspi-2.7.0}/daspi/__init__.py +6 -0
  3. {daspi-2.5.0 → daspi-2.7.0}/daspi/anova/model.py +3 -2
  4. {daspi-2.5.0 → daspi-2.7.0}/daspi/constants.py +21 -0
  5. {daspi-2.5.0 → daspi-2.7.0}/daspi/plotlib/chart.py +143 -1
  6. {daspi-2.5.0 → daspi-2.7.0}/daspi/plotlib/plotter.py +371 -0
  7. {daspi-2.5.0 → daspi-2.7.0}/daspi/strings.py +15 -0
  8. {daspi-2.5.0 → daspi-2.7.0}/pyproject.toml +1 -1
  9. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Formatting_Features_Test_alignments_basic.png +0 -0
  10. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Formatting_Features_Test_all_alignments.png +0 -0
  11. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Formatting_Features_Test_angles_basic.png +0 -0
  12. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Formatting_Features_Test_callable_formatters.png +0 -0
  13. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Formatting_Features_Test_combined_all_features.png +0 -0
  14. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Formatting_Features_Test_extreme_angles.png +0 -0
  15. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Formatting_Features_Test_formatters_basic.png +0 -0
  16. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Formatting_Features_Test_formatters_scientific.png +0 -0
  17. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Formatting_Features_Test_multivariate_formatting.png +0 -0
  18. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Formatting_Features_Test_orientation_mapping.png +0 -0
  19. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Formatting_Features_Test_percentage_formatter.png +0 -0
  20. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/GaussianKDEContourUnivariate_comparison_with_violin.png +0 -0
  21. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/GaussianKDEContourUnivariate_custom_color.png +0 -0
  22. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/GaussianKDEContourUnivariate_custom_width.png +0 -0
  23. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/GaussianKDEContourUnivariate_joint_chart_mixed_plots.png +0 -0
  24. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/GaussianKDEContourUnivariate_multivariate_chart_facets.png +0 -0
  25. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/GaussianKDEContourUnivariate_resolution_high.png +0 -0
  26. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_horizontal.png +0 -0
  27. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_no_fade.png +0 -0
  28. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_no_fill.png +0 -0
  29. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_simple.png +0 -0
  30. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/GaussianKDEContourUnivariate_single_chart_with_hue.png +0 -0
  31. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/JointChart_bar_stacking.png +0 -0
  32. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/JointChart_pareto_marked.png +0 -0
  33. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/JointChart_probability_dists-prob.png +0 -0
  34. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/JointChart_regression_kde.png +0 -0
  35. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/MultivariateChart_full-stripes.png +0 -0
  36. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/MultivariateChart_full.png +0 -0
  37. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_bivariate-univariate-charts_contour-mean-test.png +0 -0
  38. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_bivariate-univariate-charts_mean-test.png +0 -0
  39. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_bivariate-univariate-charts_simple.png +0 -0
  40. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_bivariate-univariate-charts_smoothed.png +0 -0
  41. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_bivariate-univariate-charts_user.png +0 -0
  42. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_goodness_of_fit_charts_basic.png +0 -0
  43. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_goodness_of_fit_charts_refit-epoch-7.png +0 -0
  44. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_pair_comparison_charts_basic.png +0 -0
  45. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_parameter_relevance_charts_basic.png +0 -0
  46. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_process-capabity-analysis-charts_hue.png +0 -0
  47. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_residual_charts_basic.png +0 -0
  48. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_KDE-cumulative_multiple.png +0 -0
  49. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_KDE_multiple.png +0 -0
  50. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_KDE_ridge.png +0 -0
  51. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_beeswarm_multiple.png +0 -0
  52. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_beeswarm_simple.png +0 -0
  53. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_blandaltman_simple.png +0 -0
  54. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_blandaltman_user.png +0 -0
  55. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_box_fill.png +0 -0
  56. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_box_multiple.png +0 -0
  57. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_box_simple.png +0 -0
  58. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_categorical-float-features_simple.png +0 -0
  59. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_errorbar_mean-test.png +0 -0
  60. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_errorbar_sem.png +0 -0
  61. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_errorbar_std-test.png +0 -0
  62. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_errorbar_var-test.png +0 -0
  63. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_fitted-density_cdf-multiple.png +0 -0
  64. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_jitter_multiple.png +0 -0
  65. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_jitter_simple.png +0 -0
  66. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_line_hue.png +0 -0
  67. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_line_hue_size.png +0 -0
  68. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_pareto-threshold_simple.png +0 -0
  69. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_pareto_simple.png +0 -0
  70. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_pareto_transposed.png +0 -0
  71. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_quantiles_multiple.png +0 -0
  72. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_quantiles_simple.png +0 -0
  73. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_full.png +0 -0
  74. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_hue-shape.png +0 -0
  75. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_hue-size.png +0 -0
  76. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_hue.png +0 -0
  77. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_shape.png +0 -0
  78. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_size-shape.png +0 -0
  79. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_size.png +0 -0
  80. daspi-2.7.0/tests/charts/SingleChart_smoothing_ma-ema.png +0 -0
  81. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_violin_mono.png +0 -0
  82. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_violin_multiple.png +0 -0
  83. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_violin_simple.png +0 -0
  84. {daspi-2.5.0 → daspi-2.7.0}/tests/plotlib_chart_test.py +94 -0
  85. {daspi-2.5.0 → daspi-2.7.0}/tests/plotlib_plotter_test.py +151 -0
  86. {daspi-2.5.0 → daspi-2.7.0}/tests/plotlib_visual_test.py +35 -0
  87. daspi-2.5.0/tests/charts/_debug_kde_bottom_crop.png +0 -0
  88. daspi-2.5.0/tests/charts/_debug_violin_bottom_crop.png +0 -0
  89. daspi-2.5.0/tests/charts/_debug_violin_top_crop.png +0 -0
  90. {daspi-2.5.0 → daspi-2.7.0}/LICENSE +0 -0
  91. {daspi-2.5.0 → daspi-2.7.0}/README.md +0 -0
  92. {daspi-2.5.0 → daspi-2.7.0}/daspi/_typing.py +0 -0
  93. {daspi-2.5.0 → daspi-2.7.0}/daspi/_version.py +0 -0
  94. {daspi-2.5.0 → daspi-2.7.0}/daspi/anova/__init__.py +0 -0
  95. {daspi-2.5.0 → daspi-2.7.0}/daspi/anova/convert.py +0 -0
  96. {daspi-2.5.0 → daspi-2.7.0}/daspi/anova/tables.py +0 -0
  97. {daspi-2.5.0 → daspi-2.7.0}/daspi/config.py +0 -0
  98. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/__init__.py +0 -0
  99. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/ancova.csv +0 -0
  100. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/anova.csv +0 -0
  101. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/anova2.csv +0 -0
  102. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/anova2_unbalanced.csv +0 -0
  103. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/anova3.csv +0 -0
  104. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/anova3_unbalanced.csv +0 -0
  105. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/carpet_full-factorial.csv +0 -0
  106. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/covariate.csv +0 -0
  107. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/drop_card.csv +0 -0
  108. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/eeprom_full-factorial.csv +0 -0
  109. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/eeprom_partial-factorial.csv +0 -0
  110. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/grnr_adjustment.csv +0 -0
  111. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/grnr_layer_thickness.csv +0 -0
  112. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/grnr_spc.csv +0 -0
  113. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/iris.csv +0 -0
  114. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/mpg.csv +0 -0
  115. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/painkillers-dissolution.csv +0 -0
  116. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/partial_factorial.csv +0 -0
  117. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/penguins.csv +0 -0
  118. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/process_capability.mpx +0 -0
  119. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/salt_sticks.csv +0 -0
  120. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/shoe-sole.csv +0 -0
  121. {daspi-2.5.0 → daspi-2.7.0}/daspi/datasets/tips.csv +0 -0
  122. {daspi-2.5.0 → daspi-2.7.0}/daspi/doe/__init__.py +0 -0
  123. {daspi-2.5.0 → daspi-2.7.0}/daspi/doe/build.py +0 -0
  124. {daspi-2.5.0 → daspi-2.7.0}/daspi/plotlib/__init__.py +0 -0
  125. {daspi-2.5.0 → daspi-2.7.0}/daspi/plotlib/appearance.py +0 -0
  126. {daspi-2.5.0 → daspi-2.7.0}/daspi/plotlib/classify.py +0 -0
  127. {daspi-2.5.0 → daspi-2.7.0}/daspi/plotlib/facets.py +0 -0
  128. {daspi-2.5.0 → daspi-2.7.0}/daspi/plotlib/precast.py +0 -0
  129. {daspi-2.5.0 → daspi-2.7.0}/daspi/plotlib/styles/daspi-dark.mplstyle +0 -0
  130. {daspi-2.5.0 → daspi-2.7.0}/daspi/plotlib/styles/daspi.mplstyle +0 -0
  131. {daspi-2.5.0 → daspi-2.7.0}/daspi/plotlib/styles/ggplot2.mplstyle +0 -0
  132. {daspi-2.5.0 → daspi-2.7.0}/daspi/plotlib/styles/seaborn.mplstyle +0 -0
  133. {daspi-2.5.0 → daspi-2.7.0}/daspi/requirements.txt +0 -0
  134. {daspi-2.5.0 → daspi-2.7.0}/daspi/statistics/__init__.py +0 -0
  135. {daspi-2.5.0 → daspi-2.7.0}/daspi/statistics/confidence.py +0 -0
  136. {daspi-2.5.0 → daspi-2.7.0}/daspi/statistics/estimation.py +0 -0
  137. {daspi-2.5.0 → daspi-2.7.0}/daspi/statistics/hypothesis.py +0 -0
  138. {daspi-2.5.0 → daspi-2.7.0}/daspi/statistics/montecarlo.py +0 -0
  139. {daspi-2.5.0 → daspi-2.7.0}/tests/ANOVA_SS_Fehler.mpx +0 -0
  140. {daspi-2.5.0 → daspi-2.7.0}/tests/ANOVA_SS_Fehler.mpx.bak +0 -0
  141. {daspi-2.5.0 → daspi-2.7.0}/tests/GageRnR.mpx +0 -0
  142. {daspi-2.5.0 → daspi-2.7.0}/tests/GageRnR.mpx.bak +0 -0
  143. {daspi-2.5.0 → daspi-2.7.0}/tests/__init__.py +0 -0
  144. {daspi-2.5.0 → daspi-2.7.0}/tests/anova_convert_test.py +0 -0
  145. {daspi-2.5.0 → daspi-2.7.0}/tests/anova_model_test.py +0 -0
  146. {daspi-2.5.0 → daspi-2.7.0}/tests/anova_tables_test.py +0 -0
  147. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/JointChart_kdes_kde-mean.png +0 -0
  148. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/JointChart_kdes_mixed-kde.png +0 -0
  149. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/JointChart_probability_norm-prob.png +0 -0
  150. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_gage_rnr_model_basic.png +0 -0
  151. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/Precasts_gage_study_model_basic.png +0 -0
  152. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_KDE-cumulative_simple.png +0 -0
  153. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_KDE_simple.png +0 -0
  154. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_fitted-density_pdf-data.png +0 -0
  155. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_fitted-density_pdf-norm.png +0 -0
  156. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_simple-stripes-65ci.png +0 -0
  157. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_simple-stripes-99ci.png +0 -0
  158. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_simple-stripes.png +0 -0
  159. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_simple.png +0 -0
  160. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_scatter_transposed.png +0 -0
  161. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_violine-contour_simple.png +0 -0
  162. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_violine_mono.png +0 -0
  163. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_violine_multiple.png +0 -0
  164. {daspi-2.5.0 → daspi-2.7.0}/tests/charts/SingleChart_violine_simple.png +0 -0
  165. {daspi-2.5.0 → daspi-2.7.0}/tests/config_test.py +0 -0
  166. {daspi-2.5.0 → daspi-2.7.0}/tests/data/anova3_result.csv +0 -0
  167. {daspi-2.5.0 → daspi-2.7.0}/tests/data/dists_10-samples.csv +0 -0
  168. {daspi-2.5.0 → daspi-2.7.0}/tests/data/dists_25-samples.csv +0 -0
  169. {daspi-2.5.0 → daspi-2.7.0}/tests/data/gage_rnr.csv +0 -0
  170. {daspi-2.5.0 → daspi-2.7.0}/tests/data/gage_study.csv +0 -0
  171. {daspi-2.5.0 → daspi-2.7.0}/tests/data/generate_dists.py +0 -0
  172. {daspi-2.5.0 → daspi-2.7.0}/tests/data/grnr_d-optimal.csv +0 -0
  173. {daspi-2.5.0 → daspi-2.7.0}/tests/data/uncertainties.csv +0 -0
  174. {daspi-2.5.0 → daspi-2.7.0}/tests/doe_build_test.py +0 -0
  175. {daspi-2.5.0 → daspi-2.7.0}/tests/plotlib_appearance_test.py +0 -0
  176. {daspi-2.5.0 → daspi-2.7.0}/tests/plotlib_classify_test.py +0 -0
  177. {daspi-2.5.0 → daspi-2.7.0}/tests/plotlib_facets_test.py +0 -0
  178. {daspi-2.5.0 → daspi-2.7.0}/tests/plotlib_templates_test.py +0 -0
  179. {daspi-2.5.0 → daspi-2.7.0}/tests/r2_pred.mpx +0 -0
  180. {daspi-2.5.0 → daspi-2.7.0}/tests/r2_pred.mpx.bak +0 -0
  181. {daspi-2.5.0 → daspi-2.7.0}/tests/statistics_confidence_test.py +0 -0
  182. {daspi-2.5.0 → daspi-2.7.0}/tests/statistics_estimation_test.py +0 -0
  183. {daspi-2.5.0 → daspi-2.7.0}/tests/statistics_hypothesis_test.py +0 -0
  184. {daspi-2.5.0 → daspi-2.7.0}/tests/statistics_montecarlo_test.py +0 -0
  185. {daspi-2.5.0 → daspi-2.7.0}/tests/strings_test.py +0 -0
  186. {daspi-2.5.0 → daspi-2.7.0}/tests/test_full_factorial_design_builder.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: DaSPi
3
- Version: 2.5.0
3
+ Version: 2.7.0
4
4
  Summary: Visualize and analyze your data with DaSPi. This package is designed for users who want to find relevant influencing factors in processes and validate improvements.
5
5
  Author-Email: Reto Jäggli <reto@jaeggli.email>
6
6
  License: MIT
@@ -80,6 +80,7 @@ if TYPE_CHECKING:
80
80
  ConfidenceInterval,
81
81
  DensityCurve,
82
82
  ErrorBar,
83
+ ExponentialSmoothingLine,
83
84
  FittedDensity,
84
85
  GaussianKDE,
85
86
  GaussianKDEContour,
@@ -90,6 +91,7 @@ if TYPE_CHECKING:
90
91
  LinearRegressionLine,
91
92
  LoessLine,
92
93
  MeanTest,
94
+ MovingAverageLine,
93
95
  ParallelCoordinate,
94
96
  Pareto,
95
97
  Plotter,
@@ -240,6 +242,7 @@ _LAZY_SUBMODULES: dict[str, str] = {
240
242
  'ConfidenceInterval': '.plotlib.plotter',
241
243
  'DensityCurve': '.plotlib.plotter',
242
244
  'ErrorBar': '.plotlib.plotter',
245
+ 'ExponentialSmoothingLine': '.plotlib.plotter',
243
246
  'FittedDensity': '.plotlib.plotter',
244
247
  'GaussianKDE': '.plotlib.plotter',
245
248
  'GaussianKDEContour': '.plotlib.plotter',
@@ -250,6 +253,7 @@ _LAZY_SUBMODULES: dict[str, str] = {
250
253
  'LinearRegressionLine': '.plotlib.plotter',
251
254
  'LoessLine': '.plotlib.plotter',
252
255
  'MeanTest': '.plotlib.plotter',
256
+ 'MovingAverageLine': '.plotlib.plotter',
253
257
  'ParallelCoordinate': '.plotlib.plotter',
254
258
  'Pareto': '.plotlib.plotter',
255
259
  'Plotter': '.plotlib.plotter',
@@ -376,6 +380,7 @@ __all__ = [
376
380
  'DistributionEstimator',
377
381
  'Dodger',
378
382
  'ErrorBar',
383
+ 'ExponentialSmoothingLine',
379
384
  'Factor',
380
385
  'FittedDensity',
381
386
  'FractionalFactorialDesignBuilder',
@@ -404,6 +409,7 @@ __all__ = [
404
409
  'Lowess',
405
410
  'MeanTest',
406
411
  'MeasurementUncertainty',
412
+ 'MovingAverageLine',
407
413
  'MultivariateChart',
408
414
  'GoodnessOfFitCharts',
409
415
  'PairComparisonCharts',
@@ -376,12 +376,13 @@ class LinearModel(BaseHTMLReprModel):
376
376
  covariates=['temperature', 'preparation'],
377
377
  order=2,)
378
378
 
379
- # Store goodnes of fit values for each elimination step
379
+ # Store and visualize goodnes of fit values for each elimination step
380
380
  df_gof = pd.concat(model.recursive_elimination())
381
+ dsp.GoodnessOfFitCharts(df_gof, model).plot().stripes().label(info=True)
381
382
 
382
383
  # Plot residual and parameter relevance analysis
383
384
  dsp.ResidualsCharts(model).plot().stripes().label(info=True)
384
- dsp.ParameterRelevanceCharts(model).plot().label(info=True)
385
+ dsp.ParameterRelevanceCharts(model).plot().stripes().label(info=True)
385
386
 
386
387
  # Get HTML output
387
388
  model
@@ -203,6 +203,12 @@ class _Kw_:
203
203
  """Keyword arguments for confidence interval area for fit."""
204
204
  return {'zorder': 2.2, 'alpha': 0.8, 'marker': ''}
205
205
 
206
+ @property
207
+ def FIT_LINE_HANDLE(self) -> dict[str, Any]:
208
+ """Keyword arguments for the legend handle of a fitted line
209
+ (e.g. `MovingAverageLine`, `ExponentialSmoothingLine`)."""
210
+ return {'lw': LINE.WIDTH, 'alpha': 0.8}
211
+
206
212
  @property
207
213
  def FIT_CI(self) -> dict[str, Any]:
208
214
  """Keyword arguments for confidence interval area for fit."""
@@ -520,6 +526,14 @@ class _Plotter_:
520
526
  SUBGROUP: Literal['_subgroup_'] = '_subgroup_'
521
527
  """Column name for subgroups used mostly in TransformPlotter."""
522
528
 
529
+ SMOOTHED_TARGET: Literal['_smoothed_target_'] = '_smoothed_target_'
530
+ """Column name for smoothed target values (moving average,
531
+ exponential smoothing)."""
532
+
533
+ SMOOTHED_FEATURE: Literal['_smoothed_feature_'] = '_smoothed_feature_'
534
+ """Column name for the feature values matching the smoothed target
535
+ values (moving average, exponential smoothing)."""
536
+
523
537
  @property
524
538
  def REGRESSION_CI_NAMES(self) -> tuple[str, str, str, str]:
525
539
  """Get names for regression confidences in order:
@@ -788,6 +802,13 @@ class _Default_:
788
802
  - 6 = ±3 σ, capturing about 99.7% of the data.
789
803
  """
790
804
 
805
+ MA_WINDOW: Literal[5] = 5
806
+ """Default window size for the `MovingAverageLine` Plotter."""
807
+
808
+ EWM_ALPHA: float = 0.3
809
+ """Default smoothing factor (alpha) for the
810
+ `ExponentialSmoothingLine` Plotter."""
811
+
791
812
  @property
792
813
  def MARKER(self) -> str:
793
814
  """Default marker for scatter plots."""
@@ -62,6 +62,7 @@ import pandas as pd
62
62
  from matplotlib.axes import Axes
63
63
  from matplotlib.axis import XAxis, YAxis
64
64
  from matplotlib.figure import Figure
65
+ from matplotlib.lines import Line2D
65
66
  from matplotlib.ticker import AutoMinorLocator, Formatter
66
67
  from numpy.typing import NDArray
67
68
  from pandas.core.frame import DataFrame
@@ -113,7 +114,7 @@ def check_label_order[T](method: Callable[..., T]) -> Callable[..., T]:
113
114
  If the decorated method is called after label() method.
114
115
  """
115
116
  @wraps(method)
116
- def wrapper(self: Chart, *args: Any, **kwargs: Any) -> T:
117
+ def wrapper(self: 'Chart', *args: Any, **kwargs: Any) -> T:
117
118
  assert not hasattr(self, 'label_facets'), (
118
119
  f'Cannot call {method.__name__}() after label(). '
119
120
  'The label() method must be called after stripes() and plot().')
@@ -121,6 +122,21 @@ def check_label_order[T](method: Callable[..., T]) -> Callable[..., T]:
121
122
  return wrapper
122
123
 
123
124
 
125
+ _XY_SET_PARAMS: dict[str, tuple[str, str]] = {
126
+ 'lim': ('xlim', 'ylim'),
127
+ 'bound': ('xbound', 'ybound'),
128
+ 'margin': ('xmargin', 'ymargin'),
129
+ 'scale': ('xscale', 'yscale'),
130
+ 'ticks': ('xticks', 'yticks'),
131
+ 'ticklabels': ('xticklabels', 'yticklabels'),
132
+ 'inverted': ('xinverted', 'yinverted'),
133
+ 'autoscale': ('autoscalex_on', 'autoscaley_on'),
134
+ }
135
+ """Mapping of generic axis parameters to their corresponding Axes.set
136
+ keys. The keys correspond to the parameters used in the `Axes.set`
137
+ method for the x and y axes, respectively."""
138
+
139
+
124
140
  class Chart(ABC):
125
141
  """
126
142
  Abstract base class for creating chart visualizations.
@@ -443,6 +459,124 @@ class Chart(ABC):
443
459
  enhance readability and provide context for the visualized data.
444
460
  """
445
461
 
462
+ @check_label_order
463
+ def set(
464
+ self,
465
+ ax: int | tuple[int, int] | Literal['all', 'first', 'last'] | None = 'all',
466
+ *,
467
+ feature_lim: tuple[float, float] | None = None,
468
+ target_lim: tuple[float, float] | None = None,
469
+ feature_bound: tuple[float, float] | None = None,
470
+ target_bound: tuple[float, float] | None = None,
471
+ feature_margin: float | None = None,
472
+ target_margin: float | None = None,
473
+ feature_scale: str | None = None,
474
+ target_scale: str | None = None,
475
+ feature_ticks: Sequence[float] | None = None,
476
+ target_ticks: Sequence[float] | None = None,
477
+ feature_ticklabels: Sequence[str] | None = None,
478
+ target_ticklabels: Sequence[str] | None = None,
479
+ feature_inverted: bool | None = None,
480
+ target_inverted: bool | None = None,
481
+ feature_autoscale: bool | None = None,
482
+ target_autoscale: bool | None = None,
483
+ **kwds: Any,
484
+ ) -> Self:
485
+ """Set properties on one, several or all Axes of this chart.
486
+
487
+ This is a thin wrapper around matplotlib's
488
+ ``Axes.set(**kwargs)``. The `feature_*`/`target_*` keywords
489
+ mirror the x/y-paired properties of ``Axes.set`` (e.g. `xlim`
490
+ and `ylim`) but are named after the chart's feature and target
491
+ variable instead, so they resolve to the correct axis based on
492
+ the `target_on_y` attribute. All other matplotlib ``Axes.set``
493
+ properties that have no x/y counterpart (e.g. `title`,
494
+ `aspect`, `facecolor`) can be passed directly via `**kwds`.
495
+
496
+ Note that `xlabel`/`ylabel` are intentionally not supported
497
+ here, use the `label()` method to set axis labels instead.
498
+
499
+ Parameters
500
+ ----------
501
+ ax : int | tuple[int, int] | {'all', 'first', 'last'} | None, optional
502
+ Selects which Axes the properties are applied to:
503
+ - int or tuple[int, int]: the Axes at that position in the
504
+ `axes` grid (see `AxesFacets.__getitem__`).
505
+ - 'all': every Axes in the grid, by default.
506
+ - 'first': only the first Axes in the grid.
507
+ - 'last': only the last Axes in the grid.
508
+ - None: the Axes that was last worked on (falls back to the
509
+ default Axes if none was worked on yet).
510
+ feature_lim, target_lim : tuple[float, float], optional
511
+ Feature/target axis view limits (`xlim`/`ylim`).
512
+ feature_bound, target_bound : tuple[float, float], optional
513
+ Feature/target axis bounds (`xbound`/`ybound`).
514
+ feature_margin, target_margin : float, optional
515
+ Feature/target axis margins (`xmargin`/`ymargin`).
516
+ feature_scale, target_scale : str, optional
517
+ Feature/target axis scale (`xscale`/`yscale`).
518
+ feature_ticks, target_ticks : Sequence[float], optional
519
+ Feature/target axis tick locations (`xticks`/`yticks`).
520
+ feature_ticklabels, target_ticklabels : Sequence[str], optional
521
+ Feature/target axis tick labels
522
+ (`xticklabels`/`yticklabels`).
523
+ feature_inverted, target_inverted : bool, optional
524
+ Whether the feature/target axis is inverted
525
+ (`xinverted`/`yinverted`).
526
+ feature_autoscale, target_autoscale : bool, optional
527
+ Whether the feature/target axis autoscales
528
+ (`autoscalex_on`/`autoscaley_on`).
529
+ **kwds
530
+ Additional keyword arguments forwarded as-is to
531
+ `Axes.set()`, for properties without a feature/target
532
+ counterpart (e.g. `title`, `aspect`, `facecolor`,
533
+ `visible`, `zorder`).
534
+
535
+ Returns
536
+ -------
537
+ Self
538
+ The updated Chart object.
539
+ """
540
+ feature_values = {
541
+ 'lim': feature_lim, 'bound': feature_bound,
542
+ 'margin': feature_margin, 'scale': feature_scale,
543
+ 'ticks': feature_ticks, 'ticklabels': feature_ticklabels,
544
+ 'inverted': feature_inverted, 'autoscale': feature_autoscale}
545
+ target_values = {
546
+ 'lim': target_lim, 'bound': target_bound,
547
+ 'margin': target_margin, 'scale': target_scale,
548
+ 'ticks': target_ticks, 'ticklabels': target_ticklabels,
549
+ 'inverted': target_inverted, 'autoscale': target_autoscale}
550
+
551
+ feature_axis = 0 if self.target_on_y else 1
552
+ target_axis = 1 if self.target_on_y else 0
553
+ kwds = dict(kwds)
554
+ for name, value in feature_values.items():
555
+ if value is not None:
556
+ kwds[_XY_SET_PARAMS[name][feature_axis]] = value
557
+ for name, value in target_values.items():
558
+ if value is not None:
559
+ kwds[_XY_SET_PARAMS[name][target_axis]] = value
560
+
561
+ if ax == 'all':
562
+ axes = self.axes.flat
563
+ elif ax == 'first':
564
+ axes = [self.axes.flat[0]]
565
+ elif ax == 'last':
566
+ axes = [self.axes.flat[-1]]
567
+ elif ax is None:
568
+ current = self._ax if self._ax is not None else self.axes.ax
569
+ assert current is not None, (
570
+ 'No current Axes to set properties on, specify `ax` '
571
+ 'explicitly.')
572
+ axes = [current]
573
+ else:
574
+ axes = [self.axes[ax]]
575
+
576
+ for _ax in axes:
577
+ _ax.set(**kwds)
578
+ return self
579
+
446
580
  def save(
447
581
  self,
448
582
  file_name: str | Path,
@@ -740,6 +874,14 @@ class SingleChart(Chart):
740
874
  handle_label[self.size] = self.sizing.handles_labels()
741
875
  if hasattr(self, 'stripes_facets'):
742
876
  handle_label[STR['stripes']] = self.stripes_facets.handles_labels()
877
+ smoothers = {
878
+ label: Line2D(
879
+ xdata=[], ydata=[], color=plot.color, **KW.FIT_LINE_HANDLE)
880
+ for plot in self._plots
881
+ if (label := getattr(plot, 'legend_label', None)) is not None}
882
+ if smoothers:
883
+ handle_label[STR['smoothing']] = (
884
+ tuple(smoothers.values()), tuple(smoothers.keys()))
743
885
  return handle_label
744
886
 
745
887
  def _check_current_data_(self) -> bool: