jarvisplot 2.0.5__tar.gz → 2.0.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/JarvisPLOT.egg-info/PKG-INFO +1 -1
  2. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/JarvisPLOT.egg-info/SOURCES.txt +1 -0
  3. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/PKG-INFO +1 -1
  4. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/colorbar_runtime.py +81 -3
  5. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/debug_config.py +15 -0
  6. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/design_runtime.py +49 -0
  7. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/figure.py +25 -3
  8. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/layout_runtime.py +48 -3
  9. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/method_registry.py +1 -0
  10. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/2x1/rect5x1.json +8 -0
  11. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/2x1/rect_cmap.json +14 -0
  12. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/2x1/rect_marginal.json +74 -23
  13. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/2x1/ternary_cmap.json +14 -0
  14. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/4x1/rect_cmap.json +14 -0
  15. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/4x1/ternary_cmap.json +3 -0
  16. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/colors/colormaps.json +13 -0
  17. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/gambit/2x1/rect_cmap.json +14 -0
  18. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/gambit/2x1/ternary.json +2 -2
  19. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/gambit/2x1/ternary_cmap.json +14 -0
  20. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/column_demand.py +6 -8
  21. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/data_access.py +2 -3
  22. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/expr_names.py +28 -1
  23. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/debug-overlay.yaml +2 -1
  24. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/method_notes.yaml +12 -0
  25. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/style-axes.yaml +2 -0
  26. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/method_contracts.py +1 -0
  27. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/core/layer.json +1 -0
  28. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/manifest.json +2 -0
  29. jarvisplot-2.0.6/jarvisplot/schema/methods/hist2d.json +37 -0
  30. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/pyproject.toml +1 -1
  31. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_axis_title.py +41 -0
  32. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/JarvisPLOT.egg-info/dependency_links.txt +0 -0
  33. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/JarvisPLOT.egg-info/entry_points.txt +0 -0
  34. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/JarvisPLOT.egg-info/requires.txt +0 -0
  35. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/JarvisPLOT.egg-info/top_level.txt +0 -0
  36. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/README.md +0 -0
  37. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/__init__.py +0 -0
  38. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/adapters_rect.py +0 -0
  39. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/adapters_ternary.py +0 -0
  40. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/cards/std_axes_adapter_config.json +0 -0
  41. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/config_runtime.py +0 -0
  42. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/data_pipelines.py +0 -0
  43. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/density_cell_runtime.py +0 -0
  44. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/dynesty_runtime.py +0 -0
  45. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/figure_types.py +0 -0
  46. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/helper.py +0 -0
  47. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/interp_2d_runtime.py +0 -0
  48. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/interp_natural_neighbor.py +0 -0
  49. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/interp_natural_neighbor_exact.py +0 -0
  50. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/layer_runtime.py +0 -0
  51. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/posterior_density_runtime.py +0 -0
  52. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/posterior_hpd.py +0 -0
  53. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/posterior_mesh.py +0 -0
  54. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/preprocessor.py +0 -0
  55. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/preprocessor_runtime.py +0 -0
  56. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/profile_runtime.py +0 -0
  57. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/Figure/style_runtime.py +0 -0
  58. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/__init__.py +0 -0
  59. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/agent_digest.py +0 -0
  60. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/agent_io.py +0 -0
  61. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cache_store.py +0 -0
  62. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/capabilities.py +0 -0
  63. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/1x1/ternary.json +0 -0
  64. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/2x1/dynesty_runplot.json +0 -0
  65. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/2x1/rect.json +0 -0
  66. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/2x1/rectratio.json +0 -0
  67. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/2x1/ternary.json +0 -0
  68. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/4x1/rect.json +0 -0
  69. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/a4paper/4x1/ternary.json +0 -0
  70. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/args.json +0 -0
  71. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/default/output.json +0 -0
  72. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/flowchart/default.json +0 -0
  73. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/gambit/1x1/ternary.json +0 -0
  74. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/icons/JarvisHEP.png +0 -0
  75. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/icons/flowchart/JarvisHEP.png +0 -0
  76. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/icons/flowchart/calculator.png +0 -0
  77. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/icons/flowchart/inputfile.png +0 -0
  78. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/icons/flowchart/opera.png +0 -0
  79. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/icons/flowchart/outputfile.png +0 -0
  80. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/icons/flowchart/sampler.png +0 -0
  81. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/icons/gambit.png +0 -0
  82. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/icons/gambit_small.png +0 -0
  83. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cards/style_preference.json +0 -0
  84. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cli.py +0 -0
  85. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/cli_help.py +0 -0
  86. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/client.py +0 -0
  87. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/column_probe.py +0 -0
  88. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/config.py +0 -0
  89. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/config_address.py +0 -0
  90. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/core.py +0 -0
  91. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/core_assets.py +0 -0
  92. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/core_runtime.py +0 -0
  93. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/data_loader.py +0 -0
  94. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/data_loader_hdf5.py +0 -0
  95. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/data_loader_runtime.py +0 -0
  96. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/data_loader_summary.py +0 -0
  97. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/diagnostic_guidance.py +0 -0
  98. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/diagnostics.py +0 -0
  99. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/dryrun_runtime.py +0 -0
  100. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/fix_apply.py +0 -0
  101. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/flowchart.py +0 -0
  102. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/inner_func.py +0 -0
  103. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/man_catalog.py +0 -0
  104. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/man_methods.py +0 -0
  105. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/man_render_agent.py +0 -0
  106. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/man_render_human.py +0 -0
  107. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/man_transforms.py +0 -0
  108. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/agent-output.yaml +0 -0
  109. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/cli-map.yaml +0 -0
  110. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/data-columns.yaml +0 -0
  111. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/diagnostics.yaml +0 -0
  112. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/dryrun-viz.yaml +0 -0
  113. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/layer-method.yaml +0 -0
  114. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/manifest.yaml +0 -0
  115. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/type-posterior-2d.yaml +0 -0
  116. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/type-profile-2d.yaml +0 -0
  117. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/validate.yaml +0 -0
  118. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/workflow.yaml +0 -0
  119. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/manual_cards/yaml-root.yaml +0 -0
  120. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/memtrace.py +0 -0
  121. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/render_health.py +0 -0
  122. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/core/common.json +0 -0
  123. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/core/dataset.json +0 -0
  124. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/core/figure.json +0 -0
  125. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/core/transform.json +0 -0
  126. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/bar.json +0 -0
  127. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/barh.json +0 -0
  128. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/contour.json +0 -0
  129. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/contourf.json +0 -0
  130. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/dynesty_runplot.json +0 -0
  131. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/errorbar.json +0 -0
  132. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/fill.json +0 -0
  133. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/fill_between.json +0 -0
  134. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/fill_betweenx.json +0 -0
  135. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/hist.json +0 -0
  136. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/imshow.json +0 -0
  137. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/jpcontour.json +0 -0
  138. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/jpcontourf.json +0 -0
  139. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/jpfield.json +0 -0
  140. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/pcolor.json +0 -0
  141. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/pcolormesh.json +0 -0
  142. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/plot.json +0 -0
  143. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/quiver.json +0 -0
  144. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/scatter.json +0 -0
  145. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/step.json +0 -0
  146. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/tricontour.json +0 -0
  147. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/tricontourf.json +0 -0
  148. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/tripcolor.json +0 -0
  149. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/tripcolor_axes.json +0 -0
  150. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/triplot.json +0 -0
  151. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/voronoi.json +0 -0
  152. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/methods/voronoif.json +0 -0
  153. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema/plot-config.json +0 -0
  154. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema_catalog.py +0 -0
  155. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/schema_diagnostics.py +0 -0
  156. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/templates_catalog.py +0 -0
  157. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/transform_contracts.py +0 -0
  158. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/utils/__init__.py +0 -0
  159. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/utils/cmaps.py +0 -0
  160. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/utils/dataframes.py +0 -0
  161. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/utils/expression.py +0 -0
  162. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/utils/interpolator.py +0 -0
  163. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/utils/pathing.py +0 -0
  164. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/validation.py +0 -0
  165. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/verbs/__init__.py +0 -0
  166. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/verbs/cap.py +0 -0
  167. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/verbs/config_cmd.py +0 -0
  168. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/verbs/data.py +0 -0
  169. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/verbs/doctor.py +0 -0
  170. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/verbs/dryrun.py +0 -0
  171. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/verbs/explain.py +0 -0
  172. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/verbs/man.py +0 -0
  173. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/verbs/suggest.py +0 -0
  174. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/verbs/template.py +0 -0
  175. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/verbs/validate.py +0 -0
  176. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/jarvisplot/yaml_io.py +0 -0
  177. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/setup.cfg +0 -0
  178. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_agent_digest.py +0 -0
  179. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_agent_envelope.py +0 -0
  180. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_capabilities.py +0 -0
  181. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_card_debug_shape.py +0 -0
  182. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_cli_help.py +0 -0
  183. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_cli_verbs.py +0 -0
  184. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_cmaps.py +0 -0
  185. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_column_existence.py +0 -0
  186. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_config_addressing.py +0 -0
  187. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_config_edit.py +0 -0
  188. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_config_expand.py +0 -0
  189. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_data_access.py +0 -0
  190. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_data_describe.py +0 -0
  191. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_data_head_eval.py +0 -0
  192. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_data_loader_contracts.py +0 -0
  193. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_data_pipelines.py +0 -0
  194. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_debug_config.py +0 -0
  195. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_debug_switches.py +0 -0
  196. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_debug_yaml_override.py +0 -0
  197. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_density_cell_transform.py +0 -0
  198. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_design_runtime.py +0 -0
  199. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_diagnostic_guidance.py +0 -0
  200. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_docs_status_labels.py +0 -0
  201. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_doctor_partial.py +0 -0
  202. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_explain.py +0 -0
  203. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_figure_contracts.py +0 -0
  204. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_figure_type_expander.py +0 -0
  205. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_fix_application.py +0 -0
  206. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_flowchart_renderer.py +0 -0
  207. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_interp_2d_transform.py +0 -0
  208. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_interp_natural_neighbor.py +0 -0
  209. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_interpolator_contracts.py +0 -0
  210. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_jpcontour_methods.py +0 -0
  211. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_man_cli.py +0 -0
  212. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_method_contracts.py +0 -0
  213. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_parse_data_metadata.py +0 -0
  214. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_pathing_contracts.py +0 -0
  215. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_posterior_hpd.py +0 -0
  216. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_render_health.py +0 -0
  217. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_row_ledger.py +0 -0
  218. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_schema_catalog.py +0 -0
  219. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_suggest.py +0 -0
  220. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_suggest_axes.py +0 -0
  221. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_template_catalog.py +0 -0
  222. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_template_json.py +0 -0
  223. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_ternary_debug.py +0 -0
  224. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_transform_contracts.py +0 -0
  225. {jarvisplot-2.0.5 → jarvisplot-2.0.6}/tests/test_validate_no_matplotlib.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: JarvisPLOT
