batplot 1.8.53__tar.gz → 1.8.55__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 (348) hide show
  1. {batplot-1.8.53 → batplot-1.8.55}/PKG-INFO +2 -2
  2. {batplot-1.8.53 → batplot-1.8.55}/README.md +1 -1
  3. {batplot-1.8.53 → batplot-1.8.55}/batplot/__init__.py +1 -1
  4. {batplot-1.8.53 → batplot-1.8.55}/batplot/args.py +69 -8
  5. {batplot-1.8.53 → batplot-1.8.55}/batplot/data/CHANGELOG.md +11 -0
  6. {batplot-1.8.53 → batplot-1.8.55}/batplot/data/latest_release_notes.json +1 -1
  7. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_commands.py +18 -14
  8. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_menu_io.py +12 -5
  9. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_cpc.py +4 -1
  10. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_dqdv_2d.py +4 -1
  11. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_ec.py +4 -1
  12. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_histo.py +4 -1
  13. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_operando.py +4 -1
  14. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_xy.py +75 -36
  15. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/xy_batch_helpers.py +14 -2
  16. batplot-1.8.55/batplot/plot_modes/common/color_menu_help.py +228 -0
  17. batplot-1.8.55/batplot/plot_modes/common/curve_look_help.py +140 -0
  18. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/fonts.py +16 -1
  19. batplot-1.8.55/batplot/plot_modes/common/layout_compat.py +515 -0
  20. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/menu_rendering.py +61 -6
  21. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/palettes.py +18 -0
  22. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/spines.py +120 -4
  23. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/style_routing.py +2 -2
  24. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/terminal.py +37 -0
  25. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/actions.py +6 -10
  26. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/colors.py +80 -41
  27. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/interactive.py +22 -10
  28. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/labels.py +13 -7
  29. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/panel_menus.py +42 -12
  30. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/session.py +17 -15
  31. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/style.py +65 -18
  32. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/wasd_menu.py +9 -1
  33. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/actions.py +4 -9
  34. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/colors.py +36 -41
  35. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/interactive.py +26 -13
  36. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/labels.py +13 -7
  37. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/line_style.py +19 -10
  38. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/session.py +64 -8
  39. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/spine_colors.py +26 -16
  40. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/style.py +57 -0
  41. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/style_apply.py +38 -21
  42. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/undo_state.py +6 -0
  43. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/colors.py +36 -26
  44. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/density_curve.py +9 -4
  45. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/interactive.py +27 -14
  46. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/labels.py +18 -3
  47. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/line_style.py +10 -5
  48. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/session.py +2 -2
  49. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/spines.py +12 -4
  50. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/actions.py +2 -2
  51. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/cif_menu.py +3 -0
  52. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/colors.py +58 -38
  53. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/interactive.py +63 -12
  54. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/labels.py +21 -10
  55. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/layout.py +6 -0
  56. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/line_style.py +35 -25
  57. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/plot.py +19 -0
  58. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/session.py +27 -0
  59. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/spine_colors.py +36 -27
  60. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/style.py +140 -24
  61. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/style_apply.py +52 -15
  62. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/undo_state.py +14 -0
  63. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/arrange.py +33 -49
  64. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/axis_units.py +17 -8
  65. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/cif.py +49 -13
  66. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/colors.py +60 -43
  67. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/interactive.py +19 -16
  68. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/labels.py +25 -4
  69. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/line_style.py +19 -10
  70. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/pipeline.py +5 -2
  71. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/session.py +39 -12
  72. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/spines.py +64 -5
  73. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/style.py +217 -86
  74. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/undo_state.py +26 -10
  75. {batplot-1.8.53 → batplot-1.8.55}/batplot/ui.py +233 -21
  76. {batplot-1.8.53 → batplot-1.8.55}/batplot/utils.py +57 -4
  77. {batplot-1.8.53 → batplot-1.8.55}/batplot.egg-info/PKG-INFO +2 -2
  78. {batplot-1.8.53 → batplot-1.8.55}/batplot.egg-info/SOURCES.txt +11 -0
  79. {batplot-1.8.53 → batplot-1.8.55}/pyproject.toml +1 -1
  80. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_session.py +2 -2
  81. batplot-1.8.55/tests/test_batch_spine_sync.py +204 -0
  82. {batplot-1.8.53 → batplot-1.8.55}/tests/test_contracts.py +30 -0
  83. {batplot-1.8.53 → batplot-1.8.55}/tests/test_cpc_canvas_undo.py +7 -5
  84. batplot-1.8.55/tests/test_curve_look_help.py +95 -0
  85. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_noninteractive_bugs.py +58 -4
  86. {batplot-1.8.53 → batplot-1.8.55}/tests/test_ec_cpc_geometry_pisb_keys.py +7 -6
  87. {batplot-1.8.53 → batplot-1.8.55}/tests/test_histo_geometry_pisb_keys.py +7 -8
  88. {batplot-1.8.53 → batplot-1.8.55}/tests/test_histo_style_pisb_keys.py +7 -8
  89. {batplot-1.8.53 → batplot-1.8.55}/tests/test_label_shortcuts_math_help.py +31 -0
  90. batplot-1.8.55/tests/test_line_submenu_pisb_widths.py +156 -0
  91. {batplot-1.8.53 → batplot-1.8.55}/tests/test_menu_rendering_presentation.py +22 -5
  92. {batplot-1.8.53 → batplot-1.8.55}/tests/test_operando_cif_color.py +6 -6
  93. {batplot-1.8.53 → batplot-1.8.55}/tests/test_operando_geometry_pisb_keys.py +1 -1
  94. {batplot-1.8.53 → batplot-1.8.55}/tests/test_operando_roundtrip.py +2 -2
  95. {batplot-1.8.53 → batplot-1.8.55}/tests/test_operando_style_pisb_keys.py +1 -1
  96. batplot-1.8.55/tests/test_quit_confirm_export_save.py +98 -0
  97. {batplot-1.8.53 → batplot-1.8.55}/tests/test_spine_colors_pisb.py +216 -0
  98. batplot-1.8.55/tests/test_spine_wasd_figure_help.py +56 -0
  99. batplot-1.8.55/tests/test_stack_rearrange_tick_spacing.py +229 -0
  100. batplot-1.8.55/tests/test_style_layout_compat.py +230 -0
  101. batplot-1.8.55/tests/test_tick_display_color_contract.py +331 -0
  102. {batplot-1.8.53 → batplot-1.8.55}/tests/test_xy_axis_units.py +55 -5
  103. batplot-1.8.55/tests/test_xy_bps_bpsg_key_matrix.py +291 -0
  104. {batplot-1.8.53 → batplot-1.8.55}/tests/test_xy_cif_add.py +92 -6
  105. {batplot-1.8.53 → batplot-1.8.55}/tests/test_xy_geometry_pisb_keys.py +119 -4
  106. {batplot-1.8.53 → batplot-1.8.55}/tests/test_xy_style_pisb_keys.py +47 -18
  107. batplot-1.8.53/tests/test_batch_spine_sync.py +0 -82
  108. {batplot-1.8.53 → batplot-1.8.55}/DEVELOPING.md +0 -0
  109. {batplot-1.8.53 → batplot-1.8.55}/LICENSE +0 -0
  110. {batplot-1.8.53 → batplot-1.8.55}/MANIFEST.in +0 -0
  111. {batplot-1.8.53 → batplot-1.8.55}/NOTICE +0 -0
  112. {batplot-1.8.53 → batplot-1.8.55}/batplot/_mpl_backend.py +0 -0
  113. {batplot-1.8.53 → batplot-1.8.55}/batplot/batch.py +0 -0
  114. {batplot-1.8.53 → batplot-1.8.55}/batplot/batplot.py +0 -0
  115. {batplot-1.8.53 → batplot-1.8.55}/batplot/canvas_interactive.py +0 -0
  116. {batplot-1.8.53 → batplot-1.8.55}/batplot/cif.py +0 -0
  117. {batplot-1.8.53 → batplot-1.8.55}/batplot/cli.py +0 -0
  118. {batplot-1.8.53 → batplot-1.8.55}/batplot/cli_save.py +0 -0
  119. {batplot-1.8.53 → batplot-1.8.55}/batplot/color_utils.py +0 -0
  120. {batplot-1.8.53 → batplot-1.8.55}/batplot/config.py +0 -0
  121. {batplot-1.8.53 → batplot-1.8.55}/batplot/converters.py +0 -0
  122. {batplot-1.8.53 → batplot-1.8.55}/batplot/dev_upgrade.py +0 -0
  123. {batplot-1.8.53 → batplot-1.8.55}/batplot/ec_common.py +0 -0
  124. {batplot-1.8.53 → batplot-1.8.55}/batplot/modes.py +0 -0
  125. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/__init__.py +0 -0
  126. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/__init__.py +0 -0
  127. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_crosshair.py +0 -0
  128. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_figure_io.py +0 -0
  129. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_geom_helpers.py +0 -0
  130. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_io.py +0 -0
  131. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_menu_helpers.py +0 -0
  132. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_panel_state.py +0 -0
  133. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_scoped_sync.py +0 -0
  134. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/common.py +0 -0
  135. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/cpc_batch_helpers.py +0 -0
  136. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/dqdv_2d_batch_helpers.py +0 -0
  137. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/ec_batch_helpers.py +0 -0
  138. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/histo_batch_helpers.py +0 -0
  139. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/kinds.py +0 -0
  140. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/load.py +0 -0
  141. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/operando_batch_helpers.py +0 -0
  142. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/batch_session/routing.py +0 -0
  143. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/__init__.py +0 -0
  144. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/axis_state.py +0 -0
  145. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/batch_font.py +0 -0
  146. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/crosshair_export.py +0 -0
  147. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/files.py +0 -0
  148. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/font_extras.py +0 -0
  149. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/interactive_state.py +0 -0
  150. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/line_dash.py +0 -0
  151. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/menus.py +0 -0
  152. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/overview_metrics.py +0 -0
  153. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/session_data_guarantee.py +0 -0
  154. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/session_helpers.py +0 -0
  155. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/session_key_smoke.py +0 -0
  156. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/size_spec.py +0 -0
  157. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/smoothing.py +0 -0
  158. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/sources.py +0 -0
  159. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/state_capture.py +0 -0
  160. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/common/title_offsets.py +0 -0
  161. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/__init__.py +0 -0
  162. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/add_file.py +0 -0
  163. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/legend.py +0 -0
  164. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/legend_order.py +0 -0
  165. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/load.py +0 -0
  166. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/menu.py +0 -0
  167. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/overview.py +0 -0
  168. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/routing.py +0 -0
  169. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/cpc/snapshots.py +0 -0
  170. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/__init__.py +0 -0
  171. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/capacity_cum.py +0 -0
  172. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/dqdv_2d.py +0 -0
  173. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/dual_axis_menu.py +0 -0
  174. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/export.py +0 -0
  175. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/legend.py +0 -0
  176. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/legend_order.py +0 -0
  177. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/menu.py +0 -0
  178. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/overview.py +0 -0
  179. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/routing.py +0 -0
  180. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/electrochem/smoothing_menu.py +0 -0
  181. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/__init__.py +0 -0
  182. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/actions.py +0 -0
  183. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/fonts.py +0 -0
  184. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/load.py +0 -0
  185. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/plot.py +0 -0
  186. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/routing.py +0 -0
  187. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/toggles.py +0 -0
  188. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/wizard.py +0 -0
  189. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/histo/y_range.py +0 -0
  190. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/__init__.py +0 -0
  191. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/axes_limits_menu.py +0 -0
  192. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/axis_units.py +0 -0
  193. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/grid.py +0 -0
  194. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/intensity_menu.py +0 -0
  195. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/ions_axis.py +0 -0
  196. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/layout_menu.py +0 -0
  197. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/menu.py +0 -0
  198. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/peaks.py +0 -0
  199. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/routing.py +0 -0
  200. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/operando/visibility.py +0 -0
  201. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/session_routing.py +0 -0
  202. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/__init__.py +0 -0
  203. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/actions.py +0 -0
  204. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/axis_range.py +0 -0
  205. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/data_ops.py +0 -0
  206. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/derivative.py +0 -0
  207. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/full_data.py +0 -0
  208. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/game.py +0 -0
  209. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/menu.py +0 -0
  210. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/offset_menu.py +0 -0
  211. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/peaks.py +0 -0
  212. {batplot-1.8.53 → batplot-1.8.55}/batplot/plot_modes/xy/smoothing.py +0 -0
  213. {batplot-1.8.53 → batplot-1.8.55}/batplot/plotting.py +0 -0
  214. {batplot-1.8.53 → batplot-1.8.55}/batplot/readers.py +0 -0
  215. {batplot-1.8.53 → batplot-1.8.55}/batplot/readers_common.py +0 -0
  216. {batplot-1.8.53 → batplot-1.8.55}/batplot/readers_ec.py +0 -0
  217. {batplot-1.8.53 → batplot-1.8.55}/batplot/readers_xrd.py +0 -0
  218. {batplot-1.8.53 → batplot-1.8.55}/batplot/screen_color.py +0 -0
  219. {batplot-1.8.53 → batplot-1.8.55}/batplot/session.py +0 -0
  220. {batplot-1.8.53 → batplot-1.8.55}/batplot/showcol.py +0 -0
  221. {batplot-1.8.53 → batplot-1.8.55}/batplot/strip_header.py +0 -0
  222. {batplot-1.8.53 → batplot-1.8.55}/batplot/style.py +0 -0
  223. {batplot-1.8.53 → batplot-1.8.55}/batplot/version_check.py +0 -0
  224. {batplot-1.8.53 → batplot-1.8.55}/batplot.egg-info/dependency_links.txt +0 -0
  225. {batplot-1.8.53 → batplot-1.8.55}/batplot.egg-info/entry_points.txt +0 -0
  226. {batplot-1.8.53 → batplot-1.8.55}/batplot.egg-info/requires.txt +0 -0
  227. {batplot-1.8.53 → batplot-1.8.55}/batplot.egg-info/top_level.txt +0 -0
  228. {batplot-1.8.53 → batplot-1.8.55}/setup.cfg +0 -0
  229. {batplot-1.8.53 → batplot-1.8.55}/setup.py +0 -0
  230. {batplot-1.8.53 → batplot-1.8.55}/tests/test_all_menus_smoke.py +0 -0
  231. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_all_modes_sync.py +0 -0
  232. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_cpc_key_isolation.py +0 -0
  233. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_crosshair.py +0 -0
  234. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_dqdv_key_isolation.py +0 -0
  235. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_ec_cycles_status.py +0 -0
  236. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_font_menu.py +0 -0
  237. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_gc_key_isolation.py +0 -0
  238. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_geom_menu.py +0 -0
  239. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_geometry_pisb_keys.py +0 -0
  240. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_histo_key_isolation.py +0 -0
  241. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_menu_parity.py +0 -0
  242. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_operando_key_isolation.py +0 -0
  243. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_panel_status.py +0 -0
  244. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_pisb_contract.py +0 -0
  245. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_scoped_sync_modes.py +0 -0
  246. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_style_pisb_keys.py +0 -0
  247. {batplot-1.8.53 → batplot-1.8.55}/tests/test_batch_xy_key_isolation.py +0 -0
  248. {batplot-1.8.53 → batplot-1.8.55}/tests/test_bc_new_fields_defaults.py +0 -0
  249. {batplot-1.8.53 → batplot-1.8.55}/tests/test_bruker_intensity.py +0 -0
  250. {batplot-1.8.53 → batplot-1.8.55}/tests/test_cif_tick_crystallography.py +0 -0
  251. {batplot-1.8.53 → batplot-1.8.55}/tests/test_cli_all_flags.py +0 -0
  252. {batplot-1.8.53 → batplot-1.8.55}/tests/test_cli_save.py +0 -0
  253. {batplot-1.8.53 → batplot-1.8.55}/tests/test_cli_smoke.py +0 -0
  254. {batplot-1.8.53 → batplot-1.8.55}/tests/test_color_display_hex.py +0 -0
  255. {batplot-1.8.53 → batplot-1.8.55}/tests/test_color_listing_visible.py +0 -0
  256. {batplot-1.8.53 → batplot-1.8.55}/tests/test_color_utils.py +0 -0
  257. {batplot-1.8.53 → batplot-1.8.55}/tests/test_common_files.py +0 -0
  258. {batplot-1.8.53 → batplot-1.8.55}/tests/test_common_palettes.py +0 -0
  259. {batplot-1.8.53 → batplot-1.8.55}/tests/test_convert_xrd.py +0 -0
  260. {batplot-1.8.53 → batplot-1.8.55}/tests/test_cpc_add_file.py +0 -0
  261. {batplot-1.8.53 → batplot-1.8.55}/tests/test_cpc_legend_order.py +0 -0
  262. {batplot-1.8.53 → batplot-1.8.55}/tests/test_cpc_roundtrip.py +0 -0
  263. {batplot-1.8.53 → batplot-1.8.55}/tests/test_critical_stability_fixes.py +0 -0
  264. {batplot-1.8.53 → batplot-1.8.55}/tests/test_cross_os_deeper.py +0 -0
  265. {batplot-1.8.53 → batplot-1.8.55}/tests/test_cross_os_oe_paths.py +0 -0
  266. {batplot-1.8.53 → batplot-1.8.55}/tests/test_cross_platform_parity.py +0 -0
  267. {batplot-1.8.53 → batplot-1.8.55}/tests/test_crosshair_export.py +0 -0
  268. {batplot-1.8.53 → batplot-1.8.55}/tests/test_csv_readers.py +0 -0
  269. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_residual_pisb_gates.py +0 -0
  270. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_round10_bc_safe.py +0 -0
  271. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_round11_title_fidelity.py +0 -0
  272. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_round12_commercial_gates.py +0 -0
  273. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_round13_final_key_audit.py +0 -0
  274. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_round3_pisb_gates.py +0 -0
  275. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_round4_pisb_gates.py +0 -0
  276. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_round5_pisb_gates.py +0 -0
  277. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_round6_session_fidelity.py +0 -0
  278. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_round7_root_helpers.py +0 -0
  279. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_round8_root_helpers.py +0 -0
  280. {batplot-1.8.53 → batplot-1.8.55}/tests/test_deep_round9_root_helpers.py +0 -0
  281. {batplot-1.8.53 → batplot-1.8.55}/tests/test_default_sizes_and_oe_persistence.py +0 -0
  282. {batplot-1.8.53 → batplot-1.8.55}/tests/test_dev_upgrade.py +0 -0
  283. {batplot-1.8.53 → batplot-1.8.55}/tests/test_dqdv_contour_session_keys.py +0 -0
  284. {batplot-1.8.53 → batplot-1.8.55}/tests/test_dqdv_smooth_status.py +0 -0
  285. {batplot-1.8.53 → batplot-1.8.55}/tests/test_dual_axis_menu_audit.py +0 -0
  286. {batplot-1.8.53 → batplot-1.8.55}/tests/test_dual_mode_pisb.py +0 -0
  287. {batplot-1.8.53 → batplot-1.8.55}/tests/test_dual_pisb_hard_gates.py +0 -0
  288. {batplot-1.8.53 → batplot-1.8.55}/tests/test_dual_tk_a_coupling.py +0 -0
  289. {batplot-1.8.53 → batplot-1.8.55}/tests/test_dual_top_wasd_both_layers.py +0 -0
  290. {batplot-1.8.53 → batplot-1.8.55}/tests/test_ec_cpc_style_pisb_keys.py +0 -0
  291. {batplot-1.8.53 → batplot-1.8.55}/tests/test_ec_cycle_identity_roundtrip.py +0 -0
  292. {batplot-1.8.53 → batplot-1.8.55}/tests/test_ec_cycles_three_color_modes.py +0 -0
  293. {batplot-1.8.53 → batplot-1.8.55}/tests/test_ec_multifile_color_menu.py +0 -0
  294. {batplot-1.8.53 → batplot-1.8.55}/tests/test_ec_old_session_three_color_modes.py +0 -0
  295. {batplot-1.8.53 → batplot-1.8.55}/tests/test_ec_roundtrip.py +0 -0
  296. {batplot-1.8.53 → batplot-1.8.55}/tests/test_ec_session_bc_new_keys.py +0 -0
  297. {batplot-1.8.53 → batplot-1.8.55}/tests/test_every_key_behavioral_walk.py +0 -0
  298. {batplot-1.8.53 → batplot-1.8.55}/tests/test_file_dialogs_os.py +0 -0
  299. {batplot-1.8.53 → batplot-1.8.55}/tests/test_final_audit_residuals.py +0 -0
  300. {batplot-1.8.53 → batplot-1.8.55}/tests/test_full_menu_audit_gaps.py +0 -0
  301. {batplot-1.8.53 → batplot-1.8.55}/tests/test_gc_cumulative.py +0 -0
  302. {batplot-1.8.53 → batplot-1.8.55}/tests/test_geom_size_highlight.py +0 -0
  303. {batplot-1.8.53 → batplot-1.8.55}/tests/test_hard_check_twin_and_batch.py +0 -0
  304. {batplot-1.8.53 → batplot-1.8.55}/tests/test_histo.py +0 -0
  305. {batplot-1.8.53 → batplot-1.8.55}/tests/test_histo_interactive_imports.py +0 -0
  306. {batplot-1.8.53 → batplot-1.8.55}/tests/test_imk_stderr_guard.py +0 -0
  307. {batplot-1.8.53 → batplot-1.8.55}/tests/test_interactive_handler_intent.py +0 -0
  308. {batplot-1.8.53 → batplot-1.8.55}/tests/test_interactive_menu_smoke.py +0 -0
  309. {batplot-1.8.53 → batplot-1.8.55}/tests/test_interactive_state.py +0 -0
  310. {batplot-1.8.53 → batplot-1.8.55}/tests/test_line_dash_styles.py +0 -0
  311. {batplot-1.8.53 → batplot-1.8.55}/tests/test_menu_handler_imports.py +0 -0
  312. {batplot-1.8.53 → batplot-1.8.55}/tests/test_menu_prompt_order.py +0 -0
  313. {batplot-1.8.53 → batplot-1.8.55}/tests/test_mpl_backend.py +0 -0
  314. {batplot-1.8.53 → batplot-1.8.55}/tests/test_operando_axis_units.py +0 -0
  315. {batplot-1.8.53 → batplot-1.8.55}/tests/test_operando_batch_menu.py +0 -0
  316. {batplot-1.8.53 → batplot-1.8.55}/tests/test_operando_cif_add.py +0 -0
  317. {batplot-1.8.53 → batplot-1.8.55}/tests/test_operando_layout_menu.py +0 -0
  318. {batplot-1.8.53 → batplot-1.8.55}/tests/test_operando_peaks_axis_units.py +0 -0
  319. {batplot-1.8.53 → batplot-1.8.55}/tests/test_operando_spine_isolation.py +0 -0
  320. {batplot-1.8.53 → batplot-1.8.55}/tests/test_operando_submenu_smoke.py +0 -0
  321. {batplot-1.8.53 → batplot-1.8.55}/tests/test_overview_metrics.py +0 -0
  322. {batplot-1.8.53 → batplot-1.8.55}/tests/test_pi_axis_units_persistence.py +0 -0
  323. {batplot-1.8.53 → batplot-1.8.55}/tests/test_pisb_deep_all_modes.py +0 -0
  324. {batplot-1.8.53 → batplot-1.8.55}/tests/test_recent_axis_names.py +0 -0
  325. {batplot-1.8.53 → batplot-1.8.55}/tests/test_screen_color.py +0 -0
  326. {batplot-1.8.53 → batplot-1.8.55}/tests/test_screen_color_pisb.py +0 -0
  327. {batplot-1.8.53 → batplot-1.8.55}/tests/test_secondary_spine_colors.py +0 -0
  328. {batplot-1.8.53 → batplot-1.8.55}/tests/test_session_backward_compat.py +0 -0
  329. {batplot-1.8.53 → batplot-1.8.55}/tests/test_session_font_restore.py +0 -0
  330. {batplot-1.8.53 → batplot-1.8.55}/tests/test_session_full_data_guarantee.py +0 -0
  331. {batplot-1.8.53 → batplot-1.8.55}/tests/test_session_save_integrity.py +0 -0
  332. {batplot-1.8.53 → batplot-1.8.55}/tests/test_session_style_restore_parity.py +0 -0
  333. {batplot-1.8.53 → batplot-1.8.55}/tests/test_spine_wasd_pisb_all_modes.py +0 -0
  334. {batplot-1.8.53 → batplot-1.8.55}/tests/test_state_capture.py +0 -0
  335. {batplot-1.8.53 → batplot-1.8.55}/tests/test_strip_header.py +0 -0
  336. {batplot-1.8.53 → batplot-1.8.55}/tests/test_stupid_input_hardening.py +0 -0
  337. {batplot-1.8.53 → batplot-1.8.55}/tests/test_style_import_integrity.py +0 -0
  338. {batplot-1.8.53 → batplot-1.8.55}/tests/test_style_routing.py +0 -0
  339. {batplot-1.8.53 → batplot-1.8.55}/tests/test_tick_visibility_save_truth.py +0 -0
  340. {batplot-1.8.53 → batplot-1.8.55}/tests/test_undo_deep_all_modes.py +0 -0
  341. {batplot-1.8.53 → batplot-1.8.55}/tests/test_undo_stack_integrity.py +0 -0
  342. {batplot-1.8.53 → batplot-1.8.55}/tests/test_xrd_crosshair_bragg.py +0 -0
  343. {batplot-1.8.53 → batplot-1.8.55}/tests/test_xy_full_data_retention.py +0 -0
  344. {batplot-1.8.53 → batplot-1.8.55}/tests/test_xy_generic_xy_default.py +0 -0
  345. {batplot-1.8.53 → batplot-1.8.55}/tests/test_xy_modules.py +0 -0
  346. {batplot-1.8.53 → batplot-1.8.55}/tests/test_xy_offset_menu.py +0 -0
  347. {batplot-1.8.53 → batplot-1.8.55}/tests/test_xy_roundtrip.py +0 -0
  348. {batplot-1.8.53 → batplot-1.8.55}/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.53
