jarvisplot 2.0.3__tar.gz → 2.0.5__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 (239) hide show
  1. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/JarvisPLOT.egg-info/PKG-INFO +1 -1
  2. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/JarvisPLOT.egg-info/SOURCES.txt +10 -0
  3. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/PKG-INFO +1 -1
  4. jarvisplot-2.0.5/jarvisplot/Figure/debug_config.py +451 -0
  5. jarvisplot-2.0.5/jarvisplot/Figure/design_runtime.py +588 -0
  6. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/figure.py +208 -47
  7. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/layout_runtime.py +36 -9
  8. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/capabilities.py +4 -0
  9. jarvisplot-2.0.5/jarvisplot/cards/a4paper/1x1/ternary.json +298 -0
  10. jarvisplot-2.0.5/jarvisplot/cards/a4paper/2x1/dynesty_runplot.json +686 -0
  11. jarvisplot-2.0.5/jarvisplot/cards/a4paper/2x1/rect.json +435 -0
  12. jarvisplot-2.0.5/jarvisplot/cards/a4paper/2x1/rect5x1.json +679 -0
  13. jarvisplot-2.0.5/jarvisplot/cards/a4paper/2x1/rect_cmap.json +481 -0
  14. jarvisplot-2.0.5/jarvisplot/cards/a4paper/2x1/rect_marginal.json +609 -0
  15. jarvisplot-2.0.5/jarvisplot/cards/a4paper/2x1/rectratio.json +511 -0
  16. jarvisplot-2.0.5/jarvisplot/cards/a4paper/2x1/ternary.json +462 -0
  17. jarvisplot-2.0.5/jarvisplot/cards/a4paper/2x1/ternary_cmap.json +503 -0
  18. jarvisplot-2.0.5/jarvisplot/cards/a4paper/4x1/rect_cmap.json +466 -0
  19. jarvisplot-2.0.5/jarvisplot/cards/gambit/1x1/ternary.json +298 -0
  20. jarvisplot-2.0.5/jarvisplot/cards/gambit/2x1/rect_cmap.json +492 -0
  21. jarvisplot-2.0.5/jarvisplot/cards/gambit/2x1/ternary.json +476 -0
  22. jarvisplot-2.0.5/jarvisplot/cards/gambit/2x1/ternary_cmap.json +519 -0
  23. jarvisplot-2.0.5/jarvisplot/cards/icons/JarvisHEP.png +0 -0
  24. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/style_preference.json +3 -1
  25. jarvisplot-2.0.5/jarvisplot/manual_cards/debug-overlay.yaml +64 -0
  26. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/manifest.yaml +5 -0
  27. jarvisplot-2.0.5/jarvisplot/schema/core/figure.json +230 -0
  28. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/pyproject.toml +1 -1
  29. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_axis_title.py +80 -0
  30. jarvisplot-2.0.5/tests/test_card_debug_shape.py +75 -0
  31. jarvisplot-2.0.5/tests/test_debug_config.py +147 -0
  32. jarvisplot-2.0.5/tests/test_debug_switches.py +180 -0
  33. jarvisplot-2.0.5/tests/test_debug_yaml_override.py +147 -0
  34. jarvisplot-2.0.5/tests/test_design_runtime.py +227 -0
  35. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_figure_contracts.py +90 -0
  36. jarvisplot-2.0.5/tests/test_ternary_debug.py +151 -0
  37. jarvisplot-2.0.3/jarvisplot/Figure/design_runtime.py +0 -137
  38. jarvisplot-2.0.3/jarvisplot/cards/a4paper/1x1/ternary.json +0 -6
  39. jarvisplot-2.0.3/jarvisplot/cards/a4paper/2x1/dynesty_runplot.json +0 -165
  40. jarvisplot-2.0.3/jarvisplot/cards/a4paper/2x1/rect.json +0 -143
  41. jarvisplot-2.0.3/jarvisplot/cards/a4paper/2x1/rect5x1.json +0 -352
  42. jarvisplot-2.0.3/jarvisplot/cards/a4paper/2x1/rect_cmap.json +0 -189
  43. jarvisplot-2.0.3/jarvisplot/cards/a4paper/2x1/ternary.json +0 -142
  44. jarvisplot-2.0.3/jarvisplot/cards/a4paper/4x1/rect_cmap.json +0 -174
  45. jarvisplot-2.0.3/jarvisplot/cards/a4paper/4x1/ternary_cmap.json +0 -189
  46. jarvisplot-2.0.3/jarvisplot/cards/gambit/1x1/ternary.json +0 -6
  47. jarvisplot-2.0.3/jarvisplot/cards/gambit/2x1/rect_cmap.json +0 -200
  48. jarvisplot-2.0.3/jarvisplot/cards/gambit/2x1/ternary.json +0 -156
  49. jarvisplot-2.0.3/jarvisplot/cards/gambit/2x1/ternary_cmap.json +0 -205
  50. jarvisplot-2.0.3/jarvisplot/cards/icons/flowchart/JarvisHEP.png +0 -0
  51. jarvisplot-2.0.3/jarvisplot/schema/core/figure.json +0 -127
  52. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/JarvisPLOT.egg-info/dependency_links.txt +0 -0
  53. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/JarvisPLOT.egg-info/entry_points.txt +0 -0
  54. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/JarvisPLOT.egg-info/requires.txt +0 -0
  55. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/JarvisPLOT.egg-info/top_level.txt +0 -0
  56. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/README.md +0 -0
  57. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/__init__.py +0 -0
  58. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/adapters_rect.py +0 -0
  59. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/adapters_ternary.py +0 -0
  60. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/cards/std_axes_adapter_config.json +0 -0
  61. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/colorbar_runtime.py +0 -0
  62. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/config_runtime.py +0 -0
  63. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/data_pipelines.py +0 -0
  64. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/density_cell_runtime.py +0 -0
  65. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/dynesty_runtime.py +0 -0
  66. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/figure_types.py +0 -0
  67. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/helper.py +0 -0
  68. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/interp_2d_runtime.py +0 -0
  69. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/interp_natural_neighbor.py +0 -0
  70. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/interp_natural_neighbor_exact.py +0 -0
  71. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/layer_runtime.py +0 -0
  72. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/method_registry.py +0 -0
  73. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/posterior_density_runtime.py +0 -0
  74. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/posterior_hpd.py +0 -0
  75. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/posterior_mesh.py +0 -0
  76. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/preprocessor.py +0 -0
  77. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/preprocessor_runtime.py +0 -0
  78. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/profile_runtime.py +0 -0
  79. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/Figure/style_runtime.py +0 -0
  80. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/__init__.py +0 -0
  81. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/agent_digest.py +0 -0
  82. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/agent_io.py +0 -0
  83. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cache_store.py +0 -0
  84. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/a4paper/4x1/rect.json +0 -0
  85. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/a4paper/4x1/ternary.json +0 -0
  86. {jarvisplot-2.0.3/jarvisplot/cards/a4paper/2x1 → jarvisplot-2.0.5/jarvisplot/cards/a4paper/4x1}/ternary_cmap.json +0 -0
  87. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/args.json +0 -0
  88. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/colors/colormaps.json +0 -0
  89. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/default/output.json +0 -0
  90. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/flowchart/default.json +0 -0
  91. {jarvisplot-2.0.3/jarvisplot/cards/icons → jarvisplot-2.0.5/jarvisplot/cards/icons/flowchart}/JarvisHEP.png +0 -0
  92. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/icons/flowchart/calculator.png +0 -0
  93. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/icons/flowchart/inputfile.png +0 -0
  94. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/icons/flowchart/opera.png +0 -0
  95. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/icons/flowchart/outputfile.png +0 -0
  96. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/icons/flowchart/sampler.png +0 -0
  97. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/icons/gambit.png +0 -0
  98. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cards/icons/gambit_small.png +0 -0
  99. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cli.py +0 -0
  100. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/cli_help.py +0 -0
  101. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/client.py +0 -0
  102. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/column_demand.py +0 -0
  103. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/column_probe.py +0 -0
  104. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/config.py +0 -0
  105. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/config_address.py +0 -0
  106. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/core.py +0 -0
  107. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/core_assets.py +0 -0
  108. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/core_runtime.py +0 -0
  109. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/data_access.py +0 -0
  110. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/data_loader.py +0 -0
  111. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/data_loader_hdf5.py +0 -0
  112. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/data_loader_runtime.py +0 -0
  113. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/data_loader_summary.py +0 -0
  114. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/diagnostic_guidance.py +0 -0
  115. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/diagnostics.py +0 -0
  116. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/dryrun_runtime.py +0 -0
  117. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/expr_names.py +0 -0
  118. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/fix_apply.py +0 -0
  119. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/flowchart.py +0 -0
  120. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/inner_func.py +0 -0
  121. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/man_catalog.py +0 -0
  122. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/man_methods.py +0 -0
  123. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/man_render_agent.py +0 -0
  124. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/man_render_human.py +0 -0
  125. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/man_transforms.py +0 -0
  126. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/agent-output.yaml +0 -0
  127. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/cli-map.yaml +0 -0
  128. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/data-columns.yaml +0 -0
  129. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/diagnostics.yaml +0 -0
  130. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/dryrun-viz.yaml +0 -0
  131. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/layer-method.yaml +0 -0
  132. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/method_notes.yaml +0 -0
  133. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/style-axes.yaml +0 -0
  134. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/type-posterior-2d.yaml +0 -0
  135. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/type-profile-2d.yaml +0 -0
  136. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/validate.yaml +0 -0
  137. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/workflow.yaml +0 -0
  138. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/manual_cards/yaml-root.yaml +0 -0
  139. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/memtrace.py +0 -0
  140. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/method_contracts.py +0 -0
  141. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/render_health.py +0 -0
  142. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/core/common.json +0 -0
  143. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/core/dataset.json +0 -0
  144. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/core/layer.json +0 -0
  145. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/core/transform.json +0 -0
  146. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/manifest.json +0 -0
  147. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/bar.json +0 -0
  148. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/barh.json +0 -0
  149. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/contour.json +0 -0
  150. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/contourf.json +0 -0
  151. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/dynesty_runplot.json +0 -0
  152. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/errorbar.json +0 -0
  153. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/fill.json +0 -0
  154. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/fill_between.json +0 -0
  155. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/fill_betweenx.json +0 -0
  156. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/hist.json +0 -0
  157. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/imshow.json +0 -0
  158. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/jpcontour.json +0 -0
  159. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/jpcontourf.json +0 -0
  160. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/jpfield.json +0 -0
  161. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/pcolor.json +0 -0
  162. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/pcolormesh.json +0 -0
  163. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/plot.json +0 -0
  164. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/quiver.json +0 -0
  165. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/scatter.json +0 -0
  166. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/step.json +0 -0
  167. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/tricontour.json +0 -0
  168. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/tricontourf.json +0 -0
  169. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/tripcolor.json +0 -0
  170. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/tripcolor_axes.json +0 -0
  171. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/triplot.json +0 -0
  172. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/voronoi.json +0 -0
  173. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/methods/voronoif.json +0 -0
  174. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema/plot-config.json +0 -0
  175. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema_catalog.py +0 -0
  176. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/schema_diagnostics.py +0 -0
  177. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/templates_catalog.py +0 -0
  178. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/transform_contracts.py +0 -0
  179. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/utils/__init__.py +0 -0
  180. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/utils/cmaps.py +0 -0
  181. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/utils/dataframes.py +0 -0
  182. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/utils/expression.py +0 -0
  183. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/utils/interpolator.py +0 -0
  184. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/utils/pathing.py +0 -0
  185. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/validation.py +0 -0
  186. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/verbs/__init__.py +0 -0
  187. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/verbs/cap.py +0 -0
  188. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/verbs/config_cmd.py +0 -0
  189. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/verbs/data.py +0 -0
  190. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/verbs/doctor.py +0 -0
  191. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/verbs/dryrun.py +0 -0
  192. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/verbs/explain.py +0 -0
  193. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/verbs/man.py +0 -0
  194. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/verbs/suggest.py +0 -0
  195. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/verbs/template.py +0 -0
  196. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/verbs/validate.py +0 -0
  197. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/jarvisplot/yaml_io.py +0 -0
  198. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/setup.cfg +0 -0
  199. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_agent_digest.py +0 -0
  200. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_agent_envelope.py +0 -0
  201. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_capabilities.py +0 -0
  202. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_cli_help.py +0 -0
  203. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_cli_verbs.py +0 -0
  204. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_cmaps.py +0 -0
  205. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_column_existence.py +0 -0
  206. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_config_addressing.py +0 -0
  207. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_config_edit.py +0 -0
  208. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_config_expand.py +0 -0
  209. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_data_access.py +0 -0
  210. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_data_describe.py +0 -0
  211. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_data_head_eval.py +0 -0
  212. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_data_loader_contracts.py +0 -0
  213. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_data_pipelines.py +0 -0
  214. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_density_cell_transform.py +0 -0
  215. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_diagnostic_guidance.py +0 -0
  216. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_docs_status_labels.py +0 -0
  217. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_doctor_partial.py +0 -0
  218. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_explain.py +0 -0
  219. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_figure_type_expander.py +0 -0
  220. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_fix_application.py +0 -0
  221. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_flowchart_renderer.py +0 -0
  222. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_interp_2d_transform.py +0 -0
  223. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_interp_natural_neighbor.py +0 -0
  224. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_interpolator_contracts.py +0 -0
  225. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_jpcontour_methods.py +0 -0
  226. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_man_cli.py +0 -0
  227. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_method_contracts.py +0 -0
  228. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_parse_data_metadata.py +0 -0
  229. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_pathing_contracts.py +0 -0
  230. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_posterior_hpd.py +0 -0
  231. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_render_health.py +0 -0
  232. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_row_ledger.py +0 -0
  233. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_schema_catalog.py +0 -0
  234. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_suggest.py +0 -0
  235. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_suggest_axes.py +0 -0
  236. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_template_catalog.py +0 -0
  237. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_template_json.py +0 -0
  238. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/tests/test_transform_contracts.py +0 -0
  239. {jarvisplot-2.0.3 → jarvisplot-2.0.5}/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.3