3
- Version: 2.0.5
3
+ Version: 2.0.6
4
4
  Summary: Jarvis-PLOT: YAML-driven plotting engine
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -137,6 +137,7 @@ jarvisplot/schema/methods/fill.json
137
137
  jarvisplot/schema/methods/fill_between.json
138
138
  jarvisplot/schema/methods/fill_betweenx.json
139
139
  jarvisplot/schema/methods/hist.json
140
+ jarvisplot/schema/methods/hist2d.json
140
141
  jarvisplot/schema/methods/imshow.json
141
142
  jarvisplot/schema/methods/jpcontour.json
142
143
  jarvisplot/schema/methods/jpcontourf.json
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: JarvisPLOT
3
- Version: 2.0.5
3
+ Version: 2.0.6
4
4
  Summary: Jarvis-PLOT: YAML-driven plotting engine
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -56,6 +56,20 @@ def axc_color_config(frame: Mapping[str, Any], cb_name: str = "axc") -> dict:
56
56
  return out
57
57
 
58
58
 
59
+ def layer_cmap_wins(fig, cb_name: str, color_cfg: Mapping[str, Any]) -> bool:
60
+ """Whether a layer's own ``cmap`` may override ``frame[cb_name].color.cmap``.
61
+
62
+ A cmap that reached the frame from the **style card** is a preset: the
63
+ card says what this colorbar normally looks like, and a layer naming its
64
+ own is the more specific statement, so the layer wins. A cmap written in
65
+ the **project YAML** is the author talking about this one figure, so it
66
+ wins instead. Same defaults < card < YAML order the Debug block uses.
67
+ """
68
+ if color_cfg.get("cmap") is None:
69
+ return True
70
+ return str(cb_name) not in (getattr(fig, "yaml_colorbar_cmaps", None) or set())
71
+
72
+
59
73
  # ---------------------------------------------------------------------------