3
+ Version: 1.8.55
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
@@ -86,7 +86,7 @@ pip install batplot
86
86
 
87
87
  - User manual: https://chem-plot.github.io/batplot/
88
88
  - Tutorial: https://drive.google.com/file/d/1NTFJWNBbWW4mgz0H5ZelGjuOBWxoFgkr/view
89
- - Tutorial files: https://github.com/chem-plot/batplot/blob/main/batplot_tutorial.zip
89
+ - Demo files: https://github.com/chem-plot/batplot/blob/main/batplot_demo_files.zip
90
90
 
91
91
  ---
92
92
 
@@ -30,7 +30,7 @@ pip install batplot
30
30
 
31
31
  - User manual: https://chem-plot.github.io/batplot/
32
32
  - Tutorial: https://drive.google.com/file/d/1NTFJWNBbWW4mgz0H5ZelGjuOBWxoFgkr/view
33
- - Tutorial files: https://github.com/chem-plot/batplot/blob/main/batplot_tutorial.zip
33
+ - Demo files: https://github.com/chem-plot/batplot/blob/main/batplot_demo_files.zip
34
34
 
35
35
  ---
36
36
 
@@ -7,7 +7,7 @@ import importlib.abc
7
7
  import importlib.machinery
8
8
  import sys
9
9
 