3
+ Version: 2.0.5
4
4
  Summary: Jarvis-PLOT: YAML-driven plotting engine
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -53,6 +53,7 @@ jarvisplot/Figure/adapters_ternary.py
53
53
  jarvisplot/Figure/colorbar_runtime.py
54
54
  jarvisplot/Figure/config_runtime.py
55
55
  jarvisplot/Figure/data_pipelines.py
56
+ jarvisplot/Figure/debug_config.py
56
57
  jarvisplot/Figure/density_cell_runtime.py
57
58
  jarvisplot/Figure/design_runtime.py
58
59
  jarvisplot/Figure/dynesty_runtime.py
@@ -80,6 +81,8 @@ jarvisplot/cards/a4paper/2x1/dynesty_runplot.json
80
81
  jarvisplot/cards/a4paper/2x1/rect.json
81
82
  jarvisplot/cards/a4paper/2x1/rect5x1.json
82
83
  jarvisplot/cards/a4paper/2x1/rect_cmap.json
84
+ jarvisplot/cards/a4paper/2x1/rect_marginal.json
85
+ jarvisplot/cards/a4paper/2x1/rectratio.json
83
86
  jarvisplot/cards/a4paper/2x1/ternary.json
84
87
  jarvisplot/cards/a4paper/2x1/ternary_cmap.json