60
74
  # Scalar helpers
61
75
  # ---------------------------------------------------------------------------
@@ -151,6 +165,55 @@ _CONTOUR_LIKE_METHODS = frozenset({
151
165
  "jpcontour", "jpcontourf",
152
166
  })
153
167
 
168
+ #: Methods that bin their own data: the colour channel is the bin content, so
169
+ #: there is no ``z`` column for the pre-scan to read. It has to run the same
170
+ #: binning matplotlib will run.
171
+ _BINNED_COLOR_METHODS = frozenset({"hist2d"})
172
+
173
+
174
+ def _hist2d_bin_values(df, coor: dict, style: dict):
175
+ """Reproduce the bin contents ``Axes.hist2d`` will colour.
176
+
177
+ ``Axes.hist2d`` is ``np.histogram2d`` followed by ``pcolormesh``, so the
178
+ same call with the same ``bins`` / ``range`` / ``density`` / ``weights``
179
+ gives the pre-scan the colour range without drawing anything.
180
+ """
181
+ if df is None:
182
+ return None
183
+
184
+ def _channel(key):
185
+ src = coor.get(key)
186
+ if isinstance(src, dict) and "expr" in src:
187
+ return eval_dataframe_expression(df, src["expr"], logger=None)
188
+ if src is None:
189
+ src = style.get(key)
190
+ if src is None or isinstance(src, str):
191
+ return None
192
+ return np.asarray(src, dtype=float)
193
+
194
+ x = _channel("x")
195
+ y = _channel("y")
196
+ if x is None or y is None:
197
+ return None
198
+
199
+ values, _, _ = np.histogram2d(
200
+ np.asarray(x, dtype=float),
201
+ np.asarray(y, dtype=float),
202
+ bins=style.get("bins", 10),
203
+ range=style.get("range"),
204
+ density=bool(style.get("density", False)),
205
+ weights=_channel("weights"),
206
+ )
207
+ # `cmin` / `cmax` blank a bin out entirely; a blanked bin must not drag the
208
+ # colorbar range with it.
209
+ cmin = style.get("cmin")
210
+ cmax = style.get("cmax")
211
+ if cmin is not None:
212
+ values = values[values >= float(cmin)]
213
+ if cmax is not None:
214
+ values = values[values <= float(cmax)]
215
+ return values
216
+
154
217
 
