batplot 1.8.47__tar.gz → 1.8.48__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 (219) hide show
  1. {batplot-1.8.47 → batplot-1.8.48}/PKG-INFO +1 -1
  2. {batplot-1.8.47 → batplot-1.8.48}/batplot/__init__.py +1 -1
  3. {batplot-1.8.47 → batplot-1.8.48}/batplot/data/CHANGELOG.md +4 -0
  4. batplot-1.8.48/batplot/data/latest_release_notes.json +7 -0
  5. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/batch_figure_io.py +11 -8
  6. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/batch_menu_io.py +1 -1
  7. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/common.py +1 -1
  8. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/menu_cpc.py +1 -1
  9. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/menu_ec.py +4 -35
  10. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/menu_histo.py +7 -5
  11. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/operando_batch_helpers.py +12 -10
  12. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/font_extras.py +14 -8
  13. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/menus.py +43 -28
  14. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/palettes.py +6 -1
  15. batplot-1.8.48/batplot/plot_modes/common/session_helpers.py +251 -0
  16. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/session_key_smoke.py +1 -1
  17. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/spines.py +10 -2
  18. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/cpc/__init__.py +2 -2
  19. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/cpc/interactive.py +6 -1229
  20. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/cpc/legend.py +22 -6
  21. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/cpc/routing.py +1 -1
  22. batplot-1.8.48/batplot/plot_modes/cpc/session.py +1006 -0
  23. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/cpc/snapshots.py +7 -5
  24. batplot-1.8.48/batplot/plot_modes/cpc/style.py +1274 -0
  25. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/__init__.py +2 -2
  26. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/dqdv_2d.py +4 -28
  27. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/interactive.py +1 -12
  28. batplot-1.8.48/batplot/plot_modes/electrochem/session.py +1207 -0
  29. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/style.py +3 -13
  30. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/__init__.py +2 -2
  31. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/interactive.py +2 -12
  32. batplot-1.8.48/batplot/plot_modes/operando/session.py +1056 -0
  33. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/style.py +3 -21
  34. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/style_apply.py +452 -348
  35. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/__init__.py +2 -2
  36. batplot-1.8.48/batplot/plot_modes/xy/axis_range.py +568 -0
  37. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/interactive.py +77 -22
  38. batplot-1.8.48/batplot/plot_modes/xy/session.py +1336 -0
  39. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/style.py +22 -23
  40. {batplot-1.8.47 → batplot-1.8.48}/batplot/readers.py +9 -374
  41. batplot-1.8.48/batplot/readers_xrd.py +401 -0
  42. batplot-1.8.48/batplot/session.py +107 -0
  43. {batplot-1.8.47 → batplot-1.8.48}/batplot/version_check.py +2 -7
  44. {batplot-1.8.47 → batplot-1.8.48}/batplot.egg-info/PKG-INFO +1 -1
  45. {batplot-1.8.47 → batplot-1.8.48}/batplot.egg-info/SOURCES.txt +4 -0
  46. {batplot-1.8.47 → batplot-1.8.48}/pyproject.toml +1 -1
  47. batplot-1.8.48/tests/test_cli_all_flags.py +154 -0
  48. {batplot-1.8.47 → batplot-1.8.48}/tests/test_contracts.py +16 -12
  49. {batplot-1.8.47 → batplot-1.8.48}/tests/test_ec_roundtrip.py +30 -0
  50. {batplot-1.8.47 → batplot-1.8.48}/tests/test_interactive_menu_smoke.py +22 -4
  51. {batplot-1.8.47 → batplot-1.8.48}/tests/test_xy_roundtrip.py +50 -0
  52. batplot-1.8.47/batplot/data/latest_release_notes.json +0 -12
  53. batplot-1.8.47/batplot/plot_modes/cpc/session.py +0 -23
  54. batplot-1.8.47/batplot/plot_modes/electrochem/session.py +0 -15
  55. batplot-1.8.47/batplot/plot_modes/operando/session.py +0 -15
  56. batplot-1.8.47/batplot/plot_modes/xy/axis_range.py +0 -611
  57. batplot-1.8.47/batplot/plot_modes/xy/session.py +0 -15
  58. batplot-1.8.47/batplot/session.py +0 -4791
  59. {batplot-1.8.47 → batplot-1.8.48}/DEVELOPING.md +0 -0
  60. {batplot-1.8.47 → batplot-1.8.48}/LICENSE +0 -0
  61. {batplot-1.8.47 → batplot-1.8.48}/MANIFEST.in +0 -0
  62. {batplot-1.8.47 → batplot-1.8.48}/NOTICE +0 -0
  63. {batplot-1.8.47 → batplot-1.8.48}/README.md +0 -0
  64. {batplot-1.8.47 → batplot-1.8.48}/batplot/_mpl_backend.py +0 -0
  65. {batplot-1.8.47 → batplot-1.8.48}/batplot/args.py +0 -0
  66. {batplot-1.8.47 → batplot-1.8.48}/batplot/batch.py +0 -0
  67. {batplot-1.8.47 → batplot-1.8.48}/batplot/batplot.py +0 -0
  68. {batplot-1.8.47 → batplot-1.8.48}/batplot/canvas_interactive.py +0 -0
  69. {batplot-1.8.47 → batplot-1.8.48}/batplot/cif.py +0 -0
  70. {batplot-1.8.47 → batplot-1.8.48}/batplot/cli.py +0 -0
  71. {batplot-1.8.47 → batplot-1.8.48}/batplot/cli_save.py +0 -0
  72. {batplot-1.8.47 → batplot-1.8.48}/batplot/color_utils.py +0 -0
  73. {batplot-1.8.47 → batplot-1.8.48}/batplot/config.py +0 -0
  74. {batplot-1.8.47 → batplot-1.8.48}/batplot/converters.py +0 -0
  75. {batplot-1.8.47 → batplot-1.8.48}/batplot/dev_upgrade.py +0 -0
  76. {batplot-1.8.47 → batplot-1.8.48}/batplot/ec_common.py +0 -0
  77. {batplot-1.8.47 → batplot-1.8.48}/batplot/modes.py +0 -0
  78. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/__init__.py +0 -0
  79. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/__init__.py +0 -0
  80. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/batch_commands.py +0 -0
  81. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/batch_crosshair.py +0 -0
  82. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/batch_geom_helpers.py +0 -0
  83. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/batch_io.py +0 -0
  84. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/batch_menu_helpers.py +0 -0
  85. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/batch_panel_state.py +0 -0
  86. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/cpc_batch_helpers.py +0 -0
  87. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/ec_batch_helpers.py +0 -0
  88. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/histo_batch_helpers.py +0 -0
  89. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/kinds.py +0 -0
  90. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/load.py +0 -0
  91. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/menu_operando.py +0 -0
  92. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/menu_xy.py +0 -0
  93. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/routing.py +0 -0
  94. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/batch_session/xy_batch_helpers.py +0 -0
  95. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/__init__.py +0 -0
  96. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/axis_state.py +0 -0
  97. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/batch_font.py +0 -0
  98. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/crosshair_export.py +0 -0
  99. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/files.py +0 -0
  100. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/fonts.py +0 -0
  101. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/interactive_state.py +0 -0
  102. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/menu_rendering.py +0 -0
  103. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/size_spec.py +0 -0
  104. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/smoothing.py +0 -0
  105. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/sources.py +0 -0
  106. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/state_capture.py +0 -0
  107. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/style_routing.py +0 -0
  108. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/terminal.py +0 -0
  109. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/common/title_offsets.py +0 -0
  110. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/cpc/actions.py +0 -0
  111. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/cpc/colors.py +0 -0
  112. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/cpc/labels.py +0 -0
  113. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/cpc/menu.py +0 -0
  114. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/actions.py +0 -0
  115. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/colors.py +0 -0
  116. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/export.py +0 -0
  117. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/labels.py +0 -0
  118. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/legend.py +0 -0
  119. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/legend_order.py +0 -0
  120. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/line_style.py +0 -0
  121. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/menu.py +0 -0
  122. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/routing.py +0 -0
  123. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/spine_colors.py +0 -0
  124. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/electrochem/style_apply.py +0 -0
  125. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/__init__.py +0 -0
  126. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/actions.py +0 -0
  127. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/colors.py +0 -0
  128. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/density_curve.py +0 -0
  129. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/fonts.py +0 -0
  130. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/interactive.py +0 -0
  131. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/labels.py +0 -0
  132. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/line_style.py +0 -0
  133. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/load.py +0 -0
  134. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/plot.py +0 -0
  135. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/routing.py +0 -0
  136. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/session.py +0 -0
  137. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/spines.py +0 -0
  138. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/toggles.py +0 -0
  139. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/wizard.py +0 -0
  140. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/histo/y_range.py +0 -0
  141. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/actions.py +0 -0
  142. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/colors.py +0 -0
  143. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/grid.py +0 -0
  144. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/ions_axis.py +0 -0
  145. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/labels.py +0 -0
  146. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/layout.py +0 -0
  147. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/layout_menu.py +0 -0
  148. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/line_style.py +0 -0
  149. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/menu.py +0 -0
  150. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/peaks.py +0 -0
  151. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/plot.py +0 -0
  152. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/routing.py +0 -0
  153. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/operando/visibility.py +0 -0
  154. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/session_routing.py +0 -0
  155. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/actions.py +0 -0
  156. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/arrange.py +0 -0
  157. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/cif.py +0 -0
  158. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/colors.py +0 -0
  159. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/data_ops.py +0 -0
  160. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/derivative.py +0 -0
  161. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/game.py +0 -0
  162. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/labels.py +0 -0
  163. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/line_style.py +0 -0
  164. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/menu.py +0 -0
  165. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/peaks.py +0 -0
  166. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/pipeline.py +0 -0
  167. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/smoothing.py +0 -0
  168. {batplot-1.8.47 → batplot-1.8.48}/batplot/plot_modes/xy/spines.py +0 -0
  169. {batplot-1.8.47 → batplot-1.8.48}/batplot/plotting.py +0 -0
  170. {batplot-1.8.47 → batplot-1.8.48}/batplot/showcol.py +0 -0
  171. {batplot-1.8.47 → batplot-1.8.48}/batplot/style.py +0 -0
  172. {batplot-1.8.47 → batplot-1.8.48}/batplot/ui.py +0 -0
  173. {batplot-1.8.47 → batplot-1.8.48}/batplot/utils.py +0 -0
  174. {batplot-1.8.47 → batplot-1.8.48}/batplot.egg-info/dependency_links.txt +0 -0
  175. {batplot-1.8.47 → batplot-1.8.48}/batplot.egg-info/entry_points.txt +0 -0
  176. {batplot-1.8.47 → batplot-1.8.48}/batplot.egg-info/requires.txt +0 -0
  177. {batplot-1.8.47 → batplot-1.8.48}/batplot.egg-info/top_level.txt +0 -0
  178. {batplot-1.8.47 → batplot-1.8.48}/setup.cfg +0 -0
  179. {batplot-1.8.47 → batplot-1.8.48}/setup.py +0 -0
  180. {batplot-1.8.47 → batplot-1.8.48}/tests/test_batch_all_modes_sync.py +0 -0
  181. {batplot-1.8.47 → batplot-1.8.48}/tests/test_batch_crosshair.py +0 -0
  182. {batplot-1.8.47 → batplot-1.8.48}/tests/test_batch_ec_cycles_status.py +0 -0
  183. {batplot-1.8.47 → batplot-1.8.48}/tests/test_batch_font_menu.py +0 -0
  184. {batplot-1.8.47 → batplot-1.8.48}/tests/test_batch_geom_menu.py +0 -0
  185. {batplot-1.8.47 → batplot-1.8.48}/tests/test_batch_menu_parity.py +0 -0
  186. {batplot-1.8.47 → batplot-1.8.48}/tests/test_batch_panel_status.py +0 -0
  187. {batplot-1.8.47 → batplot-1.8.48}/tests/test_batch_pisb_contract.py +0 -0
  188. {batplot-1.8.47 → batplot-1.8.48}/tests/test_batch_session.py +0 -0
  189. {batplot-1.8.47 → batplot-1.8.48}/tests/test_batch_spine_sync.py +0 -0
  190. {batplot-1.8.47 → batplot-1.8.48}/tests/test_bruker_intensity.py +0 -0
  191. {batplot-1.8.47 → batplot-1.8.48}/tests/test_cli_save.py +0 -0
  192. {batplot-1.8.47 → batplot-1.8.48}/tests/test_cli_smoke.py +0 -0
  193. {batplot-1.8.47 → batplot-1.8.48}/tests/test_color_listing_visible.py +0 -0
  194. {batplot-1.8.47 → batplot-1.8.48}/tests/test_color_utils.py +0 -0
  195. {batplot-1.8.47 → batplot-1.8.48}/tests/test_common_files.py +0 -0
  196. {batplot-1.8.47 → batplot-1.8.48}/tests/test_common_palettes.py +0 -0
  197. {batplot-1.8.47 → batplot-1.8.48}/tests/test_cpc_roundtrip.py +0 -0
  198. {batplot-1.8.47 → batplot-1.8.48}/tests/test_critical_stability_fixes.py +0 -0
  199. {batplot-1.8.47 → batplot-1.8.48}/tests/test_cross_platform_parity.py +0 -0
  200. {batplot-1.8.47 → batplot-1.8.48}/tests/test_crosshair_export.py +0 -0
  201. {batplot-1.8.47 → batplot-1.8.48}/tests/test_csv_readers.py +0 -0
  202. {batplot-1.8.47 → batplot-1.8.48}/tests/test_dev_upgrade.py +0 -0
  203. {batplot-1.8.47 → batplot-1.8.48}/tests/test_dqdv_contour_session_keys.py +0 -0
  204. {batplot-1.8.47 → batplot-1.8.48}/tests/test_histo.py +0 -0
  205. {batplot-1.8.47 → batplot-1.8.48}/tests/test_histo_interactive_imports.py +0 -0
  206. {batplot-1.8.47 → batplot-1.8.48}/tests/test_imk_stderr_guard.py +0 -0
  207. {batplot-1.8.47 → batplot-1.8.48}/tests/test_interactive_state.py +0 -0
  208. {batplot-1.8.47 → batplot-1.8.48}/tests/test_menu_handler_imports.py +0 -0
  209. {batplot-1.8.47 → batplot-1.8.48}/tests/test_menu_prompt_order.py +0 -0
  210. {batplot-1.8.47 → batplot-1.8.48}/tests/test_mpl_backend.py +0 -0
  211. {batplot-1.8.47 → batplot-1.8.48}/tests/test_operando_batch_menu.py +0 -0
  212. {batplot-1.8.47 → batplot-1.8.48}/tests/test_operando_layout_menu.py +0 -0
  213. {batplot-1.8.47 → batplot-1.8.48}/tests/test_operando_roundtrip.py +0 -0
  214. {batplot-1.8.47 → batplot-1.8.48}/tests/test_session_backward_compat.py +0 -0
  215. {batplot-1.8.47 → batplot-1.8.48}/tests/test_session_font_restore.py +0 -0
  216. {batplot-1.8.47 → batplot-1.8.48}/tests/test_state_capture.py +0 -0
  217. {batplot-1.8.47 → batplot-1.8.48}/tests/test_style_routing.py +0 -0
  218. {batplot-1.8.47 → batplot-1.8.48}/tests/test_xy_modules.py +0 -0
  219. {batplot-1.8.47 → batplot-1.8.48}/tests/test_xy_source_files.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batplot