85
88
  jarvisplot/cards/a4paper/4x1/rect.json
@@ -105,6 +108,7 @@ jarvisplot/cards/icons/flowchart/sampler.png
105
108
  jarvisplot/manual_cards/agent-output.yaml
106
109
  jarvisplot/manual_cards/cli-map.yaml
107
110
  jarvisplot/manual_cards/data-columns.yaml
111
+ jarvisplot/manual_cards/debug-overlay.yaml
108
112
  jarvisplot/manual_cards/diagnostics.yaml
109
113
  jarvisplot/manual_cards/dryrun-viz.yaml
110
114
  jarvisplot/manual_cards/layer-method.yaml
@@ -171,6 +175,7 @@ tests/test_agent_digest.py
171
175
  tests/test_agent_envelope.py
172
176
  tests/test_axis_title.py
173
177
  tests/test_capabilities.py
178
+ tests/test_card_debug_shape.py
174
179
  tests/test_cli_help.py
175
180
  tests/test_cli_verbs.py
176
181
  tests/test_cmaps.py
@@ -183,7 +188,11 @@ tests/test_data_describe.py
183
188
  tests/test_data_head_eval.py
184
189
  tests/test_data_loader_contracts.py
185
190
  tests/test_data_pipelines.py
191
+ tests/test_debug_config.py
192
+ tests/test_debug_switches.py
193
+ tests/test_debug_yaml_override.py
186
194
  tests/test_density_cell_transform.py
