jarvisplot 2.1.7__tar.gz → 2.1.9__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.7 → jarvisplot-2.1.9}/JarvisPLOT.egg-info/PKG-INFO +40 -1
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/JarvisPLOT.egg-info/SOURCES.txt +19 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/PKG-INFO +40 -1
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/README.md +39 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/config_runtime.py +3 -1
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/debug_config.py +7 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/design_runtime.py +4 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/figure.py +31 -7
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/figure_types.py +10 -1
- jarvisplot-2.1.9/jarvisplot/Figure/forest_debug.py +35 -0
- jarvisplot-2.1.9/jarvisplot/Figure/forest_legend.py +88 -0
- jarvisplot-2.1.9/jarvisplot/Figure/forest_runtime.py +294 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/layer_runtime.py +1 -1
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/legend_runtime.py +3 -3
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/preprocessor.py +28 -1
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/preprocessor_runtime.py +27 -5
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/style_runtime.py +14 -0
- jarvisplot-2.1.9/jarvisplot/cache_registry.py +346 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cache_store.py +78 -8
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/capabilities.py +7 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/args.json +13 -2
- jarvisplot-2.1.9/jarvisplot/cards/forest/swiss_column.json +196 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/style_preference.json +3 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/column_demand.py +41 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/core.py +57 -7
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/core_runtime.py +203 -43
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/data_access.py +15 -15
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/data_loader.py +45 -2
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/data_loader_hdf5.py +0 -2
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/data_loader_runtime.py +69 -20
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/dryrun_runtime.py +62 -0
- jarvisplot-2.1.9/jarvisplot/forest_contract.py +436 -0
- jarvisplot-2.1.9/jarvisplot/forest_text.py +86 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/legend_cards.py +2 -2
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/man_render_agent.py +7 -0
- jarvisplot-2.1.9/jarvisplot/manual_cards/cache.yaml +57 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/cli-map.yaml +3 -1
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/manifest.yaml +3 -0
- jarvisplot-2.1.9/jarvisplot/manual_cards/type-forest.yaml +244 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/core/figure.json +297 -3
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/manifest.json +5 -2
- jarvisplot-2.1.9/jarvisplot/schema/types/forest.json +824 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/templates_catalog.py +18 -0
- jarvisplot-2.1.9/jarvisplot/utils/expression.py +425 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/validation.py +40 -2
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/verbs/__init__.py +1 -0
- jarvisplot-2.1.9/jarvisplot/verbs/cache.py +179 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/verbs/config_cmd.py +9 -2
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/verbs/doctor.py +1 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/pyproject.toml +1 -1
- jarvisplot-2.1.9/tests/test_add_column.py +58 -0
- jarvisplot-2.1.9/tests/test_cache_cleanup.py +75 -0
- jarvisplot-2.1.9/tests/test_cache_registry.py +455 -0
- jarvisplot-2.1.9/tests/test_column_pruning.py +251 -0
- jarvisplot-2.1.9/tests/test_examples_validate.py +29 -0
- jarvisplot-2.1.9/tests/test_expression_semantics.py +185 -0
- jarvisplot-2.1.9/tests/test_forest.py +619 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_parse_data_metadata.py +75 -0
- jarvisplot-2.1.9/tests/test_render_lifecycle.py +175 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_template_catalog.py +7 -0
- jarvisplot-2.1.7/jarvisplot/utils/expression.py +0 -125
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/JarvisPLOT.egg-info/dependency_links.txt +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/JarvisPLOT.egg-info/entry_points.txt +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/JarvisPLOT.egg-info/requires.txt +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/JarvisPLOT.egg-info/top_level.txt +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/__init__.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/adapters_rect.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/adapters_ternary.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/adaptive_cdf_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/bin_stat_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/cards/std_axes_adapter_config.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/colorbar_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/corr_layout.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/corr_layout_diamond.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/corr_order.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/correlation_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/corrplot_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/data_pipelines.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/density_cell_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/distribution_1d_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/dynesty_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/helper.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/interp_2d_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/interp_natural_neighbor.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/interp_natural_neighbor_exact.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/layout_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/method_registry.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/posterior_density_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/posterior_hpd.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/posterior_mesh.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/profile_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/Figure/significance_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/__init__.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/agent_digest.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/agent_io.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/1x1/ternary.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/2x1/dynesty_runplot.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/2x1/rect.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/2x1/rect5x1.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/2x1/rect_cmap.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/2x1/rect_marginal.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/2x1/rectratio.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/2x1/ternary.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/2x1/ternary_cmap.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/4x1/rect.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/4x1/rect_cmap.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/4x1/ternary.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/a4paper/4x1/ternary_cmap.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/colors/colormaps.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/corrplot/diamond.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/corrplot/matrix.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/default/output.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/flowchart/default.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/gambit/1x1/ternary.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/gambit/2x1/rect_cmap.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/gambit/2x1/ternary.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/gambit/2x1/ternary_cmap.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/icons/JarvisHEP.png +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/icons/flowchart/JarvisHEP.png +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/icons/flowchart/calculator.png +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/icons/flowchart/inputfile.png +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/icons/flowchart/opera.png +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/icons/flowchart/outputfile.png +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/icons/flowchart/sampler.png +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/icons/gambit.png +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/icons/gambit_small.png +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/legends/compact/legend-card.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/legends/default/legend-card.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/legends/paper/legend-card.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cards/legends/presentation/legend-card.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cli.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/cli_help.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/client.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/column_probe.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/config.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/config_address.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/core_assets.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/data_generation_contracts.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/data_loader_summary.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/dataset_types.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/diagnostic_guidance.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/diagnostics.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/distribution_1d_config.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/expr_names.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/fix_apply.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/flowchart.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/generated_data.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/inner_func.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/man_catalog.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/man_methods.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/man_render_human.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/man_transforms.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/agent-output.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/data-columns.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/debug-overlay.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/diagnostics.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/dryrun-viz.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/field-interp.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/generated-data.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/layer-method.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/legend.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/method_notes.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/style-axes.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/type-correlation-matrix.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/type-posterior-2d.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/type-profile-2d.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/validate.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/workflow.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/manual_cards/yaml-root.yaml +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/memtrace.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/method_contracts.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/render_health.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/core/common.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/core/dataset.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/core/distribution-1d.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/core/generated-data.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/core/layer.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/core/legend-card.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/core/legend.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/core/transform.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/bar.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/barh.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/contour.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/contourf.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/corrplot.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/dynesty_runplot.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/errorbar.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/fill.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/fill_between.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/fill_betweenx.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/hist.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/hist2d.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/imshow.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/jpcontour.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/jpcontourf.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/jpfield.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/pcolor.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/pcolormesh.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/plot.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/quiver.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/scatter.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/stairs.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/step.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/tricontour.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/tricontourf.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/tripcolor.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/tripcolor_axes.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/triplot.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/voronoi.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/methods/voronoif.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema/plot-config.json +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema_catalog.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/schema_diagnostics.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/transform_contracts.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/utils/__init__.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/utils/cmaps.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/utils/dataframes.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/utils/interpolator.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/utils/pathing.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/verbs/cap.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/verbs/data.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/verbs/dryrun.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/verbs/explain.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/verbs/man.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/verbs/suggest.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/verbs/template.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/verbs/validate.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/jarvisplot/yaml_io.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/setup.cfg +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_adaptive_cdf.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_agent_digest.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_agent_envelope.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_axis_title.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_capabilities.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_card_debug_shape.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_cli_help.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_cli_verbs.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_cmaps.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_column_existence.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_config_addressing.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_config_edit.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_config_expand.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_correlation_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_corrplot.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_data_access.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_data_describe.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_data_head_eval.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_data_loader_contracts.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_data_pipelines.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_debug_config.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_debug_switches.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_debug_yaml_override.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_density_cell_transform.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_design_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_diagnostic_guidance.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_distribution_1d_transform.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_docs_status_labels.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_doctor_partial.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_explain.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_figure_contracts.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_figure_type_expander.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_fix_application.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_flowchart_renderer.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_generated_data.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_imshow_adapter.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_interp_2d_transform.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_interp_natural_neighbor.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_interpolator_contracts.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_jpcontour_methods.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_layer_legend.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_legend_cards.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_legend_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_man_cli.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_method_contracts.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_pathing_contracts.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_posterior_hpd.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_profile_runtime.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_render_health.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_row_ledger.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_schema_catalog.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_suggest.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_suggest_axes.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_template_json.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_ternary_debug.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/tests/test_transform_contracts.py +0 -0
- {jarvisplot-2.1.7 → jarvisplot-2.1.9}/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.9
|
|
4
4
|
Summary: Jarvis-PLOT: YAML-driven plotting engine
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -66,6 +66,7 @@ Render with a bare path — there is no `jplot run`:
|
|
|
66
66
|
```bash
|
|
67
67
|
jplot path/to/config.yaml
|
|
68
68
|
jplot path/to/config.yaml --rebuild-cache
|
|
69
|
+
jplot path/to/config.yaml --print
|
|
69
70
|
```
|
|
70
71
|
|
|
71
72
|
Everything else is discovery and judgement, in three groups.
|
|
@@ -218,9 +219,45 @@ from jarvisplot import render_flowchart, render_flowchart_file
|
|
|
218
219
|
- You can set `project.workdir` in YAML.
|
|
219
220
|
- If `output.dir` is omitted, Jarvis-PLOT defaults to `<workdir>/plots/`.
|
|
220
221
|
- Data cache is stored in `<workdir>/.cache/`.
|
|
222
|
+
- `--print` accepts the current settings and renders final figures without the logo. It announces that, after all enabled figures are saved successfully, cache payloads used or created by this run will be deleted (pipeline data and metadata, named/shared data, summaries, and HDF5 materialization slots). Rendering failures or a run with no enabled figures keep the cache. Unrelated cache entries and the lightweight fingerprint manifest are retained; later renders rebuild deleted entries as needed.
|
|
221
223
|
- Profiling pipelines are prebuilt once and reused from cache when source fingerprint and profile settings are unchanged.
|
|
222
224
|
- Profiling uses a fast two-stage grid reduction (`pregrid` + render `bin`) for large datasets.
|
|
223
225
|
|
|
226
|
+
Plot caches are automatically registered in `~/.jarvis/plot.json` (or
|
|
227
|
+
`$JARVIS_HOME/plot.json`). The registry groups caches by workdir and records
|
|
228
|
+
associated YAML paths and last use; payloads stay in their original directories.
|
|
229
|
+
This includes caches created by `data describe` and default `dryrun --with-data`
|
|
230
|
+
exports. Sizes are calculated when listing, rather than stored in the registry.
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
jplot cache list
|
|
234
|
+
jplot cache scan ~/Jarvis-Workshop # register existing plot caches
|
|
235
|
+
jplot cache clean --workdir /path/to/project # this directory and all nested projects; repeatable
|
|
236
|
+
jplot cache clean --all --older-than 30 # unused for at least 30 days
|
|
237
|
+
jplot cache clean --all --dry-run # preview; no deletion/index changes
|
|
238
|
+
jplot cache clean --all # clean all registered inactive caches
|
|
239
|
+
jplot cache -h
|
|
240
|
+
jplot man cache
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`--workdir PATH` selects registered caches in PATH itself and all of its
|
|
244
|
+
subdirectories, even when PATH has no cache of its own. Repeat it to select
|
|
245
|
+
multiple directory trees; overlapping selections are deduplicated. Use
|
|
246
|
+
`cache scan PATH` first for old caches that have not been registered.
|
|
247
|
+
|
|
248
|
+
All cache subcommands accept `--json` and use the existing CLI envelope and
|
|
249
|
+
exit codes (0 success/partial, 1 failure, 2 usage). Non-TTY stdout defaults to
|
|
250
|
+
JSON; human results go to stderr. Active caches are skipped (`ok: null` when
|
|
251
|
+
the remaining operation succeeds), and records for missing paths are pruned
|
|
252
|
+
during cleanup. Only marked Jarvis-PLOT components are removed; source data,
|
|
253
|
+
plots, and unrelated `.cache` content are retained. Failed deletions retain
|
|
254
|
+
their registry entries. Scanning adopts legacy caches only when the four
|
|
255
|
+
pipeline directories and a compatible `manifest.json` identify them; old
|
|
256
|
+
unmarked twin-only directories need a new `dryrun --with-data` run to register.
|
|
257
|
+
An explicitly supplied `--out-dir` is an export directory and is not registered.
|
|
258
|
+
Concurrent registry writes use a lock and atomic replacement. Registration
|
|
259
|
+
failures warn without preventing rendering.
|
|
260
|
+
|
|
224
261
|
### Example: SUSYRun2 Ternary Plots
|
|
225
262
|
|
|
226
263
|
```bash
|
|
@@ -313,3 +350,5 @@ Read the context docs and roadmap before changing parsing, transforms, rendering
|
|
|
313
350
|
## License
|
|
314
351
|
|
|
315
352
|
MIT License
|
|
353
|
+
|
|
354
|
+
Create a continuous forest figure with `type: forest`, a generic row table and optional point table. The default Swiss-column card uses 82.5 mm width and 5.5 mm row pitch; every row shares one numerical x domain. See [the forest contract](docs/specs/FOREST.md), [native examples](Example/forest/README.md), or `jplot man forest --json`.
|
|
@@ -9,6 +9,7 @@ JarvisPLOT.egg-info/top_level.txt
|
|
|
9
9
|
jarvisplot/__init__.py
|
|
10
10
|
jarvisplot/agent_digest.py
|
|
11
11
|
jarvisplot/agent_io.py
|
|
12
|
+
jarvisplot/cache_registry.py
|
|
12
13
|
jarvisplot/cache_store.py
|
|
13
14
|
jarvisplot/capabilities.py
|
|
14
15
|
jarvisplot/cli.py
|
|
@@ -35,6 +36,8 @@ jarvisplot/dryrun_runtime.py
|
|
|
35
36
|
jarvisplot/expr_names.py
|
|
36
37
|
jarvisplot/fix_apply.py
|
|
37
38
|
jarvisplot/flowchart.py
|
|
39
|
+
jarvisplot/forest_contract.py
|
|
40
|
+
jarvisplot/forest_text.py
|
|
38
41
|
jarvisplot/generated_data.py
|
|
39
42
|
jarvisplot/inner_func.py
|
|
40
43
|
jarvisplot/legend_cards.py
|
|
@@ -72,6 +75,9 @@ jarvisplot/Figure/distribution_1d_runtime.py
|
|
|
72
75
|
jarvisplot/Figure/dynesty_runtime.py
|
|
73
76
|
jarvisplot/Figure/figure.py
|
|
74
77
|
jarvisplot/Figure/figure_types.py
|
|
78
|
+
jarvisplot/Figure/forest_debug.py
|
|
79
|
+
jarvisplot/Figure/forest_legend.py
|
|
80
|
+
jarvisplot/Figure/forest_runtime.py
|
|
75
81
|
jarvisplot/Figure/helper.py
|
|
76
82
|
jarvisplot/Figure/interp_2d_runtime.py
|
|
77
83
|
jarvisplot/Figure/interp_natural_neighbor.py
|
|
@@ -109,6 +115,7 @@ jarvisplot/cards/corrplot/diamond.json
|
|
|
109
115
|
jarvisplot/cards/corrplot/matrix.json
|
|
110
116
|
jarvisplot/cards/default/output.json
|
|
111
117
|
jarvisplot/cards/flowchart/default.json
|
|
118
|
+
jarvisplot/cards/forest/swiss_column.json
|
|
112
119
|
jarvisplot/cards/gambit/1x1/ternary.json
|
|
113
120
|
jarvisplot/cards/gambit/2x1/rect_cmap.json
|
|
114
121
|
jarvisplot/cards/gambit/2x1/ternary.json
|
|
@@ -127,6 +134,7 @@ jarvisplot/cards/legends/default/legend-card.json
|
|
|
127
134
|
jarvisplot/cards/legends/paper/legend-card.json
|
|
128
135
|
jarvisplot/cards/legends/presentation/legend-card.json
|
|
129
136
|
jarvisplot/manual_cards/agent-output.yaml
|
|
137
|
+
jarvisplot/manual_cards/cache.yaml
|
|
130
138
|
jarvisplot/manual_cards/cli-map.yaml
|
|
131
139
|
jarvisplot/manual_cards/data-columns.yaml
|
|
132
140
|
jarvisplot/manual_cards/debug-overlay.yaml
|
|
@@ -140,6 +148,7 @@ jarvisplot/manual_cards/manifest.yaml
|
|
|
140
148
|
jarvisplot/manual_cards/method_notes.yaml
|
|
141
149
|
jarvisplot/manual_cards/style-axes.yaml
|
|
142
150
|
jarvisplot/manual_cards/type-correlation-matrix.yaml
|
|
151
|
+
jarvisplot/manual_cards/type-forest.yaml
|
|
143
152
|
jarvisplot/manual_cards/type-posterior-2d.yaml
|
|
144
153
|
jarvisplot/manual_cards/type-profile-2d.yaml
|
|
145
154
|
jarvisplot/manual_cards/validate.yaml
|
|
@@ -186,6 +195,7 @@ jarvisplot/schema/methods/tripcolor_axes.json
|
|
|
186
195
|
jarvisplot/schema/methods/triplot.json
|
|
187
196
|
jarvisplot/schema/methods/voronoi.json
|
|
188
197
|
jarvisplot/schema/methods/voronoif.json
|
|
198
|
+
jarvisplot/schema/types/forest.json
|
|
189
199
|
jarvisplot/utils/__init__.py
|
|
190
200
|
jarvisplot/utils/cmaps.py
|
|
191
201
|
jarvisplot/utils/dataframes.py
|
|
@@ -193,6 +203,7 @@ jarvisplot/utils/expression.py
|
|
|
193
203
|
jarvisplot/utils/interpolator.py
|
|
194
204
|
jarvisplot/utils/pathing.py
|
|
195
205
|
jarvisplot/verbs/__init__.py
|
|
206
|
+
jarvisplot/verbs/cache.py
|
|
196
207
|
jarvisplot/verbs/cap.py
|
|
197
208
|
jarvisplot/verbs/config_cmd.py
|
|
198
209
|
jarvisplot/verbs/data.py
|
|
@@ -204,15 +215,19 @@ jarvisplot/verbs/suggest.py
|
|
|
204
215
|
jarvisplot/verbs/template.py
|
|
205
216
|
jarvisplot/verbs/validate.py
|
|
206
217
|
tests/test_adaptive_cdf.py
|
|
218
|
+
tests/test_add_column.py
|
|
207
219
|
tests/test_agent_digest.py
|
|
208
220
|
tests/test_agent_envelope.py
|
|
209
221
|
tests/test_axis_title.py
|
|
222
|
+
tests/test_cache_cleanup.py
|
|
223
|
+
tests/test_cache_registry.py
|
|
210
224
|
tests/test_capabilities.py
|
|
211
225
|
tests/test_card_debug_shape.py
|
|
212
226
|
tests/test_cli_help.py
|
|
213
227
|
tests/test_cli_verbs.py
|
|
214
228
|
tests/test_cmaps.py
|
|
215
229
|
tests/test_column_existence.py
|
|
230
|
+
tests/test_column_pruning.py
|
|
216
231
|
tests/test_config_addressing.py
|
|
217
232
|
tests/test_config_edit.py
|
|
218
233
|
tests/test_config_expand.py
|
|
@@ -232,11 +247,14 @@ tests/test_diagnostic_guidance.py
|
|
|
232
247
|
tests/test_distribution_1d_transform.py
|
|
233
248
|
tests/test_docs_status_labels.py
|
|
234
249
|
tests/test_doctor_partial.py
|
|
250
|
+
tests/test_examples_validate.py
|
|
235
251
|
tests/test_explain.py
|
|
252
|
+
tests/test_expression_semantics.py
|
|
236
253
|
tests/test_figure_contracts.py
|
|
237
254
|
tests/test_figure_type_expander.py
|
|
238
255
|
tests/test_fix_application.py
|
|
239
256
|
tests/test_flowchart_renderer.py
|
|
257
|
+
tests/test_forest.py
|
|
240
258
|
tests/test_generated_data.py
|
|
241
259
|
tests/test_imshow_adapter.py
|
|
242
260
|
tests/test_interp_2d_transform.py
|
|
@@ -253,6 +271,7 @@ tests/test_pathing_contracts.py
|
|
|
253
271
|
tests/test_posterior_hpd.py
|
|
254
272
|
tests/test_profile_runtime.py
|
|
255
273
|
tests/test_render_health.py
|
|
274
|
+
tests/test_render_lifecycle.py
|
|
256
275
|
tests/test_row_ledger.py
|
|
257
276
|
tests/test_schema_catalog.py
|
|
258
277
|
tests/test_suggest.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: JarvisPLOT
|
|
3
|
-
Version: 2.1.
|
|
3
|
+
Version: 2.1.9
|
|
4
4
|
Summary: Jarvis-PLOT: YAML-driven plotting engine
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -66,6 +66,7 @@ Render with a bare path — there is no `jplot run`:
|
|
|
66
66
|
```bash
|
|
67
67
|
jplot path/to/config.yaml
|
|
68
68
|
jplot path/to/config.yaml --rebuild-cache
|
|
69
|
+
jplot path/to/config.yaml --print
|
|
69
70
|
```
|
|
70
71
|
|
|
71
72
|
Everything else is discovery and judgement, in three groups.
|
|
@@ -218,9 +219,45 @@ from jarvisplot import render_flowchart, render_flowchart_file
|
|
|
218
219
|
- You can set `project.workdir` in YAML.
|
|
219
220
|
- If `output.dir` is omitted, Jarvis-PLOT defaults to `<workdir>/plots/`.
|
|
220
221
|
- Data cache is stored in `<workdir>/.cache/`.
|
|
222
|
+
- `--print` accepts the current settings and renders final figures without the logo. It announces that, after all enabled figures are saved successfully, cache payloads used or created by this run will be deleted (pipeline data and metadata, named/shared data, summaries, and HDF5 materialization slots). Rendering failures or a run with no enabled figures keep the cache. Unrelated cache entries and the lightweight fingerprint manifest are retained; later renders rebuild deleted entries as needed.
|
|
221
223
|
- Profiling pipelines are prebuilt once and reused from cache when source fingerprint and profile settings are unchanged.
|
|
222
224
|
- Profiling uses a fast two-stage grid reduction (`pregrid` + render `bin`) for large datasets.
|
|
223
225
|
|
|
226
|
+
Plot caches are automatically registered in `~/.jarvis/plot.json` (or
|
|
227
|
+
`$JARVIS_HOME/plot.json`). The registry groups caches by workdir and records
|
|
228
|
+
associated YAML paths and last use; payloads stay in their original directories.
|
|
229
|
+
This includes caches created by `data describe` and default `dryrun --with-data`
|
|
230
|
+
exports. Sizes are calculated when listing, rather than stored in the registry.
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
jplot cache list
|
|
234
|
+
jplot cache scan ~/Jarvis-Workshop # register existing plot caches
|
|
235
|
+
jplot cache clean --workdir /path/to/project # this directory and all nested projects; repeatable
|
|
236
|
+
jplot cache clean --all --older-than 30 # unused for at least 30 days
|
|
237
|
+
jplot cache clean --all --dry-run # preview; no deletion/index changes
|
|
238
|
+
jplot cache clean --all # clean all registered inactive caches
|
|
239
|
+
jplot cache -h
|
|
240
|
+
jplot man cache
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`--workdir PATH` selects registered caches in PATH itself and all of its
|
|
244
|
+
subdirectories, even when PATH has no cache of its own. Repeat it to select
|
|
245
|
+
multiple directory trees; overlapping selections are deduplicated. Use
|
|
246
|
+
`cache scan PATH` first for old caches that have not been registered.
|
|
247
|
+
|
|
248
|
+
All cache subcommands accept `--json` and use the existing CLI envelope and
|
|
249
|
+
exit codes (0 success/partial, 1 failure, 2 usage). Non-TTY stdout defaults to
|
|
250
|
+
JSON; human results go to stderr. Active caches are skipped (`ok: null` when
|
|
251
|
+
the remaining operation succeeds), and records for missing paths are pruned
|
|
252
|
+
during cleanup. Only marked Jarvis-PLOT components are removed; source data,
|
|
253
|
+
plots, and unrelated `.cache` content are retained. Failed deletions retain
|
|
254
|
+
their registry entries. Scanning adopts legacy caches only when the four
|
|
255
|
+
pipeline directories and a compatible `manifest.json` identify them; old
|
|
256
|
+
unmarked twin-only directories need a new `dryrun --with-data` run to register.
|
|
257
|
+
An explicitly supplied `--out-dir` is an export directory and is not registered.
|
|
258
|
+
Concurrent registry writes use a lock and atomic replacement. Registration
|
|
259
|
+
failures warn without preventing rendering.
|
|
260
|
+
|
|
224
261
|
### Example: SUSYRun2 Ternary Plots
|
|
225
262
|
|
|
226
263
|
```bash
|
|
@@ -313,3 +350,5 @@ Read the context docs and roadmap before changing parsing, transforms, rendering
|
|
|
313
350
|
## License
|
|
314
351
|
|
|
315
352
|
MIT License
|
|
353
|
+
|
|
354
|
+
Create a continuous forest figure with `type: forest`, a generic row table and optional point table. The default Swiss-column card uses 82.5 mm width and 5.5 mm row pitch; every row shares one numerical x domain. See [the forest contract](docs/specs/FOREST.md), [native examples](Example/forest/README.md), or `jplot man forest --json`.
|
|
@@ -44,6 +44,7 @@ Render with a bare path — there is no `jplot run`:
|
|
|
44
44
|
```bash
|
|
45
45
|
jplot path/to/config.yaml
|
|
46
46
|
jplot path/to/config.yaml --rebuild-cache
|
|
47
|
+
jplot path/to/config.yaml --print
|
|
47
48
|
```
|
|
48
49
|
|
|
49
50
|
Everything else is discovery and judgement, in three groups.
|
|
@@ -196,9 +197,45 @@ from jarvisplot import render_flowchart, render_flowchart_file
|
|
|
196
197
|
- You can set `project.workdir` in YAML.
|
|
197
198
|
- If `output.dir` is omitted, Jarvis-PLOT defaults to `<workdir>/plots/`.
|
|
198
199
|
- Data cache is stored in `<workdir>/.cache/`.
|
|
200
|
+
- `--print` accepts the current settings and renders final figures without the logo. It announces that, after all enabled figures are saved successfully, cache payloads used or created by this run will be deleted (pipeline data and metadata, named/shared data, summaries, and HDF5 materialization slots). Rendering failures or a run with no enabled figures keep the cache. Unrelated cache entries and the lightweight fingerprint manifest are retained; later renders rebuild deleted entries as needed.
|
|
199
201
|
- Profiling pipelines are prebuilt once and reused from cache when source fingerprint and profile settings are unchanged.
|
|
200
202
|
- Profiling uses a fast two-stage grid reduction (`pregrid` + render `bin`) for large datasets.
|
|
201
203
|
|
|
204
|
+
Plot caches are automatically registered in `~/.jarvis/plot.json` (or
|
|
205
|
+
`$JARVIS_HOME/plot.json`). The registry groups caches by workdir and records
|
|
206
|
+
associated YAML paths and last use; payloads stay in their original directories.
|
|
207
|
+
This includes caches created by `data describe` and default `dryrun --with-data`
|
|
208
|
+
exports. Sizes are calculated when listing, rather than stored in the registry.
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
jplot cache list
|
|
212
|
+
jplot cache scan ~/Jarvis-Workshop # register existing plot caches
|
|
213
|
+
jplot cache clean --workdir /path/to/project # this directory and all nested projects; repeatable
|
|
214
|
+
jplot cache clean --all --older-than 30 # unused for at least 30 days
|
|
215
|
+
jplot cache clean --all --dry-run # preview; no deletion/index changes
|
|
216
|
+
jplot cache clean --all # clean all registered inactive caches
|
|
217
|
+
jplot cache -h
|
|
218
|
+
jplot man cache
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
`--workdir PATH` selects registered caches in PATH itself and all of its
|
|
222
|
+
subdirectories, even when PATH has no cache of its own. Repeat it to select
|
|
223
|
+
multiple directory trees; overlapping selections are deduplicated. Use
|
|
224
|
+
`cache scan PATH` first for old caches that have not been registered.
|
|
225
|
+
|
|
226
|
+
All cache subcommands accept `--json` and use the existing CLI envelope and
|
|
227
|
+
exit codes (0 success/partial, 1 failure, 2 usage). Non-TTY stdout defaults to
|
|
228
|
+
JSON; human results go to stderr. Active caches are skipped (`ok: null` when
|
|
229
|
+
the remaining operation succeeds), and records for missing paths are pruned
|
|
230
|
+
during cleanup. Only marked Jarvis-PLOT components are removed; source data,
|
|
231
|
+
plots, and unrelated `.cache` content are retained. Failed deletions retain
|
|
232
|
+
their registry entries. Scanning adopts legacy caches only when the four
|
|
233
|
+
pipeline directories and a compatible `manifest.json` identify them; old
|
|
234
|
+
unmarked twin-only directories need a new `dryrun --with-data` run to register.
|
|
235
|
+
An explicitly supplied `--out-dir` is an export directory and is not registered.
|
|
236
|
+
Concurrent registry writes use a lock and atomic replacement. Registration
|
|
237
|
+
failures warn without preventing rendering.
|
|
238
|
+
|
|
202
239
|
### Example: SUSYRun2 Ternary Plots
|
|
203
240
|
|
|
204
241
|
```bash
|
|
@@ -291,3 +328,5 @@ Read the context docs and roadmap before changing parsing, transforms, rendering
|
|
|
291
328
|
## License
|
|
292
329
|
|
|
293
330
|
MIT License
|
|
331
|
+
|
|
332
|
+
Create a continuous forest figure with `type: forest`, a generic row table and optional point table. The default Swiss-column card uses 82.5 mm width and 5.5 mm row pitch; every row shares one numerical x domain. See [the forest contract](docs/specs/FOREST.md), [native examples](Example/forest/README.md), or `jplot man forest --json`.
|
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Mapping
|
|
5
5
|
|
|
6
|
+
from .style_runtime import normalize_style_tokens
|
|
7
|
+
|
|
6
8
|
|
|
7
9
|
def apply_figure_config(fig, info: Mapping) -> bool:
|
|
8
10
|
"""Apply a YAML figure block to a Figure instance."""
|
|
@@ -55,7 +57,7 @@ def apply_figure_config(fig, info: Mapping) -> bool:
|
|
|
55
57
|
)
|
|
56
58
|
|
|
57
59
|
if "style" in info:
|
|
58
|
-
style_tokens = info["style"]
|
|
60
|
+
style_tokens = normalize_style_tokens(info["style"])
|
|
59
61
|
else:
|
|
60
62
|
style_tokens = ["a4paper_2x1"]
|
|
61
63
|
fig.style = style_tokens
|
|
@@ -71,6 +71,13 @@ _LABEL_FONT = {
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
DEFAULT_DEBUG = {
|
|
74
|
+
"forest_grid": {
|
|
75
|
+
"show": True,
|
|
76
|
+
"columns": {"show": True, "plot": {"color": "#DA291C", "linewidth": 0.3, "linestyle": ":", "alpha": 0.7}},
|
|
77
|
+
"baselines": {"show": True, "plot": {"color": "#DA291C", "linewidth": 0.2, "linestyle": "--", "alpha": 0.5}},
|
|
78
|
+
"bands": {"show": True, "Rectangle": {"edgecolor": "#DA291C", "linewidth": 0.25, "fill": False, "alpha": 0.5}},
|
|
79
|
+
"labels": {"show": True, "text": {"color": "#DA291C", "fontsize": 4, "ha": "left", "va": "top"}},
|
|
80
|
+
},
|
|
74
81
|
# Which axes gets fully dimensioned and hosts the info panel. First match wins.
|
|
75
82
|
"primary_order": ["ax", "ax0", "ax1", "axtri"],
|
|
76
83
|
"units": {"cm_per_inch": 2.54, "pt_per_inch": 72.0},
|
|
@@ -185,6 +185,10 @@ def draw_design_reference(fig) -> None:
|
|
|
185
185
|
|
|
186
186
|
|
|
187
187
|
def _draw(fig) -> None:
|
|
188
|
+
if hasattr(fig, 'forest_layout'):
|
|
189
|
+
from .forest_debug import draw_forest_reference
|
|
190
|
+
draw_forest_reference(fig, _debug_config(fig)['forest_grid'])
|
|
191
|
+
return
|
|
188
192
|
F = fig.fig
|
|
189
193
|
w_in, h_in = (float(v) for v in F.get_size_inches())
|
|
190
194
|
debug = _debug_config(fig)
|
|
@@ -11,7 +11,7 @@ from types import MethodType
|
|
|
11
11
|
from .adapters_rect import StdAxesAdapter
|
|
12
12
|
from .adapters_ternary import TernaryAxesAdapter
|
|
13
13
|
from .method_registry import resolve_callable
|
|
14
|
-
from .style_runtime import resolve_style_bundle_payload
|
|
14
|
+
from .style_runtime import normalize_style_tokens, resolve_style_bundle_payload
|
|
15
15
|
from .config_runtime import apply_figure_config
|
|
16
16
|
from .design_runtime import draw_design_reference
|
|
17
17
|
from .legend_runtime import apply_legend
|
|
@@ -399,10 +399,13 @@ class Figure:
|
|
|
399
399
|
|
|
400
400
|
|
|
401
401
|
@style.setter
|
|
402
|
-
def style(self, value) -> None:
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
raise TypeError
|
|
402
|
+
def style(self, value) -> None:
|
|
403
|
+
value = normalize_style_tokens(value)
|
|
404
|
+
if not isinstance(value, list) or len(value) not in (1, 2):
|
|
405
|
+
raise TypeError(
|
|
406
|
+
"style must name a card family or [family, variant], e.g. "
|
|
407
|
+
"a4paper_2x1 or [a4paper_2x1, rect]; got {!r}".format(value)
|
|
408
|
+
)
|
|
406
409
|
family, selected, bundle = resolve_style_bundle_payload(self.jpstyles, value)
|
|
407
410
|
self._frame = deepcopy(bundle["Frame"])
|
|
408
411
|
self._legend_disabled_axes = set()
|
|
@@ -508,7 +511,7 @@ class Figure:
|
|
|
508
511
|
return {kk: self._ensure_pandas_data(vv, reason=reason) for kk, vv in data.items()}
|
|
509
512
|
return data
|
|
510
513
|
|
|
511
|
-
def _concat_loaded_data(self, items):
|
|
514
|
+
def _concat_loaded_data(self, items, layer_name: str = ""):
|
|
512
515
|
if len(items) == 0:
|
|
513
516
|
return None
|
|
514
517
|
if len(items) == 1:
|
|
@@ -519,7 +522,28 @@ class Figure:
|
|
|
519
522
|
pandas_items = [self._ensure_pandas_data(item, reason="concat-layer") for item in items]
|
|
520
523
|
try:
|
|
521
524
|
return pd.concat(pandas_items, ignore_index=False)
|
|
522
|
-
except Exception:
|
|
525
|
+
except Exception as exc:
|
|
526
|
+
# Keep drawing what can be drawn, but never drop data silently.
|
|
527
|
+
if self.logger:
|
|
528
|
+
shapes = ", ".join(
|
|
529
|
+
str(getattr(item, "shape", type(item).__name__)) for item in pandas_items
|
|
530
|
+
)
|
|
531
|
+
self.logger.warning(
|
|
532
|
+
"Layer '{}': the {} data blocks could not be concatenated, so only "
|
|
533
|
+
"the first block is drawn and the other {} are dropped.\n"
|
|
534
|
+
"\t reason \t-> {}: {}\n"
|
|
535
|
+
"\t blocks \t-> {}\n"
|
|
536
|
+
"\t hint \t\t-> blocks combined with `combine: concat` must be tables "
|
|
537
|
+
"with compatible columns (no duplicated column names); use "
|
|
538
|
+
"`combine: separate` to draw them independently.".format(
|
|
539
|
+
layer_name or "<unnamed>",
|
|
540
|
+
len(pandas_items),
|
|
541
|
+
len(pandas_items) - 1,
|
|
542
|
+
type(exc).__name__,
|
|
543
|
+
exc,
|
|
544
|
+
shapes,
|
|
545
|
+
)
|
|
546
|
+
)
|
|
523
547
|
return pandas_items[0]
|
|
524
548
|
|
|
525
549
|
def _store_share_data_if_needed(self, layer, data, cache_ref: str | None = None):
|
|
@@ -752,7 +752,8 @@ def expand_correlation_matrix(info: Mapping[str, Any]) -> dict[str, Any]:
|
|
|
752
752
|
|
|
753
753
|
# Types that expand_figure_type can lower to layers. Keep in sync with
|
|
754
754
|
# expand_figure_type dispatch and capabilities.figure_types.
|
|
755
|
-
|
|
755
|
+
NATIVE_FIGURE_TYPES = frozenset({"forest"})
|
|
756
|
+
KNOWN_FIGURE_TYPES = frozenset({"posterior_2d", "profile_2d", "correlation_matrix"}) | NATIVE_FIGURE_TYPES
|
|
756
757
|
|
|
757
758
|
|
|
758
759
|
def expand_figure_type(info: Any) -> Any:
|
|
@@ -849,6 +850,7 @@ def expand_typed_figures(
|
|
|
849
850
|
raise KeyError(f"figure(s) not found: {', '.join(missing)}")
|
|
850
851
|
|
|
851
852
|
expanded_names: list[str] = []
|
|
853
|
+
native_found = False
|
|
852
854
|
for index, fig in enumerate(figures):
|
|
853
855
|
if not isinstance(fig, Mapping):
|
|
854
856
|
continue
|
|
@@ -876,6 +878,12 @@ def expand_typed_figures(
|
|
|
876
878
|
_note(logger, msg)
|
|
877
879
|
continue
|
|
878
880
|
|
|
881
|
+
if fig_type in NATIVE_FIGURE_TYPES:
|
|
882
|
+
# Native table-driven formats keep their public contract. Their
|
|
883
|
+
# physical solve is inspectable, not a list of hand-authored layers.
|
|
884
|
+
native_found = True
|
|
885
|
+
continue
|
|
886
|
+
|
|
879
887
|
try:
|
|
880
888
|
out = expand_figure_type(fig)
|
|
881
889
|
except Exception as exc:
|
|
@@ -897,6 +905,7 @@ def expand_typed_figures(
|
|
|
897
905
|
|
|
898
906
|
if (
|
|
899
907
|
not expanded_names
|
|
908
|
+
and not native_found
|
|
900
909
|
and not allow_noop
|
|
901
910
|
and raise_on_error
|
|
902
911
|
and wanted is not None
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Read-only Swiss grid and physical band references on a separate overlay."""
|
|
2
|
+
from matplotlib.patches import Rectangle
|
|
3
|
+
from ..forest_text import font_properties
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def draw_forest_reference(fig, cfg):
|
|
7
|
+
if not cfg['show'] or any(ax.get_label() == 'forest-design-reference' for ax in fig.fig.axes):
|
|
8
|
+
return
|
|
9
|
+
scene = fig.forest_layout
|
|
10
|
+
g = scene['geometry']
|
|
11
|
+
ax = fig.fig.add_axes([0, 0, 1, 1], label='forest-design-reference', zorder=10000)
|
|
12
|
+
ax.set(xlim=(0, scene['width_mm']), ylim=(scene['height_mm'], 0)); ax.axis('off')
|
|
13
|
+
ax.patch.set_alpha(0)
|
|
14
|
+
if cfg['columns']['show']:
|
|
15
|
+
for index, x in enumerate(g['grid_lines_mm']):
|
|
16
|
+
line, = ax.plot([x]*2, [0, scene['height_mm']], **cfg['columns']['plot'])
|
|
17
|
+
line.set_gid(f'forest-grid-{index:02d}')
|
|
18
|
+
if cfg['labels']['show']:
|
|
19
|
+
opts = dict(cfg['labels']['text'])
|
|
20
|
+
size = opts.pop('fontsize')
|
|
21
|
+
for index, x in enumerate(g['grid_lines_mm'][:-1]):
|
|
22
|
+
ax.text(x, g['top_axis_y_mm']+.35, f'{index+1:02d}', fontproperties=font_properties(size, scene['typography']['family']), **opts)
|
|
23
|
+
if cfg['baselines']['show']:
|
|
24
|
+
ys = [g[key] for key in ('meta_y_mm','title_y_mm','description_y_mm','x_label_y_mm','column_header_y_mm','top_tick_y_mm')]
|
|
25
|
+
ys += [r['top_mm']+g[key] for r in scene['rows'] for key in ('cell_y_mm','plot_y_mm')]
|
|
26
|
+
for index, y in enumerate(ys):
|
|
27
|
+
line, = ax.plot([g['plot_left_mm'], g['plot_right_mm']], [y]*2, **cfg['baselines']['plot'])
|
|
28
|
+
line.set_gid(f'forest-baseline-{index:03d}')
|
|
29
|
+
if cfg['bands']['show']:
|
|
30
|
+
for index, row in enumerate(scene['rows']):
|
|
31
|
+
for name, y, height in (('text', row['top_mm'], g['plot_y_mm']-g['point_band_mm']/2),
|
|
32
|
+
('marks', row['top_mm']+g['plot_y_mm']-g['point_band_mm']/2, g['point_band_mm'])):
|
|
33
|
+
box = Rectangle((g['plot_left_mm'], y), scene['plot_width_mm'], height, **cfg['bands']['Rectangle'])
|
|
34
|
+
box.set_gid(f'forest-band-{name}-{index:03d}')
|
|
35
|
+
ax.add_patch(box)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""A native legend handler for the actual forest glyph artist container."""
|
|
2
|
+
from matplotlib.container import Container
|
|
3
|
+
from matplotlib.legend_handler import HandlerBase, HandlerPathCollection
|
|
4
|
+
from matplotlib.lines import Line2D
|
|
5
|
+
from matplotlib.patches import Rectangle
|
|
6
|
+
from matplotlib.offsetbox import VPacker
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class PhysicalLegendColumn(VPacker):
|
|
10
|
+
"""Recompute physical column width for each raster/vector renderer."""
|
|
11
|
+
def __init__(self, width_mm, **kwargs):
|
|
12
|
+
super().__init__(**kwargs)
|
|
13
|
+
self.width_pt = width_mm*72/25.4
|
|
14
|
+
|
|
15
|
+
def _get_bbox_and_child_offsets(self, renderer):
|
|
16
|
+
self.width = self.width_pt*renderer.points_to_pixels(1)
|
|
17
|
+
return super()._get_bbox_and_child_offsets(renderer)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ForestGlyph(Container):
|
|
21
|
+
def __init__(self, artists, *, glyph):
|
|
22
|
+
super().__init__(artists)
|
|
23
|
+
self.glyph = glyph
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class HandlerForestPoint(HandlerPathCollection):
|
|
27
|
+
"""Place one point at the left of its compact native key."""
|
|
28
|
+
def __init__(self, key_width_pt):
|
|
29
|
+
super().__init__(numpoints=1)
|
|
30
|
+
self.key_width_pt = key_width_pt
|
|
31
|
+
|
|
32
|
+
def get_xdata(self, legend, xdescent, ydescent, width, height, fontsize):
|
|
33
|
+
x = -xdescent+self.key_width_pt/2
|
|
34
|
+
return [x, x], [x]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def group_glyph_and_points(legend, config, layers, glyph_object, *, base_dir=None):
|
|
38
|
+
"""Use the canonical native items, with glyphs left and point classes right.
|
|
39
|
+
|
|
40
|
+
Matplotlib normally balances item counts across columns, which would place
|
|
41
|
+
some point classes beside the box sample. Repack its existing item boxes
|
|
42
|
+
without recreating handles, labels, or their handlers.
|
|
43
|
+
"""
|
|
44
|
+
from matplotlib.offsetbox import DrawingArea
|
|
45
|
+
from ..legend_cards import resolve_axes_legend
|
|
46
|
+
kwargs, entries = resolve_axes_legend(config, layers, base_dir=base_dir)
|
|
47
|
+
if kwargs.get('ncols', kwargs.get('ncol', 1)) != 2:
|
|
48
|
+
return
|
|
49
|
+
legend._ncols = 2
|
|
50
|
+
if kwargs.get('reverse', False):
|
|
51
|
+
entries = list(reversed(entries))
|
|
52
|
+
objects = {id(text): entry['object'] for text, entry in zip(legend.get_texts(), entries)}
|
|
53
|
+
columns = legend._legend_handle_box.get_children()
|
|
54
|
+
groups = [[], []]
|
|
55
|
+
for column in columns:
|
|
56
|
+
for item in column.get_children():
|
|
57
|
+
label = item.get_children()[-1]._text
|
|
58
|
+
groups[0 if objects[id(label)] == glyph_object else 1].append(item)
|
|
59
|
+
# Preserve the empty semantic column when only one group is present.
|
|
60
|
+
legend._legend_handle_box._children = [
|
|
61
|
+
VPacker(pad=0, sep=legend.labelspacing*legend._fontsize,
|
|
62
|
+
align='left', children=items or [DrawingArea(0, 0)])
|
|
63
|
+
for items in groups
|
|
64
|
+
]
|
|
65
|
+
legend._legend_handle_box.align = 'top'
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class HandlerForestGlyph(HandlerBase):
|
|
69
|
+
def create_artists(self, legend, orig_handle, xdescent, ydescent, width, height, fontsize, trans):
|
|
70
|
+
whisker = orig_handle[0]
|
|
71
|
+
left, right = -xdescent, width-xdescent
|
|
72
|
+
yc = (height-ydescent)/2
|
|
73
|
+
half = height*.32
|
|
74
|
+
stroke = {'color': whisker.get_color(), 'linewidth': whisker.get_linewidth(), 'transform': trans}
|
|
75
|
+
artists = [Line2D([left, right], [yc, yc], **stroke)]
|
|
76
|
+
for xx in (left, right):
|
|
77
|
+
artists.append(Line2D([xx, xx], [yc-half, yc+half], **stroke))
|
|
78
|
+
if orig_handle.glyph == 'box':
|
|
79
|
+
box, median = orig_handle[1:]
|
|
80
|
+
artists.append(Rectangle((left+width*.25, yc-half), width*.5, half*2,
|
|
81
|
+
facecolor=box.get_facecolor(), edgecolor=box.get_edgecolor(),
|
|
82
|
+
linewidth=box.get_linewidth(), alpha=box.get_alpha(), transform=trans))
|
|
83
|
+
artists.append(Line2D([(left+right)/2]*2, [yc-half, yc+half], color=median.get_color(), linewidth=median.get_linewidth(), transform=trans))
|
|
84
|
+
else:
|
|
85
|
+
point = orig_handle[1]
|
|
86
|
+
artists.append(Line2D([(left+right)/2], [yc], linestyle='', marker=point.get_marker(), color=point.get_color(),
|
|
87
|
+
markersize=point.get_markersize(), markeredgewidth=point.get_markeredgewidth(), transform=trans))
|
|
88
|
+
return artists
|