10
- __version__ = "1.8.53"
10
+ __version__ = "1.8.55"
11
11
 
12
12
 
13
13
  _LEGACY_MODULE_ALIASES = {
@@ -173,7 +173,7 @@ def _print_general_help() -> None:
173
173
  "Features:\n"
174
174
  " • Interactive (--i): styling, ranges, fonts, export, sessions\n"
175
175
  " • XRD wavelength: --wl 1.54 or file.xye:1.5406 for Q conversion\n"
176
- " • XRD axis units (interactive): Options u converts 2θ ↔ Q ↔ d (XY + operando; needs λ for 2θ)\n"
176
+ " • XRD axis units (interactive): Options u converts 2θ ↔ Q (XY; needs λ for 2θ); operando also offers d\n"
177
177
  " • CIF phase ticks: add .cif (or file.cif:wl); ticks follow the current axis (2θ / Q / d)\n"
178
178
  " • X-axis range: --xrange min max\n"
179
179
  " • Save figure: --out filename (default .svg)\n"
@@ -218,8 +218,9 @@ def _print_xy_help() -> None:
218
218
  "A wavelength can be converted into a different wave length by file.xye:1.54:0.709.\n"
219
219
  "For electrochemistry CSV/MPT time-potential plots, use --xaxis time.\n\n"
220
220
  "Interactive XRD axis units (Options u):\n"
221
- " In --i, press u to convert the plotted XRD axis among 2θ ↔ Q ↔ d (XRD data only).\n"
221
+ " In --i, press u to convert the plotted XRD axis between 2θ ↔ Q (XRD data only).\n"
222
222
  " Conversions involving 2θ need λ (--wl, file:wl, or prompt). CIF ticks stay Bragg-aligned.\n"
223
+ " d-spacing is not offered as a plot domain in 1D Options u.\n"
223
224
  " Not for PDF (.gr), XAS (.nor/.chik/.chir), or other non-diffraction axes.\n"
224
225
  " Example: batplot data.xye:0.709 --xaxis 2theta --i then u → q (uses λ=0.709 Å).\n\n"
225
226
  "CIF phase ticks:\n"
@@ -773,20 +774,66 @@ def parse_args(argv=None):
773
774
  # Keys use the exact file token (e.g. "file.xy:1.54") for wavelength match.
774
775
  # Style files (.bps, .bpsg, .bpcfg) are NOT treated as file tokens so that
775
776
  # "batplot --all style.bps --readcol 2 3" uses global readcol, not per-file.
777
+ #
778
+ # Values of known options (--wl 0.259, --xaxis q, --out out.svg, …) must
779
+ # NOT update last_file_token. Otherwise
780
+ # batplot TD_R02.dat --wl 0.259 --readcol 1 3
781
+ # binds readcol to "0.259" and the plot silently falls back to cols 1,2.
776
782
  # ====================================================================
777
783
  readcol_by_file = {}
778
784
  global_readcol_expanded = None
779
785
  filtered_argv = []
780
786
  last_file_token = None
781
787
  _STYLE_EXTENSIONS = ('.bps', '.bpsg', '.bpcfg')
788
+ # Exact value counts for options that take fixed nargs (after short→long).
789
+ # store_true / flag-only options are omitted (0 values).
790
+ _OPTION_VALUE_COUNTS = {
791
+ '--wl': 1,
792
+ '--xaxis': 1,
793
+ '--out': 1,
794
+ '--savefig': 1,
795
+ '--delta': 1,
796
+ '--format': 1,
797
+ '--mass': 1,
798
+ '--cd': 1,
799
+ '--average': 1,
800
+ '--sum': 1,
801
+ '--histocol': 1,
802
+ '--binwidth': 1,
803
+ '--bins': 1,
804
+ '--ext': 1,
805
+ '--convert-ext': 1,
806
+ '--xrange': 2,
807
+ '--convert': 2,
808
+ '--pw': 2,
809
+ '--b': 2,
810
+ '--readcolxy': 2,
811
+ '--readcolxye': 2,
812
+ '--readcolqye': 2,
813
+ '--readcolnor': 2,
814
+ '--readcoldat': 2,
815
+ '--readcolcsv': 2,
816
+ '--readcolc': 2,
817
+ '--readcols': 2,
818
+ }
819
+ for _ext in custom_readcol_exts:
820
+ _OPTION_VALUE_COUNTS[f'--readcol{_ext}'] = 2
821
+ # Optional single value (nargs='?'): consume at most one non-option token.
822
+ _OPTIONAL_ONE_VALUE = {'--all', '--help', '--extract-brml-scans'}
823
+
824
+ def _option_value_count(flag: str) -> int:
825
+ if flag in _OPTION_VALUE_COUNTS:
826
+ return _OPTION_VALUE_COUNTS[flag]
827
+ if flag in _OPTIONAL_ONE_VALUE:
828
+ return 1
829
+ if flag == '--fullprof':
830
+ # nargs='+': consume following non-option tokens
831
+ return 10**9
832
+ return 0
833
+
782
834
  i = 0
783
835
  while i < len(argv):
784
836
  arg = argv[i]
785
- # Track non-option tokens as potential file specs (exclude style files)
786
- if not arg.startswith('-'):
787
- arg_lower = arg.lower()
788
- if not arg_lower.endswith(_STYLE_EXTENSIONS):
789
- last_file_token = arg
790
837
  if arg == '--readcol' and i + 1 < len(argv):
791
838
  tokens = []
792
839
  j = i + 1
@@ -824,9 +871,23 @@ def parse_args(argv=None):
824
871
  global_readcol_expanded = pairs[0] if len(pairs) == 1 else pairs
825
872
  i = j
826
873
  continue
874
+ if arg.startswith('-'):
875
+ filtered_argv.append(arg)
876
+ n_vals = _option_value_count(arg)
877
+ i += 1
878
+ taken = 0
879
+ while taken < n_vals and i < len(argv) and not argv[i].startswith('-'):
880
+ filtered_argv.append(argv[i])
881
+ i += 1
882
+ taken += 1
883
+ continue
884
+ # Non-option: potential file spec (exclude style files)
885
+ arg_lower = arg.lower()
886
+ if not arg_lower.endswith(_STYLE_EXTENSIONS):
887
+ last_file_token = arg
827
888
  filtered_argv.append(arg)
828
889
  i += 1
829
-
890
+
830
891
  argv = filtered_argv
831
892
 
832
893
  # ====================================================================
@@ -1,5 +1,16 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.8.55] - 2026-09-15
4
+ - Bug fixes
5
+
6
+
7
+ ## [1.8.54] - 2026-09-14
8
+ - Fix --readcol after --wl / other option values (cols no longer stuck on 1–2)
9
+ - Quit prompt: e=export and s=save work in every interactive / batch menu
10
+ - Color menus (c/k): WASD side rectangle like spines t, for all modes
11
+ - User manual homepage: GitHub repo + tutorial zip links
12
+
13
+
3
14
  ## [1.8.53] - 2026-09-09