155
218
  def layer_uses_color(style: dict, coor: dict, method_key: str) -> bool:
156
219
  """Return True if this layer will need a colorbar."""
@@ -169,16 +232,30 @@ def layer_uses_color(style: dict, coor: dict, method_key: str) -> bool:
169
232
  if method_key in _COLORED_Z_METHODS and _is_numeric_color_source(style_z):
170
233
  return True
171
234
 
235
+ # A self-binning method always has a colour channel -- its own bin contents.
236
+ if method_key in _BINNED_COLOR_METHODS:
237
+ return True
238
+
172
239
  return False
173
240
 
174
241
 
175
- def collect_layer_color_range(df, coor: dict, style: dict, *, scale: str | None = None):
242
+ def collect_layer_color_range(
243
+ df, coor: dict, style: dict, *, scale: str | None = None, method_key: str | None = None
244
+ ):
176
245
  """Extract (data_min, data_max) for the colour channel of a single layer.
177
246
 
178
247
  Returns (None, None) when no finite data is available.
179
248
  """
180
249
  arr = None
181
- if isinstance(coor.get("z"), dict) and "expr" in coor["z"]:
250
+ if str(method_key or "").strip().lower() in _BINNED_COLOR_METHODS:
251
+ try:
252
+ arr = _hist2d_bin_values(df, coor, style)
253
+ except Exception:
254
+ # A malformed bins/range only stops the colorbar from being
255
+ # pre-sized. Let the real draw call raise it, where the error
256
+ # names the layer instead of surfacing out of the pre-scan.
257
+ arr = None
258
+ elif isinstance(coor.get("z"), dict) and "expr" in coor["z"]:
182
259
  arr = eval_dataframe_expression(df, coor["z"]["expr"], logger=None)
