batplot 1.8.52__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.
- {batplot-1.8.52 → batplot-1.8.55}/DEVELOPING.md +4 -1
- {batplot-1.8.52 → batplot-1.8.55}/PKG-INFO +12 -15
- {batplot-1.8.52 → batplot-1.8.55}/README.md +11 -14
- {batplot-1.8.52 → batplot-1.8.55}/batplot/__init__.py +1 -1
- {batplot-1.8.52 → batplot-1.8.55}/batplot/_mpl_backend.py +13 -2
- {batplot-1.8.52 → batplot-1.8.55}/batplot/args.py +89 -18
- {batplot-1.8.52 → batplot-1.8.55}/batplot/batch.py +35 -22
- {batplot-1.8.52 → batplot-1.8.55}/batplot/batplot.py +12 -3
- {batplot-1.8.52 → batplot-1.8.55}/batplot/cli.py +14 -1
- {batplot-1.8.52 → batplot-1.8.55}/batplot/config.py +2 -2
- {batplot-1.8.52 → batplot-1.8.55}/batplot/data/CHANGELOG.md +15 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/data/latest_release_notes.json +1 -1
- {batplot-1.8.52 → batplot-1.8.55}/batplot/dev_upgrade.py +41 -19
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_commands.py +18 -14
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_geom_helpers.py +30 -19
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_menu_io.py +12 -5
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/cpc_batch_helpers.py +16 -4
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/dqdv_2d_batch_helpers.py +11 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/ec_batch_helpers.py +156 -15
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/histo_batch_helpers.py +23 -21
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_cpc.py +83 -14
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_dqdv_2d.py +23 -8
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_ec.py +110 -18
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_histo.py +13 -1
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_operando.py +65 -26
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/menu_xy.py +195 -95
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/operando_batch_helpers.py +87 -46
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/xy_batch_helpers.py +116 -33
- batplot-1.8.55/batplot/plot_modes/common/color_menu_help.py +228 -0
- batplot-1.8.55/batplot/plot_modes/common/curve_look_help.py +140 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/fonts.py +16 -1
- batplot-1.8.55/batplot/plot_modes/common/layout_compat.py +515 -0
- batplot-1.8.55/batplot/plot_modes/common/menu_rendering.py +260 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/palettes.py +18 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/session_helpers.py +12 -4
- batplot-1.8.55/batplot/plot_modes/common/size_spec.py +217 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/sources.py +37 -5
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/spines.py +120 -4
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/style_routing.py +2 -2
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/terminal.py +193 -3
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/actions.py +6 -10
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/add_file.py +3 -7
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/colors.py +91 -39
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/interactive.py +22 -10
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/labels.py +39 -19
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/menu.py +5 -5
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/panel_menus.py +42 -12
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/session.py +34 -15
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/style.py +117 -30
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/wasd_menu.py +9 -1
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/actions.py +4 -9
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/colors.py +171 -88
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/interactive.py +31 -14
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/labels.py +41 -18
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/line_style.py +19 -10
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/menu.py +5 -5
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/session.py +78 -21
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/spine_colors.py +26 -16
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/style.py +73 -2
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/style_apply.py +47 -24
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/undo_state.py +15 -2
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/colors.py +60 -40
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/density_curve.py +10 -5
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/interactive.py +33 -19
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/labels.py +38 -13
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/line_style.py +10 -5
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/plot.py +7 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/session.py +2 -2
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/spines.py +17 -4
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/actions.py +2 -2
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/axis_units.py +2 -2
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/cif_menu.py +63 -47
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/colors.py +72 -42
- batplot-1.8.55/batplot/plot_modes/operando/interactive.py +3841 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/labels.py +59 -65
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/layout.py +19 -2
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/layout_menu.py +36 -29
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/line_style.py +35 -25
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/menu.py +21 -21
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/plot.py +92 -21
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/routing.py +5 -9
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/session.py +32 -2
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/spine_colors.py +61 -23
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/style.py +140 -24
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/style_apply.py +81 -24
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/undo_state.py +14 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/visibility.py +7 -1
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/arrange.py +33 -49
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/axis_range.py +80 -20
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/axis_units.py +20 -11
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/cif.py +243 -63
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/colors.py +86 -52
- batplot-1.8.55/batplot/plot_modes/xy/full_data.py +693 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/interactive.py +19 -16
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/labels.py +46 -18
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/line_style.py +19 -10
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/menu.py +21 -5
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/pipeline.py +40 -29
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/session.py +127 -41
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/spines.py +71 -7
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/style.py +266 -105
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/undo_state.py +31 -10
- {batplot-1.8.52 → batplot-1.8.55}/batplot/screen_color.py +85 -11
- {batplot-1.8.52 → batplot-1.8.55}/batplot/showcol.py +19 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/ui.py +312 -97
- {batplot-1.8.52 → batplot-1.8.55}/batplot/utils.py +309 -64
- {batplot-1.8.52 → batplot-1.8.55}/batplot/version_check.py +28 -12
- {batplot-1.8.52 → batplot-1.8.55}/batplot.egg-info/PKG-INFO +12 -15
- {batplot-1.8.52 → batplot-1.8.55}/batplot.egg-info/SOURCES.txt +26 -0
- {batplot-1.8.52 → batplot-1.8.55}/pyproject.toml +1 -1
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_all_menus_smoke.py +7 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_all_modes_sync.py +7 -0
- batplot-1.8.55/tests/test_batch_cpc_key_isolation.py +340 -0
- batplot-1.8.55/tests/test_batch_dqdv_key_isolation.py +292 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_ec_cycles_status.py +8 -2
- batplot-1.8.55/tests/test_batch_gc_key_isolation.py +376 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_geometry_pisb_keys.py +0 -4
- batplot-1.8.55/tests/test_batch_histo_key_isolation.py +169 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_menu_parity.py +6 -3
- batplot-1.8.55/tests/test_batch_operando_key_isolation.py +161 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_session.py +2 -2
- batplot-1.8.55/tests/test_batch_spine_sync.py +204 -0
- batplot-1.8.55/tests/test_batch_xy_key_isolation.py +200 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_common_palettes.py +19 -2
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_contracts.py +32 -2
- batplot-1.8.55/tests/test_cpc_canvas_undo.py +120 -0
- batplot-1.8.55/tests/test_cross_os_deeper.py +226 -0
- batplot-1.8.55/tests/test_curve_look_help.py +95 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_noninteractive_bugs.py +58 -4
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_round12_commercial_gates.py +2 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_dev_upgrade.py +37 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_ec_cpc_geometry_pisb_keys.py +7 -6
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_ec_cycle_identity_roundtrip.py +27 -10
- batplot-1.8.55/tests/test_ec_cycles_three_color_modes.py +215 -0
- batplot-1.8.55/tests/test_ec_old_session_three_color_modes.py +196 -0
- batplot-1.8.55/tests/test_file_dialogs_os.py +257 -0
- batplot-1.8.55/tests/test_geom_size_highlight.py +81 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_histo_geometry_pisb_keys.py +7 -8
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_histo_style_pisb_keys.py +7 -8
- batplot-1.8.55/tests/test_label_shortcuts_math_help.py +151 -0
- batplot-1.8.55/tests/test_line_submenu_pisb_widths.py +156 -0
- batplot-1.8.55/tests/test_menu_rendering_presentation.py +76 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_operando_batch_menu.py +3 -2
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_operando_cif_add.py +43 -6
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_operando_cif_color.py +6 -6
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_operando_geometry_pisb_keys.py +1 -1
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_operando_roundtrip.py +2 -2
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_operando_style_pisb_keys.py +1 -1
- batplot-1.8.55/tests/test_quit_confirm_export_save.py +98 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_spine_colors_pisb.py +216 -0
- batplot-1.8.55/tests/test_spine_wasd_figure_help.py +56 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_spine_wasd_pisb_all_modes.py +57 -3
- batplot-1.8.55/tests/test_stack_rearrange_tick_spacing.py +229 -0
- batplot-1.8.55/tests/test_style_layout_compat.py +230 -0
- batplot-1.8.55/tests/test_tick_display_color_contract.py +331 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_xy_axis_units.py +55 -5
- batplot-1.8.55/tests/test_xy_bps_bpsg_key_matrix.py +291 -0
- batplot-1.8.55/tests/test_xy_cif_add.py +756 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_xy_full_data_retention.py +79 -0
- batplot-1.8.55/tests/test_xy_generic_xy_default.py +373 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_xy_geometry_pisb_keys.py +119 -4
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_xy_style_pisb_keys.py +47 -18
- batplot-1.8.52/batplot/plot_modes/common/menu_rendering.py +0 -145
- batplot-1.8.52/batplot/plot_modes/common/size_spec.py +0 -72
- batplot-1.8.52/batplot/plot_modes/operando/interactive.py +0 -1924
- batplot-1.8.52/batplot/plot_modes/xy/full_data.py +0 -416
- batplot-1.8.52/tests/test_batch_spine_sync.py +0 -82
- batplot-1.8.52/tests/test_xy_cif_add.py +0 -408
- {batplot-1.8.52 → batplot-1.8.55}/LICENSE +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/MANIFEST.in +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/NOTICE +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/canvas_interactive.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/cif.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/cli_save.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/color_utils.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/converters.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/ec_common.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/modes.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/__init__.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/__init__.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_crosshair.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_figure_io.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_io.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_menu_helpers.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_panel_state.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/batch_scoped_sync.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/common.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/kinds.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/load.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/batch_session/routing.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/__init__.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/axis_state.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/batch_font.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/crosshair_export.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/files.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/font_extras.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/interactive_state.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/line_dash.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/menus.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/overview_metrics.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/session_data_guarantee.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/session_key_smoke.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/smoothing.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/state_capture.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/common/title_offsets.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/__init__.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/legend.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/legend_order.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/load.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/overview.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/routing.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/cpc/snapshots.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/__init__.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/capacity_cum.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/dqdv_2d.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/dual_axis_menu.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/export.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/legend.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/legend_order.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/overview.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/routing.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/electrochem/smoothing_menu.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/__init__.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/actions.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/fonts.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/load.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/routing.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/toggles.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/wizard.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/histo/y_range.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/__init__.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/axes_limits_menu.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/grid.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/intensity_menu.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/ions_axis.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/operando/peaks.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/session_routing.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/__init__.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/actions.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/data_ops.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/derivative.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/game.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/offset_menu.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/peaks.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plot_modes/xy/smoothing.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/plotting.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/readers.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/readers_common.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/readers_ec.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/readers_xrd.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/session.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/strip_header.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot/style.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot.egg-info/dependency_links.txt +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot.egg-info/entry_points.txt +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot.egg-info/requires.txt +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/batplot.egg-info/top_level.txt +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/setup.cfg +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/setup.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_crosshair.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_font_menu.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_geom_menu.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_panel_status.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_pisb_contract.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_scoped_sync_modes.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_batch_style_pisb_keys.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_bc_new_fields_defaults.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_bruker_intensity.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_cif_tick_crystallography.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_cli_all_flags.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_cli_save.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_cli_smoke.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_color_display_hex.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_color_listing_visible.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_color_utils.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_common_files.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_convert_xrd.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_cpc_add_file.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_cpc_legend_order.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_cpc_roundtrip.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_critical_stability_fixes.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_cross_os_oe_paths.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_cross_platform_parity.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_crosshair_export.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_csv_readers.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_residual_pisb_gates.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_round10_bc_safe.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_round11_title_fidelity.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_round13_final_key_audit.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_round3_pisb_gates.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_round4_pisb_gates.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_round5_pisb_gates.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_round6_session_fidelity.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_round7_root_helpers.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_round8_root_helpers.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_deep_round9_root_helpers.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_default_sizes_and_oe_persistence.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_dqdv_contour_session_keys.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_dqdv_smooth_status.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_dual_axis_menu_audit.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_dual_mode_pisb.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_dual_pisb_hard_gates.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_dual_tk_a_coupling.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_dual_top_wasd_both_layers.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_ec_cpc_style_pisb_keys.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_ec_multifile_color_menu.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_ec_roundtrip.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_ec_session_bc_new_keys.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_every_key_behavioral_walk.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_final_audit_residuals.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_full_menu_audit_gaps.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_gc_cumulative.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_hard_check_twin_and_batch.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_histo.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_histo_interactive_imports.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_imk_stderr_guard.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_interactive_handler_intent.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_interactive_menu_smoke.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_interactive_state.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_line_dash_styles.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_menu_handler_imports.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_menu_prompt_order.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_mpl_backend.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_operando_axis_units.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_operando_layout_menu.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_operando_peaks_axis_units.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_operando_spine_isolation.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_operando_submenu_smoke.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_overview_metrics.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_pi_axis_units_persistence.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_pisb_deep_all_modes.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_recent_axis_names.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_screen_color.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_screen_color_pisb.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_secondary_spine_colors.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_session_backward_compat.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_session_font_restore.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_session_full_data_guarantee.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_session_save_integrity.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_session_style_restore_parity.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_state_capture.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_strip_header.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_stupid_input_hardening.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_style_import_integrity.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_style_routing.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_tick_visibility_save_truth.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_undo_deep_all_modes.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_undo_stack_integrity.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_xrd_crosshair_bragg.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_xy_modules.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_xy_offset_menu.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_xy_roundtrip.py +0 -0
- {batplot-1.8.52 → batplot-1.8.55}/tests/test_xy_source_files.py +0 -0
|
@@ -460,7 +460,10 @@ Before changing release behavior:
|
|
|
460
460
|
`--dev-upgrade` runs `sync_pyproject_package_data()` to refresh
|
|
461
461
|
`[tool.setuptools.package-data]`.
|
|
462
462
|
- Git: `_git_stage_release_snapshot()` stages tracked updates and all untracked
|
|
463
|
-
non-ignored paths (no hand-maintained file list)
|
|
463
|
+
non-ignored paths (no hand-maintained file list), and **always** re-stages
|
|
464
|
+
the MkDocs user manual (`docs/`, `mkdocs.yml`, `.github/workflows/docs.yml`,
|
|
465
|
+
`scripts/capture_manual_figures.py`) so GitHub Pages updates on every
|
|
466
|
+
`--dev-upgrade` / `--dev-git` push.
|
|
464
467
|
4. Keep GitHub/PyPI conflict handling explicit and testable.
|
|
465
468
|
|
|
466
469
|
Canonical version files checked on every release:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: batplot
|
|
3
|
-
Version: 1.8.
|
|
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
|
|
@@ -58,22 +58,22 @@ Dynamic: license-file
|
|
|
58
58
|
|
|
59
59
|
**Interactive plotting tool for battery and materials characterization data**
|
|
60
60
|
|
|
61
|
-
`batplot` is a
|
|
61
|
+
`batplot` is a Command-line based software for quick visuallization of 1D (x,y) and 2D (x,y,z) data with interactive styling and session management. It is designed for researchers within the fields of materials sciences and electrochemistry who do not have programming skills.
|
|
62
|
+
The electrochemistry and operando plots were inspired from Amalie Skurtveit's python scripts (https://github.com/piieceofcake?tab=repositories).
|
|
62
63
|
|
|
63
64
|
## Features
|
|
64
65
|
|
|
65
66
|
With a single line of command to easily plot publication-ready plots with customized, intuitive interactive editing features such as:
|
|
66
67
|
- **Electrochemistry Plot**: Galvanostatic cycling (GC), cyclic voltammetry (CV), differential capacity (dQdV), capacity per cycle (CPC) with multi-file support
|
|
67
|
-
- **1D XY plot**: Designed for XRD, PDF, XAS (XANES/EXAFS) but also support other types
|
|
68
|
+
- **1D XY plot**: Designed for 1D data such as XRD, PDF, XAS (XANES/EXAFS) but also support other types
|
|
68
69
|
- **Operando Contour plot**: Correlate in-situ characterizations (XRD/PDF/XAS) with electrochemical data
|
|
69
70
|
- **XRD axis units**: Interactive Options `u` converts 2θ ↔ Q ↔ d (XY and operando); CIF phase ticks follow the current domain
|
|
70
71
|
- **Histogram mode**: Column histograms from tabular `.csv`/`.txt` data (e.g. particle-size lists)
|
|
71
72
|
- **Interactive plotting**: Real-time editing customized for each type of plottings
|
|
72
|
-
- **Session
|
|
73
|
+
- **Session Save**: Save and reload complete plot states with `.pkl` files
|
|
73
74
|
- **Style Management**: Import/export plot styles as `.bps`/`.bpsg` files (histogram: `.bpsh`)
|
|
74
75
|
- **Batch Processing**: Export each file separately with `--all`
|
|
75
|
-
|
|
76
|
-
- **Strip header lines**: `--strip-header N` removes the first N lines from a file or a folder of files (with `--ext`) and writes copies into a `stripped/` subfolder (originals untouched)
|
|
76
|
+
|
|
77
77
|
|
|
78
78
|
## Installation
|
|
79
79
|
|
|
@@ -84,8 +84,9 @@ pip install batplot
|
|
|
84
84
|
|
|
85
85
|
## Quick Start
|
|
86
86
|
|
|
87
|
+
- User manual: https://chem-plot.github.io/batplot/
|
|
87
88
|
- Tutorial: https://drive.google.com/file/d/1NTFJWNBbWW4mgz0H5ZelGjuOBWxoFgkr/view
|
|
88
|
-
-
|
|
89
|
+
- Demo files: https://github.com/chem-plot/batplot/blob/main/batplot_demo_files.zip
|
|
89
90
|
|
|
90
91
|
---
|
|
91
92
|
|
|
@@ -263,18 +264,12 @@ batplot file1.csv file2.csv --gc --save
|
|
|
263
264
|
|
|
264
265
|
### Galvanostatic cycling (GC)
|
|
265
266
|
|
|
266
|
-
GC mode plots potential vs. capacity for each charge/discharge cycle—the primary visualization for battery cycling data.
|
|
267
|
-
|
|
268
|
-
By default each half-cycle resets capacity near 0 (cycles overlaid). With `--gc --cum`, capacity is laid **end-to-end** (cumulative / throughput capacity) so charge and discharge connect from the start to the end of the experiment; cycle colors, multifile overlay, overview, display mode, style/session save, and `--ro` still apply.
|
|
267
|
+
GC mode plots potential vs. capacity for each charge/discharge cycle—the primary visualization for battery cycling data. *batplot* automatically detects cycles from Neware `.csv` or Biologic `.mpt` files, assigns each cycle a distinct color, and supports both specific capacity (mAh/g) and raw capacity. For `.mpt` files, pass `--mass` (mg) to compute specific capacity. Discontinuous or paused experiments are handled by splitting data into contiguous charge/discharge segments. Use the interactive menu to customize colors, visibility, and export.
|
|
269
268
|
|
|
270
269
|
```bash
|
|
271
270
|
# From .csv (capacity in file)
|
|
272
271
|
batplot battery.csv --gc --i
|
|
273
272
|
|
|
274
|
-
# Cumulative capacity (charge/discharge connected end-to-end)
|
|
275
|
-
batplot battery.csv --gc --cum --i
|
|
276
|
-
batplot f1.csv f2.csv --gc --cum --i
|
|
277
|
-
|
|
278
273
|
# From .mpt (requires --mass in mg)
|
|
279
274
|
batplot battery.mpt --gc --mass 7.0 --i
|
|
280
275
|
|
|
@@ -496,6 +491,8 @@ With `--interactive`:
|
|
|
496
491
|
|
|
497
492
|
## Help & Documentation
|
|
498
493
|
|
|
494
|
+
Illustrated user manual (GitHub Pages): https://chem-plot.github.io/batplot/
|
|
495
|
+
|
|
499
496
|
```bash
|
|
500
497
|
batplot --h # General help
|
|
501
498
|
batplot --h xy # XY mode guide
|
|
@@ -503,7 +500,7 @@ batplot --h ec # Electrochemistry guide
|
|
|
503
500
|
batplot --h op # Operando guide
|
|
504
501
|
batplot --h histo # Histogram mode guide
|
|
505
502
|
batplot --v # Version and release notes
|
|
506
|
-
batplot --m # Open
|
|
503
|
+
batplot --m # Open online user manual (https://chem-plot.github.io/batplot/)
|
|
507
504
|
```
|
|
508
505
|
|
|
509
506
|
---
|
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
**Interactive plotting tool for battery and materials characterization data**
|
|
4
4
|
|
|
5
|
-
`batplot` is a
|
|
5
|
+
`batplot` is a Command-line based software for quick visuallization of 1D (x,y) and 2D (x,y,z) data with interactive styling and session management. It is designed for researchers within the fields of materials sciences and electrochemistry who do not have programming skills.
|
|
6
|
+
The electrochemistry and operando plots were inspired from Amalie Skurtveit's python scripts (https://github.com/piieceofcake?tab=repositories).
|
|
6
7
|
|
|
7
8
|
## Features
|
|
8
9
|
|
|
9
10
|
With a single line of command to easily plot publication-ready plots with customized, intuitive interactive editing features such as:
|
|
10
11
|
- **Electrochemistry Plot**: Galvanostatic cycling (GC), cyclic voltammetry (CV), differential capacity (dQdV), capacity per cycle (CPC) with multi-file support
|
|
11
|
-
- **1D XY plot**: Designed for XRD, PDF, XAS (XANES/EXAFS) but also support other types
|
|
12
|
+
- **1D XY plot**: Designed for 1D data such as XRD, PDF, XAS (XANES/EXAFS) but also support other types
|
|
12
13
|
- **Operando Contour plot**: Correlate in-situ characterizations (XRD/PDF/XAS) with electrochemical data
|
|
13
14
|
- **XRD axis units**: Interactive Options `u` converts 2θ ↔ Q ↔ d (XY and operando); CIF phase ticks follow the current domain
|
|
14
15
|
- **Histogram mode**: Column histograms from tabular `.csv`/`.txt` data (e.g. particle-size lists)
|
|
15
16
|
- **Interactive plotting**: Real-time editing customized for each type of plottings
|
|
16
|
-
- **Session
|
|
17
|
+
- **Session Save**: Save and reload complete plot states with `.pkl` files
|
|
17
18
|
- **Style Management**: Import/export plot styles as `.bps`/`.bpsg` files (histogram: `.bpsh`)
|
|
18
19
|
- **Batch Processing**: Export each file separately with `--all`
|
|
19
|
-
|
|
20
|
-
- **Strip header lines**: `--strip-header N` removes the first N lines from a file or a folder of files (with `--ext`) and writes copies into a `stripped/` subfolder (originals untouched)
|
|
20
|
+
|
|
21
21
|
|
|
22
22
|
## Installation
|
|
23
23
|
|
|
@@ -28,8 +28,9 @@ pip install batplot
|
|
|
28
28
|
|
|
29
29
|
## Quick Start
|
|
30
30
|
|
|
31
|
+
- User manual: https://chem-plot.github.io/batplot/
|
|
31
32
|
- Tutorial: https://drive.google.com/file/d/1NTFJWNBbWW4mgz0H5ZelGjuOBWxoFgkr/view
|
|
32
|
-
-
|
|
33
|
+
- Demo files: https://github.com/chem-plot/batplot/blob/main/batplot_demo_files.zip
|
|
33
34
|
|
|
34
35
|
---
|
|
35
36
|
|
|
@@ -207,18 +208,12 @@ batplot file1.csv file2.csv --gc --save
|
|
|
207
208
|
|
|
208
209
|
### Galvanostatic cycling (GC)
|
|
209
210
|
|
|
210
|
-
GC mode plots potential vs. capacity for each charge/discharge cycle—the primary visualization for battery cycling data.
|
|
211
|
-
|
|
212
|
-
By default each half-cycle resets capacity near 0 (cycles overlaid). With `--gc --cum`, capacity is laid **end-to-end** (cumulative / throughput capacity) so charge and discharge connect from the start to the end of the experiment; cycle colors, multifile overlay, overview, display mode, style/session save, and `--ro` still apply.
|
|
211
|
+
GC mode plots potential vs. capacity for each charge/discharge cycle—the primary visualization for battery cycling data. *batplot* automatically detects cycles from Neware `.csv` or Biologic `.mpt` files, assigns each cycle a distinct color, and supports both specific capacity (mAh/g) and raw capacity. For `.mpt` files, pass `--mass` (mg) to compute specific capacity. Discontinuous or paused experiments are handled by splitting data into contiguous charge/discharge segments. Use the interactive menu to customize colors, visibility, and export.
|
|
213
212
|
|
|
214
213
|
```bash
|
|
215
214
|
# From .csv (capacity in file)
|
|
216
215
|
batplot battery.csv --gc --i
|
|
217
216
|
|
|
218
|
-
# Cumulative capacity (charge/discharge connected end-to-end)
|
|
219
|
-
batplot battery.csv --gc --cum --i
|
|
220
|
-
batplot f1.csv f2.csv --gc --cum --i
|
|
221
|
-
|
|
222
217
|
# From .mpt (requires --mass in mg)
|
|
223
218
|
batplot battery.mpt --gc --mass 7.0 --i
|
|
224
219
|
|
|
@@ -440,6 +435,8 @@ With `--interactive`:
|
|
|
440
435
|
|
|
441
436
|
## Help & Documentation
|
|
442
437
|
|
|
438
|
+
Illustrated user manual (GitHub Pages): https://chem-plot.github.io/batplot/
|
|
439
|
+
|
|
443
440
|
```bash
|
|
444
441
|
batplot --h # General help
|
|
445
442
|
batplot --h xy # XY mode guide
|
|
@@ -447,7 +444,7 @@ batplot --h ec # Electrochemistry guide
|
|
|
447
444
|
batplot --h op # Operando guide
|
|
448
445
|
batplot --h histo # Histogram mode guide
|
|
449
446
|
batplot --v # Version and release notes
|
|
450
|
-
batplot --m # Open
|
|
447
|
+
batplot --m # Open online user manual (https://chem-plot.github.io/batplot/)
|
|
451
448
|
```
|
|
452
449
|
|
|
453
450
|
---
|
|
@@ -58,7 +58,7 @@ def is_interactive_backend() -> bool:
|
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def _headless_context() -> bool:
|
|
61
|
-
"""True when batplot must stay on a non-interactive backend (CI/pytest)."""
|
|
61
|
+
"""True when batplot must stay on a non-interactive backend (CI/pytest/SSH)."""
|
|
62
62
|
if os.environ.get("BATPLOT_HEADLESS", "").lower() in ("1", "true", "yes"):
|
|
63
63
|
return True
|
|
64
64
|
if os.environ.get("CI", "").lower() in ("1", "true", "yes"):
|
|
@@ -67,11 +67,16 @@ def _headless_context() -> bool:
|
|
|
67
67
|
return True
|
|
68
68
|
if "pytest" in sys.modules:
|
|
69
69
|
return True
|
|
70
|
+
# Linux SSH / containers without a graphical session: do not try Tk/Qt.
|
|
71
|
+
# macOS/Windows GUI apps do not rely on DISPLAY/WAYLAND_DISPLAY.
|
|
72
|
+
if sys.platform.startswith("linux"):
|
|
73
|
+
if not (os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY")):
|
|
74
|
+
return True
|
|
70
75
|
return False
|
|
71
76
|
|
|
72
77
|
|
|
73
78
|
def running_headless() -> bool:
|
|
74
|
-
"""True under pytest, CI, or
|
|
79
|
+
"""True under pytest, CI, no Linux display, or ``BATPLOT_HEADLESS``."""
|
|
75
80
|
return _headless_context()
|
|
76
81
|
|
|
77
82
|
|
|
@@ -148,6 +153,12 @@ def ensure_gui_backend(args=None) -> bool:
|
|
|
148
153
|
if _should_respect_env_agg():
|
|
149
154
|
return False
|
|
150
155
|
|
|
156
|
+
# Linux without DISPLAY/WAYLAND: skip Tk/Qt attempts (SSH/containers).
|
|
157
|
+
if sys.platform.startswith("linux") and not (
|
|
158
|
+
os.environ.get("DISPLAY") or os.environ.get("WAYLAND_DISPLAY")
|
|
159
|
+
):
|
|
160
|
+
return is_interactive_backend()
|
|
161
|
+
|
|
151
162
|
if _USER_SET_MPLBACKEND:
|
|
152
163
|
env_be = os.environ.get("MPLBACKEND")
|
|
153
164
|
if env_be and not _is_noninteractive_backend(env_be):
|
|
@@ -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
|
|
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"
|
|
@@ -191,7 +191,7 @@ def _print_general_help() -> None:
|
|
|
191
191
|
" batplot --h ec # Electrochemistry (GC/dQdV/CV/CPC) guide\n"
|
|
192
192
|
" batplot --h op # Operando contour guide (also: batplot --help contour)\n"
|
|
193
193
|
" batplot --h histo # Histogram mode guide (.csv/.txt column data)\n"
|
|
194
|
-
" batplot --m # Open
|
|
194
|
+
" batplot --m # Open online user manual (https://chem-plot.github.io/batplot/)\n\n"
|
|
195
195
|
|
|
196
196
|
"Contact & Updates:\n"
|
|
197
197
|
" Subscribe to batplot-lab@kjemi.uio.no for updates\n"
|
|
@@ -200,6 +200,7 @@ def _print_general_help() -> None:
|
|
|
200
200
|
" Email: tianda@uio.no\n"
|
|
201
201
|
" Personal page: https://www.mn.uio.no/kjemi/english/people/aca/tianda/\n"
|
|
202
202
|
" GitHub: https://github.com/chem-plot/batplot\n"
|
|
203
|
+
" User manual: https://chem-plot.github.io/batplot/\n"
|
|
203
204
|
" Kindly cite Tian's github page if the plot is used for publication\n"
|
|
204
205
|
)
|
|
205
206
|
_print_help(msg)
|
|
@@ -209,13 +210,17 @@ def _print_xy_help() -> None:
|
|
|
209
210
|
msg = (
|
|
210
211
|
"XY plots (XRD/PDF/XAS and many more)\n\n"
|
|
211
212
|
"Supported files: .xye .xy .qye .dat .csv .gr .nor .chik .chir .txt .brml .raw .xrdml .rasx and other formats. CIF overlays supported.\n\n"
|
|
212
|
-
"Axis detection: .qye→Q, .gr→r, .nor→energy, .chik→k, .chir→r
|
|
213
|
+
"Axis detection: .qye→Q, .gr→r, .nor→energy, .chik→k, .chir→r; XRD vendor/\n"
|
|
214
|
+
" file:wl / --wl imply Q or 2θ as documented. Otherwise (e.g. batplot file.xy)\n"
|
|
215
|
+
" cols 1–2 plot with labels X / Y — use --xaxis (Q, 2theta, d, r, k, energy, time\n"
|
|
216
|
+
" or a custom name) when you want a typed axis.\n"
|
|
213
217
|
"If mixing 2θ data in Q, give wavelength per-file (file.xye:1.5406) or global flag --wl.\n"
|
|
214
218
|
"A wavelength can be converted into a different wave length by file.xye:1.54:0.709.\n"
|
|
215
219
|
"For electrochemistry CSV/MPT time-potential plots, use --xaxis time.\n\n"
|
|
216
220
|
"Interactive XRD axis units (Options u):\n"
|
|
217
|
-
" In --i, press u to convert the plotted XRD axis
|
|
221
|
+
" In --i, press u to convert the plotted XRD axis between 2θ ↔ Q (XRD data only).\n"
|
|
218
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"
|
|
219
224
|
" Not for PDF (.gr), XAS (.nor/.chik/.chir), or other non-diffraction axes.\n"
|
|
220
225
|
" Example: batplot data.xye:0.709 --xaxis 2theta --i then u → q (uses λ=0.709 Å).\n\n"
|
|
221
226
|
"CIF phase ticks:\n"
|
|
@@ -225,6 +230,7 @@ def _print_xy_help() -> None:
|
|
|
225
230
|
" batplot scan.xye:1.54 phase.cif --i\n"
|
|
226
231
|
" batplot scan.xye phase.cif:0.709 --xaxis 2theta --wl 0.709 --i\n\n"
|
|
227
232
|
"Examples:\n"
|
|
233
|
+
" batplot file.xy --i # Quick plot cols 1–2 as X/Y\n"
|
|
228
234
|
" batplot file.xy file2.xye --xaxis 2theta --i # Plot XRD data in 2theta space\n"
|
|
229
235
|
" batplot file1.xye:1.5406 file2.txt:0.709 --i # Plot XRD data in different wavelengths in q space\n"
|
|
230
236
|
" batplot data1.xye data2.xye --wl 1.54 --i # Same Wavelength for Q conversion\n"
|
|
@@ -236,7 +242,8 @@ def _print_xy_help() -> None:
|
|
|
236
242
|
" batplot file1.xy file2.xy --1d --stack --i # First derivative\n"
|
|
237
243
|
" batplot allfiles --i # All files in directory\n"
|
|
238
244
|
" batplot allfiles --xaxis 2theta --xrange 10 80 # All with axis and range\n"
|
|
239
|
-
" batplot --all
|
|
245
|
+
" batplot --all # Batch: each file → Figures/ (X/Y default)\n"
|
|
246
|
+
" batplot --all --xaxis 2theta --xrange 10 80 # Batch with typed XRD axis\n"
|
|
240
247
|
" batplot file1.xy file2.xye --xaxis 2theta style.bps # Style + export\n\n"
|
|
241
248
|
"Tips and options:\n"
|
|
242
249
|
"[XY plot]\n"
|
|
@@ -443,7 +450,7 @@ def _print_op_help() -> None:
|
|
|
443
450
|
"Standard XY files:\n"
|
|
444
451
|
" • Folder should contain .xy/.xye/.qye/.dat files.\n"
|
|
445
452
|
" • Intensity scale is auto-adjusted between min/max values.\n"
|
|
446
|
-
" •
|
|
453
|
+
" • Default axis is 2θ when no .qye; use --xaxis Q or --wl for Q conversion.\n"
|
|
447
454
|
" • If a .mpt file is present, a side panel is added for dual-panel mode (time/potential/temp/etc.).\n"
|
|
448
455
|
" • Without a .mpt file, operando-only mode shows the contour plot alone.\n"
|
|
449
456
|
" • --1d / --2d: plot the first derivative (dy/dx) of each scan as a contour plot.\n\n"
|
|
@@ -767,20 +774,66 @@ def parse_args(argv=None):
|
|
|
767
774
|
# Keys use the exact file token (e.g. "file.xy:1.54") for wavelength match.
|
|
768
775
|
# Style files (.bps, .bpsg, .bpcfg) are NOT treated as file tokens so that
|
|
769
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.
|
|
770
782
|
# ====================================================================
|
|
771
783
|
readcol_by_file = {}
|
|
772
784
|
global_readcol_expanded = None
|
|
773
785
|
filtered_argv = []
|
|
774
786
|
last_file_token = None
|
|
775
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
|
+
|
|
776
834
|
i = 0
|
|
777
835
|
while i < len(argv):
|
|
778
836
|
arg = argv[i]
|
|
779
|
-
# Track non-option tokens as potential file specs (exclude style files)
|
|
780
|
-
if not arg.startswith('-'):
|
|
781
|
-
arg_lower = arg.lower()
|
|
782
|
-
if not arg_lower.endswith(_STYLE_EXTENSIONS):
|
|
783
|
-
last_file_token = arg
|
|
784
837
|
if arg == '--readcol' and i + 1 < len(argv):
|
|
785
838
|
tokens = []
|
|
786
839
|
j = i + 1
|
|
@@ -818,9 +871,23 @@ def parse_args(argv=None):
|
|
|
818
871
|
global_readcol_expanded = pairs[0] if len(pairs) == 1 else pairs
|
|
819
872
|
i = j
|
|
820
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
|
|
821
888
|
filtered_argv.append(arg)
|
|
822
889
|
i += 1
|
|
823
|
-
|
|
890
|
+
|
|
824
891
|
argv = filtered_argv
|
|
825
892
|
|
|
826
893
|
# ====================================================================
|
|
@@ -852,23 +919,27 @@ def parse_args(argv=None):
|
|
|
852
919
|
# weren't in the parser yet when we built it
|
|
853
920
|
ns, _unknown = parser.parse_known_args(argv)
|
|
854
921
|
if getattr(ns, "manual", False):
|
|
855
|
-
manual_url = "https://
|
|
922
|
+
manual_url = "https://chem-plot.github.io/batplot/"
|
|
856
923
|
try:
|
|
857
924
|
opened = webbrowser.open(manual_url)
|
|
858
925
|
if _HAS_RICH and _console:
|
|
859
926
|
if opened:
|
|
860
|
-
_console.print("\n[green]Opened
|
|
927
|
+
_console.print("\n[green]Opened user manual in browser[/green]")
|
|
861
928
|
else:
|
|
862
|
-
_console.print(f"\n[yellow]
|
|
929
|
+
_console.print(f"\n[yellow]User manual:[/yellow] {manual_url}")
|
|
863
930
|
else:
|
|
864
|
-
print(
|
|
931
|
+
print(
|
|
932
|
+
"\nOpened user manual in browser"
|
|
933
|
+
if opened
|
|
934
|
+
else f"\nUser manual: {manual_url}"
|
|
935
|
+
)
|
|
865
936
|
except Exception as exc: # pragma: no cover - best effort
|
|
866
937
|
if _HAS_RICH and _console:
|
|
867
938
|
_console.print(f"\n[red]Failed to open manual:[/red] {exc}")
|
|
868
|
-
_console.print(f"[yellow]
|
|
939
|
+
_console.print(f"[yellow]User manual:[/yellow] {manual_url}")
|
|
869
940
|
else:
|
|
870
941
|
print(f"\nFailed to open manual: {exc}")
|
|
871
|
-
print(f"
|
|
942
|
+
print(f"User manual: {manual_url}")
|
|
872
943
|
sys.exit(0)
|
|
873
944
|
|
|
874
945
|
topic = getattr(ns, 'help', None)
|
|
@@ -110,7 +110,7 @@ def batch_process(directory: str, args):
|
|
|
110
110
|
- .nor → Energy space (XAS, eV)
|
|
111
111
|
- .chik → k-space (EXAFS, Å⁻¹)
|
|
112
112
|
- .chir → r-space (Fourier transform of EXAFS, Å)
|
|
113
|
-
- .xy, .xye, .dat, .csv, .txt → Generic 2-column data (
|
|
113
|
+
- .xy, .xye, .dat, .csv, .txt → Generic 2-column data (labels X/Y; optional --xaxis / --wl)
|
|
114
114
|
|
|
115
115
|
STYLE FILE SUPPORT:
|
|
116
116
|
------------------
|
|
@@ -122,7 +122,7 @@ def batch_process(directory: str, args):
|
|
|
122
122
|
directory: Path to directory containing data files
|
|
123
123
|
args: Argument namespace with batch processing options:
|
|
124
124
|
- all: Style file path (if provided) or 'all' string
|
|
125
|
-
- xaxis: X-axis type
|
|
125
|
+
- xaxis: Optional X-axis type (Q, 2theta, r, energy, k, rft); omit for X/Y
|
|
126
126
|
- xrange: Optional X-axis range (min, max)
|
|
127
127
|
- yrange: Optional Y-axis range (min, max)
|
|
128
128
|
- format: Output format ('svg' or 'png', default 'svg')
|
|
@@ -137,7 +137,7 @@ def batch_process(directory: str, args):
|
|
|
137
137
|
# ====================================================================
|
|
138
138
|
# We classify file extensions into three categories:
|
|
139
139
|
# 1. Known extensions with automatic axis detection (don't need --xaxis)
|
|
140
|
-
# 2.
|
|
140
|
+
# 2. Generic / unknown extensions → X/Y unless --xaxis / --wl given
|
|
141
141
|
# 3. Excluded extensions (not data files, skip them)
|
|
142
142
|
# ====================================================================
|
|
143
143
|
|
|
@@ -209,7 +209,7 @@ def batch_process(directory: str, args):
|
|
|
209
209
|
if ext in known_ext:
|
|
210
210
|
files.append(f)
|
|
211
211
|
else:
|
|
212
|
-
# Include unknown extensions (
|
|
212
|
+
# Include unknown extensions (default X/Y; optional --xaxis / --wl)
|
|
213
213
|
files.append(f)
|
|
214
214
|
unknown_ext_files.append(f)
|
|
215
215
|
|
|
@@ -221,20 +221,15 @@ def batch_process(directory: str, args):
|
|
|
221
221
|
batch_save_xy_directory(directory, args, files)
|
|
222
222
|
return
|
|
223
223
|
|
|
224
|
-
#
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
for uf in unknown_ext_files[:5]: # Show first 5
|
|
228
|
-
print(f" - {uf}")
|
|
229
|
-
if len(unknown_ext_files) > 5:
|
|
230
|
-
print(f" ... and {len(unknown_ext_files) - 5} more")
|
|
231
|
-
print("\nKnown extensions that don't require --xaxis: .qye, .gr, .nor, .chik, .chir")
|
|
232
|
-
print("Please specify x-axis type with --xaxis (options: 2theta, Q, r, energy, k, rft)")
|
|
233
|
-
print("Example: batplot --all --xaxis 2theta")
|
|
234
|
-
return
|
|
235
|
-
|
|
236
|
-
if unknown_ext_files:
|
|
224
|
+
# Unknown extensions: without --xaxis/--wl → generic X/Y (same as interactive
|
|
225
|
+
# ``batplot file.xy``). With --xaxis, note the chosen type.
|
|
226
|
+
if unknown_ext_files and args.xaxis:
|
|
237
227
|
print(f"Note: Processing {len(unknown_ext_files)} file(s) with unknown extension(s) using --xaxis {args.xaxis}")
|
|
228
|
+
elif unknown_ext_files and getattr(args, "wl", None) is None:
|
|
229
|
+
print(
|
|
230
|
+
f"Note: Processing {len(unknown_ext_files)} file(s) as generic X/Y "
|
|
231
|
+
"(cols 1–2). Use --xaxis or --wl for XRD/PDF/XAS axis types."
|
|
232
|
+
)
|
|
238
233
|
|
|
239
234
|
print(f"Found {len(files)} files. Exporting SVG plots to Figures/")
|
|
240
235
|
|
|
@@ -315,8 +310,16 @@ def batch_process(directory: str, args):
|
|
|
315
310
|
else:
|
|
316
311
|
x, y = data[:, 0], data[:, 1]
|
|
317
312
|
e = data[:, 2] if data.shape[1] >= 3 else None
|
|
318
|
-
|
|
319
|
-
|
|
313
|
+
# Preserve historic --xaxis / --wl behavior for non-Bruker .raw:
|
|
314
|
+
# --xaxis Q → Q; other --xaxis → that type; --wl alone → 2θ
|
|
315
|
+
# Only the no-flag path is new (generic X/Y).
|
|
316
|
+
if args.xaxis:
|
|
317
|
+
ax = (args.xaxis or "").strip()
|
|
318
|
+
axis_mode = "Q" if ax.upper() == "Q" else args.xaxis
|
|
319
|
+
elif getattr(args, "wl", None) is not None:
|
|
320
|
+
axis_mode = "2theta"
|
|
321
|
+
else:
|
|
322
|
+
axis_mode = "generic"
|
|
320
323
|
else:
|
|
321
324
|
data = robust_loadtxt_skipheader(fpath)
|
|
322
325
|
if data.ndim == 1: data = data.reshape(1, -1)
|
|
@@ -370,10 +373,11 @@ def batch_process(directory: str, args):
|
|
|
370
373
|
args._batch_warned_extensions.add(ext)
|
|
371
374
|
print(f" Note: Reading '{ext}' files as 2-column (x, y) data with x-axis = {args.xaxis}")
|
|
372
375
|
elif getattr(args, 'wl', None) is not None:
|
|
373
|
-
# .txt / generic text: --wl implies XRD Q conversion (matches main
|
|
376
|
+
# .txt / generic text: --wl implies XRD Q conversion (matches main pipeline)
|
|
374
377
|
axis_mode = 'Q'
|
|
375
378
|
else:
|
|
376
|
-
|
|
379
|
+
# Quick plot: cols 1–2 with labels X / Y (matches interactive)
|
|
380
|
+
axis_mode = 'generic'
|
|
377
381
|
|
|
378
382
|
# Convert to Q if needed
|
|
379
383
|
if axis_mode == 'Q' and ext not in ('.qye', '.gr', '.nor'):
|
|
@@ -446,9 +450,18 @@ def batch_process(directory: str, args):
|
|
|
446
450
|
ax_b.set_xlabel(r"k ($\mathrm{\AA}^{-1}$)")
|
|
447
451
|
elif axis_mode == 'rft':
|
|
448
452
|
ax_b.set_xlabel("Radial distance (Å)")
|
|
453
|
+
elif axis_mode == 'generic':
|
|
454
|
+
ax_b.set_xlabel("X")
|
|
455
|
+
elif args.xaxis and str(args.xaxis).lower() not in (
|
|
456
|
+
"2theta", "two_theta", "tth", "q", "d", "r", "energy", "k", "rft", "time",
|
|
457
|
+
):
|
|
458
|
+
ax_b.set_xlabel(str(args.xaxis))
|
|
449
459
|
else:
|
|
450
460
|
ax_b.set_xlabel("2θ (deg)")
|
|
451
|
-
|
|
461
|
+
if axis_mode == 'generic' and not getattr(args, 'norm', False):
|
|
462
|
+
ax_b.set_ylabel("Y")
|
|
463
|
+
else:
|
|
464
|
+
ax_b.set_ylabel("Normalized intensity (a.u.)" if getattr(args, 'norm', False) else "Intensity")
|
|
452
465
|
ax_b.set_title(fname)
|
|
453
466
|
fig_b.subplots_adjust(left=0.18, right=0.97, bottom=0.16, top=0.90)
|
|
454
467
|
# Get output format from args, default to svg
|
|
@@ -201,9 +201,12 @@ def _prepare_allfiles_directory(target_dir: str, args, use_relative_paths: bool
|
|
|
201
201
|
print(f" - {uf}")
|
|
202
202
|
if len(unknown_ext_files) > 5:
|
|
203
203
|
print(f" ... and {len(unknown_ext_files) - 5} more")
|
|
204
|
-
print("These will be read as 2-column (x, y) data.")
|
|
205
|
-
if not args.xaxis:
|
|
206
|
-
print(
|
|
204
|
+
print("These will be read as 2-column (x, y) data with labels X / Y by default.")
|
|
205
|
+
if not args.xaxis and getattr(args, "wl", None) is None:
|
|
206
|
+
print(
|
|
207
|
+
"Tip: Optional --xaxis / --wl for typed axes "
|
|
208
|
+
"(e.g. --xaxis 2theta, --xaxis Q); omit them for quick X/Y plots."
|
|
209
|
+
)
|
|
207
210
|
|
|
208
211
|
print(f"Found {len(all_xy_files)} files to plot together")
|
|
209
212
|
args.files = all_xy_files
|
|
@@ -373,6 +376,12 @@ def batplot_main() -> int: # type: ignore
|
|
|
373
376
|
Exit code: 0 for success, non-zero for error
|
|
374
377
|
(Follows Unix convention: 0 = success, non-zero = error)
|
|
375
378
|
"""
|
|
379
|
+
# Defense in depth: also install when called without cli.main().
|
|
380
|
+
try:
|
|
381
|
+
from .plot_modes.common.terminal import install_safe_builtins
|
|
382
|
+
install_safe_builtins()
|
|
383
|
+
except Exception:
|
|
384
|
+
pass
|
|
376
385
|
# ====================================================================
|
|
377
386
|
# STEP 1: PARSE COMMAND-LINE ARGUMENTS
|
|
378
387
|
# ====================================================================
|
|
@@ -61,6 +61,12 @@ def main(argv: Optional[list] = None) -> int:
|
|
|
61
61
|
>>> main()
|
|
62
62
|
0
|
|
63
63
|
"""
|
|
64
|
+
# Windows cp1252-safe print/input for all interactive menus and errors.
|
|
65
|
+
try:
|
|
66
|
+
from .plot_modes.common.terminal import install_safe_builtins
|
|
67
|
+
install_safe_builtins()
|
|
68
|
+
except Exception:
|
|
69
|
+
pass
|
|
64
70
|
# ====================================================================
|
|
65
71
|
# STEP 0.5: CHECK FOR DEVELOPER UPGRADE COMMAND
|
|
66
72
|
# ====================================================================
|
|
@@ -163,7 +169,14 @@ def main(argv: Optional[list] = None) -> int:
|
|
|
163
169
|
# Other exceptions (unexpected bugs) will still show full traceback
|
|
164
170
|
# for debugging purposes.
|
|
165
171
|
# ====================================================================
|
|
166
|
-
|
|
172
|
+
try:
|
|
173
|
+
from .plot_modes.common.terminal import safe_console_print
|
|
174
|
+
safe_console_print(f"Error: {e}", file=sys.stderr)
|
|
175
|
+
except Exception:
|
|
176
|
+
try:
|
|
177
|
+
sys.stderr.write(f"Error: {e}\n")
|
|
178
|
+
except Exception:
|
|
179
|
+
sys.stderr.write("Error: (message not printable on this console)\n")
|
|
167
180
|
return 1 # Non-zero exit code indicates error
|
|
168
181
|
|
|
169
182
|
finally:
|
|
@@ -112,7 +112,7 @@ def load_config() -> Dict[str, Any]:
|
|
|
112
112
|
|
|
113
113
|
# Try to read and parse JSON file
|
|
114
114
|
try:
|
|
115
|
-
with open(config_file, 'r') as f:
|
|
115
|
+
with open(config_file, 'r', encoding='utf-8') as f:
|
|
116
116
|
return json.load(f) # Parse JSON string into Python dictionary
|
|
117
117
|
except (json.JSONDecodeError, IOError):
|
|
118
118
|
# File exists but is corrupted or unreadable
|
|
@@ -128,7 +128,7 @@ def save_config(config: Dict[str, Any]) -> bool:
|
|
|
128
128
|
"""
|
|
129
129
|
config_file = get_config_file()
|
|
130
130
|
try:
|
|
131
|
-
with open(config_file, 'w') as f:
|
|
131
|
+
with open(config_file, 'w', encoding='utf-8') as f:
|
|
132
132
|
# indent=2 makes JSON file human-readable (pretty-printed)
|
|
133
133
|
json.dump(config, f, indent=2)
|
|
134
134
|
return True
|
|
@@ -1,5 +1,20 @@
|
|
|
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
|
+
|
|
14
|
+
## [1.8.53] - 2026-09-09
|
|
15
|
+
- Bug fixes
|
|
16
|
+
|
|
17
|
+
|
|
3
18
|
## [1.8.52] - 2026-08-08
|
|
4
19
|
- Bug fixes
|
|
5
20
|
|