4
15
  - Bug fixes
5
16
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.8.53",
2
+ "version": "1.8.55",
3
3
  "custom_message": "- Bug fixes",
4
4
  "update_notes": [
5
5
  "- Bug fixes"
@@ -26,20 +26,24 @@ def append_batch_io_shortcuts(options: List[str], panels: Sequence[Any]) -> None
26
26
 
27
27
 
28
28
  def batch_quit_confirm(*, allow_export: bool = True) -> str | None:
29
- """Return ``y`` to quit, ``s`` to save all sessions first, or ``None`` to stay."""
30
- try:
31
- if allow_export:
32
- prompt = "Quit batch interactive? (s=save all sessions, y/n): "
33
- else:
34
- prompt = "Quit batch interactive? Quit now? (y/n): "
35
- confirm = safe_input(colorize_prompt(prompt), cancel_on_interrupt=True).strip().lower()
36
- except (KeyboardInterrupt, EOFError):
37
- return "y"
38
- if confirm == "y":
39
- return "y"
40
- if allow_export and confirm == "s":
41
- return "s"
42
- return None
29
+ """Return ``y`` to quit, ``e``/``s`` to run export/save next, or ``None`` to stay."""
30
+ from ..common.terminal import confirm_quit_interactive
31
+
32
+ if not allow_export:
33
+ try:
34
+ confirm = safe_input(
35
+ colorize_prompt("Quit batch interactive? Quit now? (y/n): "),
36
+ cancel_on_interrupt=True,
37
+ ).strip().lower()
38
+ except (KeyboardInterrupt, EOFError):
39
+ return "y"
40
+ return "y" if confirm == "y" else None
41
+
42
+ return confirm_quit_interactive(
43
+ label="Quit batch interactive?",
44
+ safe_input_fn=lambda prompt: safe_input(prompt, cancel_on_interrupt=True),
45
+ colorize_fn=colorize_prompt,
46
+ )
43
47
 
44
48
 
45
49
  def run_batch_save_all(panels: Sequence[Any], save_panel: Callable[[Any, str], None]) -> None:
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from typing import Any, Callable, Sequence
6
6
 
7
- from .batch_commands import batch_quit_confirm, run_batch_overwrite_sessions, run_batch_save_all
7
+ from .batch_commands import batch_quit_confirm, run_batch_overwrite_sessions
8
8
  from .batch_figure_io import run_batch_export_figures, run_batch_overwrite_figures
9
9
  from .batch_io import run_batch_export_style, run_batch_import_style, run_batch_save_sessions
10
10
 
@@ -12,13 +12,20 @@ from .batch_io import run_batch_export_style, run_batch_import_style, run_batch_
12
12
  def batch_quit_or_save_all(
13
13
  panels: Sequence[Any],
14
14
  save_panel: Callable[[Any, str], None],
15
- ) -> bool:
16
- """Handle ``q`` quit prompt. Returns True when the menu loop should exit."""
15
+ ) -> bool | str:
16
+ """Handle ``q`` quit prompt.
17
+
18
+ Returns:
19
+ ``True`` when the menu loop should exit,
20
+ ``"e"`` / ``"s"`` to dispatch export/save on the next loop iteration,
21
+ ``False`` to stay in the menu.
22
+ """
23
+ _ = (panels, save_panel) # call-site signature unchanged; e/s use pending keys
17
24
  action = batch_quit_confirm(allow_export=True)