183
260
  elif isinstance(coor.get("c"), dict) and "expr" in coor["c"]:
184
261
  arr = eval_dataframe_expression(df, coor["c"]["expr"], logger=None)
@@ -394,13 +471,14 @@ def collect_and_attach_colorbar(
394
471
  if not axc._cb.get("used"):
395
472
  frame = getattr(fig, "frame", {})
396
473
  color_cfg = axc_color_config(frame, cb_name)
397
- if color_cfg.get("cmap") is None and style.get("cmap") is not None:
474
+ if style.get("cmap") is not None and layer_cmap_wins(fig, cb_name, color_cfg):
398
475
  color_cfg["cmap"] = style.get("cmap")
399
476
  data_range = collect_layer_color_range(
400
477
  df,
401
478
  coor,
402
479
  style,
403
480
  scale=color_cfg.get("scale"),
481
+ method_key=method_key,
404
482
  )
405
483
  if data_range != (None, None):
406
484
  axc._cb.update(
@@ -238,6 +238,21 @@ DEFAULT_DEBUG = {
238
238
  "bottom": {"show": True},
239
239
  },
240
240
  "colorbar_gap": {"show": True, "template": "%.3f cm"},
241
+ # A layout reference has no layers, so nothing feeds the colorbar and it
242
+ # stays an empty box -- the one part of the page the reference cannot
243
+ # show. Fill it with the card's own colormap. A colorbar a layer did
244
+ # feed is a real result and is left alone.
245
+ "colorbar_preview": {
246
+ "show": True,
247
+ "samples": 256,
248
+ "fallback_cmap": "viridis",
249
+ "imshow": {
250
+ "aspect": "auto",
251
+ "interpolation": "bilinear",
252
+ "origin": "lower",
253
+ "zorder": 1,
254
+ },
255
+ },
241
256
  # The layout panel. One type scale for every figure: the box is sized to
242
257
  # its content and may run past the axes, rather than shrinking its text to
243
258
  # fit a short axes and printing the same numbers at a different size on
@@ -36,6 +36,7 @@ from __future__ import annotations
36
36
  from collections.abc import Mapping
37
37
 
38
38
  import matplotlib as mpl
39
+ import numpy as np
39
40
 
40
41
 
41
42
  from .debug_config import resolve_debug_config as _debug_config
@@ -110,6 +111,51 @@ def _position(ax):
110
111
  return None
111
112
 
112
113
 
114
+ def _preview_colorbar(fig, name, cfg):
115
+ """Paint an empty colorbar axes with the colormap its card would use.
116
+
117
+ ``Figure._finalize_axc`` returns early when no layer fed the bar, which is
118
+ always the case for a pure layout reference (``layers: []``). The result
119
+ is a blank box exactly where the reader wants to judge the bar's width and
120
+ height, so fill it here. A bar a layer really did feed keeps its result:
121
+ this only ever touches ``_cb['used'] is False``.
122
+ """
123
+ axc = fig.axes.get(name)
124
+ if axc is None:
125
+ return
126
+ if dict(getattr(axc, "_cb", None) or {}).get("used"):
127
+ return
128
+
129
+ from .colorbar_runtime import axc_color_config, axc_is_horizontal
130
+
131
+ cmap = axc_color_config(fig.frame, name).get("cmap") or cfg["fallback_cmap"]
132
+ is_h = axc_is_horizontal(fig.frame, name)
133
+ ramp = np.linspace(0.0, 1.0, int(cfg["samples"])).reshape(-1, 1)
134
+ if is_h:
135
+ ramp = ramp.reshape(1, -1)
136
+
137
+ raw = _raw(axc)
138
+ raw.imshow(
139
+ ramp,
140
+ cmap=cmap,
141
+ extent=(*raw.get_xlim(), *raw.get_ylim()),
142
+ **cfg["imshow"],
143
+ )
144
+
145
+ # ``_finalize_axc`` returns on ``_cb['used'] is False`` -- before it reaches
146
+ # ``minorticks_on`` and ``_apply_axc_tick_config``. So an unfed colorbar
147
+ # keeps matplotlib's default ticks: both sides, pointing out, full-size
148
+ # labels, no minor locator. The reference is meant to show the tick
149
+ # treatment the card asks for, so run the same two steps here.
150
+ from matplotlib.ticker import AutoMinorLocator
151
+
152
+ axis = raw.xaxis if is_h else raw.yaxis
153
+ axis.set_minor_locator(AutoMinorLocator())
154
+ apply = getattr(fig, "_apply_axc_tick_config", None)
155
+ if callable(apply):
156
+ apply(name, axc)
157
+
158
+
113
159
  def _axis_info_lines(name, pos, w_cm, h_cm, *, detail_cfg, fig=None):
114
160
  """Return the three-line layout entry used in the information panel."""
115
161
  l, b, w, h = pos
@@ -381,6 +427,9 @@ def _draw(fig) -> None:
381
427
  vertical_label_side=margin_side,
382
428
  )
383
429
 
430
+ if name.startswith("axc") and _shown(debug["colorbar_preview"]):
431
+ _preview_colorbar(fig, name, debug["colorbar_preview"])
432
+
384
433
  if name.startswith("axc") and primary_pos is not None:
385
434
  # gap between the primary axes' right edge and this colorbar's left edge
386
435
  pl, pb, pw, ph = primary_pos
@@ -23,6 +23,7 @@ from .layout_runtime import (
23
23
  apply_axis_endpoints,
24
24
  apply_auto_ticks,
25
25
  apply_axis_title,
26
+ apply_grid,
26
27
  apply_manual_ticks,
27
28
  SIDE_AXES,
28
29
  ensure_rect_axes,
@@ -33,6 +34,7 @@ from .layout_runtime import (
33
34
  )
34
35
  from .colorbar_runtime import (
35
36
  axc_color_config,
37
+ layer_cmap_wins,
36
38
  axc_is_horizontal,
37
39
  collect_layer_color_range,
38
40
  layer_uses_color,
@@ -246,6 +248,10 @@ class Figure:
246
248
  # self._jpdatas: Optional[list] = []
247
249
  self._logger = None
248
250
  self._frame = {}
251
+ # Colorbar axes whose cmap the project YAML names outright. A cmap
252
+ # that only came from the style card is a preset the layer may
253
+ # override; one written here is not.
254
+ self._yaml_axc_cmaps: set = set()
249
255
  self._outinfo = {}
250
256
  self._output_metadata = {}
251
257
  self._yaml_dir = None # directory of the active YAML file (used to resolve relative paths)
@@ -348,8 +354,17 @@ class Figure:
348
354
  if self._frame is None:
349
355
  self._frame = value
350
356
  else:
357
+ for _name, _node in (value or {}).items():
358
+ _color = _node.get("color") if isinstance(_node, dict) else None
359
+ if isinstance(_color, dict) and "cmap" in _color:
360
+ self._yaml_axc_cmaps.add(str(_name))
351
361
  from deepmerge import always_merger
352
362
  self._frame = always_merger.merge(self._frame, value)
363
+
364
+ @property
365
+ def yaml_colorbar_cmaps(self) -> set:
366
+ """Colorbar axes whose cmap came from the YAML rather than the card."""
367
+ return self._yaml_axc_cmaps
353
368
 
354
369
  @property
355
370
  def style(self) -> Optional[dict]:
@@ -363,6 +378,7 @@ class Figure:
363
378
  raise TypeError
364
379
  family, selected, bundle = resolve_style_bundle_payload(self.jpstyles, value)
365
380
  self._frame = deepcopy(bundle["Frame"])
381
+ self._yaml_axc_cmaps = set()
366
382
  self._style = deepcopy(bundle["Style"])
367
383
  self._debug_config = deepcopy(bundle.get("Debug", {}))
368
384
  self._default_layers = deepcopy(bundle.get("Layers", []))
@@ -883,7 +899,9 @@ class Figure:
883
899
  if not layer_uses_color(style, coor, method_key):
884
900
  continue
885
901
 
886
- if style.get("cmap") is not None:
902
+ if style.get("cmap") is not None and layer_cmap_wins(
903
+ self, cb_name, axc_color_config(self.frame, cb_name)
904
+ ):
887
905
  cb_style_cmaps.setdefault(cb_name, style.get("cmap"))
888
906
 
889
907
  # Load data for color range only — do not append health observations
@@ -893,7 +911,9 @@ class Figure:
893
911
  if df is not None:
894
912
  df = self._ensure_pandas_data(df, reason="prescan:colorbar")
895
913
  color_cfg = axc_color_config(self.frame, cb_name)
896
- lo, hi = collect_layer_color_range(df, coor, style, scale=color_cfg.get("scale"))
914
+ lo, hi = collect_layer_color_range(
915
+ df, coor, style, scale=color_cfg.get("scale"), method_key=method_key
916
+ )
897
917
  if lo is not None or hi is not None:
898
918
  cb_ranges.setdefault(cb_name, []).append((lo, hi))
899
919
  # Release immediately to preserve memory profile
@@ -905,7 +925,7 @@ class Figure:
905
925
  if axc_obj is None or not hasattr(axc_obj, "_cb"):
906
926
  continue
907
927
  color_cfg = axc_color_config(self.frame, cb_name)
908
- if color_cfg.get("cmap") is None and cb_name in cb_style_cmaps:
928
+ if cb_name in cb_style_cmaps and layer_cmap_wins(self, cb_name, color_cfg):
909
929
  color_cfg["cmap"] = cb_style_cmaps[cb_name]
910
930
  axc_obj._cb.update(
911
931
  precompute_colorbar_cb(color_cfg, ranges, logger=self.logger)
@@ -1004,6 +1024,8 @@ class Figure:
1004
1024
  self.ax.tick_params(**self.frame['ax']['ticks'].get("major", {}))
1005
1025
  self.ax.tick_params(**self.frame['ax']['ticks'].get("minor", {}))
1006
1026
 
1027
+ apply_grid(self, self.axes['ax'], 'ax')
1028
+
1007
1029
  self._apply_axis_endpoints(self.axes['ax'], self.frame['ax'].get('xaxis', {}), "x")
1008
1030
  self._apply_axis_endpoints(self.axes['ax'], self.frame['ax'].get('yaxis', {}), "y")
1009
1031
 
@@ -85,6 +85,42 @@ def hide_log_minor_tick_labels(ax_obj, which: str) -> None:
85
85
  )
86
86
 
87
87
 
88
+ def apply_grid(fig, ax_obj, ax_name: str) -> None:
89
+ """Draw the configured major / minor grid on a rectangular axes.
90
+
91
+ Shaped like ``ticks``: one block per matplotlib call, splatted verbatim
92
+ into ``Axes.grid``. Ternary cards keep their own hand-drawn grid under
93
+ ``grid.sep`` / ``grid.style``, so only the two call blocks are read here
94
+ and every other key in the node is left alone -- which is also why the
95
+ dead ``grid`` blocks the rect cards inherited stay dead.
96
+
97
+ ``axisbelow`` is a sibling key rather than a ``grid`` kwarg because it is
98
+ the only thing that decides whether the grid lands over or under the data:
99
+ a ``zorder`` passed to ``Axes.grid`` sets the gridline's own zorder, but
100
+ the Axis artist is drawn as a unit at the zorder ``set_axisbelow`` gives
101
+ it, so the kwarg alone never lifts a grid above a filled layer.
102
+ """
103
+ grid_cfg = fig.frame.get(ax_name, {}).get("grid", {})
104
+ if not isinstance(grid_cfg, dict):
105
+ return
106
+ target = ax_obj.ax if hasattr(ax_obj, "ax") else ax_obj
107
+
108
+ if "axisbelow" in grid_cfg:
109
+ target.set_axisbelow(grid_cfg["axisbelow"])
110
+
111
+ for which in ("major", "minor"):
112
+ block = grid_cfg.get(which)
113
+ if not isinstance(block, dict) or not block:
114
+ continue
115
+ try:
116
+ target.grid(**block)
117
+ except Exception as exc:
118
+ if getattr(fig, "logger", None):
119
+ fig.logger.warning(
120
+ f"grid.{which} on axes '{ax_name}' ignored: {exc}"
121
+ )
122
+
123
+
88
124
  def ensure_rect_axes(fig, ax_name: str, kwgs: dict):
89
125
  if not is_rect_ax(ax_name):
90
126
  allowed = ", ".join(repr(n) for n in SIDE_AXES)
@@ -159,9 +195,18 @@ def ensure_rect_axes(fig, ax_name: str, kwgs: dict):
159
195
  if isinstance(ylabel_coords, dict) and {"x", "y"} <= set(ylabel_coords):
160
196
  ax_obj.yaxis.set_label_coords(ylabel_coords["x"], ylabel_coords["y"])
161
197
 
162
- ax_obj.tick_params(**fig.frame.get(ax_name, {}).get("ticks", {}).get("both", {}))
163
- ax_obj.tick_params(**fig.frame.get(ax_name, {}).get("ticks", {}).get("major", {}))
164
- ax_obj.tick_params(**fig.frame.get(ax_name, {}).get("ticks", {}).get("minor", {}))
198
+ ticks_cfg = fig.frame.get(ax_name, {}).get("ticks", {})
199
+ ax_obj.tick_params(**ticks_cfg.get("both", {}))
200
+ ax_obj.tick_params(**ticks_cfg.get("major", {}))
201
+ ax_obj.tick_params(**ticks_cfg.get("minor", {}))
202
+
203
+ # `ticks.x/y.positions` was honoured on ax and on the colorbars but never
204
+ # here, so a side or numbered axes silently kept matplotlib's automatic
205
+ # locator -- even though has_manual_ticks already reads this same node.
206
+ apply_manual_ticks(fig, ax_obj, "x", ticks_cfg.get("x", {}) or {})
207
+ apply_manual_ticks(fig, ax_obj, "y", ticks_cfg.get("y", {}) or {})
208
+
209
+ apply_grid(fig, ax_obj, ax_name)
165
210
 
166
211
  apply_axis_endpoints(fig, ax_obj, fig.frame.get(ax_name, {}).get("xaxis", {}), "x")
167
212
  apply_axis_endpoints(fig, ax_obj, fig.frame.get(ax_name, {}).get("yaxis", {}), "y")
@@ -41,6 +41,7 @@ METHOD_DISPATCH: Dict[str, str] = {
41
41
  "plot": "plot",
42
42
  "scatter": "scatter",
43
43
  "hist": "hist",
44
+ "hist2d": "hist2d",
44
45
  "errorbar": "errorbar",
45
46
  "fill": "fill",
46
47
  "fill_between": "fill_between",
@@ -101,6 +101,8 @@
101
101
  "left": true,
102
102
  "right": true,
103
103
  "bottom": true,
104
+ "labelbottom": false,
105
+ "labeltop": false,
104
106
  "which": "both"
105
107
  },
106
108
  "major": {
@@ -155,6 +157,8 @@
155
157
  "left": true,
156
158
  "right": true,
157
159
  "bottom": true,
160
+ "labelbottom": false,
161
+ "labeltop": false,
158
162
  "which": "both"
159
163
  },
160
164
  "major": {
@@ -209,6 +213,8 @@
209
213
  "left": true,
210
214
  "right": true,
211
215
  "bottom": true,
216
+ "labelbottom": false,
217
+ "labeltop": false,
212
218
  "which": "both"
213
219
  },
214
220
  "major": {
@@ -263,6 +269,8 @@
263
269
  "left": true,
264
270
  "right": true,
265
271
  "bottom": true,
272
+ "labelbottom": false,
273
+ "labeltop": false,
266
274
  "which": "both"
267
275
  },
268
276
  "major": {
@@ -143,6 +143,9 @@
143
143
  ]
144
144
  },
145
145
  "axc": {
146
+ "color": {
147
+ "cmap": "jarvis_rainbow2"
148
+ },
146
149
  "label": {
147
150
  "ylabel": "",
148
151
  "loc": "center",
@@ -401,6 +404,17 @@
401
404
  "show": true,
402
405
  "template": "%.3f cm"
403
406
  },
407
+ "colorbar_preview": {
408
+ "show": true,
409
+ "samples": 256,
410
+ "fallback_cmap": "viridis",
411
+ "imshow": {
412
+ "aspect": "auto",
413
+ "interpolation": "bilinear",
414
+ "origin": "lower",
415
+ "zorder": 1
416
+ }
417
+ },
404
418
  "panel": {
405
419
  "show": true,
406
420
  "pad_x_max": 0.018,