batplot 1.8.47__tar.gz → 1.8.50__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.
- {batplot-1.8.47 → batplot-1.8.50}/PKG-INFO +31 -2
- {batplot-1.8.47 → batplot-1.8.50}/README.md +30 -1
- {batplot-1.8.47 → batplot-1.8.50}/batplot/__init__.py +1 -1
- {batplot-1.8.47 → batplot-1.8.50}/batplot/args.py +20 -3
- {batplot-1.8.47 → batplot-1.8.50}/batplot/batch.py +6 -4
- {batplot-1.8.47 → batplot-1.8.50}/batplot/batplot.py +47 -8
- {batplot-1.8.47 → batplot-1.8.50}/batplot/canvas_interactive.py +17 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot/color_utils.py +34 -15
- {batplot-1.8.47 → batplot-1.8.50}/batplot/data/CHANGELOG.md +16 -0
- batplot-1.8.50/batplot/data/latest_release_notes.json +9 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/batch_figure_io.py +11 -8
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/batch_menu_io.py +1 -1
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/common.py +1 -1
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/ec_batch_helpers.py +15 -3
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/load.py +3 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/menu_cpc.py +24 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/menu_ec.py +33 -43
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/menu_histo.py +8 -6
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/menu_operando.py +54 -10
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/menu_xy.py +107 -4
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/operando_batch_helpers.py +12 -10
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/font_extras.py +14 -8
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/menu_rendering.py +56 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/menus.py +43 -28
- batplot-1.8.50/batplot/plot_modes/common/overview_metrics.py +782 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/palettes.py +6 -1
- batplot-1.8.50/batplot/plot_modes/common/session_helpers.py +251 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/session_key_smoke.py +1 -1
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/spines.py +13 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/terminal.py +12 -1
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/cpc/__init__.py +2 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/cpc/actions.py +38 -9
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/cpc/interactive.py +26 -1229
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/cpc/legend.py +22 -6
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/cpc/menu.py +3 -2
- batplot-1.8.50/batplot/plot_modes/cpc/overview.py +202 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/cpc/routing.py +1 -1
- batplot-1.8.50/batplot/plot_modes/cpc/session.py +1008 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/cpc/snapshots.py +7 -5
- batplot-1.8.50/batplot/plot_modes/cpc/style.py +1289 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/__init__.py +2 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/actions.py +7 -4
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/colors.py +10 -5
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/dqdv_2d.py +4 -28
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/interactive.py +27 -12
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/menu.py +11 -2
- batplot-1.8.50/batplot/plot_modes/electrochem/overview.py +185 -0
- batplot-1.8.50/batplot/plot_modes/electrochem/session.py +1209 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/style.py +8 -14
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/style_apply.py +6 -3
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/actions.py +8 -7
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/colors.py +10 -8
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/interactive.py +3 -4
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/plot.py +12 -4
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/session.py +23 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/__init__.py +2 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/actions.py +8 -5
- batplot-1.8.50/batplot/plot_modes/operando/axis_units.py +424 -0
- batplot-1.8.50/batplot/plot_modes/operando/colors.py +353 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/interactive.py +354 -174
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/layout.py +20 -1
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/menu.py +17 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/plot.py +287 -25
- batplot-1.8.50/batplot/plot_modes/operando/session.py +1119 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/style.py +65 -34
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/style_apply.py +583 -341
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/visibility.py +4 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/__init__.py +2 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/actions.py +7 -1
- batplot-1.8.50/batplot/plot_modes/xy/axis_range.py +578 -0
- batplot-1.8.50/batplot/plot_modes/xy/axis_units.py +770 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/cif.py +572 -27
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/colors.py +8 -1
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/data_ops.py +24 -8
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/interactive.py +421 -70
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/labels.py +8 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/menu.py +16 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/pipeline.py +202 -74
- batplot-1.8.50/batplot/plot_modes/xy/session.py +1452 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/style.py +334 -51
- {batplot-1.8.47 → batplot-1.8.50}/batplot/readers.py +9 -374
- batplot-1.8.50/batplot/readers_xrd.py +425 -0
- batplot-1.8.50/batplot/session.py +107 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/utils.py +85 -31
- {batplot-1.8.47 → batplot-1.8.50}/batplot/version_check.py +3 -6
- {batplot-1.8.47 → batplot-1.8.50}/batplot.egg-info/PKG-INFO +31 -2
- {batplot-1.8.47 → batplot-1.8.50}/batplot.egg-info/SOURCES.txt +24 -0
- {batplot-1.8.47 → batplot-1.8.50}/pyproject.toml +1 -1
- batplot-1.8.50/tests/test_all_menus_smoke.py +1977 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_batch_menu_parity.py +3 -1
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_batch_session.py +7 -1
- batplot-1.8.50/tests/test_bc_new_fields_defaults.py +101 -0
- batplot-1.8.50/tests/test_cif_tick_crystallography.py +82 -0
- batplot-1.8.50/tests/test_cli_all_flags.py +154 -0
- batplot-1.8.50/tests/test_color_display_hex.py +59 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_contracts.py +16 -12
- batplot-1.8.50/tests/test_deep_noninteractive_bugs.py +282 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_ec_roundtrip.py +31 -1
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_histo.py +1 -1
- batplot-1.8.50/tests/test_interactive_menu_smoke.py +545 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_interactive_state.py +29 -0
- batplot-1.8.50/tests/test_operando_axis_units.py +258 -0
- batplot-1.8.50/tests/test_operando_cif_add.py +213 -0
- batplot-1.8.50/tests/test_operando_cif_color.py +183 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_operando_roundtrip.py +2 -1
- batplot-1.8.50/tests/test_operando_submenu_smoke.py +226 -0
- batplot-1.8.50/tests/test_overview_metrics.py +216 -0
- batplot-1.8.50/tests/test_pi_axis_units_persistence.py +140 -0
- batplot-1.8.50/tests/test_pisb_deep_all_modes.py +656 -0
- batplot-1.8.50/tests/test_undo_deep_all_modes.py +177 -0
- batplot-1.8.50/tests/test_xy_axis_units.py +466 -0
- batplot-1.8.50/tests/test_xy_cif_add.py +408 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_xy_modules.py +16 -2
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_xy_roundtrip.py +93 -0
- batplot-1.8.47/batplot/data/latest_release_notes.json +0 -12
- batplot-1.8.47/batplot/plot_modes/cpc/session.py +0 -23
- batplot-1.8.47/batplot/plot_modes/electrochem/session.py +0 -15
- batplot-1.8.47/batplot/plot_modes/operando/colors.py +0 -173
- batplot-1.8.47/batplot/plot_modes/operando/session.py +0 -15
- batplot-1.8.47/batplot/plot_modes/xy/axis_range.py +0 -611
- batplot-1.8.47/batplot/plot_modes/xy/session.py +0 -15
- batplot-1.8.47/batplot/session.py +0 -4791
- batplot-1.8.47/tests/test_interactive_menu_smoke.py +0 -236
- {batplot-1.8.47 → batplot-1.8.50}/DEVELOPING.md +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/LICENSE +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/MANIFEST.in +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/NOTICE +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/_mpl_backend.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/cif.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/cli.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/cli_save.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/config.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/converters.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/dev_upgrade.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/ec_common.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/modes.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/__init__.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/__init__.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/batch_commands.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/batch_crosshair.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/batch_geom_helpers.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/batch_io.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/batch_menu_helpers.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/batch_panel_state.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/cpc_batch_helpers.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/histo_batch_helpers.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/kinds.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/routing.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/batch_session/xy_batch_helpers.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/__init__.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/axis_state.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/batch_font.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/crosshair_export.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/files.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/fonts.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/interactive_state.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/size_spec.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/smoothing.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/sources.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/state_capture.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/style_routing.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/common/title_offsets.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/cpc/colors.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/cpc/labels.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/export.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/labels.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/legend.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/legend_order.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/line_style.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/routing.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/electrochem/spine_colors.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/__init__.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/density_curve.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/fonts.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/labels.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/line_style.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/load.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/routing.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/spines.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/toggles.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/wizard.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/histo/y_range.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/grid.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/ions_axis.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/labels.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/layout_menu.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/line_style.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/peaks.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/operando/routing.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/session_routing.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/arrange.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/derivative.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/game.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/line_style.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/peaks.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/smoothing.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plot_modes/xy/spines.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/plotting.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/showcol.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/style.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot/ui.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot.egg-info/dependency_links.txt +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot.egg-info/entry_points.txt +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot.egg-info/requires.txt +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/batplot.egg-info/top_level.txt +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/setup.cfg +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/setup.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_batch_all_modes_sync.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_batch_crosshair.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_batch_ec_cycles_status.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_batch_font_menu.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_batch_geom_menu.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_batch_panel_status.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_batch_pisb_contract.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_batch_spine_sync.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_bruker_intensity.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_cli_save.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_cli_smoke.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_color_listing_visible.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_color_utils.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_common_files.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_common_palettes.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_cpc_roundtrip.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_critical_stability_fixes.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_cross_platform_parity.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_crosshair_export.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_csv_readers.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_dev_upgrade.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_dqdv_contour_session_keys.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_histo_interactive_imports.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_imk_stderr_guard.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_menu_handler_imports.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_menu_prompt_order.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_mpl_backend.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_operando_batch_menu.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_operando_layout_menu.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_session_backward_compat.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_session_font_restore.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_state_capture.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/tests/test_style_routing.py +0 -0
- {batplot-1.8.47 → batplot-1.8.50}/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.
|
|
3
|
+
Version: 1.8.50
|
|
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
|
|
@@ -64,6 +64,7 @@ With a single line of command to easily plot publication-ready plots with custom
|
|
|
64
64
|
- **Electrochemistry Plot**: Galvanostatic cycling (GC), cyclic voltammetry (CV), differential capacity (dQdV), capacity per cycle (CPC) with multi-file support
|
|
65
65
|
- **1D XY plot**: Designed for XRD, PDF, XAS (XANES/EXAFS) but also support other types
|
|
66
66
|
- **Operando Contour plot**: Correlate in-situ characterizations (XRD/PDF/XAS) with electrochemical data
|
|
67
|
+
- **XRD axis units**: Interactive Options `u` converts 2θ ↔ Q ↔ d (XY and operando); CIF phase ticks follow the current domain
|
|
67
68
|
- **Histogram mode**: Column histograms from tabular `.csv`/`.txt` data (e.g. particle-size lists)
|
|
68
69
|
- **Interactive plotting**: Real-time editing customized for each type of plottings
|
|
69
70
|
- **Session Persistence**: Save and reload complete plot states with `.pkl` files
|
|
@@ -94,11 +95,12 @@ In batplot, --xaxis is frequently used to indicate the data type.
|
|
|
94
95
|
|
|
95
96
|
```bash
|
|
96
97
|
|
|
97
|
-
# Specify X-axis type (Q, 2theta, r, k, energy, time or any user defined names)
|
|
98
|
+
# Specify X-axis type (Q, 2theta, d, r, k, energy, time or any user defined names)
|
|
98
99
|
# By defauly, batplot will skip the header lines, plot the first and second columns as x and y
|
|
99
100
|
# Q and q are equivalent (case-insensitive)
|
|
100
101
|
batplot pattern.xye --xaxis 2theta --i
|
|
101
102
|
batplot data.qye --xaxis q --i
|
|
103
|
+
batplot data.xye --xaxis d --wl 1.54 --i
|
|
102
104
|
batplot data.txt --xaxis whatever --i
|
|
103
105
|
|
|
104
106
|
# Set X-axis range
|
|
@@ -191,6 +193,27 @@ batplot file1.xy file2.xy --stack --i
|
|
|
191
193
|
batplot allfiles --xaxis 2theta --xrange 15 75 --i
|
|
192
194
|
```
|
|
193
195
|
|
|
196
|
+
**XRD Options `u` (axis units):** On diffraction plots only, press `u` to convert the x-axis among **2θ ↔ Q ↔ d**. Conversions that involve 2θ need a wavelength (`--wl`, `file:wl`, or a prompt). Data, axis labels/limits, and CIF ticks stay in sync. Not available for PDF/XAS or other non-XRD axes.
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
# Launch in 2θ, then use Options u → q (or d) inside the menu
|
|
200
|
+
batplot data.xye:0.709 --xaxis 2theta --i
|
|
201
|
+
batplot data.xye --xaxis 2theta --wl 1.5406 --i
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### CIF phase ticks
|
|
205
|
+
|
|
206
|
+
Add one or more `.cif` files to overlay Bragg reflection markers. Peaks are stored in Q and drawn in the current axis domain (2θ / Q / d). Use `cif` in the interactive menu to add, rename, or hide sets; after Options `u`, ticks redraw in the new units.
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Q plot + CIF ticks
|
|
210
|
+
batplot scan.xye:1.54 phase.cif --i
|
|
211
|
+
|
|
212
|
+
# 2θ plot: give λ for data and/or CIF (file.cif:wl)
|
|
213
|
+
batplot scan.xye phase.cif:0.709 --xaxis 2theta --wl 0.709 --i
|
|
214
|
+
batplot scan.xye:1.54 phase.cif --stack --i
|
|
215
|
+
```
|
|
216
|
+
|
|
194
217
|
### Session save without interactive menu (`--save`)
|
|
195
218
|
|
|
196
219
|
```bash
|
|
@@ -306,6 +329,12 @@ batplot --operando --1d --i
|
|
|
306
329
|
batplot folder phase.cif:1.54 --operando --i
|
|
307
330
|
```
|
|
308
331
|
|
|
332
|
+
**XRD Options `u`:** In the operando interactive menu, press `u` to convert the contour x-axis among **2θ ↔ Q ↔ d** (XRD only; needs λ for 2θ). CIF ticks follow the new domain. Prefer an explicit `--xaxis` when combining with `--wl` (e.g. `--xaxis 2theta --wl 0.709` keeps degrees; `--wl` alone still defaults to Q).
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
batplot folder phase.cif --operando --xaxis 2theta --wl 0.709 --i
|
|
336
|
+
```
|
|
337
|
+
|
|
309
338
|
Operando column selection:
|
|
310
339
|
- `--readcolc <x> <y>`: columns for the contour plot (from .xy/.xye/.qye/.dat files)
|
|
311
340
|
- `--readcols <x> <y>`: columns for the side panel (from .mpt file)
|
|
@@ -10,6 +10,7 @@ With a single line of command to easily plot publication-ready plots with custom
|
|
|
10
10
|
- **Electrochemistry Plot**: Galvanostatic cycling (GC), cyclic voltammetry (CV), differential capacity (dQdV), capacity per cycle (CPC) with multi-file support
|
|
11
11
|
- **1D XY plot**: Designed for XRD, PDF, XAS (XANES/EXAFS) but also support other types
|
|
12
12
|
- **Operando Contour plot**: Correlate in-situ characterizations (XRD/PDF/XAS) with electrochemical data
|
|
13
|
+
- **XRD axis units**: Interactive Options `u` converts 2θ ↔ Q ↔ d (XY and operando); CIF phase ticks follow the current domain
|
|
13
14
|
- **Histogram mode**: Column histograms from tabular `.csv`/`.txt` data (e.g. particle-size lists)
|
|
14
15
|
- **Interactive plotting**: Real-time editing customized for each type of plottings
|
|
15
16
|
- **Session Persistence**: Save and reload complete plot states with `.pkl` files
|
|
@@ -40,11 +41,12 @@ In batplot, --xaxis is frequently used to indicate the data type.
|
|
|
40
41
|
|
|
41
42
|
```bash
|
|
42
43
|
|
|
43
|
-
# Specify X-axis type (Q, 2theta, r, k, energy, time or any user defined names)
|
|
44
|
+
# Specify X-axis type (Q, 2theta, d, r, k, energy, time or any user defined names)
|
|
44
45
|
# By defauly, batplot will skip the header lines, plot the first and second columns as x and y
|
|
45
46
|
# Q and q are equivalent (case-insensitive)
|
|
46
47
|
batplot pattern.xye --xaxis 2theta --i
|
|
47
48
|
batplot data.qye --xaxis q --i
|
|
49
|
+
batplot data.xye --xaxis d --wl 1.54 --i
|
|
48
50
|
batplot data.txt --xaxis whatever --i
|
|
49
51
|
|
|
50
52
|
# Set X-axis range
|
|
@@ -137,6 +139,27 @@ batplot file1.xy file2.xy --stack --i
|
|
|
137
139
|
batplot allfiles --xaxis 2theta --xrange 15 75 --i
|
|
138
140
|
```
|
|
139
141
|
|
|
142
|
+
**XRD Options `u` (axis units):** On diffraction plots only, press `u` to convert the x-axis among **2θ ↔ Q ↔ d**. Conversions that involve 2θ need a wavelength (`--wl`, `file:wl`, or a prompt). Data, axis labels/limits, and CIF ticks stay in sync. Not available for PDF/XAS or other non-XRD axes.
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Launch in 2θ, then use Options u → q (or d) inside the menu
|
|
146
|
+
batplot data.xye:0.709 --xaxis 2theta --i
|
|
147
|
+
batplot data.xye --xaxis 2theta --wl 1.5406 --i
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### CIF phase ticks
|
|
151
|
+
|
|
152
|
+
Add one or more `.cif` files to overlay Bragg reflection markers. Peaks are stored in Q and drawn in the current axis domain (2θ / Q / d). Use `cif` in the interactive menu to add, rename, or hide sets; after Options `u`, ticks redraw in the new units.
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# Q plot + CIF ticks
|
|
156
|
+
batplot scan.xye:1.54 phase.cif --i
|
|
157
|
+
|
|
158
|
+
# 2θ plot: give λ for data and/or CIF (file.cif:wl)
|
|
159
|
+
batplot scan.xye phase.cif:0.709 --xaxis 2theta --wl 0.709 --i
|
|
160
|
+
batplot scan.xye:1.54 phase.cif --stack --i
|
|
161
|
+
```
|
|
162
|
+
|
|
140
163
|
### Session save without interactive menu (`--save`)
|
|
141
164
|
|
|
142
165
|
```bash
|
|
@@ -252,6 +275,12 @@ batplot --operando --1d --i
|
|
|
252
275
|
batplot folder phase.cif:1.54 --operando --i
|
|
253
276
|
```
|
|
254
277
|
|
|
278
|
+
**XRD Options `u`:** In the operando interactive menu, press `u` to convert the contour x-axis among **2θ ↔ Q ↔ d** (XRD only; needs λ for 2θ). CIF ticks follow the new domain. Prefer an explicit `--xaxis` when combining with `--wl` (e.g. `--xaxis 2theta --wl 0.709` keeps degrees; `--wl` alone still defaults to Q).
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
batplot folder phase.cif --operando --xaxis 2theta --wl 0.709 --i
|
|
282
|
+
```
|
|
283
|
+
|
|
255
284
|
Operando column selection:
|
|
256
285
|
- `--readcolc <x> <y>`: columns for the contour plot (from .xy/.xye/.qye/.dat files)
|
|
257
286
|
- `--readcols <x> <y>`: columns for the side panel (from .mpt file)
|
|
@@ -172,6 +172,8 @@ def _print_general_help() -> None:
|
|
|
172
172
|
"Features:\n"
|
|
173
173
|
" • Interactive (--i): styling, ranges, fonts, export, sessions\n"
|
|
174
174
|
" • XRD wavelength: --wl 1.54 or file.xye:1.5406 for Q conversion\n"
|
|
175
|
+
" • XRD axis units (interactive): Options u converts 2θ ↔ Q ↔ d (XY + operando; needs λ for 2θ)\n"
|
|
176
|
+
" • CIF phase ticks: add .cif (or file.cif:wl); ticks follow the current axis (2θ / Q / d)\n"
|
|
175
177
|
" • X-axis range: --xrange min max\n"
|
|
176
178
|
" • Save figure: --out filename (default .svg)\n"
|
|
177
179
|
" • Save session: --save (choose folder + name; default stem for single file / --all batch)\n"
|
|
@@ -204,10 +206,21 @@ def _print_xy_help() -> None:
|
|
|
204
206
|
msg = (
|
|
205
207
|
"XY plots (XRD/PDF/XAS and many more)\n\n"
|
|
206
208
|
"Supported files: .xye .xy .qye .dat .csv .gr .nor .chik .chir .txt .brml .raw .xrdml .rasx and other formats. CIF overlays supported.\n\n"
|
|
207
|
-
"Axis detection: .qye→Q, .gr→r, .nor→energy, .chik→k, .chir→r, else use --xaxis (Q, 2theta, r, k, energy, time or user defined).\n"
|
|
209
|
+
"Axis detection: .qye→Q, .gr→r, .nor→energy, .chik→k, .chir→r, else use --xaxis (Q, 2theta, d, r, k, energy, time or user defined).\n"
|
|
208
210
|
"If mixing 2θ data in Q, give wavelength per-file (file.xye:1.5406) or global flag --wl.\n"
|
|
209
211
|
"A wavelength can be converted into a different wave length by file.xye:1.54:0.709.\n"
|
|
210
212
|
"For electrochemistry CSV/MPT time-potential plots, use --xaxis time.\n\n"
|
|
213
|
+
"Interactive XRD axis units (Options u):\n"
|
|
214
|
+
" In --i, press u to convert the plotted XRD axis among 2θ ↔ Q ↔ d (XRD data only).\n"
|
|
215
|
+
" Conversions involving 2θ need λ (--wl, file:wl, or prompt). CIF ticks stay Bragg-aligned.\n"
|
|
216
|
+
" Not for PDF (.gr), XAS (.nor/.chik/.chir), or other non-diffraction axes.\n"
|
|
217
|
+
" Example: batplot data.xye:0.709 --xaxis 2theta --i then u → q (uses λ=0.709 Å).\n\n"
|
|
218
|
+
"CIF phase ticks:\n"
|
|
219
|
+
" Add .cif files on the command line (optional :wl for 2θ). Peaks are stored in Q and\n"
|
|
220
|
+
" drawn in the current domain (2θ / Q / d). In --i use cif to add/reorder/hide ticks;\n"
|
|
221
|
+
" after Options u, ticks redraw in the new units. Example:\n"
|
|
222
|
+
" batplot scan.xye:1.54 phase.cif --i\n"
|
|
223
|
+
" batplot scan.xye phase.cif:0.709 --xaxis 2theta --wl 0.709 --i\n\n"
|
|
211
224
|
"Examples:\n"
|
|
212
225
|
" batplot file.xy file2.xye --xaxis 2theta --i # Plot XRD data in 2theta space\n"
|
|
213
226
|
" batplot file1.xye:1.5406 file2.txt:0.709 --i # Plot XRD data in different wavelengths in q space\n"
|
|
@@ -225,6 +238,7 @@ def _print_xy_help() -> None:
|
|
|
225
238
|
"Tips and options:\n"
|
|
226
239
|
"[XY plot]\n"
|
|
227
240
|
" --i : open interactive menu for styling, ranges, fonts, export, sessions\n"
|
|
241
|
+
" (XRD: Options u = convert axis 2θ ↔ Q ↔ d; cif = phase tick overlay)\n"
|
|
228
242
|
" --delta <float> : spacing between curves, e.g. --delta 0.1\n"
|
|
229
243
|
" --norm : normalize intensity to 0-1 range. Stack mode (--stack) auto-normalizes\n"
|
|
230
244
|
" --chik : EXAFS χ(k) plot (sets labels to k (Å⁻¹) vs χ(k))\n"
|
|
@@ -236,8 +250,8 @@ def _print_xy_help() -> None:
|
|
|
236
250
|
" --xrange <min> <max> : set x-axis range, e.g. --xrange 0 10\n"
|
|
237
251
|
" --out <filename> : save figure to file, e.g. --out file.svg\n"
|
|
238
252
|
" --save : save .pkl session (prompt folder + name; no --i menu)\n"
|
|
239
|
-
" --xaxis <type> : set x-axis type (Q, 2theta, r, k, energy, rft, time, or user defined)\n"
|
|
240
|
-
" Q and q are equivalent (case-insensitive). e.g. --xaxis 2theta, --xaxis Q, --xaxis
|
|
253
|
+
" --xaxis <type> : set x-axis type (Q, 2theta, d, r, k, energy, rft, time, or user defined)\n"
|
|
254
|
+
" Q and q are equivalent (case-insensitive). e.g. --xaxis 2theta, --xaxis Q, --xaxis d\n"
|
|
241
255
|
" --ro : swap x and y axes (exchange x and y values before plotting)\n"
|
|
242
256
|
" e.g. --xaxis time --ro plots time as y-axis and potential as x-axis\n"
|
|
243
257
|
" --wl <float> : set wavelength for Q conversion for all files, e.g. --wl 1.5406\n"
|
|
@@ -426,6 +440,9 @@ def _print_op_help() -> None:
|
|
|
426
440
|
"Interactive (--i): menu has (Styles), (Operando), (Side Panel), (Options) columns.\n"
|
|
427
441
|
"Resize axes/canvas, change colormap, set intensity range (oz), side-panel options,\n"
|
|
428
442
|
"geometry tweaks, toggle spines/ticks/labels, print/export/import style, save session.\n"
|
|
443
|
+
"XRD only — Options u: convert contour X among 2θ ↔ Q ↔ d (needs λ for 2θ; CIF ticks follow).\n"
|
|
444
|
+
"CIF: add .cif on the command line or via the CIF submenu; ticks stay Bragg-aligned after u.\n"
|
|
445
|
+
" Example: batplot folder phase.cif --operando --xaxis 2theta --wl 0.709 --i\n"
|
|
429
446
|
"Session save without menu: --save (combined operando plot — session name required).\n"
|
|
430
447
|
)
|
|
431
448
|
_print_help(msg)
|
|
@@ -255,6 +255,7 @@ def batch_process(directory: str, args):
|
|
|
255
255
|
# We detect the format from the file extension and use the
|
|
256
256
|
# appropriate reader function.
|
|
257
257
|
# ============================================================
|
|
258
|
+
file_wl = getattr(args, "wl", None)
|
|
258
259
|
|
|
259
260
|
if ext == '.gr':
|
|
260
261
|
x, y = read_gr_file(fpath); e = None
|
|
@@ -281,8 +282,9 @@ def batch_process(directory: str, args):
|
|
|
281
282
|
elif ext in ('.brml', '.xrdml', '.rasx') or (ext == '.raw' and is_bruker_raw(fpath)):
|
|
282
283
|
x, y, e, wl_from_file = read_xrd_vendor_file(fpath)
|
|
283
284
|
axis_mode = '2theta'
|
|
284
|
-
if
|
|
285
|
-
args.wl
|
|
285
|
+
if file_wl is None and wl_from_file is not None:
|
|
286
|
+
# Per-file wavelength only — do not mutate shared args.wl
|
|
287
|
+
file_wl = wl_from_file
|
|
286
288
|
elif ext == '.raw':
|
|
287
289
|
# .raw from non-Bruker instrument: load as generic text
|
|
288
290
|
data = robust_loadtxt_skipheader(fpath)
|
|
@@ -374,12 +376,12 @@ def batch_process(directory: str, args):
|
|
|
374
376
|
|
|
375
377
|
# Convert to Q if needed
|
|
376
378
|
if axis_mode == 'Q' and ext not in ('.qye', '.gr', '.nor'):
|
|
377
|
-
if
|
|
379
|
+
if file_wl is None:
|
|
378
380
|
axis_mode = '2theta'
|
|
379
381
|
x_plot = x
|
|
380
382
|
else:
|
|
381
383
|
theta_rad = np.radians(x/2)
|
|
382
|
-
x_plot = 4*np.pi*np.sin(theta_rad)/
|
|
384
|
+
x_plot = 4*np.pi*np.sin(theta_rad)/file_wl
|
|
383
385
|
else:
|
|
384
386
|
x_plot = x
|
|
385
387
|
|
|
@@ -414,6 +414,8 @@ def batplot_main() -> int: # type: ignore
|
|
|
414
414
|
getattr(args, 'histo', False), # Histogram mode
|
|
415
415
|
getattr(args, 'all', None) is not None, # Batch mode flag
|
|
416
416
|
getattr(args, 'convert', None) is not None, # Conversion mode
|
|
417
|
+
getattr(args, 'canvas', False), # Canvas combine mode
|
|
418
|
+
getattr(args, 'extract_brml_scans', None) is not None, # BRML scan extract
|
|
417
419
|
])
|
|
418
420
|
|
|
419
421
|
# If no files AND no special flags, nothing to do
|
|
@@ -422,12 +424,37 @@ def batplot_main() -> int: # type: ignore
|
|
|
422
424
|
print("Use 'batplot --v' for version and release info, 'batplot --h' for CLI help, or 'batplot --m' to open the user manual.")
|
|
423
425
|
return 0 # Exit successfully (not an error, just nothing to do)
|
|
424
426
|
|
|
427
|
+
# --extract-brml-scans: extract each XRD scan from .brml to .xy files, then exit
|
|
428
|
+
if getattr(args, "extract_brml_scans", None) is not None:
|
|
429
|
+
from .readers_xrd import extract_bruker_brml_scans
|
|
430
|
+
|
|
431
|
+
brml_files = [f for f in (args.files or []) if str(f).lower().endswith(".brml")]
|
|
432
|
+
if not brml_files:
|
|
433
|
+
print("batplot --extract-brml-scans: provide at least one .brml file.")
|
|
434
|
+
return 1
|
|
435
|
+
out_opt = getattr(args, "extract_brml_scans", "")
|
|
436
|
+
status = 0
|
|
437
|
+
for brml in brml_files:
|
|
438
|
+
try:
|
|
439
|
+
stem = os.path.splitext(os.path.basename(brml))[0]
|
|
440
|
+
out_dir = out_opt if out_opt else f"{stem}_scans"
|
|
441
|
+
if not os.path.isabs(out_dir):
|
|
442
|
+
out_dir = os.path.join(os.path.dirname(os.path.abspath(brml)) or ".", out_dir)
|
|
443
|
+
scans = extract_bruker_brml_scans(brml, out_dir=out_dir)
|
|
444
|
+
print(f"Extracted {len(scans)} scan(s) from {brml} → {out_dir}")
|
|
445
|
+
except Exception as exc:
|
|
446
|
+
print(f"Error extracting {brml}: {exc}")
|
|
447
|
+
status = 1
|
|
448
|
+
return status
|
|
449
|
+
|
|
425
450
|
from ._mpl_backend import ensure_gui_backend
|
|
426
451
|
|
|
427
452
|
ensure_gui_backend(args)
|
|
428
453
|
|
|
429
|
-
# Histogram mode (tabular CSV/TXT)
|
|
430
|
-
|
|
454
|
+
# Histogram mode (tabular CSV/TXT) — after convert so --histo --convert still converts
|
|
455
|
+
# (convert is handled below after allfiles expansion when both flags appear).
|
|
456
|
+
# Prefer convert when both are set.
|
|
457
|
+
if getattr(args, 'histo', False) and getattr(args, 'convert', None) is None:
|
|
431
458
|
from .plot_modes.histo.routing import handle_histo_mode
|
|
432
459
|
return handle_histo_mode(args)
|
|
433
460
|
|
|
@@ -550,20 +577,32 @@ def batplot_main() -> int: # type: ignore
|
|
|
550
577
|
if len(args.files) == 1:
|
|
551
578
|
sole = args.files[0]
|
|
552
579
|
if sole.lower() == 'all':
|
|
553
|
-
|
|
554
|
-
|
|
580
|
+
if getattr(args, "interactive", False):
|
|
581
|
+
_prepare_allfiles_directory(os.getcwd(), args, use_relative_paths=True)
|
|
582
|
+
# Continue to interactive multi-file plotting
|
|
583
|
+
else:
|
|
584
|
+
batch_process(os.getcwd(), args)
|
|
585
|
+
raise SystemExit(0)
|
|
555
586
|
elif sole.lower() == 'allfiles':
|
|
556
587
|
_prepare_allfiles_directory(os.getcwd(), args, use_relative_paths=True)
|
|
557
588
|
# Continue to normal plotting mode with all files
|
|
558
589
|
elif os.path.isdir(sole):
|
|
559
|
-
|
|
560
|
-
|
|
590
|
+
if getattr(args, "interactive", False):
|
|
591
|
+
_prepare_allfiles_directory(os.path.abspath(sole), args, use_relative_paths=False)
|
|
592
|
+
# Continue to interactive multi-file plotting of directory contents
|
|
593
|
+
else:
|
|
594
|
+
batch_process(os.path.abspath(sole), args)
|
|
595
|
+
raise SystemExit(0)
|
|
561
596
|
|
|
562
597
|
# --- XY Batch Mode: check for --all flag for XY files ---
|
|
563
598
|
# Handle --all flag for XY batch processing (consistent with EC batch mode)
|
|
564
599
|
if not ec_mode_active and getattr(args, 'all', None) is not None:
|
|
565
|
-
|
|
566
|
-
|
|
600
|
+
if getattr(args, "interactive", False):
|
|
601
|
+
# --all --i: expand cwd files into interactive session instead of SVG batch
|
|
602
|
+
_prepare_allfiles_directory(os.getcwd(), args, use_relative_paths=True)
|
|
603
|
+
else:
|
|
604
|
+
batch_process(os.getcwd(), args)
|
|
605
|
+
raise SystemExit(0)
|
|
567
606
|
|
|
568
607
|
# ---------------- Canvas mode: combine multiple .pkl sessions ----------------
|
|
569
608
|
canvas_status = _run_canvas_route(args)
|
|
@@ -103,10 +103,16 @@ def _load_panel_session(path: str) -> Optional[Tuple[str, Any, Dict[str, Any]]]:
|
|
|
103
103
|
return None
|
|
104
104
|
fig, ax, menu_kwargs = res
|
|
105
105
|
return ('xy', (fig, ax, menu_kwargs), {'menu_kwargs': menu_kwargs})
|
|
106
|
+
if kind == 'histo':
|
|
107
|
+
from .plot_modes.histo.session import load_histo_session
|
|
108
|
+
res = load_histo_session(path)
|
|
109
|
+
if not res:
|
|
110
|
+
return None
|
|
111
|
+
return ('histo', res, {})
|
|
106
112
|
except Exception as e:
|
|
107
113
|
print(f" Error loading {path}: {e}")
|
|
108
114
|
return None
|
|
109
|
-
print(f" {path}: unknown session format (supported: XY/1D, EC/GC/CV/dQdV, CPC/EPC, operando)")
|
|
115
|
+
print(f" {path}: unknown session format (supported: XY/1D, EC/GC/CV/dQdV, CPC/EPC, operando, histo)")
|
|
110
116
|
return None
|
|
111
117
|
|
|
112
118
|
|
|
@@ -158,7 +164,11 @@ def _default_positions_from_sizes(
|
|
|
158
164
|
|
|
159
165
|
def _print_canvas_menu(panels: List[Tuple[str, str]]):
|
|
160
166
|
"""Print canvas menu with panel numbers and filenames."""
|
|
161
|
-
|
|
167
|
+
from batplot.plot_modes.common.menu_rendering import menu_block_begin, menu_block_end
|
|
168
|
+
|
|
169
|
+
print()
|
|
170
|
+
menu_block_begin(force_new=True)
|
|
171
|
+
print("\033[1mCanvas Interactive Menu:\033[0m")
|
|
162
172
|
for i, (_, path) in enumerate(panels):
|
|
163
173
|
name = os.path.basename(path)
|
|
164
174
|
print(f" \033[93m{i+1}\033[0m: {name}")
|
|
@@ -167,6 +177,7 @@ def _print_canvas_menu(panels: List[Tuple[str, str]]):
|
|
|
167
177
|
print(" 1-9: edit panel • p: insert image • t: add text • Backspace: delete selected annotation")
|
|
168
178
|
print(" e: export • s: save (includes images/text) • q q: quit")
|
|
169
179
|
print(" (Click canvas first for keys; orange box = picture or text overlay)")
|
|
180
|
+
menu_block_end()
|
|
170
181
|
|
|
171
182
|
|
|
172
183
|
def _event_to_figure_coords(fig, event) -> Optional[Tuple[float, float]]:
|
|
@@ -664,6 +675,10 @@ def run_canvas_mode(pkl_paths: List[str]) -> None:
|
|
|
664
675
|
elif kind == 'xy':
|
|
665
676
|
fig, ax, menu_kwargs = data
|
|
666
677
|
interactive_menu(fig, ax, **normalize_xy_menu_kwargs({**menu_kwargs, 'canvas_mode': True}))
|
|
678
|
+
elif kind == 'histo':
|
|
679
|
+
from .plot_modes.histo.interactive import histo_interactive_menu
|
|
680
|
+
fig, ax, state = data
|
|
681
|
+
histo_interactive_menu(fig, ax, state)
|
|
667
682
|
except Exception as e:
|
|
668
683
|
print(f"Panel menu failed: {e}")
|
|
669
684
|
finally:
|
|
@@ -261,6 +261,16 @@ def _ansi_color_block_from_rgba(rgba) -> str:
|
|
|
261
261
|
return "[??]"
|
|
262
262
|
|
|
263
263
|
|
|
264
|
+
def to_display_hex(color) -> Optional[str]:
|
|
265
|
+
"""Normalize any matplotlib-accepted color to lowercase ``#rrggbb`` (no alpha)."""
|
|
266
|
+
if color is None:
|
|
267
|
+
return None
|
|
268
|
+
try:
|
|
269
|
+
return str(mcolors.to_hex(mcolors.to_rgba(color), keep_alpha=False)).lower()
|
|
270
|
+
except Exception:
|
|
271
|
+
return None
|
|
272
|
+
|
|
273
|
+
|
|
264
274
|
def color_block(color: Optional[str]) -> str:
|
|
265
275
|
"""Return a colored block (ANSI) for the supplied color string."""
|
|
266
276
|
if not color:
|
|
@@ -273,17 +283,21 @@ def color_block(color: Optional[str]) -> str:
|
|
|
273
283
|
|
|
274
284
|
|
|
275
285
|
def format_color_listing(color) -> str:
|
|
276
|
-
"""Return ``<swatch> <hex>`` for menu listings (curves, saved colors, etc.).
|
|
286
|
+
"""Return ``<swatch> <hex>`` for menu listings (curves, saved colors, etc.).
|
|
287
|
+
|
|
288
|
+
Always prefers a hex code next to the ANSI color cube so every mode shows
|
|
289
|
+
the same readable form (e.g. ``██ #1f77b4``), including named colors,
|
|
290
|
+
``C0`` cycle colors, and RGBA tuples from matplotlib artists.
|
|
291
|
+
"""
|
|
277
292
|
if color is None:
|
|
278
293
|
return f"{color_block(None)} --"
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
return f"{color_block(color)} {mcolors.to_hex(rgba)}"
|
|
282
|
-
except Exception:
|
|
294
|
+
hex_code = to_display_hex(color)
|
|
295
|
+
if hex_code is None:
|
|
283
296
|
text = str(color).strip()
|
|
284
297
|
if not text:
|
|
285
298
|
return f"{color_block(None)} --"
|
|
286
|
-
return f"{color_block(
|
|
299
|
+
return f"{color_block(None)} {text}"
|
|
300
|
+
return f"{color_block(hex_code)} {hex_code}"
|
|
287
301
|
|
|
288
302
|
|
|
289
303
|
def color_bar(colors: Sequence[str]) -> str:
|
|
@@ -543,21 +557,23 @@ def resolve_color_token(token: str, fig=None) -> str:
|
|
|
543
557
|
colors = get_user_color_list(fig)
|
|
544
558
|
# Check if index is valid (within bounds of color list)
|
|
545
559
|
if 0 <= idx < len(colors):
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
#
|
|
549
|
-
|
|
560
|
+
token = colors[idx]
|
|
561
|
+
|
|
562
|
+
# Normalize named / cycle / RGBA colors to lowercase hex for consistent
|
|
563
|
+
# display and storage across modes. Unknown tokens pass through unchanged.
|
|
564
|
+
hex_code = to_display_hex(token)
|
|
565
|
+
return hex_code if hex_code is not None else token
|
|
550
566
|
|
|
551
567
|
|
|
552
568
|
def print_user_colors(fig=None) -> None:
|
|
553
|
-
"""Print saved colors with indices and
|
|
569
|
+
"""Print saved colors with indices, color cubes, and hex codes."""
|
|
554
570
|
colors = get_user_color_list(fig)
|
|
555
571
|
if not colors:
|
|
556
572
|
print("No saved user colors.")
|
|
557
573
|
return
|
|
558
574
|
print("Saved colors:")
|
|
559
575
|
for idx, color in enumerate(colors, 1):
|
|
560
|
-
print(f" {idx}: {
|
|
576
|
+
print(f" {idx}: {format_color_listing(color)}")
|
|
561
577
|
|
|
562
578
|
|
|
563
579
|
def manage_user_colors(fig=None) -> None:
|
|
@@ -567,7 +583,7 @@ def manage_user_colors(fig=None) -> None:
|
|
|
567
583
|
print("\n\033[1mUser color list:\033[0m")
|
|
568
584
|
if colors:
|
|
569
585
|
for idx, color in enumerate(colors, 1):
|
|
570
|
-
print(f" {idx}: {
|
|
586
|
+
print(f" {idx}: {format_color_listing(color)}")
|
|
571
587
|
else:
|
|
572
588
|
print(" (empty)")
|
|
573
589
|
print("Options: \033[96ma\033[0m=add colors \033[96md\033[0m=delete numbers \033[96mc\033[0m=clear \033[96mq\033[0m=back")
|
|
@@ -588,8 +604,9 @@ def manage_user_colors(fig=None) -> None:
|
|
|
588
604
|
colors = get_user_color_list(fig)
|
|
589
605
|
added = 0
|
|
590
606
|
for col in new_colors:
|
|
591
|
-
|
|
592
|
-
|
|
607
|
+
hex_col = to_display_hex(col) or col
|
|
608
|
+
if hex_col not in colors and col not in colors:
|
|
609
|
+
colors.append(hex_col)
|
|
593
610
|
added += 1
|
|
594
611
|
_save_user_colors(colors, fig)
|
|
595
612
|
print(f"Added {added} color(s).")
|
|
@@ -640,11 +657,13 @@ __all__ = [
|
|
|
640
657
|
'color_bar',
|
|
641
658
|
'color_block',
|
|
642
659
|
'ensure_colormap',
|
|
660
|
+
'format_color_listing',
|
|
643
661
|
'get_colormap',
|
|
644
662
|
'manage_user_colors',
|
|
645
663
|
'palette_preview',
|
|
646
664
|
'print_user_colors',
|
|
647
665
|
'remove_user_color',
|
|
666
|
+
'to_display_hex',
|
|
648
667
|
'resolve_color_token',
|
|
649
668
|
'get_user_color_list',
|
|
650
669
|
]
|
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.8.50] - 2026-08-02
|
|
4
|
+
- Cosmetic changes of interactive interface
|
|
5
|
+
- Better CIF file handling
|
|
6
|
+
- Bug fixes
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## [1.8.49] - 2026-07-30
|
|
10
|
+
- GC/CPC interactive overview key `o`: per-cycle capacity & CE table
|
|
11
|
+
(respects CPC invert-efficiency), capacity retention over a cycle range,
|
|
12
|
+
summary stats, and CSV/TXT export. Also available in batch EC/CPC menus.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [1.8.48] - 2026-07-29
|
|
16
|
+
- Bug fixes on session reload
|
|
17
|
+
|
|
18
|
+
|
|
3
19
|
## [1.8.47] - 2026-07-21
|
|
4
20
|
- Added Batch Interactive mode, loading multiple saved .pkl sessions
|
|
5
21
|
(must be the same type, e.g All are GC) to edit basic styles and
|
|
@@ -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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
|
40
|
+
saved: list[tuple[Any, Any, Any]] = []
|
|
36
41
|
try:
|
|
37
|
-
for owner, patch in
|
|
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],
|
|
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
|
|
@@ -75,9 +75,19 @@ def default_ec_tick_state() -> dict:
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
|
|
78
|
-
def ec_tick_state_from_fig(fig: Any) -> dict:
|
|
79
|
-
"""Rebuild the flat EC tick_state dict from the stored WASD state.
|
|
78
|
+
def ec_tick_state_from_fig(fig: Any, ax: Any | None = None) -> dict:
|
|
79
|
+
"""Rebuild the flat EC tick_state dict from the stored WASD state.
|
|
80
|
+
|
|
81
|
+
Falls back to ``ax._saved_tick_state`` when ``fig._ec_wasd_state`` is missing
|
|
82
|
+
(older sessions / loaders that only seeded the axis attribute).
|
|
83
|
+
"""
|
|
80
84
|
wasd = getattr(fig, "_ec_wasd_state", None)
|
|
85
|
+
if not isinstance(wasd, dict) and ax is not None:
|
|
86
|
+
saved = getattr(ax, "_saved_tick_state", None)
|
|
87
|
+
if isinstance(saved, dict) and saved:
|
|
88
|
+
out = default_ec_tick_state()
|
|
89
|
+
out.update(saved)
|
|
90
|
+
return out
|
|
81
91
|
if isinstance(wasd, dict):
|
|
82
92
|
top = wasd.get("top", {})
|
|
83
93
|
bot = wasd.get("bottom", {})
|
|
@@ -148,6 +158,8 @@ def ensure_ec_fig_state(panel: EcPanel, file_data: list[dict], is_multi_file: bo
|
|
|
148
158
|
try:
|
|
149
159
|
fig._ec_file_data = file_data
|
|
150
160
|
fig._ec_is_multi_file = is_multi_file
|
|
161
|
+
# Batch EC sessions are GC-only (kind=ec_gc)
|
|
162
|
+
fig._ec_overview_enabled = True
|
|
151
163
|
if is_multi_file and not hasattr(fig, "_ec_legend_file_order"):
|
|
152
164
|
fig._ec_legend_file_order = list(range(len(file_data)))
|
|
153
165
|
except Exception:
|
|
@@ -304,7 +316,7 @@ def run_ec_batch_spine_menu(
|
|
|
304
316
|
"""Full WASD spine/tick editor on the reference panel, synced to all panels."""
|
|
305
317
|
ax = ref.ax
|
|
306
318
|
fig = ref.fig
|
|
307
|
-
tick_state = ec_tick_state_from_fig(fig)
|
|
319
|
+
tick_state = ec_tick_state_from_fig(fig, ax)
|
|
308
320
|
|
|
309
321
|
def _get_spine_visible(side: str) -> bool:
|
|
310
322
|
sp = ax.spines.get(side)
|
|
@@ -170,6 +170,9 @@ def _load_one_panel(kind: str, path: str):
|
|
|
170
170
|
"mly": False,
|
|
171
171
|
"mry": False,
|
|
172
172
|
}
|
|
173
|
+
saved = getattr(ax, "_saved_tick_state", None) or getattr(fig, "_saved_tick_state", None)
|
|
174
|
+
if isinstance(saved, dict) and saved:
|
|
175
|
+
tick_state.update(saved)
|
|
173
176
|
return CpcPanel(
|
|
174
177
|
path=path,
|
|
175
178
|
fig=fig,
|