18
25
  if action == "y":
19
26
  return True
20
- if action == "s":
21
- run_batch_save_all(panels, save_panel)
27
+ if action in ("e", "s"):
28
+ return action
22
29
  return False
23
30
 
24
31
 
@@ -385,8 +385,11 @@ def run_cpc_batch_menu(panels: List[CpcPanel]) -> None:
385
385
  continue
386
386
 
387
387
  if cmd == "q":
388
- if batch_quit_or_save_all(panels, _save_cpc_panel):
388
+ result = batch_quit_or_save_all(panels, _save_cpc_panel)
389
+ if result is True:
389
390
  break
391
+ if result in ("e", "s"):
392
+ pending = result
390
393
  continue
391
394
 
392
395
  if cmd == "b":
@@ -185,8 +185,11 @@ def run_dqdv_2d_batch_menu(panels: List[OperandoPanel]) -> None:
185
185
  continue
186
186
 
187
187
  if cmd == "q":
188
- if batch_quit_or_save_all(panels, save_dqdv_2d_panel):
188
+ result = batch_quit_or_save_all(panels, save_dqdv_2d_panel)
189
+ if result is True:
189
190
  break
191
+ if result in ("e", "s"):
192
+ pending = result
190
193
  continue
191
194
 
192
195
  if cmd == "b":
