jarvisplot 2.1.4__tar.gz → 2.1.6__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.
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/JarvisPLOT.egg-info/PKG-INFO +12 -3
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/JarvisPLOT.egg-info/SOURCES.txt +12 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/PKG-INFO +12 -3
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/README.md +11 -2
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/adapters_rect.py +28 -9
- jarvisplot-2.1.6/jarvisplot/Figure/adaptive_cdf_runtime.py +131 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/design_runtime.py +6 -2
- jarvisplot-2.1.6/jarvisplot/Figure/distribution_1d_runtime.py +165 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/figure.py +38 -10
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/figure_types.py +11 -1
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/interp_2d_runtime.py +39 -4
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/interp_natural_neighbor.py +274 -8
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/interp_natural_neighbor_exact.py +330 -59
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/layer_runtime.py +113 -93
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/posterior_density_runtime.py +1 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/preprocessor.py +45 -3
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/preprocessor_runtime.py +6 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/profile_runtime.py +16 -26
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/capabilities.py +33 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/column_demand.py +25 -1
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/column_probe.py +6 -0
- jarvisplot-2.1.6/jarvisplot/data_generation_contracts.py +22 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/data_loader.py +39 -4
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/data_loader_runtime.py +6 -1
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/dataset_types.py +11 -2
- jarvisplot-2.1.6/jarvisplot/distribution_1d_config.py +167 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/dryrun_runtime.py +120 -31
- jarvisplot-2.1.6/jarvisplot/generated_data.py +131 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/man_methods.py +2 -1
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/man_render_agent.py +28 -3
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/man_transforms.py +24 -21
- jarvisplot-2.1.6/jarvisplot/manual_cards/field-interp.yaml +138 -0
- jarvisplot-2.1.6/jarvisplot/manual_cards/generated-data.yaml +94 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/manifest.yaml +13 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/method_notes.yaml +37 -5
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/type-profile-2d.yaml +7 -1
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/yaml-root.yaml +4 -1
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/core/dataset.json +12 -4
- jarvisplot-2.1.6/jarvisplot/schema/core/distribution-1d.json +72 -0
- jarvisplot-2.1.6/jarvisplot/schema/core/generated-data.json +90 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/core/layer.json +15 -2
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/core/transform.json +8 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/manifest.json +4 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/transform_contracts.py +194 -5
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/validation.py +2 -1
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/verbs/cap.py +52 -5
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/verbs/man.py +2 -1
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/pyproject.toml +1 -1
- jarvisplot-2.1.6/tests/test_adaptive_cdf.py +141 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_capabilities.py +23 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_data_loader_contracts.py +37 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_density_cell_transform.py +36 -0
- jarvisplot-2.1.6/tests/test_distribution_1d_transform.py +234 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_figure_contracts.py +43 -0
- jarvisplot-2.1.6/tests/test_generated_data.py +276 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_interp_2d_transform.py +99 -9
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_interp_natural_neighbor.py +29 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_jpcontour_methods.py +12 -3
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_man_cli.py +18 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_profile_runtime.py +51 -1
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_schema_catalog.py +3 -2
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/JarvisPLOT.egg-info/dependency_links.txt +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/JarvisPLOT.egg-info/entry_points.txt +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/JarvisPLOT.egg-info/requires.txt +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/JarvisPLOT.egg-info/top_level.txt +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/__init__.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/adapters_ternary.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/bin_stat_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/cards/std_axes_adapter_config.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/colorbar_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/config_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/corr_layout.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/corr_layout_diamond.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/corr_order.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/correlation_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/corrplot_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/data_pipelines.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/debug_config.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/density_cell_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/dynesty_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/helper.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/layout_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/method_registry.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/posterior_hpd.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/posterior_mesh.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/significance_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/Figure/style_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/__init__.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/agent_digest.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/agent_io.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cache_store.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/1x1/ternary.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/2x1/dynesty_runplot.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/2x1/rect.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/2x1/rect5x1.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/2x1/rect_cmap.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/2x1/rect_marginal.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/2x1/rectratio.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/2x1/ternary.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/2x1/ternary_cmap.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/4x1/rect.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/4x1/rect_cmap.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/4x1/ternary.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/a4paper/4x1/ternary_cmap.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/args.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/colors/colormaps.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/corrplot/diamond.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/corrplot/matrix.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/default/output.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/flowchart/default.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/gambit/1x1/ternary.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/gambit/2x1/rect_cmap.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/gambit/2x1/ternary.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/gambit/2x1/ternary_cmap.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/icons/JarvisHEP.png +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/icons/flowchart/JarvisHEP.png +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/icons/flowchart/calculator.png +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/icons/flowchart/inputfile.png +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/icons/flowchart/opera.png +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/icons/flowchart/outputfile.png +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/icons/flowchart/sampler.png +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/icons/gambit.png +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/icons/gambit_small.png +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cards/style_preference.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cli.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/cli_help.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/client.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/config.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/config_address.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/core.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/core_assets.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/core_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/data_access.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/data_loader_hdf5.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/data_loader_summary.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/diagnostic_guidance.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/diagnostics.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/expr_names.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/fix_apply.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/flowchart.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/inner_func.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/man_catalog.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/man_render_human.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/agent-output.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/cli-map.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/data-columns.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/debug-overlay.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/diagnostics.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/dryrun-viz.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/layer-method.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/style-axes.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/type-correlation-matrix.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/type-posterior-2d.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/validate.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/manual_cards/workflow.yaml +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/memtrace.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/method_contracts.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/render_health.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/core/common.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/core/figure.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/bar.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/barh.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/contour.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/contourf.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/corrplot.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/dynesty_runplot.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/errorbar.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/fill.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/fill_between.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/fill_betweenx.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/hist.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/hist2d.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/imshow.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/jpcontour.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/jpcontourf.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/jpfield.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/pcolor.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/pcolormesh.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/plot.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/quiver.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/scatter.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/stairs.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/step.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/tricontour.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/tricontourf.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/tripcolor.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/tripcolor_axes.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/triplot.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/voronoi.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/methods/voronoif.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema/plot-config.json +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema_catalog.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/schema_diagnostics.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/templates_catalog.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/utils/__init__.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/utils/cmaps.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/utils/dataframes.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/utils/expression.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/utils/interpolator.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/utils/pathing.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/verbs/__init__.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/verbs/config_cmd.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/verbs/data.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/verbs/doctor.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/verbs/dryrun.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/verbs/explain.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/verbs/suggest.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/verbs/template.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/verbs/validate.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/jarvisplot/yaml_io.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/setup.cfg +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_agent_digest.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_agent_envelope.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_axis_title.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_card_debug_shape.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_cli_help.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_cli_verbs.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_cmaps.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_column_existence.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_config_addressing.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_config_edit.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_config_expand.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_correlation_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_corrplot.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_data_access.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_data_describe.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_data_head_eval.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_data_pipelines.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_debug_config.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_debug_switches.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_debug_yaml_override.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_design_runtime.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_diagnostic_guidance.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_docs_status_labels.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_doctor_partial.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_explain.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_figure_type_expander.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_fix_application.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_flowchart_renderer.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_imshow_adapter.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_interpolator_contracts.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_method_contracts.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_parse_data_metadata.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_pathing_contracts.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_posterior_hpd.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_render_health.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_row_ledger.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_suggest.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_suggest_axes.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_template_catalog.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_template_json.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_ternary_debug.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_transform_contracts.py +0 -0
- {jarvisplot-2.1.4 → jarvisplot-2.1.6}/tests/test_validate_no_matplotlib.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: JarvisPLOT
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.6
|
|
4
4
|
Summary: Jarvis-PLOT: YAML-driven plotting engine
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -161,11 +161,20 @@ The loop `jplot man` prints is:
|
|
|
161
161
|
5. `jplot <file>` — render, only when the figure itself is needed.
|
|
162
162
|
|
|
163
163
|
`jplot man --json` is the machine-readable manual: 15 topics, plus a
|
|
164
|
-
live
|
|
165
|
-
(`jplot man scatter`, `jplot man transform.profile`). Method contracts come from
|
|
164
|
+
live pages for every registered layer method and transform step
|
|
165
|
+
(`jplot man scatter`, `jplot man transform.profile`, `jplot man PDF1D`). Method contracts come from
|
|
166
166
|
the same registry `jplot cap methods` reads, so a man page cannot drift from the
|
|
167
167
|
code.
|
|
168
168
|
|
|
169
|
+
For continuous one-dimensional distributions from raw samples, use `PDF1D`
|
|
170
|
+
(CDF plus PDF) or `CDF1D` in a data transform. `coordinates.x` owns `expr`,
|
|
171
|
+
`lim`, and `grid`; optional `repeat` computes independent batch means and
|
|
172
|
+
standard deviations. See [the contract](docs/specs/PDF_CDF_1D.md) and the
|
|
173
|
+
[runnable example](Example/pdf_cdf_1d.yaml).
|
|
174
|
+
Reconstruction defaults to adaptive true CDF anchors and `monotone_c2`
|
|
175
|
+
interpolation (C2 CDF / C1 PDF). Set `anchors: all` and `interpolation: pchip`
|
|
176
|
+
to reproduce the original all-node reconstruction.
|
|
177
|
+
|
|
169
178
|
Two things worth knowing before trusting a config:
|
|
170
179
|
|
|
171
180
|
- `jplot validate` checks shape and contracts and never touches the data;
|
|
@@ -22,6 +22,7 @@ jarvisplot/core.py
|
|
|
22
22
|
jarvisplot/core_assets.py
|
|
23
23
|
jarvisplot/core_runtime.py
|
|
24
24
|
jarvisplot/data_access.py
|
|
25
|
+
jarvisplot/data_generation_contracts.py
|
|
25
26
|
jarvisplot/data_loader.py
|
|
26
27
|
jarvisplot/data_loader_hdf5.py
|
|
27
28
|
jarvisplot/data_loader_runtime.py
|
|
@@ -29,10 +30,12 @@ jarvisplot/data_loader_summary.py
|
|
|
29
30
|
jarvisplot/dataset_types.py
|
|
30
31
|
jarvisplot/diagnostic_guidance.py
|
|
31
32
|
jarvisplot/diagnostics.py
|
|
33
|
+
jarvisplot/distribution_1d_config.py
|
|
32
34
|
jarvisplot/dryrun_runtime.py
|
|
33
35
|
jarvisplot/expr_names.py
|
|
34
36
|
jarvisplot/fix_apply.py
|
|
35
37
|
jarvisplot/flowchart.py
|
|
38
|
+
jarvisplot/generated_data.py
|
|
36
39
|
jarvisplot/inner_func.py
|
|
37
40
|
jarvisplot/man_catalog.py
|
|
38
41
|
jarvisplot/man_methods.py
|
|
@@ -51,6 +54,7 @@ jarvisplot/yaml_io.py
|
|
|
51
54
|
jarvisplot/Figure/__init__.py
|
|
52
55
|
jarvisplot/Figure/adapters_rect.py
|
|
53
56
|
jarvisplot/Figure/adapters_ternary.py
|
|
57
|
+
jarvisplot/Figure/adaptive_cdf_runtime.py
|
|
54
58
|
jarvisplot/Figure/bin_stat_runtime.py
|
|
55
59
|
jarvisplot/Figure/colorbar_runtime.py
|
|
56
60
|
jarvisplot/Figure/config_runtime.py
|
|
@@ -63,6 +67,7 @@ jarvisplot/Figure/data_pipelines.py
|
|
|
63
67
|
jarvisplot/Figure/debug_config.py
|
|
64
68
|
jarvisplot/Figure/density_cell_runtime.py
|
|
65
69
|
jarvisplot/Figure/design_runtime.py
|
|
70
|
+
jarvisplot/Figure/distribution_1d_runtime.py
|
|
66
71
|
jarvisplot/Figure/dynesty_runtime.py
|
|
67
72
|
jarvisplot/Figure/figure.py
|
|
68
73
|
jarvisplot/Figure/figure_types.py
|
|
@@ -121,6 +126,8 @@ jarvisplot/manual_cards/data-columns.yaml
|
|
|
121
126
|
jarvisplot/manual_cards/debug-overlay.yaml
|
|
122
127
|
jarvisplot/manual_cards/diagnostics.yaml
|
|
123
128
|
jarvisplot/manual_cards/dryrun-viz.yaml
|
|
129
|
+
jarvisplot/manual_cards/field-interp.yaml
|
|
130
|
+
jarvisplot/manual_cards/generated-data.yaml
|
|
124
131
|
jarvisplot/manual_cards/layer-method.yaml
|
|
125
132
|
jarvisplot/manual_cards/manifest.yaml
|
|
126
133
|
jarvisplot/manual_cards/method_notes.yaml
|
|
@@ -135,7 +142,9 @@ jarvisplot/schema/manifest.json
|
|
|
135
142
|
jarvisplot/schema/plot-config.json
|
|
136
143
|
jarvisplot/schema/core/common.json
|
|
137
144
|
jarvisplot/schema/core/dataset.json
|
|
145
|
+
jarvisplot/schema/core/distribution-1d.json
|
|
138
146
|
jarvisplot/schema/core/figure.json
|
|
147
|
+
jarvisplot/schema/core/generated-data.json
|
|
139
148
|
jarvisplot/schema/core/layer.json
|
|
140
149
|
jarvisplot/schema/core/transform.json
|
|
141
150
|
jarvisplot/schema/methods/bar.json
|
|
@@ -185,6 +194,7 @@ jarvisplot/verbs/man.py
|
|
|
185
194
|
jarvisplot/verbs/suggest.py
|
|
186
195
|
jarvisplot/verbs/template.py
|
|
187
196
|
jarvisplot/verbs/validate.py
|
|
197
|
+
tests/test_adaptive_cdf.py
|
|
188
198
|
tests/test_agent_digest.py
|
|
189
199
|
tests/test_agent_envelope.py
|
|
190
200
|
tests/test_axis_title.py
|
|
@@ -210,6 +220,7 @@ tests/test_debug_yaml_override.py
|
|
|
210
220
|
tests/test_density_cell_transform.py
|
|
211
221
|
tests/test_design_runtime.py
|
|
212
222
|
tests/test_diagnostic_guidance.py
|
|
223
|
+
tests/test_distribution_1d_transform.py
|
|
213
224
|
tests/test_docs_status_labels.py
|
|
214
225
|
tests/test_doctor_partial.py
|
|
215
226
|
tests/test_explain.py
|
|
@@ -217,6 +228,7 @@ tests/test_figure_contracts.py
|
|
|
217
228
|
tests/test_figure_type_expander.py
|
|
218
229
|
tests/test_fix_application.py
|
|
219
230
|
tests/test_flowchart_renderer.py
|
|
231
|
+
tests/test_generated_data.py
|
|
220
232
|
tests/test_imshow_adapter.py
|
|
221
233
|
tests/test_interp_2d_transform.py
|
|
222
234
|
tests/test_interp_natural_neighbor.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: JarvisPLOT
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.6
|
|
4
4
|
Summary: Jarvis-PLOT: YAML-driven plotting engine
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -161,11 +161,20 @@ The loop `jplot man` prints is:
|
|
|
161
161
|
5. `jplot <file>` — render, only when the figure itself is needed.
|
|
162
162
|
|
|
163
163
|
`jplot man --json` is the machine-readable manual: 15 topics, plus a
|
|
164
|
-
live
|
|
165
|
-
(`jplot man scatter`, `jplot man transform.profile`). Method contracts come from
|
|
164
|
+
live pages for every registered layer method and transform step
|
|
165
|
+
(`jplot man scatter`, `jplot man transform.profile`, `jplot man PDF1D`). Method contracts come from
|
|
166
166
|
the same registry `jplot cap methods` reads, so a man page cannot drift from the
|
|
167
167
|
code.
|
|
168
168
|
|
|
169
|
+
For continuous one-dimensional distributions from raw samples, use `PDF1D`
|
|
170
|
+
(CDF plus PDF) or `CDF1D` in a data transform. `coordinates.x` owns `expr`,
|
|
171
|
+
`lim`, and `grid`; optional `repeat` computes independent batch means and
|
|
172
|
+
standard deviations. See [the contract](docs/specs/PDF_CDF_1D.md) and the
|
|
173
|
+
[runnable example](Example/pdf_cdf_1d.yaml).
|
|
174
|
+
Reconstruction defaults to adaptive true CDF anchors and `monotone_c2`
|
|
175
|
+
interpolation (C2 CDF / C1 PDF). Set `anchors: all` and `interpolation: pchip`
|
|
176
|
+
to reproduce the original all-node reconstruction.
|
|
177
|
+
|
|
169
178
|
Two things worth knowing before trusting a config:
|
|
170
179
|
|
|
171
180
|
- `jplot validate` checks shape and contracts and never touches the data;
|
|
@@ -139,11 +139,20 @@ The loop `jplot man` prints is:
|
|
|
139
139
|
5. `jplot <file>` — render, only when the figure itself is needed.
|
|
140
140
|
|
|
141
141
|
`jplot man --json` is the machine-readable manual: 15 topics, plus a
|
|
142
|
-
live
|
|
143
|
-
(`jplot man scatter`, `jplot man transform.profile`). Method contracts come from
|
|
142
|
+
live pages for every registered layer method and transform step
|
|
143
|
+
(`jplot man scatter`, `jplot man transform.profile`, `jplot man PDF1D`). Method contracts come from
|
|
144
144
|
the same registry `jplot cap methods` reads, so a man page cannot drift from the
|
|
145
145
|
code.
|
|
146
146
|
|
|
147
|
+
For continuous one-dimensional distributions from raw samples, use `PDF1D`
|
|
148
|
+
(CDF plus PDF) or `CDF1D` in a data transform. `coordinates.x` owns `expr`,
|
|
149
|
+
`lim`, and `grid`; optional `repeat` computes independent batch means and
|
|
150
|
+
standard deviations. See [the contract](docs/specs/PDF_CDF_1D.md) and the
|
|
151
|
+
[runnable example](Example/pdf_cdf_1d.yaml).
|
|
152
|
+
Reconstruction defaults to adaptive true CDF anchors and `monotone_c2`
|
|
153
|
+
interpolation (C2 CDF / C1 PDF). Set `anchors: all` and `interpolation: pchip`
|
|
154
|
+
to reproduce the original all-node reconstruction.
|
|
155
|
+
|
|
147
156
|
Two things worth knowing before trusting a config:
|
|
148
157
|
|
|
149
158
|
- `jplot validate` checks shape and contracts and never touches the data;
|
|
@@ -12,7 +12,11 @@ from matplotlib.collections import PolyCollection
|
|
|
12
12
|
#
|
|
13
13
|
from .helper import _auto_clip, _mask_by_extend, voronoi_finite_polygons_2d, _clip_poly_to_rect
|
|
14
14
|
from .profile_runtime import grid_from_metadata, regular_grid_mesh
|
|
15
|
-
from .interp_natural_neighbor import
|
|
15
|
+
from .interp_natural_neighbor import (
|
|
16
|
+
drawing_backend_options,
|
|
17
|
+
log_backend_diagnostics,
|
|
18
|
+
resolve_backend,
|
|
19
|
+
)
|
|
16
20
|
from .posterior_hpd import prepare_hpd_contour_style
|
|
17
21
|
|
|
18
22
|
DEFAULT_JP_SAMPLE_GRID = 500
|
|
@@ -242,8 +246,9 @@ class StdAxesAdapter:
|
|
|
242
246
|
ny: Optional[int] = None,
|
|
243
247
|
xlim=None,
|
|
244
248
|
ylim=None,
|
|
245
|
-
nan_policy: str = "
|
|
249
|
+
nan_policy: str = "ignore",
|
|
246
250
|
backend_options: Optional[dict[str, Any]] = None,
|
|
251
|
+
logger=None,
|
|
247
252
|
):
|
|
248
253
|
x = np.asarray(x, dtype=float).reshape(-1)
|
|
249
254
|
y = np.asarray(y, dtype=float).reshape(-1)
|
|
@@ -273,8 +278,9 @@ class StdAxesAdapter:
|
|
|
273
278
|
X,
|
|
274
279
|
Y,
|
|
275
280
|
nan_policy=nan_policy,
|
|
276
|
-
backend_options=backend_options,
|
|
281
|
+
backend_options=drawing_backend_options(backend_options),
|
|
277
282
|
)
|
|
283
|
+
log_backend_diagnostics(logger, getattr(backend, "last_diagnostics", None))
|
|
278
284
|
return X, Y, np.asarray(Z, dtype=float)
|
|
279
285
|
|
|
280
286
|
def _build_jpcontour_grid(
|
|
@@ -322,9 +328,10 @@ class StdAxesAdapter:
|
|
|
322
328
|
ny: Optional[int] = None,
|
|
323
329
|
xlim=None,
|
|
324
330
|
ylim=None,
|
|
325
|
-
nan_policy: str = "
|
|
331
|
+
nan_policy: str = "ignore",
|
|
326
332
|
diagnostics: bool = False,
|
|
327
333
|
backend_options: Optional[dict[str, Any]] = None,
|
|
334
|
+
logger=None,
|
|
328
335
|
):
|
|
329
336
|
"""Interpolate scattered data on an axes-fraction grid for contour rendering.
|
|
330
337
|
|
|
@@ -361,8 +368,9 @@ class StdAxesAdapter:
|
|
|
361
368
|
Y,
|
|
362
369
|
nan_policy=nan_policy,
|
|
363
370
|
diagnostics=diagnostics,
|
|
364
|
-
backend_options=backend_options,
|
|
371
|
+
backend_options=drawing_backend_options(backend_options),
|
|
365
372
|
)
|
|
373
|
+
log_backend_diagnostics(logger, getattr(backend, "last_diagnostics", None))
|
|
366
374
|
return X, Y, np.asarray(Z, dtype=float)
|
|
367
375
|
|
|
368
376
|
# —— Common method forwarding (add as needed) ——
|
|
@@ -518,12 +526,18 @@ class StdAxesAdapter:
|
|
|
518
526
|
ny: Optional[int] = None,
|
|
519
527
|
xlim=None,
|
|
520
528
|
ylim=None,
|
|
521
|
-
nan_policy: str = "
|
|
529
|
+
nan_policy: str = "ignore",
|
|
522
530
|
diagnostics: bool = False,
|
|
523
531
|
backend_options: Optional[dict[str, Any]] = None,
|
|
524
532
|
**kwargs,
|
|
525
533
|
):
|
|
526
|
-
"""Scattered-data contour plot rendered in axes-fraction coordinates.
|
|
534
|
+
"""Scattered-data contour plot rendered in axes-fraction coordinates.
|
|
535
|
+
|
|
536
|
+
``nan_policy`` defaults to ``ignore`` here: a sample whose z is NaN --
|
|
537
|
+
an empty profile-likelihood cell, say -- is not a measurement, and
|
|
538
|
+
letting it propagate would blank the cells around it as well. Pass
|
|
539
|
+
``nan_policy="strict"`` to keep those neighbourhoods masked instead.
|
|
540
|
+
"""
|
|
527
541
|
kw = self._merge("contour", kwargs)
|
|
528
542
|
kw.pop("transform", None)
|
|
529
543
|
logger = kw.pop("_logger", None)
|
|
@@ -540,6 +554,7 @@ class StdAxesAdapter:
|
|
|
540
554
|
nan_policy=nan_policy,
|
|
541
555
|
diagnostics=diagnostics,
|
|
542
556
|
backend_options=backend_options,
|
|
557
|
+
logger=logger,
|
|
543
558
|
)
|
|
544
559
|
kw = prepare_hpd_contour_style(Z, X, Y, kw, logger=logger)
|
|
545
560
|
label_map = kw.pop("_hpd_label_map", None)
|
|
@@ -570,7 +585,7 @@ class StdAxesAdapter:
|
|
|
570
585
|
ny: Optional[int] = None,
|
|
571
586
|
xlim=None,
|
|
572
587
|
ylim=None,
|
|
573
|
-
nan_policy: str = "
|
|
588
|
+
nan_policy: str = "ignore",
|
|
574
589
|
diagnostics: bool = False,
|
|
575
590
|
backend_options: Optional[dict[str, Any]] = None,
|
|
576
591
|
**kwargs,
|
|
@@ -578,6 +593,7 @@ class StdAxesAdapter:
|
|
|
578
593
|
"""Filled scattered-data contour plot rendered in axes-fraction coordinates."""
|
|
579
594
|
kw = self._merge("contourf", kwargs)
|
|
580
595
|
kw.pop("transform", None)
|
|
596
|
+
logger = kw.pop("_logger", None)
|
|
581
597
|
X, Y, Z = self._interpolate_jpcontour_grid(
|
|
582
598
|
x,
|
|
583
599
|
y,
|
|
@@ -591,6 +607,7 @@ class StdAxesAdapter:
|
|
|
591
607
|
nan_policy=nan_policy,
|
|
592
608
|
diagnostics=diagnostics,
|
|
593
609
|
backend_options=backend_options,
|
|
610
|
+
logger=logger,
|
|
594
611
|
)
|
|
595
612
|
artists = self.ax.contourf(
|
|
596
613
|
X,
|
|
@@ -614,7 +631,7 @@ class StdAxesAdapter:
|
|
|
614
631
|
ny: Optional[int] = None,
|
|
615
632
|
xlim=None,
|
|
616
633
|
ylim=None,
|
|
617
|
-
nan_policy: str = "
|
|
634
|
+
nan_policy: str = "ignore",
|
|
618
635
|
backend_options: Optional[dict[str, Any]] = None,
|
|
619
636
|
shading: str = "auto",
|
|
620
637
|
**kwargs,
|
|
@@ -633,6 +650,7 @@ class StdAxesAdapter:
|
|
|
633
650
|
kw.pop(k, None)
|
|
634
651
|
kw.pop("shading", None)
|
|
635
652
|
kw.pop("transform", None)
|
|
653
|
+
logger = kw.pop("_logger", None)
|
|
636
654
|
X, Y, Z = self._interpolate_jpfield_grid(
|
|
637
655
|
x,
|
|
638
656
|
y,
|
|
@@ -645,6 +663,7 @@ class StdAxesAdapter:
|
|
|
645
663
|
ylim=ylim,
|
|
646
664
|
nan_policy=nan_policy,
|
|
647
665
|
backend_options=backend_options,
|
|
666
|
+
logger=logger,
|
|
648
667
|
)
|
|
649
668
|
X = np.asarray(X, dtype=float)
|
|
650
669
|
Y = np.asarray(Y, dtype=float)
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"""Adaptive empirical-CDF anchors and a local, monotone C2 quintic interpolant.
|
|
2
|
+
|
|
3
|
+
No bins, kernels, or nonlinear solver. The quartic PDF is represented in the
|
|
4
|
+
Bernstein basis; nonnegative coefficients certify nonnegativity on each whole
|
|
5
|
+
interval, rather than only at sampled output points.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from heapq import heappop, heappush
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
from scipy.interpolate import BPoly, CubicSpline, PchipInterpolator
|
|
14
|
+
|
|
15
|
+
from ..distribution_1d_config import AnchorSettings
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def monotone_c2(x: np.ndarray, y: np.ndarray) -> BPoly:
|
|
19
|
+
"""Exact C2 Hermite quintics with locally limited slopes and curvatures.
|
|
20
|
+
|
|
21
|
+
On an interval of width h and secant m, the quartic derivative's Bernstein
|
|
22
|
+
coefficients are [d0, d0+h*a0/4, 5*m-2*(d0+d1)+h*(a1-a0)/4,
|
|
23
|
+
d1-h*a1/4, d1]. Limit curvatures first, then shrink each node's (d,a)
|
|
24
|
+
together so all five coefficients are nonnegative. Each shared node has
|
|
25
|
+
one value, slope, and curvature: the assembled CDF is C2 and PDF is C1.
|
|
26
|
+
The support endpoints have zero slope/curvature, allowing constant CDF
|
|
27
|
+
extension and zero PDF extension without a boundary derivative jump.
|
|
28
|
+
"""
|
|
29
|
+
x, y = np.asarray(x, dtype=float), np.asarray(y, dtype=float)
|
|
30
|
+
if x.ndim != 1 or len(x) < 2 or y.shape != x.shape or not np.all(np.isfinite(x)) or not np.all(np.isfinite(y)):
|
|
31
|
+
raise ValueError("monotone_c2 needs matching finite 1D anchor arrays")
|
|
32
|
+
h, mass = np.diff(x), np.diff(y)
|
|
33
|
+
if np.any(h <= 0) or np.any(mass < 0):
|
|
34
|
+
raise ValueError("monotone_c2 requires strictly increasing x and nondecreasing CDF anchors")
|
|
35
|
+
# A clamped cubic estimates smooth slopes/curvatures in linear time. Its
|
|
36
|
+
# unconstrained interpolant is never returned: the quintic limiter below
|
|
37
|
+
# certifies monotonicity even where the cubic estimate would overshoot.
|
|
38
|
+
seed = CubicSpline(x, y, bc_type=((1, 0.0), (1, 0.0)))
|
|
39
|
+
slopes = np.maximum(seed(x, 1), 0.0)
|
|
40
|
+
slopes[[0, -1]] = 0.0
|
|
41
|
+
curvature = seed(x, 2)
|
|
42
|
+
# Adjacent interval constraints for the first/last PDF control coefficients.
|
|
43
|
+
lower, upper = np.full(len(x), -np.inf), np.full(len(x), np.inf)
|
|
44
|
+
lower[:-1] = -4 * slopes[:-1] / h
|
|
45
|
+
upper[1:] = 4 * slopes[1:] / h
|
|
46
|
+
curvature = np.clip(curvature, lower, upper)
|
|
47
|
+
curvature[[0, -1]] = 0.0
|
|
48
|
+
# Both contributions are nonnegative after clipping. Reducing either node
|
|
49
|
+
# cannot violate another interval's constraint, so one local pass suffices.
|
|
50
|
+
left = 2 * slopes[:-1] + h * curvature[:-1] / 4
|
|
51
|
+
right = 2 * slopes[1:] - h * curvature[1:] / 4
|
|
52
|
+
available = 5 * mass / h
|
|
53
|
+
total = left + right
|
|
54
|
+
factors = np.ones(len(h))
|
|
55
|
+
active = total > available
|
|
56
|
+
factors[active] = (available[active] / total[active]) * (1 - 32 * np.finfo(float).eps)
|
|
57
|
+
node_factors = np.ones(len(x))
|
|
58
|
+
node_factors[:-1] = np.minimum(node_factors[:-1], factors)
|
|
59
|
+
node_factors[1:] = np.minimum(node_factors[1:], factors)
|
|
60
|
+
slopes *= node_factors
|
|
61
|
+
curvature *= node_factors
|
|
62
|
+
if not np.all(np.isfinite(slopes)) or not np.all(np.isfinite(curvature)):
|
|
63
|
+
raise ValueError("monotone_c2 cannot resolve this anchor spacing; inspect support and score precision")
|
|
64
|
+
return BPoly.from_derivatives(x, np.column_stack((y, slopes, curvature)), extrapolate=False)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def interpolate_cdf(x: np.ndarray, y: np.ndarray, method: str):
|
|
68
|
+
if method == "monotone_c2":
|
|
69
|
+
return monotone_c2(x, y)
|
|
70
|
+
if method == "pchip":
|
|
71
|
+
return PchipInterpolator(x, y, extrapolate=False)
|
|
72
|
+
raise ValueError(f"unknown CDF interpolation {method!r}")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass(frozen=True)
|
|
76
|
+
class AnchorFit:
|
|
77
|
+
curve: BPoly | PchipInterpolator
|
|
78
|
+
indices: np.ndarray
|
|
79
|
+
max_error: float
|
|
80
|
+
stop_reason: str
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def fit_anchors(x: np.ndarray, y: np.ndarray, config: AnchorSettings, interpolation: str) -> AnchorFit:
|
|
84
|
+
"""Select only real empirical nodes plus the supplied support endpoints.
|
|
85
|
+
|
|
86
|
+
A bounded set of probability seeds starts the fit. Each pass evaluates
|
|
87
|
+
residuals against all empirical knots once, then scans disjoint intervals
|
|
88
|
+
and refines up to eight worst intervals. min_mass is the required observed
|
|
89
|
+
cumulative mass on EACH side of a proposed new node; it stops the selector
|
|
90
|
+
from chasing individual sample jumps. No output grid participates.
|
|
91
|
+
"""
|
|
92
|
+
if config.method == "all":
|
|
93
|
+
curve = interpolate_cdf(x, y, interpolation)
|
|
94
|
+
return AnchorFit(curve, np.arange(len(x)), 0.0, "all")
|
|
95
|
+
# Retain the first empirical value and the first empirical value reaching
|
|
96
|
+
# probability one, so the fit preserves the observed onset and upper tail.
|
|
97
|
+
last = min(int(np.searchsorted(y, 1.0)), len(x) - 1)
|
|
98
|
+
selected = {0, min(1, len(x) - 1), last, len(x) - 1}
|
|
99
|
+
seed_count = min(9, config.max_points - len(selected) + 1)
|
|
100
|
+
for target in np.linspace(0, 1, seed_count)[1:-1]:
|
|
101
|
+
index = min(int(np.searchsorted(y, target)), len(x) - 1)
|
|
102
|
+
ordered = sorted(selected)
|
|
103
|
+
slot = int(np.searchsorted(ordered, index))
|
|
104
|
+
if index in selected or slot == 0 or slot == len(ordered):
|
|
105
|
+
continue
|
|
106
|
+
if min(y[index] - y[ordered[slot - 1]], y[ordered[slot]] - y[index]) >= config.min_mass:
|
|
107
|
+
selected.add(index)
|
|
108
|
+
while True:
|
|
109
|
+
indices = np.array(sorted(selected), dtype=int)
|
|
110
|
+
curve = interpolate_cdf(x[indices], y[indices], interpolation)
|
|
111
|
+
residual = np.abs(curve(x) - y)
|
|
112
|
+
error = float(np.max(residual))
|
|
113
|
+
if error <= config.tolerance:
|
|
114
|
+
return AnchorFit(curve, indices, error, "tolerance")
|
|
115
|
+
if len(selected) >= config.max_points:
|
|
116
|
+
return AnchorFit(curve, indices, error, "max_points")
|
|
117
|
+
queue = []
|
|
118
|
+
for lo, hi in zip(indices[:-1], indices[1:]):
|
|
119
|
+
# Search only nodes with enough probability mass on both sides.
|
|
120
|
+
start = max(lo + 1, int(np.searchsorted(y, y[lo] + config.min_mass, side="left")))
|
|
121
|
+
end = min(hi, int(np.searchsorted(y, y[hi] - config.min_mass, side="right")))
|
|
122
|
+
if start >= end:
|
|
123
|
+
continue
|
|
124
|
+
index = start + int(np.argmax(residual[start:end]))
|
|
125
|
+
if residual[index] > config.tolerance:
|
|
126
|
+
heappush(queue, (-float(residual[index]), index))
|
|
127
|
+
if not queue:
|
|
128
|
+
return AnchorFit(curve, indices, error, "min_mass")
|
|
129
|
+
for _ in range(min(8, config.max_points - len(selected), len(queue))):
|
|
130
|
+
_, index = heappop(queue)
|
|
131
|
+
selected.add(index)
|
|
@@ -129,8 +129,12 @@ def _preview_colorbar(fig, name, cfg):
|
|
|
129
129
|
|
|
130
130
|
from .colorbar_runtime import axc_color_config, axc_is_horizontal
|
|
131
131
|
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
# Lightweight wrappers used by design tooling may expose only ``fig`` and
|
|
133
|
+
# ``axes``. An absent frame means there is no colorbar override, not that
|
|
134
|
+
# the rest of the debug overlay should be abandoned halfway through.
|
|
135
|
+
frame = getattr(fig, "frame", {})
|
|
136
|
+
cmap = axc_color_config(frame, name).get("cmap") or cfg["fallback_cmap"]
|
|
137
|
+
is_h = axc_is_horizontal(frame, name)
|
|
134
138
|
ramp = np.linspace(0.0, 1.0, int(cfg["samples"])).reshape(-1, 1)
|
|
135
139
|
if is_h:
|
|
136
140
|
ramp = ramp.reshape(1, -1)
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""Raw weighted samples -> continuous CDF, optionally its analytic derivative.
|
|
2
|
+
|
|
3
|
+
PDF1D and CDF1D share the reconstruction. No histogram or sample-grid
|
|
4
|
+
renormalisation participates in fitting: the grid only evaluates the interpolant.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Any, Mapping
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
import pandas as pd
|
|
12
|
+
from scipy.interpolate import PchipInterpolator
|
|
13
|
+
|
|
14
|
+
from ..distribution_1d_config import KINDS, settings
|
|
15
|
+
from ..memtrace import memtrace_checkpoint, memtrace_object_inventory
|
|
16
|
+
from ..utils.expression import eval_dataframe_expression
|
|
17
|
+
from .adaptive_cdf_runtime import fit_anchors
|
|
18
|
+
|
|
19
|
+
ALGORITHM_REVISION = "weighted-ecdf-adaptive-bernstein-c2-v3"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _values(df: pd.DataFrame, expr: Any, logger=None) -> np.ndarray:
|
|
23
|
+
values = np.asarray(eval_dataframe_expression(df, expr, logger=logger), dtype=float)
|
|
24
|
+
if values.ndim == 0:
|
|
25
|
+
return np.full(len(df), float(values))
|
|
26
|
+
if values.shape != (len(df),):
|
|
27
|
+
raise ValueError(f"expression {expr!r} must return one value per input row, got {values.shape}")
|
|
28
|
+
return values
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _infer_limits(x: np.ndarray, scale: str) -> tuple[float, float]:
|
|
32
|
+
unique = np.unique(x)
|
|
33
|
+
if len(unique) < 2:
|
|
34
|
+
raise ValueError("one unique sample cannot define a continuous support; set coordinates.x.lim")
|
|
35
|
+
lo = unique[0] - 0.5 * (unique[1] - unique[0])
|
|
36
|
+
hi = unique[-1] + 0.5 * (unique[-1] - unique[-2])
|
|
37
|
+
if scale == "log":
|
|
38
|
+
if unique[0] <= 0:
|
|
39
|
+
raise ValueError("coordinates.x.scale: log requires positive samples")
|
|
40
|
+
lo = max(lo, unique[0] * 0.5)
|
|
41
|
+
if not np.isfinite(lo) or not np.isfinite(hi) or not lo < hi:
|
|
42
|
+
raise ValueError("cannot infer finite support; set coordinates.x.lim")
|
|
43
|
+
return float(lo), float(hi)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def empirical_knots(x: np.ndarray, weights: np.ndarray, limits: tuple[float, float]):
|
|
47
|
+
"""Inclusive empirical nodes plus support endpoints; return largest atom too."""
|
|
48
|
+
lo, hi = limits
|
|
49
|
+
order = np.argsort(x, kind="stable")
|
|
50
|
+
x, weights = x[order], weights[order]
|
|
51
|
+
unique, first = np.unique(x, return_index=True)
|
|
52
|
+
# Rescaling before summation avoids overflow without changing probability.
|
|
53
|
+
scaled = weights / weights.max()
|
|
54
|
+
mass = np.add.reduceat(scaled, first)
|
|
55
|
+
mass /= mass.sum()
|
|
56
|
+
cumulative = np.minimum(np.cumsum(mass), 1.0)
|
|
57
|
+
cumulative[-1] = 1.0
|
|
58
|
+
interior = (unique > lo) & (unique < hi)
|
|
59
|
+
knots = np.r_[lo, unique[interior], hi]
|
|
60
|
+
probabilities = np.r_[0.0, cumulative[interior], 1.0]
|
|
61
|
+
return knots, probabilities, float(mass.max())
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def build_cdf(x: np.ndarray, weights: np.ndarray, limits: tuple[float, float]) -> PchipInterpolator:
|
|
65
|
+
"""Original all-anchor PCHIP path, useful for exact empirical-node comparisons.
|
|
66
|
+
|
|
67
|
+
A sample exactly at lo cannot retain its jump with F(lo)=0; its mass is
|
|
68
|
+
carried into the first interval. Other empirical nodes retain their CDF.
|
|
69
|
+
Production reconstruction uses fit_anchors with the selected settings.
|
|
70
|
+
"""
|
|
71
|
+
knots, probabilities, _ = empirical_knots(x, weights, limits)
|
|
72
|
+
return PchipInterpolator(knots, probabilities, extrapolate=False)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def distribution_1d(df: pd.DataFrame, cfg: Mapping[str, Any], kind: str, logger=None) -> pd.DataFrame:
|
|
76
|
+
if kind not in KINDS:
|
|
77
|
+
raise ValueError(f"unknown distribution transform {kind!r}")
|
|
78
|
+
if not isinstance(df, pd.DataFrame) or df.empty:
|
|
79
|
+
raise ValueError(f"{kind} needs a nonempty pandas sample table")
|
|
80
|
+
opts = settings(cfg)
|
|
81
|
+
memtrace_checkpoint(logger, f"pipeline.{kind}.before", df)
|
|
82
|
+
x = _values(df, opts.x["expr"], logger)
|
|
83
|
+
weights = _values(df, opts.weight["expr"], logger) if opts.weight else np.ones(len(df))
|
|
84
|
+
if not np.all(np.isfinite(x)) or not np.all(np.isfinite(weights)):
|
|
85
|
+
raise ValueError(f"{kind} needs finite samples and weights; filter invalid rows first")
|
|
86
|
+
if np.any(weights < 0):
|
|
87
|
+
raise ValueError(f"{kind} needs nonnegative probability weights; signed event weights are not a CDF")
|
|
88
|
+
work = pd.DataFrame({"x": x, "weight": weights})
|
|
89
|
+
if opts.repeat is not None:
|
|
90
|
+
if opts.repeat not in df.columns:
|
|
91
|
+
raise KeyError(f"{kind} missing repeat column {opts.repeat!r}")
|
|
92
|
+
if df[opts.repeat].isna().any():
|
|
93
|
+
raise ValueError(f"{kind} repeat identifiers must not be missing")
|
|
94
|
+
work["repeat"] = df[opts.repeat].to_numpy()
|
|
95
|
+
positive = weights > 0
|
|
96
|
+
if not positive.any():
|
|
97
|
+
raise ValueError(f"{kind} weights sum to zero")
|
|
98
|
+
limits = opts.limits or _infer_limits(x[positive], opts.scale)
|
|
99
|
+
lo, hi = limits
|
|
100
|
+
if np.any((x[positive] < lo) | (x[positive] > hi)):
|
|
101
|
+
raise ValueError(f"{kind} coordinates.x.lim must contain all positive-weight samples; filter first to truncate")
|
|
102
|
+
grid = np.geomspace(lo, hi, opts.grid) if opts.scale == "log" else np.linspace(lo, hi, opts.grid)
|
|
103
|
+
memtrace_object_inventory(logger, f"pipeline.{kind}.samples", {"samples": work})
|
|
104
|
+
curves = ("cdf", "pdf") if kind == "PDF1D" else ("cdf",)
|
|
105
|
+
mean = {key: np.zeros(opts.grid) for key in curves}
|
|
106
|
+
m2 = {key: np.zeros(opts.grid) for key in curves}
|
|
107
|
+
groups = work.groupby("repeat", sort=False, observed=True) if opts.repeat else [(None, work)]
|
|
108
|
+
n = 0
|
|
109
|
+
boundary_mass = False
|
|
110
|
+
diagnostics = []
|
|
111
|
+
for label, block in groups:
|
|
112
|
+
block = block.loc[block.weight > 0]
|
|
113
|
+
if block.empty:
|
|
114
|
+
raise ValueError(f"{kind} repeat {label!r} weights sum to zero")
|
|
115
|
+
bx, bw = block.x.to_numpy(), block.weight.to_numpy()
|
|
116
|
+
boundary_mass |= bool(np.any(bx == lo))
|
|
117
|
+
knots, probabilities, largest_jump = empirical_knots(bx, bw, limits)
|
|
118
|
+
fit = fit_anchors(knots, probabilities, opts.anchors, opts.interpolation)
|
|
119
|
+
cdf = fit.curve
|
|
120
|
+
diagnostics.append({
|
|
121
|
+
"repeat": label.item() if isinstance(label, np.generic) else label,
|
|
122
|
+
"n_anchors": len(fit.indices), "n_candidates": len(knots),
|
|
123
|
+
"max_cdf_error": fit.max_error, "stop_reason": fit.stop_reason,
|
|
124
|
+
"largest_empirical_jump": largest_jump,
|
|
125
|
+
})
|
|
126
|
+
if logger is not None:
|
|
127
|
+
logger.debug(f"{kind} repeat={label!r}: anchors={len(fit.indices)}/{len(knots)}, "
|
|
128
|
+
f"max CDF node error={fit.max_error:.6g}, stopped={fit.stop_reason}")
|
|
129
|
+
if opts.anchors.method == "adaptive" and fit.max_error > opts.anchors.tolerance:
|
|
130
|
+
logger.warning(f"{kind} repeat={label!r}: CDF error {fit.max_error:.6g} exceeds "
|
|
131
|
+
f"tolerance {opts.anchors.tolerance:g}; stopped at {fit.stop_reason}. "
|
|
132
|
+
"Adjust anchors settings if finer CDF reconstruction is needed.")
|
|
133
|
+
if opts.anchors.method == "adaptive" and largest_jump > max(2 * opts.anchors.tolerance, opts.anchors.min_mass):
|
|
134
|
+
logger.warning(f"{kind} repeat={label!r}: empirical probability jump {largest_jump:.6g}; "
|
|
135
|
+
"a continuous density spreads this discrete mass over an interval")
|
|
136
|
+
values = {"cdf": cdf(grid)}
|
|
137
|
+
if kind == "PDF1D":
|
|
138
|
+
pdf = cdf.derivative()(grid)
|
|
139
|
+
tolerance = 128 * np.finfo(float).eps * max(1.0, float(np.max(np.abs(pdf))))
|
|
140
|
+
if np.min(pdf) < -tolerance:
|
|
141
|
+
raise ValueError(f"{kind} produced a negative density beyond floating-point tolerance")
|
|
142
|
+
values["pdf"] = np.maximum(pdf, 0.0)
|
|
143
|
+
n += 1
|
|
144
|
+
for key in curves:
|
|
145
|
+
if not np.all(np.isfinite(values[key])):
|
|
146
|
+
raise ValueError(f"{kind} produced nonfinite {key}; inspect sample spacing/support")
|
|
147
|
+
delta = values[key] - mean[key]
|
|
148
|
+
mean[key] += delta / n
|
|
149
|
+
m2[key] += delta * (values[key] - mean[key])
|
|
150
|
+
out = {opts.name: grid}
|
|
151
|
+
for key in curves:
|
|
152
|
+
out[key] = mean[key]
|
|
153
|
+
out[f"{key}_std"] = np.sqrt(np.maximum(m2[key], 0.0) / (n - 1)) if n > 1 else np.full(opts.grid, np.nan)
|
|
154
|
+
out["n_repeats"] = n
|
|
155
|
+
table = pd.DataFrame(out)
|
|
156
|
+
table.attrs["distribution_1d"] = {
|
|
157
|
+
"algorithm": ALGORITHM_REVISION, "interpolation": opts.interpolation,
|
|
158
|
+
"anchor_method": opts.anchors.method, "support": limits, "repeats": diagnostics,
|
|
159
|
+
}
|
|
160
|
+
if logger is not None:
|
|
161
|
+
if boundary_mass:
|
|
162
|
+
logger.warning(f"{kind}: mass at the lower support boundary is spread over the first CDF interval")
|
|
163
|
+
logger.debug(f"{kind}: {len(df)} samples -> {opts.grid} points, {n} repeats, support={limits}, std ddof=1")
|
|
164
|
+
memtrace_checkpoint(logger, f"pipeline.{kind}.after", table)
|
|
165
|
+
return table
|