195
+ tests/test_design_runtime.py
187
196
  tests/test_diagnostic_guidance.py
188
197
  tests/test_docs_status_labels.py
189
198
  tests/test_doctor_partial.py
@@ -208,5 +217,6 @@ tests/test_suggest.py
208
217
  tests/test_suggest_axes.py
209
218
  tests/test_template_catalog.py
210
219
  tests/test_template_json.py
220
+ tests/test_ternary_debug.py
211
221
  tests/test_transform_contracts.py
212
222
  tests/test_validate_no_matplotlib.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: JarvisPLOT
3
- Version: 2.0.3
3
+ Version: 2.0.5
4
4
  Summary: Jarvis-PLOT: YAML-driven plotting engine
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -0,0 +1,451 @@
1
+ #!/usr/bin/env python3
2
+
3
+ """Defaults and merge rules for the design-reference debug overlay.
4
+
5
+ Split out of :mod:`design_runtime` so the configuration surface has one owner
6
+ and can be tested without importing matplotlib. The drawing code reads only
7
+ what this module hands it -- there are no literals below the unpack.
8
+
9
+ **Every appearance value lives in a block named after the matplotlib callable
10
+ that consumes it, and is splatted straight into that call:**
11
+
12
+ .. code-block:: python
13
+
14
+ ov.plot(xs, ys, **cfg["cap"]["plot"])
15
+ ov.add_patch(mpl.patches.Rectangle((l, b), w, h, **cfg["outline"]["framed"]["Rectangle"]))
16
+
17
+ So a block's keys are matplotlib's vocabulary, not Jarvis-PLOT's, and one
18
+ drawn thing owns one complete kwargs table -- no shared palette to chase, no
19
+ partial style merged with hidden Python defaults. What stays outside those
20
+ blocks is geometry: positions, spans, thresholds and the autoscale constants
21
+ that Python computes with before it draws.
22
+
23
+ Precedence, lowest to highest:
24
+
25
+ 1. :data:`DEFAULT_DEBUG` -- ships with the package, always present.
26
+ 2. A style card's root ``Debug`` block (``jarvisplot/cards/**/*.json``).
27
+ 3. A YAML ``Figures[].debug`` mapping, for one figure only.
28
+ """
29
+
30
+ from __future__ import annotations
31
+
32
+ from copy import deepcopy
33
+ from typing import Mapping
34
+
35
+ from ..diagnostics import did_you_mean
36
+
37
+ __all__ = [
38
+ "CALL_BLOCKS",
39
+ "DEFAULT_DEBUG",
40
+ "deep_update",
41
+ "merge_debug_config",
42
+ "resolve_debug_config",
43
+ ]
44
+
45
+
46
+ # Colours are written out in full inside every call block below; these names
47
+ # exist only to keep that table readable and to make the roles obvious. They
48
+ # are not a runtime indirection -- a card overrides the block, not a palette.
49
+ _DIM = "#1F21E9" # dimension lines, arrowheads and their labels
50
+ _BOX = "#111111" # outline of a framed axes
51
+ _MARGIN = "#FF3FA4" # figure border, caption, frameless-axes outline
52
+ _NAME = "#1A237E" # text inside the axes-layout panel
53
+ _PANEL = "#FFEC73" # the panel's own background
54
+ _TERNARY = "#FF42A1" # ternary tick anchors and label leaders
55
+
56
+ # The overlay sits above every real artist; text above its own artists.
57
+ _Z_OVERLAY, _Z_ARTIST, _Z_TEXT = 10000, 10001, 10002
58
+
59
+ # Background box shared by the dimension labels and the caption. Written into
60
+ # each ``text`` block in full; the alpha differs between them.
61
+ _LABEL_BBOX = {"boxstyle": "square,pad=0.12", "fc": "white", "ec": "none"}
62
+
63
+ # Typography shared by the dimension labels, likewise written out in full.
64
+ _LABEL_FONT = {
65
+ "fontsize": 5.0,
66
+ "fontweight": "normal",
67
+ "family": "monospace",
68
+ "clip_on": False,
69
+ "zorder": _Z_TEXT,
70
+ }
71
+
72
+
73
+ DEFAULT_DEBUG = {
74
+ # Which axes gets fully dimensioned and hosts the info panel. First match wins.
75
+ "primary_order": ["ax", "ax0", "ax1", "axtri"],
76
+ "units": {"cm_per_inch": 2.54, "pt_per_inch": 72.0},
77
+ # The transparent full-figure axes every annotation is drawn onto.
78
+ "overlay": {"add_axes": {"zorder": _Z_OVERLAY}},
79
+ "figure": {
80
+ "border": {
81
+ "show": True,
82
+ "Rectangle": {"fill": False, "ec": _MARGIN, "lw": 0.9, "zorder": _Z_ARTIST},
83
+ },
84
+ "caption": {
85
+ "show": True,
86
+ "x": 0.5,
87
+ "y": 0.995,
88
+ "template": "design reference · figure %.2f cm × %.2f cm",
89
+ "text": {
90
+ "color": _MARGIN,
91
+ "fontsize": 6.0,
92
+ "ha": "center",
93
+ "va": "top",
94
+ "rotation": 0,
95
+ "fontweight": "bold",
96
+ "family": "DejaVu Sans",
97
+ "clip_on": False,
98
+ "zorder": _Z_TEXT,
99
+ "bbox": {**_LABEL_BBOX, "alpha": 0.82},
100
+ },
101
+ },
102
+ # Drawn through the shared dimension machinery, so it has no call block
103
+ # of its own -- only where it sits and how its number reads.
104
+ "height_marker": {"show": True, "x": 0.035, "template": "%.2f cm"},
105
+ },
106
+ "axes": {
107
+ "frameless_extension_max": 0.018,
108
+ "frameless_extension_min": 0.006,
109
+ "frameless_extension_factor": 0.09,
110
+ "outline": {
111
+ "show": True,
112
+ # A framed axes keeps the neutral reference outline; a frameless
113
+ # one (axlogo, say) is marked as a design box instead.
114
+ "framed": {
115
+ "Rectangle": {"fill": False, "ec": _BOX, "lw": 0.45, "zorder": _Z_ARTIST},
116
+ },
117
+ "frameless": {
118
+ "Rectangle": {"fill": False, "ec": _MARGIN, "lw": 0.45, "zorder": _Z_ARTIST},
119
+ },
120
+ },
121
+ # Hash marks past the corners, drawn for frameless axes only.
122
+ "corner_ticks": {
123
+ "show": True,
124
+ "plot": {
125
+ "color": _MARGIN,
126
+ "lw": 0.45,
127
+ "solid_capstyle": "projecting",
128
+ "clip_on": False,
129
+ "zorder": _Z_ARTIST,
130
+ },
131
+ },
132
+ },
133
+ # One dimension line: two terminal cap bars, an arrow, and a label. Every
134
+ # measured distance in the overlay is drawn with these four calls.
135
+ "dimension": {
136
+ "cap_half_pt": 5.0,
137
+ "narrow_threshold_pt": 24.0,
138
+ "narrow_length_pt": 8.0,
139
+ "narrow_scale_factor": 0.45,
140
+ "narrow_scale_min": 3.0,
141
+ "narrow_scale_max": 6.0,
142
+ "label_gap": 0.008,
143
+ "corner_gap": 0.018,
144
+ "colorbar_line_offset": 0.024,
145
+ "cap": {
146
+ "plot": {
147
+ "color": _DIM,
148
+ "lw": 0.7,
149
+ "solid_capstyle": "projecting",
150
+ "clip_on": False,
151
+ "zorder": _Z_ARTIST,
152
+ },
153
+ },
154
+ # Short gaps get two inward-pointing arrows whose tails extend outside
155
+ # the interval; ``mutation_scale`` is computed from the span, between
156
+ # ``narrow_scale_min`` and ``narrow_scale_max``.
157
+ "narrow_arrow": {
158
+ "annotate": {
159
+ "zorder": _Z_ARTIST,
160
+ "arrowprops": {
161
+ "arrowstyle": "-|>",
162
+ "shrinkA": 0,
163
+ "shrinkB": 0,
164
+ "color": _DIM,
165
+ "lw": 0.7,
166
+ },
167
+ },
168
+ },
169
+ "wide_arrow": {
170
+ "annotate": {
171
+ "zorder": _Z_ARTIST,
172
+ "arrowprops": {
173
+ "arrowstyle": "<|-|>",
174
+ "shrinkA": 0,
175
+ "shrinkB": 0,
176
+ "color": _DIM,
177
+ "lw": 0.7,
178
+ "mutation_scale": 6.0,
179
+ },
180
+ },
181
+ },
182
+ "hlabel": {
183
+ "text": {
184
+ **_LABEL_FONT,
185
+ "color": _DIM,
186
+ "ha": "center",
187
+ "va": "top",
188
+ "rotation": 0,
189
+ "bbox": {**_LABEL_BBOX, "alpha": 0.5},
190
+ },
191
+ },
192
+ "vlabel_left": {
193
+ "text": {
194
+ **_LABEL_FONT,
195
+ "color": _DIM,
196
+ "ha": "right",
197
+ "va": "center",
198
+ "rotation": 90,
199
+ "bbox": {**_LABEL_BBOX, "alpha": 0.5},
200
+ },
201
+ },
202
+ "vlabel_right": {
203
+ "text": {
204
+ **_LABEL_FONT,
205
+ "color": _DIM,
206
+ "ha": "left",
207
+ "va": "center",
208
+ "rotation": 90,
209
+ "bbox": {**_LABEL_BBOX, "alpha": 0.5},
210
+ },
211
+ },
212
+ },
213
+ "numbered_axes": {
214
+ "show": True,
215
+ "right_edge": 1.0,
216
+ "marker_step": 0.040,
217
+ "label_side": "left",
218
+ "template": "%.3f cm",
219
+ "top": {"show": True},
220
+ "bottom": {"show": True},
221
+ },
222
+ # Primary-axes margin dimensions. The top/bottom pair rides the primary
223
+ # axes' right border -- just inside it, mirroring where ``left`` sits --
224
+ # so it tracks the axes it measures and leaves the layout panel the whole
225
+ # left side. ``left`` measures along the top edge and keeps its own place.
226
+ "margins": {
227
+ "template": "%.3f cm",
228
+ "label_side": "right",
229
+ # Axes that get no margin dimensions at all. A logo plate is placed by
230
+ # eye in a corner, not designed against the page edges, so measuring it
231
+ # only adds a column that collides with the ones that matter.
232
+ "exclude": ["axlogo"],
233
+ # Axes that end at the same x would draw on top of each other, so each
234
+ # one after the first steps this far further inside the border.
235
+ "marker_step": 0.040,
236
+ "left": {"show": True},
237
+ "top": {"show": True},
238
+ "bottom": {"show": True},
239
+ },
240
+ "colorbar_gap": {"show": True, "template": "%.3f cm"},
241
+ # The layout panel. One type scale for every figure: the box is sized to
242
+ # its content and may run past the axes, rather than shrinking its text to
243
+ # fit a short axes and printing the same numbers at a different size on
244
+ # every card.
245
+ "panel": {
246
+ "show": True,
247
+ "pad_x_max": 0.018,
248
+ "pad_x_min": 0.004,
249
+ "pad_x_factor": 0.025,
250
+ "pad_y_max": 0.018,
251
+ "pad_y_min": 0.004,
252
+ "pad_y_factor": 0.035,
253
+ "entry_gap": 5.0,
254
+ "char_width_factor": 0.62,
255
+ "detail_lines_per_entry": 2.0,
256
+ "text_inset_x": 0.008,
257
+ "text_inset_y": 0.006,
258
+ "box": {
259
+ "FancyBboxPatch": {
260
+ "boxstyle": "round,pad=0.004",
261
+ "facecolor": _PANEL,
262
+ "alpha": 0.5,
263
+ "edgecolor": "none",
264
+ "linewidth": 0.0,
265
+ "zorder": _Z_ARTIST,
266
+ },
267
+ },
268
+ # ``size`` is used as written on every figure; ``fontsize`` is the one
269
+ # text kwarg Python supplies, and it supplies exactly this.
270
+ "header": {
271
+ "label": "axes layout",
272
+ "size": 6.0,
273
+ "leading": 1.20,
274
+ "text": {
275
+ "color": _NAME,
276
+ "fontweight": "bold",
277
+ "ha": "left",
278
+ "va": "top",
279
+ "family": "monospace",
280
+ "clip_on": True,
281
+ "zorder": _Z_TEXT,
282
+ },
283
+ },
284
+ "name": {
285
+ "size": 7.0,
286
+ "leading": 1.15,
287
+ "text": {
288
+ "color": _NAME,
289
+ "fontweight": "bold",
290
+ "ha": "left",
291
+ "va": "top",
292
+ "family": "monospace",
293
+ "clip_on": True,
294
+ "zorder": _Z_TEXT,
295
+ },
296
+ },
297
+ "detail": {
298
+ "size": 4.6,
299
+ "leading": 1.08,
300
+ "rect_template": " rect=[%.3f, %.3f, %.3f, %.3f]",
301
+ "size_template": " width: %.3f cm height: %.3f cm",
302
+ "text": {
303
+ "color": _NAME,
304
+ "fontweight": "normal",
305
+ "ha": "left",
306
+ "va": "top",
307
+ "family": "monospace",
308
+ "clip_on": True,
309
+ "zorder": _Z_TEXT,
310
+ },
311
+ },
312
+ },
313
+ # Ternary tick anchors and label leader lines, drawn during axtri build.
314
+ "ternary": {
315
+ "tick_anchors": {
316
+ "show": True,
317
+ "scatter": {"s": 1.0, "marker": ".", "c": _TERNARY, "clip_on": False},
318
+ },
319
+ "label_leaders": {
320
+ "show": True,
321
+ "plot": {
322
+ "marker": ".",
323
+ "linestyle": "-",
324
+ "lw": 0.3,
325
+ "markersize": 1,
326
+ "c": _TERNARY,
327
+ "clip_on": False,
328
+ },
329
+ },
330
+ },
331
+ }
332
+
333
+
334
+ #: Blocks named after the matplotlib callable that receives them. Their keys
335
+ #: are matplotlib's vocabulary, so the merge stops validating inside them --
336
+ #: the same way ``layers[].style`` is a delegated zone in the YAML schema.
337
+ #: Jarvis-PLOT does not enumerate what matplotlib accepts.
338
+ CALL_BLOCKS = (
339
+ "add_axes",
340
+ "annotate",
341
+ "plot",
342
+ "scatter",
343
+ "text",
344
+ "FancyBboxPatch",
345
+ "Rectangle",
346
+ )
347
+
348
+
349
+ def deep_update(base: Mapping, override: Mapping | None) -> dict:
350
+ """Layer one override mapping over another, without validating either.
351
+
352
+ Used to combine a style card's ``Debug`` block with a figure's YAML
353
+ ``debug:`` mapping. Validation is deliberately not done here: both are
354
+ partial by design, so checking them against each other would report every
355
+ key the card happens not to mention. :func:`merge_debug_config` validates
356
+ the combined result against :data:`DEFAULT_DEBUG` once, later.
357
+
358
+ Non-mapping values replace rather than merge -- notably lists, so a card
359
+ overriding ``primary_order`` sets it instead of appending to it.
360
+ """
361
+ merged = deepcopy(dict(base))
362
+ if not isinstance(override, Mapping):
363
+ return merged
364
+ for key, value in override.items():
365
+ if isinstance(value, Mapping) and isinstance(merged.get(key), Mapping):
366
+ merged[key] = deep_update(merged[key], value)
367
+ else:
368
+ merged[key] = deepcopy(value)
369
+ return merged
370
+
371
+
372
+ def _is_delegated(key: str) -> bool:
373
+ return key in CALL_BLOCKS
374
+
375
+
376
+ def merge_debug_config(
377
+ base: Mapping,
378
+ override: Mapping | None,
379
+ *,
380
+ path: str = "",
381
+ problems: list[str] | None = None,
382
+ ) -> tuple[dict, list[str]]:
383
+ """Merge a ``Debug`` block over the defaults, reporting what it had to drop.
384
+
385
+ Returns ``(merged, problems)``. Two things used to fail in silence here and
386
+ now surface instead:
387
+
388
+ - a key the defaults do not define was carried through as inert junk, so a
389
+ typo looked exactly like a working override;
390
+ - a scalar written where the defaults hold a mapping was discarded outright.
391
+
392
+ Inside a call block (see :data:`CALL_BLOCKS`) neither check applies: those
393
+ keys belong to matplotlib. Overrides there are layered key by key, so a
394
+ card may change one arrow property without restating the rest.
395
+
396
+ Neither ever raises. A bad ``Debug`` block degrades to the defaults and says
397
+ so once, because a debug overlay must never be able to break a plot.
398
+ """
399
+ problems = [] if problems is None else problems
400
+ merged = deepcopy(dict(base))
401
+ if not isinstance(override, Mapping):
402
+ return merged, problems
403
+
404
+ for key, value in override.items():
405
+ where = f"{path}{key}"
406
+ if key not in merged:
407
+ hint = did_you_mean(str(key), [str(k) for k in merged])
408
+ suffix = f" Did you mean {hint[0]!r}?" if hint else ""
409
+ problems.append(f"{where}: unknown Debug key, ignored.{suffix}")
410
+ continue
411
+
412
+ if _is_delegated(str(key)):
413
+ # matplotlib kwargs: take the override wholesale, validate nothing.
414
+ if isinstance(merged[key], Mapping) and isinstance(value, Mapping):
415
+ merged[key] = deep_update(merged[key], value)
416
+ else:
417
+ merged[key] = deepcopy(value)
418
+ continue
419
+
420
+ if isinstance(merged[key], Mapping):
421
+ if isinstance(value, Mapping):
422
+ merged[key], _ = merge_debug_config(
423
+ merged[key], value, path=f"{where}.", problems=problems
424
+ )
425
+ else:
426
+ problems.append(
427
+ f"{where}: expected a mapping, got "
428
+ f"{type(value).__name__}; kept the default."
429
+ )
430
+ continue
431
+
432
+ merged[key] = deepcopy(value)
433
+
434
+ return merged, problems
435
+
436
+
437
+ def resolve_debug_config(fig) -> dict:
438
+ """Return the merged debug settings, logging anything the merge dropped."""
439
+ merged, problems = merge_debug_config(
440
+ DEFAULT_DEBUG,
441
+ getattr(fig, "debug_config", getattr(fig, "_debug_config", None)),
442
+ )
443
+ if problems:
444
+ logger = getattr(fig, "logger", None)
445
+ warn = getattr(logger, "warning", None)
446
+ if callable(warn):
447
+ try:
448
+ warn("Debug config:\n\t" + "\n\t".join(problems))
449
+ except Exception:
450
+ pass
451
+ return merged