@@ -279,8 +279,11 @@ def run_ec_batch_menu(panels: List[EcPanel]) -> None:
279
279
  continue
280
280
 
281
281
  if cmd == "q":
282
- if batch_quit_or_save_all(panels, _save_ec_panel):
282
+ result = batch_quit_or_save_all(panels, _save_ec_panel)
283
+ if result is True:
283
284
  break
285
+ if result in ("e", "s"):
286
+ pending = result
284
287
  continue
285
288
 
286
289
  if cmd == "b":
@@ -162,8 +162,11 @@ def run_histo_batch_menu(panels: List[HistoPanel]) -> None:
162
162
  continue
163
163
 
164
164
  if cmd == "q":
165
- if batch_quit_or_save_all(panels, _save_histo_panel):
165
+ result = batch_quit_or_save_all(panels, _save_histo_panel)
166
+ if result is True:
166
167
  break
168
+ if result in ("e", "s"):
169
+ pending = result
167
170
  continue
168
171
 
169
172
  if cmd == "b":
@@ -352,8 +352,11 @@ def run_operando_batch_menu(panels: List[OperandoPanel]) -> None:
352
352
  continue
353
353
 
354
354
  if cmd == "q":
355
- if batch_quit_or_save_all(panels, _save_operando_panel):
355
+ result = batch_quit_or_save_all(panels, _save_operando_panel)
356
+ if result is True:
356
357
  break
