jarvisplot 2.1.1__tar.gz → 2.1.2__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.1 → jarvisplot-2.1.2}/JarvisPLOT.egg-info/PKG-INFO +1 -1
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/PKG-INFO +1 -1
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/corr_layout_diamond.py +9 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/corrplot_runtime.py +203 -26
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/corrplot/diamond.json +2 -2
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/core_runtime.py +11 -2
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/pyproject.toml +1 -1
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_corrplot.py +318 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/JarvisPLOT.egg-info/SOURCES.txt +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/JarvisPLOT.egg-info/dependency_links.txt +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/JarvisPLOT.egg-info/entry_points.txt +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/JarvisPLOT.egg-info/requires.txt +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/JarvisPLOT.egg-info/top_level.txt +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/README.md +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/__init__.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/adapters_rect.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/adapters_ternary.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/bin_stat_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/cards/std_axes_adapter_config.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/colorbar_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/config_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/corr_layout.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/corr_order.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/correlation_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/data_pipelines.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/debug_config.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/density_cell_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/design_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/dynesty_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/figure.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/figure_types.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/helper.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/interp_2d_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/interp_natural_neighbor.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/interp_natural_neighbor_exact.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/layer_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/layout_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/method_registry.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/posterior_density_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/posterior_hpd.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/posterior_mesh.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/preprocessor.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/preprocessor_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/profile_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/significance_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/Figure/style_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/__init__.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/agent_digest.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/agent_io.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cache_store.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/capabilities.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/1x1/ternary.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/2x1/dynesty_runplot.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/2x1/rect.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/2x1/rect5x1.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/2x1/rect_cmap.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/2x1/rect_marginal.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/2x1/rectratio.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/2x1/ternary.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/2x1/ternary_cmap.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/4x1/rect.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/4x1/rect_cmap.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/4x1/ternary.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/a4paper/4x1/ternary_cmap.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/args.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/colors/colormaps.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/corrplot/matrix.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/default/output.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/flowchart/default.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/gambit/1x1/ternary.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/gambit/2x1/rect_cmap.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/gambit/2x1/ternary.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/gambit/2x1/ternary_cmap.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/icons/JarvisHEP.png +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/icons/flowchart/JarvisHEP.png +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/icons/flowchart/calculator.png +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/icons/flowchart/inputfile.png +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/icons/flowchart/opera.png +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/icons/flowchart/outputfile.png +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/icons/flowchart/sampler.png +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/icons/gambit.png +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/icons/gambit_small.png +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cards/style_preference.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cli.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/cli_help.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/client.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/column_demand.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/column_probe.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/config.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/config_address.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/core.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/core_assets.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/data_access.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/data_loader.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/data_loader_hdf5.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/data_loader_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/data_loader_summary.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/dataset_types.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/diagnostic_guidance.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/diagnostics.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/dryrun_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/expr_names.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/fix_apply.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/flowchart.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/inner_func.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/man_catalog.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/man_methods.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/man_render_agent.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/man_render_human.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/man_transforms.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/agent-output.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/cli-map.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/data-columns.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/debug-overlay.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/diagnostics.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/dryrun-viz.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/layer-method.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/manifest.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/method_notes.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/style-axes.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/type-correlation-matrix.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/type-posterior-2d.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/type-profile-2d.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/validate.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/workflow.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/manual_cards/yaml-root.yaml +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/memtrace.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/method_contracts.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/render_health.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/core/common.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/core/dataset.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/core/figure.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/core/layer.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/core/transform.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/manifest.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/bar.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/barh.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/contour.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/contourf.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/corrplot.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/dynesty_runplot.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/errorbar.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/fill.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/fill_between.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/fill_betweenx.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/hist.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/hist2d.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/imshow.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/jpcontour.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/jpcontourf.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/jpfield.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/pcolor.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/pcolormesh.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/plot.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/quiver.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/scatter.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/stairs.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/step.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/tricontour.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/tricontourf.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/tripcolor.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/tripcolor_axes.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/triplot.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/voronoi.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/methods/voronoif.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema/plot-config.json +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema_catalog.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/schema_diagnostics.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/templates_catalog.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/transform_contracts.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/utils/__init__.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/utils/cmaps.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/utils/dataframes.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/utils/expression.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/utils/interpolator.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/utils/pathing.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/validation.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/verbs/__init__.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/verbs/cap.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/verbs/config_cmd.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/verbs/data.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/verbs/doctor.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/verbs/dryrun.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/verbs/explain.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/verbs/man.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/verbs/suggest.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/verbs/template.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/verbs/validate.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/jarvisplot/yaml_io.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/setup.cfg +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_agent_digest.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_agent_envelope.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_axis_title.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_capabilities.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_card_debug_shape.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_cli_help.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_cli_verbs.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_cmaps.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_column_existence.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_config_addressing.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_config_edit.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_config_expand.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_correlation_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_data_access.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_data_describe.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_data_head_eval.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_data_loader_contracts.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_data_pipelines.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_debug_config.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_debug_switches.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_debug_yaml_override.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_density_cell_transform.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_design_runtime.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_diagnostic_guidance.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_docs_status_labels.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_doctor_partial.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_explain.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_figure_contracts.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_figure_type_expander.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_fix_application.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_flowchart_renderer.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_imshow_adapter.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_interp_2d_transform.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_interp_natural_neighbor.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_interpolator_contracts.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_jpcontour_methods.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_man_cli.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_method_contracts.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_parse_data_metadata.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_pathing_contracts.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_posterior_hpd.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_render_health.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_row_ledger.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_schema_catalog.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_suggest.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_suggest_axes.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_template_catalog.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_template_json.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_ternary_debug.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_transform_contracts.py +0 -0
- {jarvisplot-2.1.1 → jarvisplot-2.1.2}/tests/test_validate_no_matplotlib.py +0 -0
|
@@ -63,6 +63,15 @@ def diamond_extent(n: int, *, diag: bool = False) -> tuple[float, float, float,
|
|
|
63
63
|
|
|
64
64
|
With ``diag`` the self-pairs come in at ``u = 0`` and push both ranges out
|
|
65
65
|
by half a cell.
|
|
66
|
+
|
|
67
|
+
A half, not the quarter the pentagon of
|
|
68
|
+
:func:`corrplot_runtime._self_cell_vertices` actually reaches: that shape
|
|
69
|
+
is how a *fill* keeps a whole cell's area against the edge, and the round
|
|
70
|
+
glyphs do not take it. A circle on the diagonal is a circle, and at the
|
|
71
|
+
quarter it overhung the panel by 0.07 cells -- which is only 0.3 mm, but it
|
|
72
|
+
is 0.3 mm off the one gap the eye checks, the channel between the matrix
|
|
73
|
+
and the names, and it narrowed it on the diagonal rows alone. The panel
|
|
74
|
+
buys the half so that every glyph fits whatever shape it is.
|
|
66
75
|
"""
|
|
67
76
|
n = max(int(n), 2)
|
|
68
77
|
if diag:
|
|
@@ -161,6 +161,14 @@ _DIAMOND_ROUND = 1.0 / np.sqrt(2.0)
|
|
|
161
161
|
#: because a divider that is *nearly* the cell divider reads as a mistake.
|
|
162
162
|
_GRID_LWD = 0.3
|
|
163
163
|
|
|
164
|
+
#: Where the tint sits: under everything. It is the background the figure is
|
|
165
|
+
#: drawn *on*, so it takes the lowest layer on the axes rather than one derived
|
|
166
|
+
#: from the glyph's -- an axis draws its own tick labels at 2.5, and a tint
|
|
167
|
+
#: placed relative to the glyphs lands above that and prints over the names.
|
|
168
|
+
#: Its three pieces (the cells, the notch, the band under the label) are one
|
|
169
|
+
#: band and share one number, so they cannot drift apart.
|
|
170
|
+
_TINT_ZORDER = 0.4
|
|
171
|
+
|
|
164
172
|
#: Square glyphs are a polygon per cell and nothing else, so they skip the
|
|
165
173
|
#: patch objects entirely -- see :func:`_glyph_vertices`.
|
|
166
174
|
_POLYGON_GLYPHS = ("square", "color", "shade")
|
|
@@ -171,21 +179,87 @@ _POLYGON_GLYPHS = ("square", "color", "shade")
|
|
|
171
179
|
_FILLED_GLYPHS = ("color", "shade")
|
|
172
180
|
|
|
173
181
|
|
|
174
|
-
|
|
182
|
+
#: How far a self cell reaches past the matrix's near edge, in cells. See
|
|
183
|
+
#: :func:`_self_cell_vertices` -- it is what makes the pentagon's area a cell.
|
|
184
|
+
_SELF_REACH = 0.25
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _self_cell_vertices(rows, side: str = "left", scale: float = 1.0):
|
|
188
|
+
"""``(m, 5, 2)`` outlines for the cells on the diagonal.
|
|
189
|
+
|
|
190
|
+
A variable's pair with *itself* sits at ``u = 0``, so half of an ordinary
|
|
191
|
+
cell would hang off the matrix and print over the names. Clipping it
|
|
192
|
+
instead leaves a triangle -- half the area of every other cell, which reads
|
|
193
|
+
as a fainter diagonal rather than as the constant it is.
|
|
194
|
+
|
|
195
|
+
So it is neither: the cell keeps its point into the matrix and is squared
|
|
196
|
+
off on the outside, and the rectangle that squares it off is exactly deep
|
|
197
|
+
enough to pay back what the clip took. The triangle is ``1/4``, the
|
|
198
|
+
rectangle is ``a x 1``, so ``a = 1/4`` puts the pentagon at ``1/2`` -- the
|
|
199
|
+
area of a whole cell, for every variable, which is the only way a diagonal
|
|
200
|
+
of constant rho can look constant.
|
|
201
|
+
|
|
202
|
+
It fits without moving anything: the wedge beside each name is empty by
|
|
203
|
+
construction (see :func:`_notch_vertices`, which is what used to fill it)
|
|
204
|
+
and the quarter cell outside is page the panel takes from the gap.
|
|
205
|
+
|
|
206
|
+
``scale`` shrinks it about ``(0, k)`` exactly as ``glyph.scale`` shrinks
|
|
207
|
+
every other cell. Without it these are the only shapes on the figure drawn
|
|
208
|
+
at full size, and since they also stack without a gap in ``v`` they fuse
|
|
209
|
+
into one bar down the edge instead of reading as a cell each.
|
|
210
|
+
"""
|
|
211
|
+
k = np.asarray(rows, dtype=float)
|
|
212
|
+
flip = -1.0 if side == "right" else 1.0
|
|
213
|
+
zero = np.zeros_like(k)
|
|
214
|
+
half = 0.5 * float(scale)
|
|
215
|
+
back = flip * -2.0 * _SELF_REACH * half + zero
|
|
216
|
+
point, edge = flip * half + zero, half
|
|
217
|
+
return np.stack(
|
|
218
|
+
[
|
|
219
|
+
np.stack([back, k - edge], axis=1),
|
|
220
|
+
np.stack([zero, k - edge], axis=1),
|
|
221
|
+
np.stack([point, k], axis=1),
|
|
222
|
+
np.stack([zero, k + edge], axis=1),
|
|
223
|
+
np.stack([back, k + edge], axis=1),
|
|
224
|
+
],
|
|
225
|
+
axis=1,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def _notch_vertices(n: int, side: str = "left", diag: bool = False):
|
|
175
230
|
"""The half cells that make the matrix's near edge straight.
|
|
176
231
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
232
|
+
Whatever stands at ``u = 0`` meets the edge beside the names at a *point*,
|
|
233
|
+
so that boundary comes out as a row of notches and the tint carrying a
|
|
234
|
+
variable's band in from its name pinches to nothing there. Filling the
|
|
235
|
+
notch is what turns the sawtooth into the straight edge the rules close
|
|
236
|
+
against, and the band into one band.
|
|
237
|
+
|
|
238
|
+
The diagonal moves the notch, it does not remove it -- which is what an
|
|
239
|
+
earlier version of this card assumed, and the band broke on every shaded
|
|
240
|
+
row. Without the diagonal the near edge is ``u = 0`` and the first cells
|
|
241
|
+
are the pairs at ``u = 1/2``, so the gap is the triangle
|
|
242
|
+
``(0, k-1/2) (1/2, k) (0, k+1/2)`` *inside* the matrix. With it the near
|
|
243
|
+
edge is ``u = -1/2`` and the self cell's own left corner is the point, so
|
|
244
|
+
the gap is the pair of triangles either side of it -- together with that
|
|
245
|
+
corner, the rectangle ``[-1/2, 0] x [k-1/2, k+1/2]``.
|
|
183
246
|
|
|
184
247
|
Returned for every variable; the caller picks the tinted ones.
|
|
185
248
|
"""
|
|
186
249
|
k = np.arange(int(n), dtype=float)
|
|
187
250
|
flip = -1.0 if side == "right" else 1.0
|
|
188
251
|
zero = np.zeros_like(k)
|
|
252
|
+
if diag:
|
|
253
|
+
back = flip * -0.5 + zero
|
|
254
|
+
return np.stack(
|
|
255
|
+
[
|
|
256
|
+
np.stack([back, k - 0.5], axis=1),
|
|
257
|
+
np.stack([zero, k - 0.5], axis=1),
|
|
258
|
+
np.stack([zero, k + 0.5], axis=1),
|
|
259
|
+
np.stack([back, k + 0.5], axis=1),
|
|
260
|
+
],
|
|
261
|
+
axis=1,
|
|
262
|
+
)
|
|
189
263
|
return np.stack(
|
|
190
264
|
[
|
|
191
265
|
np.stack([zero, k - 0.5], axis=1),
|
|
@@ -329,13 +403,25 @@ def _label_rules(ax, n: int, span, color, lw: float, clip: bool,
|
|
|
329
403
|
colour and weight rather than a nearby pair, because a divider that only
|
|
330
404
|
nearly matches reads as a second, different thing.
|
|
331
405
|
|
|
406
|
+
It starts where the *cells* meet, not where the axes end. Two cells of one
|
|
407
|
+
row touch at ``u = 0`` whichever layout is drawn -- without the diagonal
|
|
408
|
+
that is also the panel's near edge, so the two were the same number and the
|
|
409
|
+
difference never showed. With the diagonal the panel reaches half a cell
|
|
410
|
+
further out, and a rule begun at the edge leaves that half cell unruled:
|
|
411
|
+
the line between two names starts in mid air instead of at the matrix.
|
|
412
|
+
|
|
332
413
|
Below the tick labels, like the band: an axis draws its labels at zorder
|
|
333
414
|
2.5, and a rule over one of them is a strike-through.
|
|
334
415
|
"""
|
|
335
416
|
from matplotlib.collections import LineCollection
|
|
336
417
|
|
|
337
418
|
target = ax.ax if hasattr(ax, "ax") else ax
|
|
338
|
-
|
|
419
|
+
try:
|
|
420
|
+
lo, hi = target.get_xlim()
|
|
421
|
+
meet = (0.0 - float(lo)) / (float(hi) - float(lo))
|
|
422
|
+
except Exception:
|
|
423
|
+
meet = span[1] if span[0] < 0.0 else span[0]
|
|
424
|
+
x0, x1 = min(span[0], meet), max(span[1], meet)
|
|
339
425
|
rules = LineCollection(
|
|
340
426
|
[[(x0, k + 0.5), (x1, k + 0.5)] for k in range(int(n) - 1)],
|
|
341
427
|
colors=color, linewidths=lw, zorder=0.6,
|
|
@@ -409,7 +495,7 @@ def _stripe_the_labels(ax, n: int, shaded, span, color, clip: bool) -> None:
|
|
|
409
495
|
ax.axhspan(
|
|
410
496
|
k - 0.5, k + 0.5, xmin=span[0], xmax=span[1],
|
|
411
497
|
facecolor=color, edgecolor="none", linewidth=0.0,
|
|
412
|
-
zorder=
|
|
498
|
+
zorder=_TINT_ZORDER, clip_on=clip,
|
|
413
499
|
)
|
|
414
500
|
|
|
415
501
|
|
|
@@ -464,7 +550,7 @@ def _glyph_vertices(kind: str, cx, cy, rho, scale: float, corners=None):
|
|
|
464
550
|
|
|
465
551
|
|
|
466
552
|
def _glyph_patches(kind: str, cx, cy, rho, scale: float, sign: float,
|
|
467
|
-
ellipse_scale: float = 1.4):
|
|
553
|
+
ellipse_scale: float = 1.4, diamond: bool = False):
|
|
468
554
|
"""One matplotlib patch per drawn cell, in data coordinates.
|
|
469
555
|
|
|
470
556
|
Only the round glyphs come through here; the square ones are built as bare
|
|
@@ -494,7 +580,22 @@ def _glyph_patches(kind: str, cx, cy, rho, scale: float, sign: float,
|
|
|
494
580
|
# the box does not -- so at k = glyph.scale the widest one covers
|
|
495
581
|
# 0.64 of the cell while a circle covers 0.9. sqrt(2) is the
|
|
496
582
|
# factor that makes the two agree, which is where 1.4 comes from.
|
|
583
|
+
#
|
|
584
|
+
# And it is the *cell's* diagonal, not the page's. `ellipse` is
|
|
585
|
+
# the one glyph with a direction, and its direction means something
|
|
586
|
+
# about the two axes of the cell it sits in: turn the lattice 45
|
|
587
|
+
# degrees and leave the ellipse behind and every one of them is
|
|
588
|
+
# reporting the wrong pair. The index map sends the cell's own
|
|
589
|
+
# frame through a +45 degree rotation (`j+1` goes to `(+1/2, +1/2)`
|
|
590
|
+
# and `i+1` to `(-1/2, +1/2)`), so the glyph turns with it.
|
|
591
|
+
#
|
|
592
|
+
# `side: right` negates u, which reflects rather than rotates and
|
|
593
|
+
# sends an angle A to 135 - A. It needs no case of its own: the
|
|
594
|
+
# angle here is a constant +/-45, and 135 - A and A + 45 differ by
|
|
595
|
+
# 180 exactly when they differ at all -- and an ellipse's angle is
|
|
596
|
+
# read modulo 180.
|
|
497
597
|
k = scale * ellipse_scale
|
|
598
|
+
lean = sign * 45.0 + (45.0 if diamond else 0.0)
|
|
498
599
|
r = 0.0 if not np.isfinite(r) else float(np.clip(r, -1.0, 1.0))
|
|
499
600
|
width = k * np.sqrt(max(1.0 + r, 0.0)) / np.sqrt(2.0)
|
|
500
601
|
# |rho| = 1 collapses the minor axis to zero, which fills no
|
|
@@ -503,7 +604,7 @@ def _glyph_patches(kind: str, cx, cy, rho, scale: float, sign: float,
|
|
|
503
604
|
# as a line, so the minor axis gets a hairline floor.
|
|
504
605
|
height = max(k * np.sqrt(max(1.0 - r, 0.0)) / np.sqrt(2.0), 0.02 * k)
|
|
505
606
|
patches.append(
|
|
506
|
-
Ellipse((x, y), width=width, height=height, angle=
|
|
607
|
+
Ellipse((x, y), width=width, height=height, angle=lean)
|
|
507
608
|
)
|
|
508
609
|
elif kind == "pie":
|
|
509
610
|
# Clockwise from twelve o'clock, as read off the page.
|
|
@@ -721,14 +822,53 @@ def draw_corrplot(ax, **kwargs):
|
|
|
721
822
|
if sig_level is not None and insig == "blank":
|
|
722
823
|
drawn &= ~insignificant
|
|
723
824
|
|
|
825
|
+
# The diagonal, when it is in. A self pair sits at `u = 0`, so anything
|
|
826
|
+
# built from an ordinary cell there hangs a quarter of a cell past the
|
|
827
|
+
# panel and prints over the names -- and everything on this figure except
|
|
828
|
+
# `_stripe_the_labels` is drawn well above the axis' own zorder of 2.5, so
|
|
829
|
+
# it prints *over* them, not under. Every shape cut from a cell therefore
|
|
830
|
+
# takes the pentagon on the diagonal: the fill, the grid outline, and the
|
|
831
|
+
# tint. See `_self_cell_vertices`.
|
|
832
|
+
self_cells = drawn & (index_x.astype(int) == index_y.astype(int))
|
|
833
|
+
|
|
834
|
+
def _with_self_cells(shapes, selection, closed_loop: bool, shape_scale=1.0):
|
|
835
|
+
"""Swap the pentagon in wherever `shapes` covers a self pair.
|
|
836
|
+
|
|
837
|
+
`selection` is the mask over *all* cells that `shapes` was built from,
|
|
838
|
+
which is not the same mask each time -- the fill is drawn for `drawn`,
|
|
839
|
+
the tint for the shaded band, the grid for everything.
|
|
840
|
+
"""
|
|
841
|
+
picked = self_cells[selection]
|
|
842
|
+
if not diamond or not np.any(picked):
|
|
843
|
+
return shapes
|
|
844
|
+
out = [np.asarray(shape) for shape in shapes]
|
|
845
|
+
pentagons = _self_cell_vertices(iy[selection & self_cells], side, shape_scale)
|
|
846
|
+
for slot, pentagon in zip(np.flatnonzero(picked), pentagons):
|
|
847
|
+
out[slot] = (
|
|
848
|
+
np.vstack([pentagon, pentagon[:1]]) if closed_loop else pentagon
|
|
849
|
+
)
|
|
850
|
+
return out
|
|
851
|
+
|
|
724
852
|
label_span = _label_span(ax, side, label_column_mm) if diamond else None
|
|
725
853
|
|
|
726
854
|
if diamond and edge_lwd > 0.0 and label_span is not None:
|
|
727
855
|
# The column is a width in axes fractions; the outline is drawn in cell
|
|
728
|
-
# units,
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
856
|
+
# units, so it is scaled by how many cells wide the panel is. Read off
|
|
857
|
+
# the axes rather than worked out as `n / 2`: with the diagonal in, the
|
|
858
|
+
# panel is a quarter cell wider than that (see `diamond_extent`), and a
|
|
859
|
+
# rule scaled by the wrong span stops short of the names it is meant to
|
|
860
|
+
# close over -- by 4% of the column, which at thirteen variables is the
|
|
861
|
+
# last two letters of the longest name left hanging outside it.
|
|
862
|
+
lo, hi = float(min(ax.get_xlim())), float(max(ax.get_xlim()))
|
|
863
|
+
u_span = hi - lo
|
|
864
|
+
# ... and measured from the panel's own near edge, which the diagonal
|
|
865
|
+
# moves out to `u = -1/4`. `_edge_rules` strikes the horizontal run
|
|
866
|
+
# from `-column_u` to `0`, so the near edge has to be added back in:
|
|
867
|
+
# left out, the rule stops a quarter cell short and the last letters of
|
|
868
|
+
# the longest name hang outside the box it is meant to close.
|
|
869
|
+
near_u = lo if side == "left" else -hi
|
|
870
|
+
column_u = (-label_span[0] if side == "left" else label_span[1] - 1.0)
|
|
871
|
+
column_u = column_u * u_span - near_u
|
|
732
872
|
_edge_rules(ax, n, column_u, side, edge_color, edge_lwd, zorder + 40, clip)
|
|
733
873
|
if diamond and grid_color and label_span is not None:
|
|
734
874
|
_label_rules(ax, n, label_span, grid_color, _GRID_LWD, clip, zorder)
|
|
@@ -763,19 +903,25 @@ def draw_corrplot(ax, **kwargs):
|
|
|
763
903
|
band = shaded[index_x.astype(int)] | shaded[index_y.astype(int)]
|
|
764
904
|
band &= drawn
|
|
765
905
|
if np.any(band):
|
|
906
|
+
# The tint is a background and keeps the plain cell, diagonal
|
|
907
|
+
# included: it has to reach the panel's edge or the band it carries
|
|
908
|
+
# from the name into the matrix comes apart there. It can, because
|
|
909
|
+
# the panel buys the whole half cell -- which is also what stops it
|
|
910
|
+
# printing over the names, and that is a clearance, not a shape.
|
|
766
911
|
cells = PolyCollection(
|
|
767
912
|
np.stack([ix[band], iy[band]], axis=1)[:, None, :]
|
|
768
913
|
+ 0.5 * _DIAMOND_CORNERS[None, :, :],
|
|
769
914
|
closed=True, facecolors=stripe_color, edgecolors="none",
|
|
770
|
-
zorder=
|
|
915
|
+
zorder=_TINT_ZORDER,
|
|
771
916
|
)
|
|
772
917
|
cells.set_clip_on(clip)
|
|
773
918
|
ax.add_collection(cells)
|
|
774
919
|
# The half cells beside the names, so the band reaches the matrix and
|
|
775
920
|
# the edge it makes is straight enough for the rules to close against.
|
|
921
|
+
# The diagonal moves this, it does not remove it: see `_notch_vertices`.
|
|
776
922
|
notches = PolyCollection(
|
|
777
|
-
_notch_vertices(n, side)[shaded], closed=True,
|
|
778
|
-
facecolors=stripe_color, edgecolors="none", zorder=
|
|
923
|
+
_notch_vertices(n, side, diag)[shaded], closed=True,
|
|
924
|
+
facecolors=stripe_color, edgecolors="none", zorder=_TINT_ZORDER,
|
|
779
925
|
)
|
|
780
926
|
notches.set_clip_on(clip)
|
|
781
927
|
ax.add_collection(notches)
|
|
@@ -790,9 +936,13 @@ def draw_corrplot(ax, **kwargs):
|
|
|
790
936
|
else:
|
|
791
937
|
if kind in _POLYGON_GLYPHS:
|
|
792
938
|
artists = PolyCollection(
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
939
|
+
_with_self_cells(
|
|
940
|
+
_glyph_vertices(
|
|
941
|
+
kind, ix[drawn], iy[drawn], rho[drawn], scale,
|
|
942
|
+
corners=_DIAMOND_CORNERS if diamond else _CORNERS,
|
|
943
|
+
),
|
|
944
|
+
drawn if kind in _FILLED_GLYPHS else np.zeros(ix.shape, dtype=bool),
|
|
945
|
+
closed_loop=False, shape_scale=scale,
|
|
796
946
|
),
|
|
797
947
|
closed=True,
|
|
798
948
|
)
|
|
@@ -800,7 +950,7 @@ def draw_corrplot(ax, **kwargs):
|
|
|
800
950
|
artists = PatchCollection(
|
|
801
951
|
_glyph_patches(
|
|
802
952
|
kind, ix[drawn], iy[drawn], rho[drawn], round_scale, sign,
|
|
803
|
-
ellipse_scale=ellipse_scale,
|
|
953
|
+
ellipse_scale=ellipse_scale, diamond=diamond,
|
|
804
954
|
),
|
|
805
955
|
match_original=False,
|
|
806
956
|
)
|
|
@@ -847,14 +997,27 @@ def draw_corrplot(ax, **kwargs):
|
|
|
847
997
|
if kind == "shade":
|
|
848
998
|
# The sign is already in the colour; the hatch is what survives a
|
|
849
999
|
# greyscale print, which is the whole point of shade.
|
|
1000
|
+
#
|
|
1001
|
+
# It runs corner to corner of the cell, and *which* corners is the
|
|
1002
|
+
# layout's business. On the square card those are the diagonal ones,
|
|
1003
|
+
# `(+/-1, +/-1) * half`. On the diamond the same cell is turned 45
|
|
1004
|
+
# degrees, so its corners are the ones straight up and straight across
|
|
1005
|
+
# -- and a stroke still drawn to `(+/-1, +/-1)` reaches `half * sqrt2`
|
|
1006
|
+
# where the cell only reaches `half / sqrt2`: twice too long, over the
|
|
1007
|
+
# boundary and into the neighbour, on every cell of the figure.
|
|
1008
|
+
step = 0.5 * scale
|
|
1009
|
+
arm = (
|
|
1010
|
+
[(0.0, step), (step, 0.0)] if diamond else [(step, step), (step, -step)]
|
|
1011
|
+
)
|
|
850
1012
|
hatch = LineCollection(
|
|
851
1013
|
[
|
|
852
1014
|
[
|
|
853
|
-
(x -
|
|
854
|
-
(x +
|
|
1015
|
+
(x - dx, y - sign * dy * np.sign(r)),
|
|
1016
|
+
(x + dx, y + sign * dy * np.sign(r)),
|
|
855
1017
|
]
|
|
856
1018
|
for x, y, r in zip(ix[drawn], iy[drawn], rho[drawn])
|
|
857
1019
|
if r != 0.0
|
|
1020
|
+
for dx, dy in [arm[0] if r > 0 else arm[1]]
|
|
858
1021
|
],
|
|
859
1022
|
colors="#FFFFFF",
|
|
860
1023
|
linewidths=0.4,
|
|
@@ -868,9 +1031,23 @@ def draw_corrplot(ax, **kwargs):
|
|
|
868
1031
|
# picture, a quarter of the paths, and at 100 variables that is 40,000
|
|
869
1032
|
# of them. The outline has to be per cell rather than n+1 ruled lines
|
|
870
1033
|
# because a `triangle` selection leaves holes for the ruling to cross.
|
|
1034
|
+
# The pentagon is a shape for glyphs that *fill* their cell. Outlining
|
|
1035
|
+
# it under a round one would be drawing a boundary the glyph does not
|
|
1036
|
+
# keep: at `rho = 1` the circle on the diagonal overhangs it, and the
|
|
1037
|
+
# flat backs line up into a grey rail down the edge of the matrix with
|
|
1038
|
+
# the circles straddling it. So there the diagonal simply carries no
|
|
1039
|
+
# outline -- the matrix's own edge is already closed by `edge.lwd`.
|
|
1040
|
+
ruled = (
|
|
1041
|
+
np.ones(ix.shape, dtype=bool)
|
|
1042
|
+
if not diamond or kind in _FILLED_GLYPHS
|
|
1043
|
+
else ~self_cells
|
|
1044
|
+
)
|
|
871
1045
|
grid = LineCollection(
|
|
872
|
-
|
|
873
|
-
|
|
1046
|
+
_with_self_cells(
|
|
1047
|
+
np.stack([ix[ruled], iy[ruled]], axis=1)[:, None, :]
|
|
1048
|
+
+ (_DIAMOND_LOOP if diamond else _CELL_LOOP)[None, :, :],
|
|
1049
|
+
ruled, closed_loop=True,
|
|
1050
|
+
),
|
|
874
1051
|
colors=grid_color, linewidths=_GRID_LWD, zorder=zorder - 10,
|
|
875
1052
|
)
|
|
876
1053
|
grid.set_clip_on(clip)
|
|
@@ -496,7 +496,7 @@
|
|
|
496
496
|
"Options": {
|
|
497
497
|
"method": {"type": "enum", "values": ["circle", "square", "ellipse", "color", "shade", "pie", "number"], "default": "circle"},
|
|
498
498
|
"type": {"type": "enum", "values": ["upper", "lower"], "default": "upper", "forbidden": ["full"]},
|
|
499
|
-
"diag": {"type": "boolean", "default":
|
|
499
|
+
"diag": {"type": "boolean", "default": true},
|
|
500
500
|
"side": {"type": "enum", "values": ["left", "right"], "default": "right"},
|
|
501
501
|
"stripe": {"type": "enum", "values": ["alternate", "none"], "default": "alternate", "false_alias": "none"},
|
|
502
502
|
"order": {"type": "enum", "values": ["original", "AOE", "FPC", "hclust", "alphabet"], "default": "original"},
|
|
@@ -511,7 +511,7 @@
|
|
|
511
511
|
"corrplot": {
|
|
512
512
|
"method": "circle",
|
|
513
513
|
"type": "upper",
|
|
514
|
-
"diag":
|
|
514
|
+
"diag": true,
|
|
515
515
|
"glyph.scale": 0.9,
|
|
516
516
|
"ellipse.scale": 1.4,
|
|
517
517
|
"outline": "sign",
|
|
@@ -895,8 +895,17 @@ def _prebuild_one(core, info: dict, card: Mapping) -> None:
|
|
|
895
895
|
_enforce_corr_contract(info, contract, name)
|
|
896
896
|
|
|
897
897
|
source = entry.get("source")
|
|
898
|
-
|
|
899
|
-
|
|
898
|
+
# A correlation layer may intentionally concatenate several root
|
|
899
|
+
# datasets. The runtime already supports source lists; the prebuild only
|
|
900
|
+
# needs one member's cheap column metadata to solve the shared geometry.
|
|
901
|
+
# Use the first registered member (the input tables are required to carry
|
|
902
|
+
# the same schema), while leaving the complete source list for the actual
|
|
903
|
+
# correlation transform below.
|
|
904
|
+
registry = getattr(core, "dataset_registry", {}) or {}
|
|
905
|
+
source_names = [source] if isinstance(source, str) else list(source or [])
|
|
906
|
+
dts = next(
|
|
907
|
+
(registry.get(item) for item in source_names if isinstance(item, str) and registry.get(item) is not None),
|
|
908
|
+
None,
|
|
900
909
|
)
|
|
901
910
|
names = list(getattr(dts, "keys", None) or [])
|
|
902
911
|
if not names:
|