3
- Version: 1.8.47
3
+ Version: 1.8.48
4
4
  Summary: Interactive plotting tool for material science (1D plot) and electrochemistry (GC, CV, dQ/dV, CPC, operando) with batch processing
5
5
  Author-email: Tian Dai <tianda@uio.no>
6
6
  License: MIT License
@@ -7,7 +7,7 @@ import importlib.abc
7
7
  import importlib.machinery
8
8
  import sys
9
9
 
10
- __version__ = "1.8.47"
10
+ __version__ = "1.8.48"
11
11
 
12
12
 
13
13
  _LEGACY_MODULE_ALIASES = {
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.8.48] - 2026-07-29
4
+ - Bug fixes on session reload
5
+
6
+
3
7
  ## [1.8.47] - 2026-07-21
4
8
  - Added Batch Interactive mode, loading multiple saved .pkl sessions
5
9
  (must be the same type, e.g All are GC) to edit basic styles and
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": "1.8.48",
3
+ "custom_message": "- Bug fixes on session reload",
4
+ "update_notes": [
5
+ "- Bug fixes on session reload"
6
+ ]
7
+ }
@@ -26,17 +26,20 @@ def save_standard_panel_figure(
26
26
  """Save a panel figure with SVG transparency handling (shared by batch export)."""
27
27
  path = ensure_exact_case_filename(path)
28
28
  _, ext = os.path.splitext(path)
29
- owners: list[tuple[Any, Any | None]] = [(fig, getattr(fig, "patch", None)), (ax, getattr(ax, "patch", None))]
30
- for extra in extra_axes:
31
- if extra is not None:
32
- owners.append((extra, getattr(extra, "patch", None)))
29
+ # Collect only real patches so restore never sees Optional patch/owner.
30
+ patch_owners: list[tuple[Any, Any]] = []
31
+ for owner in (fig, ax, *extra_axes):
32
+ if owner is None:
33
+ continue
34
+ patch = getattr(owner, "patch", None)
35
+ if patch is None:
36
+ continue
37
+ patch_owners.append((owner, patch))
33
38
 
34
39
  if ext.lower() == ".svg":
35
- saved: list[tuple[Any, Any | None, Any]] = []
40
+ saved: list[tuple[Any, Any, Any]] = []
36
41
  try:
37
- for owner, patch in owners:
38
- if patch is None:
39
- continue
42
+ for owner, patch in patch_owners:
40
43
  try:
41
44
  fc = owner.get_facecolor() if owner is fig else patch.get_facecolor()
42
45
  except Exception:
@@ -61,7 +61,7 @@ def batch_import_style(
61
61
  *,
62
62
  path_prompt: str,
63
63
  load_style: Callable[[str], Any],
64
- apply_style: Callable[[Any, Any], None],
64
+ apply_style: Callable[[Any, Any], bool | None],
65
65
  prepare: Callable[[list[int]], None] | None = None,
66
66
  on_applied: Callable[[list[int], str], None] | None = None,
67
67
  ) -> list[int] | None:
@@ -34,7 +34,7 @@ class SyncUndoStacks:
34
34
  """True when at least one panel has more than the baseline snapshot (index 0)."""
35
35
  return any(len(s) > 1 for s in self._stacks)
36
36
 
37
- def undo_all(self, restore_fn: Callable[[int, Any], None]) -> bool:
37
+ def undo_all(self, restore_fn: Callable[[int, Any], object]) -> bool:
38
38
  if not self.can_undo():
39
39
  print("No undo history.")
40
40
  return False
@@ -16,7 +16,7 @@ from ..common.menus import run_legend_position_menu
16
16
  from ..common.spines import apply_frame_and_tick_widths, parse_frame_tick_widths
17
17
  from ..common.terminal import colorize_prompt, safe_input
18
18
  from ..cpc.colors import run_cpc_color_menu
19
- from ..cpc.interactive import _apply_style, _style_snapshot
19
+ from ..cpc.style import _apply_style, _style_snapshot
20
20
  from ..cpc.labels import run_cpc_rename_menu
21
21
  from ..cpc.legend import (
22
22
  _rebuild_legend,
@@ -69,6 +69,7 @@ from .batch_menu_helpers import (
69
69
  )
70
70
  from .common import SyncUndoStacks, draw_panels, print_batch_header, set_all_panel_figure_titles
71
71
  from .ec_batch_helpers import (
72
+ default_ec_tick_state,
72
73
  ec_all_cycles,
73
74
  ec_apply_display_mode,
74
75
  ec_apply_nice_ticks,
@@ -76,6 +77,7 @@ from .ec_batch_helpers import (
76
77
  ec_normalize_file_data,
77
78
  ec_print_file_list_factory,
78
79
  ec_run_file_visibility_menu,
80
+ ec_tick_state_from_fig,
79
81
  edit_ref_then_sync,
80
82
  ensure_ec_fig_state,
81
83
  noop_snapshot,
@@ -87,44 +89,11 @@ from .load import EcPanel
87
89
 
88
90
 
89
91
  def _default_tick_state() -> dict:
90
- return {
91
- "bx": True,
92
- "tx": False,
93
- "ly": True,
94
- "ry": False,
95
- "mbx": False,
96
- "mtx": False,
97
- "mly": False,
98
- "mry": False,
99
- }
92
+ return default_ec_tick_state()
100
93
 
101
94
 
102
95
  def _tick_state_from_fig(fig) -> dict:
103
- wasd = getattr(fig, "_ec_wasd_state", None)
104
- if isinstance(wasd, dict):
105
- top = wasd.get("top", {})
106
- bot = wasd.get("bottom", {})
107
- left = wasd.get("left", {})
108
- right = wasd.get("right", {})
109
- return {
110
- "bx": bool(bot.get("ticks", True)),
111
- "tx": bool(top.get("ticks", False)),
112
- "ly": bool(left.get("ticks", True)),
113
- "ry": bool(right.get("ticks", False)),
114
- "mbx": bool(bot.get("minor", False)),
115
- "mtx": bool(top.get("minor", False)),
116
- "mly": bool(left.get("minor", False)),
117
- "mry": bool(right.get("minor", False)),
118
- "b_ticks": bool(bot.get("ticks", True)),
119
- "t_ticks": bool(top.get("ticks", False)),
120
- "l_ticks": bool(left.get("ticks", True)),
121
- "r_ticks": bool(right.get("ticks", False)),
122
- "b_labels": bool(bot.get("labels", True)),
123
- "t_labels": bool(top.get("labels", False)),
124
- "l_labels": bool(left.get("labels", True)),
125
- "r_labels": bool(right.get("labels", False)),
126
- }
127
- return _default_tick_state()
96
+ return ec_tick_state_from_fig(fig)
128
97
 
129
98
 
130
99
  def _ec_batch_has_multi_file(panels: List[EcPanel]) -> bool:
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import json
6
6
  import os
7
- from typing import List
7
+ from typing import Any, List
8
8
 
9
9
  from ..common.files import confirm_previous_path
10
10
  from ..common.menu_rendering import colorize_menu_item as _colorize_menu, print_menu_columns, prompt_menu_key
@@ -15,7 +15,7 @@ from ..histo.colors import run_histo_color_menu
15
15
  from ..histo.fonts import run_histo_font_menu, sync_histo_font_rcparams
16
16
  from ..histo.interactive import _export_style, _export_figure
17
17
  from ..histo.load import load_table
18
- from ..histo.plot import normalize_histo_title, refresh_histo_figure
18
+ from ..histo.plot import HistoState, normalize_histo_title, refresh_histo_figure
19
19
  from ..histo.session import apply_histo_snapshot, apply_histo_style_snapshot, capture_histo_snapshot, save_histo_session
20
20
  from ..histo.toggles import run_histo_toggle_menu
21
21
  from ..histo.wizard import HistoSetup, run_histo_wizard
@@ -196,11 +196,13 @@ def run_histo_batch_menu(panels: List[HistoPanel]) -> None:
196
196
  continue
197
197
 
198
198
  if cmd == "l":
199
- sync_targets = [(p.fig, p.ax, p.state) for p in panels[1:]]
199
+ line_sync_targets: list[tuple[Any, Any, HistoState]] = [
200
+ (p.fig, p.ax, p.state) for p in panels[1:]
201
+ ]
200
202
 
201
203
  def _apply_ref_line_style_to_all() -> None:
202
- if sync_targets:
203
- sync_histo_line_style_from_reference(ref.ax, ref.state, sync_targets)
204
+ if line_sync_targets:
205
+ sync_histo_line_style_from_reference(ref.ax, ref.state, line_sync_targets)
204
206
  _refresh_all()
205
207
 
206
208
  run_histo_line_style_menu(
@@ -3,7 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import json
6
- from typing import Callable, List, Sequence
6
+ from typing import Callable, List, Sequence, TypeVar
7
7
 
8
8
  from ..common.spines import (
9
9
  apply_frame_and_tick_widths,
@@ -31,6 +31,8 @@ from .batch_menu_helpers import prompt_axis_limits
31
31
  from .common import SyncUndoStacks
32
32
  from .load import OperandoPanel
33
33
 
34
+ PanelT = TypeVar("PanelT")
35
+
34
36
 
35
37
  def _cfg_signature(cfg: dict) -> str:
36
38
  try:
@@ -96,11 +98,11 @@ def _label_only_axes_geometry(axes_geom: dict | None) -> dict | None:
96
98
 
97
99
 
98
100
  def sync_style_from_ref(
99
- ref: OperandoPanel,
100
- panels: Sequence[OperandoPanel],
101
+ ref: PanelT,
102
+ panels: Sequence[PanelT],
101
103
  *,
102
- capture_panel: Callable[[OperandoPanel], dict],
103
- apply_cfg: Callable[[OperandoPanel, dict], bool],
104
+ capture_panel: Callable[[PanelT], dict],
105
+ apply_cfg: Callable[..., bool | None],
104
106
  include_geometry: bool = False,
105
107
  ) -> None:
106
108
  """Copy style (+ optional geometry) from the reference panel onto every other panel.
@@ -138,14 +140,14 @@ def sync_style_from_ref(
138
140
 
139
141
 
140
142
  def edit_ref_then_sync(
141
- ref: OperandoPanel,
142
- panels: List[OperandoPanel],
143
+ ref: PanelT,
144
+ panels: List[PanelT],
143
145
  *,
144
146
  undo: SyncUndoStacks,
145
- capture_panel: Callable[[OperandoPanel], dict],
146
- apply_cfg: Callable[[OperandoPanel, dict], bool],
147
+ capture_panel: Callable[[PanelT], dict],
148
+ apply_cfg: Callable[..., bool | None],
147
149
  draw_all: Callable[[], None],
148
- edit_fn: Callable[[], None],
150
+ edit_fn: Callable[..., object],
149
151
  include_geometry: bool = False,
150
152
  ) -> None:
151
153
  """Run a ref-only editor, then push one undo point and sync style to all panels.
@@ -133,11 +133,13 @@ def apply_font_extras_from_cfg(fig: Any, artists: Iterable[Any], cfg: dict[str,
133
133
  highlight = cfg.get("highlight")
134
134
  if highlight is not None:
135
135
  try:
136
- alpha = float(cfg.get("highlight_alpha", DEFAULT_HIGHLIGHT_ALPHA))
136
+ alpha_raw = cfg.get("highlight_alpha", DEFAULT_HIGHLIGHT_ALPHA)
137
+ alpha = float(alpha_raw) if isinstance(alpha_raw, (int, float, str)) else DEFAULT_HIGHLIGHT_ALPHA
137
138
  except (TypeError, ValueError):
138
139
  alpha = DEFAULT_HIGHLIGHT_ALPHA
139
140
  try:
140
- pad = float(cfg.get("highlight_pad", DEFAULT_HIGHLIGHT_PAD))
141
+ pad_raw = cfg.get("highlight_pad", DEFAULT_HIGHLIGHT_PAD)
142
+ pad = float(pad_raw) if isinstance(pad_raw, (int, float, str)) else DEFAULT_HIGHLIGHT_PAD
141
143
  except (TypeError, ValueError):
142
144
  pad = DEFAULT_HIGHLIGHT_PAD
143
145
  fc = cfg.get("highlight_fc", DEFAULT_HIGHLIGHT_FC)
@@ -193,7 +195,9 @@ def sync_font_rcparams_from_cfg(font_cfg: dict[str, object] | None) -> None:
193
195
  elif fam:
194
196
  set_font_family_defaults(fam, sans_serif_stack=True, update_mathtext=True)
195
197
  if font_cfg.get("size") is not None:
196
- set_font_size_default(float(font_cfg["size"]))
198
+ size_raw = font_cfg["size"]
199
+ if isinstance(size_raw, (int, float, str)):
200
+ set_font_size_default(float(size_raw))
197
201
  if font_cfg.get("mathtext_fontset"):
198
202
  mpl.rcParams["mathtext.fontset"] = font_cfg["mathtext_fontset"]
199
203
 
@@ -244,11 +248,13 @@ def apply_session_font_cfg(
244
248
  if fam:
245
249
  apply_font_family_to_artists(collected, fam)
246
250
  if font_cfg.get("size") is not None:
247
- sz = float(font_cfg["size"])
248
- apply_font_size_to_artists(collected, sz)
249
- for ax in axes:
250
- if ax is not None:
251
- sync_legend_title_fontsize(ax.get_legend(), sz)
251
+ size_raw = font_cfg["size"]
252
+ if isinstance(size_raw, (int, float, str)):
253
+ sz = float(size_raw)
254
+ apply_font_size_to_artists(collected, sz)
255
+ for ax in axes:
256
+ if ax is not None:
257
+ sync_legend_title_fontsize(ax.get_legend(), sz)
252
258
  apply_font_extras_from_cfg(fig, collected, font_cfg)
253
259
 
254
260
 
@@ -70,7 +70,7 @@ def run_font_menu(
70
70
  fonts: Optional[list[str]] = None,
71
71
  blank_exits: bool = True,
72
72
  get_current_weight: Callable[[], object] | None = None,
73
- apply_weight: Callable[[str], None] | None = None,
73
+ apply_weight: Callable[[str], object] | None = None,
74
74
  get_current_highlight: Callable[[], bool] | None = None,
75
75
  get_highlight_style: Callable[[], dict] | None = None,
76
76
  apply_highlight_toggle: Callable[[], None] | None = None,
@@ -84,31 +84,33 @@ def run_font_menu(
84
84
  different artists to update (legends, duplicate titles, secondary axes).
85
85
  """
86
86
  fonts = fonts or DEFAULT_FONT_FAMILIES
87
- has_weight = apply_weight is not None and get_current_weight is not None
88
- has_highlight = (
89
- apply_highlight_toggle is not None
90
- and get_current_highlight is not None
91
- and get_highlight_style is not None
92
- )
93
87
  while True:
94
88
  status = f"family='{get_current_family()}', size={get_current_size()}"
95
- if has_weight:
89
+ if get_current_weight is not None:
96
90
  status += f", weight={get_current_weight()}"
97
- if has_highlight:
91
+ if get_current_highlight is not None:
98
92
  on = "on" if get_current_highlight() else "off"
99
93
  status += f", highlight={on}"
100
94
  print(f"\nFont (current: {status})")
101
95
  print(" " + colorize_menu("f: family"))
102
96
  print(" " + colorize_menu("s: size"))
103
- if has_weight:
97
+ if apply_weight is not None and get_current_weight is not None:
104
98
  print(" " + colorize_menu("b: bold / weight"))
105
- if has_highlight:
99
+ if (
100
+ apply_highlight_toggle is not None
101
+ and get_current_highlight is not None
102
+ and get_highlight_style is not None
103
+ ):
106
104
  print(" " + colorize_menu("h: text highlight (bbox behind labels)"))
107
105
  print(" " + colorize_menu("q: back"))
108
106
  keys = "f/s"
109
- if has_weight:
107
+ if apply_weight is not None and get_current_weight is not None:
110
108
  keys += "/b"
111
- if has_highlight:
109
+ if (
110
+ apply_highlight_toggle is not None
111
+ and get_current_highlight is not None
112
+ and get_highlight_style is not None
113
+ ):
112
114
  keys += "/h"
113
115
  keys += "/q"
114
116
  sub = safe_input(colorize_prompt(f"Font ({keys}): ")).strip().lower()
@@ -174,12 +176,14 @@ def run_font_menu(
174
176
  process=_apply_size_choice,
175
177
  )
176
178
  continue
177
- if sub == "b" and has_weight:
179
+ if sub == "b" and apply_weight is not None and get_current_weight is not None:
180
+ weight_getter = get_current_weight
181
+ weight_applier = apply_weight
178
182
 
179
183
  def _apply_weight_choice(choice: str) -> bool:
180
184
  raw = choice.strip().lower()
181
185
  if not raw:
182
- new_w = "normal" if str(get_current_weight()).lower() == "bold" else "bold"
186
+ new_w = "normal" if str(weight_getter()).lower() == "bold" else "bold"
183
187
  elif raw in ("bold", "b"):
184
188
  new_w = "bold"
185
189
  elif raw in ("normal", "n", "regular", "r"):
@@ -188,24 +192,32 @@ def run_font_menu(
188
192
  print("Use bold, normal, or blank to toggle.")
189
193
  return False
190
194
  try:
191
- apply_weight(new_w)
195
+ weight_applier(new_w)
192
196
  print(f"Applied font weight: {new_w}")
193
197
  except Exception as exc:
194
198
  print(f"Error changing font weight: {exc}")
195
199
  return True
196
200
 
197
201
  run_repeat_input_loop(
198
- prompt=lambda: f"Font weight (current: {get_current_weight()}, bold/normal/blank=toggle, q=back): ",
202
+ prompt=lambda: f"Font weight (current: {weight_getter()}, bold/normal/blank=toggle, q=back): ",
199
203
  safe_input=safe_input,
200
204
  colorize_prompt=colorize_prompt,
201
205
  process=_apply_weight_choice,
202
206
  cancel_on_blank=False,
203
207
  )
204
208
  continue
205
- if sub == "h" and has_highlight:
209
+ if (
210
+ sub == "h"
211
+ and apply_highlight_toggle is not None
212
+ and get_current_highlight is not None
213
+ and get_highlight_style is not None
214
+ ):
215
+ hl_toggle = apply_highlight_toggle
216
+ hl_get = get_current_highlight
217
+ hl_style = get_highlight_style
206
218
  while True:
207
- st = get_highlight_style()
208
- on = "on" if get_current_highlight() else "off"
219
+ st = hl_style()
220
+ on = "on" if hl_get() else "off"
209
221
  print(f"\nText highlight (current: {on}, face={st.get('fc', 'white')}, alpha={st.get('alpha', 0.85):g}, pad={st.get('pad', 0.2):g})")
210
222
  print(" " + colorize_menu("t: toggle on/off"))
211
223
  print(" " + colorize_menu("c: face color (e.g. white, #f8f8f8)"))
@@ -217,29 +229,31 @@ def run_font_menu(
217
229
  break
218
230
  if hsub == "t":
219
231
  try:
220
- apply_highlight_toggle()
221
- print(f"Text highlight {'on' if get_current_highlight() else 'off'}.")
232
+ hl_toggle()
233
+ print(f"Text highlight {'on' if hl_get() else 'off'}.")
222
234
  except Exception as exc:
223
235
  print(f"Error toggling highlight: {exc}")
224
236
  continue
225
237
  if hsub == "c" and apply_highlight_facecolor is not None:
238
+ hl_facecolor = apply_highlight_facecolor
226
239
 
227
240
  def _apply_hl_color(spec: str) -> bool:
228
241
  try:
229
- apply_highlight_facecolor(spec)
242
+ hl_facecolor(spec)
230
243
  print(f"Highlight face color set to {spec}.")
231
244
  except Exception as exc:
232
245
  print(f"Error: {exc}")
233
246
  return True
234
247
 
235
248
  run_repeat_input_loop(
236
- prompt=lambda: f"Highlight face color (current: {get_highlight_style().get('fc', 'white')}, q=back): ",
249
+ prompt=lambda: f"Highlight face color (current: {hl_style().get('fc', 'white')}, q=back): ",
237
250
  safe_input=safe_input,
238
251
  colorize_prompt=colorize_prompt,
239
252
  process=_apply_hl_color,
240
253
  )
241
254
  continue
242
255
  if hsub == "a" and apply_highlight_alpha is not None:
256
+ hl_alpha = apply_highlight_alpha
243
257
 
244
258
  def _apply_hl_alpha(raw: str) -> bool:
245
259
  try:
@@ -251,20 +265,21 @@ def run_font_menu(
251
265
  print("Alpha must be between 0 and 1.")
252
266
  return False
253
267
  try:
254
- apply_highlight_alpha(val)
268
+ hl_alpha(val)
255
269
  print(f"Highlight alpha set to {val:g}.")
256
270
  except Exception as exc:
257
271
  print(f"Error: {exc}")
258
272
  return True
259
273
 
260
274
  run_repeat_input_loop(
261
- prompt=lambda: f"Highlight alpha (current: {get_highlight_style().get('alpha', 0.85):g}, q=back): ",
275
+ prompt=lambda: f"Highlight alpha (current: {hl_style().get('alpha', 0.85):g}, q=back): ",
262
276
  safe_input=safe_input,
263
277
  colorize_prompt=colorize_prompt,
264
278
  process=_apply_hl_alpha,
265
279
  )
266
280
  continue
267
281
  if hsub == "p" and apply_highlight_pad is not None:
282
+ hl_pad = apply_highlight_pad
268
283
 
269
284
  def _apply_hl_pad(raw: str) -> bool:
270
285
  try:
@@ -276,14 +291,14 @@ def run_font_menu(
276
291
  print("Pad must be non-negative.")
277
292
  return False
278
293
  try:
279
- apply_highlight_pad(val)
294
+ hl_pad(val)
280
295
  print(f"Highlight pad set to {val:g}.")
281
296
  except Exception as exc:
282
297
  print(f"Error: {exc}")
283
298
  return True
284
299
 
285
300
  run_repeat_input_loop(
286
- prompt=lambda: f"Highlight pad (current: {get_highlight_style().get('pad', 0.2):g}, q=back): ",
301
+ prompt=lambda: f"Highlight pad (current: {hl_style().get('pad', 0.2):g}, q=back): ",
287
302
  safe_input=safe_input,
288
303
  colorize_prompt=colorize_prompt,
289
304
  process=_apply_hl_pad,
@@ -189,7 +189,12 @@ def sample_palette_colors(
189
189
  except Exception:
190
190
  ensure_colormap("viridis")
191
191
  cmap = cmap_getter("viridis")
192
- if prefer_listed_colors and hasattr(cmap, "colors") and cmap.colors is not None:
192
+ if (
193
+ prefer_listed_colors
194
+ and cmap is not None
195
+ and hasattr(cmap, "colors")
196
+ and getattr(cmap, "colors", None) is not None
197
+ ):
193
198
  colors = cmap.colors
194
199
  out = []
195
200
  for i in range(n):