358
+ if result in ("e", "s"):
359
+ pending = result
357
360
  continue
358
361
 
359
362
  if cmd == "b":
@@ -17,11 +17,9 @@ from ..xy.style import apply_style_config, export_style_config
17
17
  from ...plotting import apply_curve_color, update_labels
18
18
  from ...color_utils import (
19
19
  format_color_listing,
20
- get_user_color_list,
21
20
  manage_user_colors,
22
21
  prompt_screen_color,
23
22
  blank_means_back,
24
- last_screen_pick_count,
25
23
  resolve_color_token,
26
24
  )
27
25
 
@@ -357,8 +355,11 @@ def run_xy_batch_menu(panels: List[XyPanel]) -> None:
357
355
  continue
358
356
 
359
357
  if cmd == "q":
360
- if batch_quit_or_save_all(panels, dump_xy_panel):
358
+ result = batch_quit_or_save_all(panels, dump_xy_panel)
359
+ if result is True:
361
360
  break
361
+ if result in ("e", "s"):
362
+ pending = result
362
363
  continue
363
364
 
364
365
  if cmd == "b":
@@ -430,20 +431,34 @@ def run_xy_batch_menu(panels: List[XyPanel]) -> None:
430
431
 
431
432
  _spine_keys = {"w": "top", "a": "left", "s": "bottom", "d": "right"}
432
433
  while True:
434
+ from ..common.color_menu_help import (
435
+ join_cyan_samples,
436
+ join_cyan_samples_spaced,
437
+ print_color_action_keys,
438
+ print_how_to_set_color_methods,
439
+ print_saved_colors_block,
440
+ print_spine_tick_keys_note,
441
+ )
442
+
433
443
  fig_ref = getattr(ref, "fig", None)
434
- user_colors = get_user_color_list(fig_ref)
435
- if user_colors:
436
- print("Saved colors (refer as number or u#):")
437
- for idx, col in enumerate(user_colors, 1):
438
- print(f" {idx}: {format_color_listing(col)}")
439
- print(" " + _colorize_menu("Spine colors: w:red a:#4561F7 (syncs to all plots)"))
440
- print(" " + _colorize_menu("v: show current colors"))
441
- print(" " + _colorize_menu("u: edit saved colors"))
442
- print(" " + _colorize_menu("e: pick color from screen"))
444
+ print_how_to_set_color_methods(
445
+ [
446
+ (
447
+ "Same color for all curves (name / #hex / saved index)",
448
+ join_cyan_samples_spaced("red", "#00FF00", "u3"),
449
+ ),
450
+ (
451
+ "Spine color (w/a/s/d) — syncs to all plots",
452
+ join_cyan_samples("w:red", "a:#4561F7"),
453
+ ),
454
+ ]
455
+ )
456
+ print_spine_tick_keys_note()
457
+ print(" (applies to ALL plots in this batch)")
458
+ print_saved_colors_block(fig_ref)
459
+ print_color_action_keys()
443
460
  color = safe_input(
444
- colorize_prompt(
445
- "Curve or spine color for ALL plots (name/#hex, w:red…, v/e/u, q=back): "
446
- ),
461
+ colorize_prompt("Selection: "),
447
462
  cancel_on_interrupt=True,
448
463
  ).strip()
449
464
  if color.lower() == "q" or blank_means_back(color):
@@ -454,6 +469,9 @@ def run_xy_batch_menu(panels: List[XyPanel]) -> None:
454
469
  if color.lower() == "u":
455
470
  manage_user_colors(fig_ref)
456
471
  continue
472
+ if color.lower() == "e":
473
+ prompt_screen_color(fig_ref)
474
+ continue
457
475
  tokens = color.split()
458
476
  is_spine = bool(tokens) and all(
459
477
  ":" in t and t.split(":", 1)[0].lower() in _spine_keys for t in tokens
@@ -477,28 +495,18 @@ def run_xy_batch_menu(panels: List[XyPanel]) -> None:
477
495
  print(f"Set {spine_name} spine to {format_color_listing(resolved)} on all plots.")
478
496
  draw_panels(panels)
479
497
  continue
480
- if color.lower() == "e":
481
- picked = prompt_screen_color(fig_ref)
482
- if not picked:
483
- continue
484
- if last_screen_pick_count() > 1:
485
- # Palette grab — saved as u#; do not recolor all curves
486
- # with only the last pick.
487
- continue
488
- color = picked
489
- else:
490
- try:
491
- color = resolve_color_token(color, fig_ref)
492
- except Exception:
493
- print(f"Invalid color: {color!r}")
494
- continue
495
- try:
496
- from matplotlib.colors import to_rgba
498
+ try:
499
+ color = resolve_color_token(color, fig_ref)
500
+ except Exception:
501
+ print(f"Invalid color: {color!r}")
502
+ continue
503
+ try:
504
+ from matplotlib.colors import to_rgba
497
505
 
498
- to_rgba(color)
499
- except Exception:
500
- print(f"Invalid color: {color!r}")
501
- continue
506
+ to_rgba(color)
507
+ except Exception:
508
+ print(f"Invalid color: {color!r}")
509
+ continue
502
510
  undo.push_all([_capture_panel(p) for p in panels])
503
511
  for p in panels:
504
512
  for ln in _iter_panel_curve_lines(p):
@@ -854,6 +862,37 @@ def run_xy_batch_menu(panels: List[XyPanel]) -> None:
854
862
  # Minimal CIF submenu: add-only (full CIF editor stays single-session).
855
863
  while True:
856
864
  print("\nCIF (batch — add only):")
865
+ # Show numbered CIF sets already on panels (same indices as single-session).
866
+ try:
867
+ any_listed = False
868
+ for pi, p in enumerate(panels):
869
+ kw = normalize_xy_menu_kwargs(p.menu_kwargs)
870
+ cg = kw.get("cif_globals") or {}
871
+ cts = list(cg.get("cif_tick_series") or [])
872
+ if not cts:
873
+ cts = list(getattr(p.fig, "_batplot_cif_tick_series", None) or [])
874
+ if not cts:
875
+ continue
876
+ any_listed = True
877
+ if len(panels) > 1:
878
+ print(f" Panel {pi + 1}:")
879
+ for i, ent in enumerate(cts):
880
+ try:
881
+ lab = ent[0]
882
+ fname = ent[1] if len(ent) > 1 else ""
883
+ except Exception:
884
+ lab, fname = f"set {i+1}", ""
885
+ base = os.path.basename(str(fname)) if fname else ""
886
+ prefix = " " if len(panels) > 1 else " "
887
+ if base:
888
+ print(f"{prefix}{i+1}: {lab} ({base})")
889
+ else:
890
+ print(f"{prefix}{i+1}: {lab}")
891
+ if not any_listed:
892
+ print(" (no CIF sets yet — use a to add)")
893
+ except Exception:
894
+ pass
895
+ print("------------------------------------------------------------")
857
896
  print(" " + _colorize_menu("a: add CIF file(s) to all plots"))
858
897
  print(" " + _colorize_menu("q: back"))
859
898
  sub = safe_input(
@@ -184,6 +184,10 @@ def sync_ref_wasd_to_panels(ref: XyPanel, panels: List[XyPanel]) -> None:
184
184
  tick_lengths = getattr(ref_fig, "_tick_lengths", None)
185
185
  tick_direction = getattr(ref_fig, "_tick_direction", None)
186
186
  tick_spacing = capture_axes_tick_locators(ref_ax, ("x", "y"))
187
+ ref_ax2 = getattr(ref_fig, "_xy_ax2", None)
188
+ tick_spacing_ax2 = (
189
+ capture_axes_tick_locators(ref_ax2, ("x", "y")) if ref_ax2 is not None else None
190
+ )
187
191
  ref_offsets = capture_title_offsets(ref_ax)
188
192
  try:
189
193
  ref_xpad = float(ref_ax.xaxis.labelpad)
@@ -226,7 +230,6 @@ def sync_ref_wasd_to_panels(ref: XyPanel, panels: List[XyPanel]) -> None:
226
230
  fig._tick_direction = tick_direction # type: ignore[attr-defined]
227
231
  for target in length_targets:
228
232
  target.tick_params(axis="both", which="both", direction=tick_direction)
229
- restore_axes_tick_locators(ax, tick_spacing, ("x", "y"))
230
233
  restore_title_offsets(ax, ref_offsets)
231
234
  try:
232
235
  if ref_xpad is not None:
@@ -235,8 +238,17 @@ def sync_ref_wasd_to_panels(ref: XyPanel, panels: List[XyPanel]) -> None:
235
238
  ax.yaxis.labelpad = ref_ypad
236
239
  except Exception:
237
240
  pass
238
- # Full WASD body (spine visibility / titles / twin) — not artist-copy.
241
+ # WASD chrome first (may NullLocator when minors off), then restore
242
+ # spacing so t→n / t→m survives batch sync (session load order parity).
239
243
  _apply_xy_batch_wasd_chrome(fig, ax, wasd, tick_state)
244
+ restore_axes_tick_locators(ax, tick_spacing, ("x", "y"))
245
+ if ax2 is not None and tick_spacing_ax2:
246
+ restore_axes_tick_locators(ax2, tick_spacing_ax2, ("x", "y"))
247
+ # Re-assert twin WASD minor visibility without wiping restored locators.
248
+ try:
249
+ sync_xy_twin_wasd(ax, fig, wasd)
250
+ except Exception:
251
+ pass
240
252
 
241
253
 
242
254
  def run_xy_batch_spine_menu(