batplot 1.1.7__tar.gz → 1.2.0__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.1.7 → batplot-1.2.0}/PKG-INFO +1 -1
- batplot-1.2.0/batplot/cli.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/cpc_interactive.py +1 -2
- {batplot-1.1.7 → batplot-1.2.0}/batplot/electrochem_interactive.py +72 -10
- {batplot-1.1.7 → batplot-1.2.0}/batplot/operando_ec_interactive.py +60 -47
- {batplot-1.1.7 → batplot-1.2.0}/batplot/style.py +121 -10
- {batplot-1.1.7 → batplot-1.2.0}/batplot/ui.py +2 -2
- {batplot-1.1.7 → batplot-1.2.0}/batplot.egg-info/PKG-INFO +1 -1
- {batplot-1.1.7 → batplot-1.2.0}/pyproject.toml +1 -1
- batplot-1.1.7/batplot/cli.py +0 -34
- {batplot-1.1.7 → batplot-1.2.0}/LICENSE +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/README.md +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/__init__.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/args.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/batch.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/batplot.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/batplot_new.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/cif.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/converters.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/interactive.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/modes.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/operando.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/plotting.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/readers.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/session.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot/utils.py +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot.egg-info/SOURCES.txt +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot.egg-info/dependency_links.txt +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot.egg-info/entry_points.txt +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot.egg-info/requires.txt +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/batplot.egg-info/top_level.txt +0 -0
- {batplot-1.1.7 → batplot-1.2.0}/setup.cfg +0 -0
|
File without changes
|
|
@@ -259,7 +259,6 @@ def _style_snapshot(fig, ax, ax2, sc_charge, sc_discharge, sc_eff, file_data=Non
|
|
|
259
259
|
'position_inches': legend_xy_in # [x, y] offset from canvas center in inches
|
|
260
260
|
},
|
|
261
261
|
'ticks': {
|
|
262
|
-
'visibility': tick_vis,
|
|
263
262
|
'widths': {
|
|
264
263
|
'x_major': _tick_width(ax.xaxis, 'major'),
|
|
265
264
|
'x_minor': _tick_width(ax.xaxis, 'minor'),
|
|
@@ -1316,7 +1315,6 @@ def cpc_interactive_menu(fig, ax, ax2, sc_charge, sc_discharge, sc_eff, file_dat
|
|
|
1316
1315
|
_print_menu(); continue
|
|
1317
1316
|
elif key == 'i':
|
|
1318
1317
|
try:
|
|
1319
|
-
push_state("import-style")
|
|
1320
1318
|
try:
|
|
1321
1319
|
files = sorted([f for f in os.listdir(os.getcwd()) if f.lower().endswith('.bpcfg')])
|
|
1322
1320
|
except Exception:
|
|
@@ -1328,6 +1326,7 @@ def cpc_interactive_menu(fig, ax, ax2, sc_charge, sc_discharge, sc_eff, file_dat
|
|
|
1328
1326
|
inp = input("Enter number to open or filename (.bpcfg; q=cancel): ").strip()
|
|
1329
1327
|
if not inp or inp.lower() == 'q':
|
|
1330
1328
|
_print_menu(); continue
|
|
1329
|
+
push_state("import-style")
|
|
1331
1330
|
if inp.isdigit() and files:
|
|
1332
1331
|
idx = int(inp)
|
|
1333
1332
|
if 1 <= idx <= len(files):
|
|
@@ -570,10 +570,10 @@ def electrochem_interactive_menu(fig, ax, cycle_lines: Dict[int, Dict[str, Optio
|
|
|
570
570
|
except Exception:
|
|
571
571
|
pass
|
|
572
572
|
|
|
573
|
-
# Convert to points and add gap (match matplotlib's labelpad =
|
|
573
|
+
# Convert to points and add gap (match matplotlib's labelpad = 8pt)
|
|
574
574
|
if max_w_px > 0:
|
|
575
575
|
tick_width_pts = max_w_px * 72.0 / dpi
|
|
576
|
-
dx_pts = tick_width_pts +
|
|
576
|
+
dx_pts = tick_width_pts + 8.0 # 8pt gap to match left labelpad
|
|
577
577
|
else:
|
|
578
578
|
dx_pts = 6.0 # Minimal spacing when no tick labels (match small labelpad)
|
|
579
579
|
|
|
@@ -981,7 +981,6 @@ def electrochem_interactive_menu(fig, ax, cycle_lines: Dict[int, Dict[str, Optio
|
|
|
981
981
|
elif key == 'i':
|
|
982
982
|
# Import style from .bpcfg (with numbered list)
|
|
983
983
|
try:
|
|
984
|
-
push_state("import-style")
|
|
985
984
|
try:
|
|
986
985
|
_bpcfg_files = sorted([f for f in os.listdir(os.getcwd()) if f.lower().endswith('.bpcfg')])
|
|
987
986
|
except Exception:
|
|
@@ -993,6 +992,7 @@ def electrochem_interactive_menu(fig, ax, cycle_lines: Dict[int, Dict[str, Optio
|
|
|
993
992
|
inp = input("Enter number to open or filename (.bpcfg, q=cancel): ").strip()
|
|
994
993
|
if not inp or inp.lower() == 'q':
|
|
995
994
|
_print_menu(len(all_cycles), is_dqdv); continue
|
|
995
|
+
push_state("import-style")
|
|
996
996
|
if inp.isdigit() and _bpcfg_files:
|
|
997
997
|
_idx = int(inp)
|
|
998
998
|
if 1 <= _idx <= len(_bpcfg_files):
|
|
@@ -1031,17 +1031,79 @@ def electrochem_interactive_menu(fig, ax, cycle_lines: Dict[int, Dict[str, Optio
|
|
|
1031
1031
|
_apply_font_family(ax, font_cfg['family'])
|
|
1032
1032
|
if font_cfg.get('size') is not None:
|
|
1033
1033
|
_apply_font_size(ax, float(font_cfg['size']))
|
|
1034
|
-
except Exception:
|
|
1034
|
+
except Exception as e:
|
|
1035
|
+
print(f"Warning: Could not apply figure/font settings: {e}")
|
|
1035
1036
|
|
|
1036
1037
|
# WASD state and dependent components
|
|
1037
1038
|
try:
|
|
1038
1039
|
wasd_state = cfg.get('wasd_state')
|
|
1039
1040
|
if wasd_state and isinstance(wasd_state, dict):
|
|
1040
|
-
#
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1041
|
+
# Apply spines
|
|
1042
|
+
for name in ('top','bottom','left','right'):
|
|
1043
|
+
side = wasd_state.get(name, {})
|
|
1044
|
+
if name in ax.spines and 'spine' in side:
|
|
1045
|
+
ax.spines[name].set_visible(bool(side['spine']))
|
|
1046
|
+
|
|
1047
|
+
# Apply major ticks & labels
|
|
1048
|
+
top_s = wasd_state.get('top', {})
|
|
1049
|
+
bot_s = wasd_state.get('bottom', {})
|
|
1050
|
+
left_s = wasd_state.get('left', {})
|
|
1051
|
+
right_s = wasd_state.get('right', {})
|
|
1052
|
+
|
|
1053
|
+
ax.tick_params(axis='x',
|
|
1054
|
+
top=bool(top_s.get('ticks', False)),
|
|
1055
|
+
bottom=bool(bot_s.get('ticks', True)),
|
|
1056
|
+
labeltop=bool(top_s.get('labels', False)),
|
|
1057
|
+
labelbottom=bool(bot_s.get('labels', True)))
|
|
1058
|
+
ax.tick_params(axis='y',
|
|
1059
|
+
left=bool(left_s.get('ticks', True)),
|
|
1060
|
+
right=bool(right_s.get('ticks', False)),
|
|
1061
|
+
labelleft=bool(left_s.get('labels', True)),
|
|
1062
|
+
labelright=bool(right_s.get('labels', False)))
|
|
1063
|
+
|
|
1064
|
+
# Apply minor ticks
|
|
1065
|
+
if top_s.get('minor') or bot_s.get('minor'):
|
|
1066
|
+
ax.xaxis.set_minor_locator(AutoMinorLocator())
|
|
1067
|
+
ax.xaxis.set_minor_formatter(NullFormatter())
|
|
1068
|
+
ax.tick_params(axis='x', which='minor',
|
|
1069
|
+
top=bool(top_s.get('minor', False)),
|
|
1070
|
+
bottom=bool(bot_s.get('minor', False)),
|
|
1071
|
+
labeltop=False, labelbottom=False)
|
|
1072
|
+
|
|
1073
|
+
if left_s.get('minor') or right_s.get('minor'):
|
|
1074
|
+
ax.yaxis.set_minor_locator(AutoMinorLocator())
|
|
1075
|
+
ax.yaxis.set_minor_formatter(NullFormatter())
|
|
1076
|
+
ax.tick_params(axis='y', which='minor',
|
|
1077
|
+
left=bool(left_s.get('minor', False)),
|
|
1078
|
+
right=bool(right_s.get('minor', False)),
|
|
1079
|
+
labelleft=False, labelright=False)
|
|
1080
|
+
|
|
1081
|
+
# Apply axis titles
|
|
1082
|
+
ax._top_xlabel_on = bool(top_s.get('title', False))
|
|
1083
|
+
ax._right_ylabel_on = bool(right_s.get('title', False))
|
|
1084
|
+
|
|
1085
|
+
# Update tick_state for consistency
|
|
1086
|
+
tick_state['t_ticks'] = bool(top_s.get('ticks', False))
|
|
1087
|
+
tick_state['t_labels'] = bool(top_s.get('labels', False))
|
|
1088
|
+
tick_state['b_ticks'] = bool(bot_s.get('ticks', True))
|
|
1089
|
+
tick_state['b_labels'] = bool(bot_s.get('labels', True))
|
|
1090
|
+
tick_state['l_ticks'] = bool(left_s.get('ticks', True))
|
|
1091
|
+
tick_state['l_labels'] = bool(left_s.get('labels', True))
|
|
1092
|
+
tick_state['r_ticks'] = bool(right_s.get('ticks', False))
|
|
1093
|
+
tick_state['r_labels'] = bool(right_s.get('labels', False))
|
|
1094
|
+
tick_state['mtx'] = bool(top_s.get('minor', False))
|
|
1095
|
+
tick_state['mbx'] = bool(bot_s.get('minor', False))
|
|
1096
|
+
tick_state['mly'] = bool(left_s.get('minor', False))
|
|
1097
|
+
tick_state['mry'] = bool(right_s.get('minor', False))
|
|
1098
|
+
|
|
1099
|
+
# Reposition titles
|
|
1100
|
+
_ui_position_top_xlabel(ax, fig, tick_state)
|
|
1101
|
+
_ui_position_bottom_xlabel(ax, fig, tick_state)
|
|
1102
|
+
_ui_position_left_ylabel(ax, fig, tick_state)
|
|
1103
|
+
_ui_position_right_ylabel(ax, fig, tick_state)
|
|
1104
|
+
|
|
1105
|
+
except Exception as e:
|
|
1106
|
+
print(f"Warning: Could not apply tick visibility: {e}")
|
|
1045
1107
|
|
|
1046
1108
|
# Spines and Ticks (widths)
|
|
1047
1109
|
try:
|
|
@@ -1903,7 +1965,7 @@ def _get_style_snapshot(fig, ax, cycle_lines: Dict, tick_state: Dict) -> Dict:
|
|
|
1903
1965
|
},
|
|
1904
1966
|
'font': {'family': font_fam0, 'size': font_size},
|
|
1905
1967
|
'spines': spines,
|
|
1906
|
-
'ticks': {'widths': tick_widths
|
|
1968
|
+
'ticks': {'widths': tick_widths},
|
|
1907
1969
|
'wasd_state': wasd_state,
|
|
1908
1970
|
'curve_linewidth': curve_linewidth,
|
|
1909
1971
|
'curve_markers': curve_marker_props,
|
|
@@ -534,6 +534,15 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
534
534
|
# Crosshair state for both axes
|
|
535
535
|
# Undo history
|
|
536
536
|
state_history = []
|
|
537
|
+
|
|
538
|
+
def _get_spine_visible(axis, which: str) -> bool:
|
|
539
|
+
"""Helper to get spine visibility status"""
|
|
540
|
+
sp = axis.spines.get(which)
|
|
541
|
+
try:
|
|
542
|
+
return bool(sp.get_visible()) if sp is not None else False
|
|
543
|
+
except Exception:
|
|
544
|
+
return False
|
|
545
|
+
|
|
537
546
|
def _snapshot(note: str = ""):
|
|
538
547
|
try:
|
|
539
548
|
fig_w, fig_h = _get_fig_size(fig)
|
|
@@ -561,37 +570,37 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
561
570
|
# WASD state for both panes
|
|
562
571
|
op_wasd = {
|
|
563
572
|
'top': {'spine': _get_spine_visible(ax, 'top'), 'ticks': ax.xaxis._major_tick_kw.get('tick1On', True),
|
|
564
|
-
'minor': bool(ax.xaxis.
|
|
573
|
+
'minor': bool(ax.xaxis._minor_tick_kw.get('tick1On', False)),
|
|
565
574
|
'labels': ax.xaxis._major_tick_kw.get('label1On', True),
|
|
566
575
|
'title': bool(getattr(ax, '_top_xlabel_on', False))},
|
|
567
576
|
'bottom': {'spine': _get_spine_visible(ax, 'bottom'), 'ticks': ax.xaxis._major_tick_kw.get('tick2On', True),
|
|
568
|
-
'minor': bool(ax.xaxis.
|
|
577
|
+
'minor': bool(ax.xaxis._minor_tick_kw.get('tick2On', False)),
|
|
569
578
|
'labels': ax.xaxis._major_tick_kw.get('label2On', True),
|
|
570
579
|
'title': bool(ax.get_xlabel())},
|
|
571
580
|
'left': {'spine': _get_spine_visible(ax, 'left'), 'ticks': ax.yaxis._major_tick_kw.get('tick1On', True),
|
|
572
|
-
'minor': bool(ax.yaxis.
|
|
581
|
+
'minor': bool(ax.yaxis._minor_tick_kw.get('tick1On', False)),
|
|
573
582
|
'labels': ax.yaxis._major_tick_kw.get('label1On', True),
|
|
574
583
|
'title': bool(ax.get_ylabel())},
|
|
575
584
|
'right': {'spine': _get_spine_visible(ax, 'right'), 'ticks': ax.yaxis._major_tick_kw.get('tick2On', False),
|
|
576
|
-
'minor': bool(ax.yaxis.
|
|
585
|
+
'minor': bool(ax.yaxis._minor_tick_kw.get('tick2On', False)),
|
|
577
586
|
'labels': ax.yaxis._major_tick_kw.get('label2On', False),
|
|
578
587
|
'title': bool(getattr(ax, '_right_ylabel_on', False))},
|
|
579
588
|
}
|
|
580
589
|
ec_wasd = {
|
|
581
590
|
'top': {'spine': _get_spine_visible(ec_ax, 'top'), 'ticks': ec_ax.xaxis._major_tick_kw.get('tick1On', True),
|
|
582
|
-
'minor': bool(ec_ax.xaxis.
|
|
591
|
+
'minor': bool(ec_ax.xaxis._minor_tick_kw.get('tick1On', False)),
|
|
583
592
|
'labels': ec_ax.xaxis._major_tick_kw.get('label1On', True),
|
|
584
593
|
'title': bool(getattr(ec_ax, '_top_xlabel_on', False))},
|
|
585
594
|
'bottom': {'spine': _get_spine_visible(ec_ax, 'bottom'), 'ticks': ec_ax.xaxis._major_tick_kw.get('tick2On', True),
|
|
586
|
-
'minor': bool(ec_ax.xaxis.
|
|
595
|
+
'minor': bool(ec_ax.xaxis._minor_tick_kw.get('tick2On', False)),
|
|
587
596
|
'labels': ec_ax.xaxis._major_tick_kw.get('label2On', True),
|
|
588
597
|
'title': bool(ec_ax.get_xlabel())},
|
|
589
598
|
'left': {'spine': _get_spine_visible(ec_ax, 'left'), 'ticks': ec_ax.yaxis._major_tick_kw.get('tick1On', False),
|
|
590
|
-
'minor': bool(ec_ax.yaxis.
|
|
599
|
+
'minor': bool(ec_ax.yaxis._minor_tick_kw.get('tick1On', False)),
|
|
591
600
|
'labels': ec_ax.yaxis._major_tick_kw.get('label1On', False),
|
|
592
601
|
'title': bool(ec_ax.get_ylabel())},
|
|
593
602
|
'right': {'spine': _get_spine_visible(ec_ax, 'right'), 'ticks': ec_ax.yaxis._major_tick_kw.get('tick2On', True),
|
|
594
|
-
'minor': bool(ec_ax.yaxis.
|
|
603
|
+
'minor': bool(ec_ax.yaxis._minor_tick_kw.get('tick2On', False)),
|
|
595
604
|
'labels': ec_ax.yaxis._major_tick_kw.get('label2On', True),
|
|
596
605
|
'title': bool(ec_ax.get_ylabel())},
|
|
597
606
|
}
|
|
@@ -615,8 +624,8 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
615
624
|
})
|
|
616
625
|
if len(state_history) > 40:
|
|
617
626
|
state_history.pop(0)
|
|
618
|
-
except Exception:
|
|
619
|
-
|
|
627
|
+
except Exception as e:
|
|
628
|
+
print(f"Warning: snapshot failed: {e}")
|
|
620
629
|
def _restore():
|
|
621
630
|
if not state_history:
|
|
622
631
|
print("No undo history."); return
|
|
@@ -1055,15 +1064,16 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1055
1064
|
print(f"Save failed: {e}")
|
|
1056
1065
|
print_menu(); continue
|
|
1057
1066
|
if cmd == 'h':
|
|
1058
|
-
_snapshot("height")
|
|
1059
1067
|
print(f"Current height: {ax_h_in:.2f} in")
|
|
1060
1068
|
val = input("New height (inches): ").strip()
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1069
|
+
if val:
|
|
1070
|
+
_snapshot("height")
|
|
1071
|
+
try:
|
|
1072
|
+
new_h = max(0.25, float(val))
|
|
1073
|
+
ax_h_in = new_h
|
|
1074
|
+
_apply_group_layout_inches(fig, ax, cbar.ax, ec_ax, ax_w_in, ax_h_in, cb_w_in, cb_gap_in, ec_gap_in, ec_w_in)
|
|
1075
|
+
except Exception as e:
|
|
1076
|
+
print(f"Invalid height: {e}")
|
|
1067
1077
|
print_menu()
|
|
1068
1078
|
elif cmd == 'r':
|
|
1069
1079
|
_snapshot("reverse")
|
|
@@ -1100,7 +1110,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1100
1110
|
if sub == 'q':
|
|
1101
1111
|
break
|
|
1102
1112
|
if sub == 'f':
|
|
1103
|
-
_snapshot("font-family")
|
|
1104
1113
|
# Common font families with numbered options
|
|
1105
1114
|
fonts = ['Arial', 'DejaVu Sans', 'Helvetica', 'Liberation Sans',
|
|
1106
1115
|
'Times New Roman', 'Courier New', 'Verdana', 'Tahoma']
|
|
@@ -1111,6 +1120,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1111
1120
|
choice = input("Font family (number or name): ").strip()
|
|
1112
1121
|
if not choice:
|
|
1113
1122
|
continue
|
|
1123
|
+
_snapshot("font-family")
|
|
1114
1124
|
# Check if it's a number
|
|
1115
1125
|
if choice.isdigit():
|
|
1116
1126
|
idx = int(choice)
|
|
@@ -1125,12 +1135,12 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1125
1135
|
set_fonts(family=choice)
|
|
1126
1136
|
print(f"Applied font family: {choice}")
|
|
1127
1137
|
elif sub == 's':
|
|
1128
|
-
_snapshot("font-size")
|
|
1129
1138
|
# Show current size and accept direct input
|
|
1130
1139
|
cur_size = plt.rcParams.get('font.size', None)
|
|
1131
1140
|
choice = input(f"Font size (current: {cur_size}): ").strip()
|
|
1132
1141
|
if not choice:
|
|
1133
1142
|
continue
|
|
1143
|
+
_snapshot("font-size")
|
|
1134
1144
|
try:
|
|
1135
1145
|
sz = float(choice)
|
|
1136
1146
|
if sz > 0:
|
|
@@ -1143,7 +1153,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1143
1153
|
print_menu()
|
|
1144
1154
|
elif cmd == 'l':
|
|
1145
1155
|
# Line widths submenu for both operando and EC panes
|
|
1146
|
-
_snapshot("line-widths")
|
|
1147
1156
|
print("Line widths: set frame (spines) and tick widths for both operando and EC")
|
|
1148
1157
|
print("Enter frame/tick width (e.g., '1.5' or 'f t' for frame/tick separately)")
|
|
1149
1158
|
print("Format examples:")
|
|
@@ -1156,6 +1165,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1156
1165
|
print_menu()
|
|
1157
1166
|
continue
|
|
1158
1167
|
|
|
1168
|
+
_snapshot("line-widths")
|
|
1159
1169
|
try:
|
|
1160
1170
|
parts = inp.split()
|
|
1161
1171
|
if len(parts) == 1:
|
|
@@ -1283,7 +1293,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1283
1293
|
axis.yaxis.set_major_locator(MaxNLocator(nbins='auto', steps=[1, 2, 5], min_n_ticks=4))
|
|
1284
1294
|
except Exception:
|
|
1285
1295
|
pass
|
|
1286
|
-
_snapshot("toggle-ticks")
|
|
1287
1296
|
while True:
|
|
1288
1297
|
print("Choose pane: o=operando, e=ec, q=back")
|
|
1289
1298
|
pane = input("ot> ").strip().lower()
|
|
@@ -1543,6 +1552,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1543
1552
|
if side == 'right' and key == 'minor':
|
|
1544
1553
|
ts['mry'] = bool(wasd['right']['minor'])
|
|
1545
1554
|
if changed:
|
|
1555
|
+
_snapshot("toggle-ticks")
|
|
1546
1556
|
_apply_wasd_axis(target, wasd)
|
|
1547
1557
|
try:
|
|
1548
1558
|
target._saved_tick_state = dict(ts)
|
|
@@ -1554,10 +1564,10 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1554
1564
|
fig.canvas.draw_idle()
|
|
1555
1565
|
print_menu()
|
|
1556
1566
|
elif cmd == 'ox':
|
|
1557
|
-
_snapshot("operando-xrange")
|
|
1558
1567
|
cur = ax.get_xlim(); print(f"Current operando X: {cur[0]:.4g} {cur[1]:.4g}")
|
|
1559
1568
|
line = input("New X range (min max, blank=cancel): ").strip()
|
|
1560
1569
|
if line:
|
|
1570
|
+
_snapshot("operando-xrange")
|
|
1561
1571
|
try:
|
|
1562
1572
|
lo, hi = map(float, line.split())
|
|
1563
1573
|
ax.set_xlim(lo, hi)
|
|
@@ -1568,10 +1578,10 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1568
1578
|
print(f"Invalid range: {e}")
|
|
1569
1579
|
print_menu()
|
|
1570
1580
|
elif cmd == 'oy':
|
|
1571
|
-
_snapshot("operando-yrange")
|
|
1572
1581
|
cur = ax.get_ylim(); print(f"Current operando Y: {cur[0]:.4g} {cur[1]:.4g}")
|
|
1573
1582
|
line = input("New Y range (min max, blank=cancel): ").strip()
|
|
1574
1583
|
if line:
|
|
1584
|
+
_snapshot("operando-yrange")
|
|
1575
1585
|
try:
|
|
1576
1586
|
lo, hi = map(float, line.split())
|
|
1577
1587
|
ax.set_ylim(lo, hi)
|
|
@@ -1582,7 +1592,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1582
1592
|
print(f"Invalid range: {e}")
|
|
1583
1593
|
print_menu()
|
|
1584
1594
|
elif cmd == 'oz':
|
|
1585
|
-
_snapshot("operando-intensity-range")
|
|
1586
1595
|
try:
|
|
1587
1596
|
cur = im.get_clim()
|
|
1588
1597
|
print(f"Current normalized intensity range: {cur[0]:.4g} {cur[1]:.4g}")
|
|
@@ -1590,6 +1599,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1590
1599
|
print("Could not retrieve current intensity range")
|
|
1591
1600
|
line = input("New intensity range (min max, blank=cancel): ").strip()
|
|
1592
1601
|
if line:
|
|
1602
|
+
_snapshot("operando-intensity-range")
|
|
1593
1603
|
try:
|
|
1594
1604
|
lo, hi = map(float, line.split())
|
|
1595
1605
|
im.set_clim(lo, hi)
|
|
@@ -1603,26 +1613,28 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1603
1613
|
print(f"Invalid range: {e}")
|
|
1604
1614
|
print_menu()
|
|
1605
1615
|
elif cmd in ('ow'):
|
|
1606
|
-
_snapshot("operando-width")
|
|
1607
1616
|
print(f"Current operando width: {ax_w_in:.2f} in")
|
|
1608
1617
|
val = input("New width (inches): ").strip()
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1618
|
+
if val:
|
|
1619
|
+
_snapshot("operando-width")
|
|
1620
|
+
try:
|
|
1621
|
+
new_w = max(0.25, float(val))
|
|
1622
|
+
ax_w_in = new_w
|
|
1623
|
+
_apply_group_layout_inches(fig, ax, cbar.ax, ec_ax, ax_w_in, ax_h_in, cb_w_in, cb_gap_in, ec_gap_in, ec_w_in)
|
|
1624
|
+
except Exception as e:
|
|
1625
|
+
print(f"Invalid width: {e}")
|
|
1615
1626
|
print_menu()
|
|
1616
1627
|
elif cmd == 'ew':
|
|
1617
|
-
_snapshot("ec-width")
|
|
1618
1628
|
print(f"Current EC width: {ec_w_in:.2f} in")
|
|
1619
1629
|
val = input("New EC width (inches): ").strip()
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1630
|
+
if val:
|
|
1631
|
+
_snapshot("ec-width")
|
|
1632
|
+
try:
|
|
1633
|
+
new_w = max(0.25, float(val))
|
|
1634
|
+
ec_w_in = new_w
|
|
1635
|
+
_apply_group_layout_inches(fig, ax, cbar.ax, ec_ax, ax_w_in, ax_h_in, cb_w_in, cb_gap_in, ec_gap_in, ec_w_in)
|
|
1636
|
+
except Exception as e:
|
|
1637
|
+
print(f"Invalid EC width: {e}")
|
|
1626
1638
|
print_menu()
|
|
1627
1639
|
elif cmd == 'oc':
|
|
1628
1640
|
# Change operando colormap (perceptually uniform suggestions)
|
|
@@ -1909,7 +1921,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1909
1921
|
# Load a .bpcfg style and apply
|
|
1910
1922
|
# Applies style properties from commands: oc, ow, ew, h, el, t, l, f, g, r
|
|
1911
1923
|
try:
|
|
1912
|
-
_snapshot("import-style")
|
|
1913
1924
|
try:
|
|
1914
1925
|
_bpcfg_files = sorted([f for f in os.listdir(os.getcwd()) if f.lower().endswith('.bpcfg')])
|
|
1915
1926
|
except Exception:
|
|
@@ -1921,6 +1932,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
1921
1932
|
inp = input("Enter number to open or filename (.bpcfg): ").strip()
|
|
1922
1933
|
if not inp:
|
|
1923
1934
|
print_menu(); continue
|
|
1935
|
+
_snapshot("import-style")
|
|
1924
1936
|
if inp.isdigit() and _bpcfg_files:
|
|
1925
1937
|
_idx = int(inp)
|
|
1926
1938
|
if 1 <= _idx <= len(_bpcfg_files):
|
|
@@ -2233,10 +2245,10 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
2233
2245
|
if sub == 'q':
|
|
2234
2246
|
break
|
|
2235
2247
|
if sub == 'x':
|
|
2236
|
-
_snapshot("rename-op-x")
|
|
2237
2248
|
cur = ax.get_xlabel() or ''
|
|
2238
2249
|
lab = input(f"New operando X label (blank=cancel, current='{cur}'): ").strip()
|
|
2239
2250
|
if lab:
|
|
2251
|
+
_snapshot("rename-op-x")
|
|
2240
2252
|
try:
|
|
2241
2253
|
ax.set_xlabel(lab)
|
|
2242
2254
|
ax._custom_labels['x'] = lab
|
|
@@ -2246,10 +2258,10 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
2246
2258
|
except Exception:
|
|
2247
2259
|
pass
|
|
2248
2260
|
elif sub == 'y':
|
|
2249
|
-
_snapshot("rename-op-y")
|
|
2250
2261
|
cur = ax.get_ylabel() or ''
|
|
2251
2262
|
lab = input(f"New operando Y label (blank=cancel, current='{cur}'): ").strip()
|
|
2252
2263
|
if lab:
|
|
2264
|
+
_snapshot("rename-op-y")
|
|
2253
2265
|
try:
|
|
2254
2266
|
ax.set_ylabel(lab)
|
|
2255
2267
|
ax._custom_labels['y'] = lab
|
|
@@ -2278,10 +2290,10 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
2278
2290
|
if sub == 'q':
|
|
2279
2291
|
break
|
|
2280
2292
|
if sub == 'x':
|
|
2281
|
-
_snapshot("rename-ec-x")
|
|
2282
2293
|
cur = ec_ax.get_xlabel() or ''
|
|
2283
2294
|
lab = input(f"New EC X label (blank=cancel, current='{cur}'): ").strip()
|
|
2284
2295
|
if lab:
|
|
2296
|
+
_snapshot("rename-ec-x")
|
|
2285
2297
|
try:
|
|
2286
2298
|
ec_ax.set_xlabel(lab)
|
|
2287
2299
|
ec_ax._custom_labels['x'] = lab
|
|
@@ -2290,10 +2302,10 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
2290
2302
|
except Exception:
|
|
2291
2303
|
pass
|
|
2292
2304
|
elif sub == 'y':
|
|
2293
|
-
_snapshot("rename-ec-y")
|
|
2294
2305
|
cur = ec_ax.get_ylabel() or ''
|
|
2295
2306
|
lab = input(f"New EC Y label (blank=cancel, current='{cur}'): ").strip()
|
|
2296
2307
|
if lab:
|
|
2308
|
+
_snapshot("rename-ec-y")
|
|
2297
2309
|
try:
|
|
2298
2310
|
ec_ax.set_ylabel(lab)
|
|
2299
2311
|
# Store against current mode
|
|
@@ -2331,22 +2343,22 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
2331
2343
|
if sub == 'q':
|
|
2332
2344
|
break
|
|
2333
2345
|
if sub == 'c':
|
|
2334
|
-
_snapshot("ec-line-color")
|
|
2335
2346
|
cur = ln.get_color()
|
|
2336
2347
|
val = input(f"Color (name or hex, current={cur}, blank=cancel): ").strip()
|
|
2337
2348
|
if not val:
|
|
2338
2349
|
continue
|
|
2350
|
+
_snapshot("ec-line-color")
|
|
2339
2351
|
try:
|
|
2340
2352
|
ln.set_color(val)
|
|
2341
2353
|
fig.canvas.draw_idle()
|
|
2342
2354
|
except Exception as e:
|
|
2343
2355
|
print(f"Invalid color: {e}")
|
|
2344
2356
|
elif sub == 'l':
|
|
2345
|
-
_snapshot("ec-line-width")
|
|
2346
2357
|
cur = ln.get_linewidth()
|
|
2347
2358
|
val = input(f"Line width (current={cur}, blank=cancel): ").strip()
|
|
2348
2359
|
if not val:
|
|
2349
2360
|
continue
|
|
2361
|
+
_snapshot("ec-line-width")
|
|
2350
2362
|
try:
|
|
2351
2363
|
lw = float(val)
|
|
2352
2364
|
if lw > 0:
|
|
@@ -2362,10 +2374,10 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
2362
2374
|
print(f"EC line styling failed: {e}")
|
|
2363
2375
|
print_menu()
|
|
2364
2376
|
elif cmd == 'et':
|
|
2365
|
-
_snapshot("ec-time-range")
|
|
2366
2377
|
cur = ec_ax.get_ylim(); print(f"Current EC time range (Y): {cur[0]:.4g} {cur[1]:.4g}")
|
|
2367
2378
|
line = input("New time range (min max, blank=cancel): ").strip()
|
|
2368
2379
|
if line:
|
|
2380
|
+
_snapshot("ec-time-range")
|
|
2369
2381
|
try:
|
|
2370
2382
|
lo, hi = map(float, line.split())
|
|
2371
2383
|
ec_ax.set_ylim(lo, hi)
|
|
@@ -2438,7 +2450,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
2438
2450
|
if not sub or sub == 'q':
|
|
2439
2451
|
print_menu(); continue
|
|
2440
2452
|
if sub == 'n':
|
|
2441
|
-
_snapshot("ey->ions")
|
|
2442
2453
|
# Get or update parameters; allow reuse of previous values
|
|
2443
2454
|
params = getattr(ec_ax, '_ion_params', {"mass_mg": None, "cap_per_ion_mAh_g": None, "start_ions": None, "material": "cathode"})
|
|
2444
2455
|
mass_mg = params.get('mass_mg')
|
|
@@ -2469,6 +2480,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
2469
2480
|
if material is None:
|
|
2470
2481
|
material = 'cathode'
|
|
2471
2482
|
ec_ax._ion_params = {"mass_mg": mass_mg, "cap_per_ion_mAh_g": cap_per_ion, "start_ions": start_ions, "material": material}
|
|
2483
|
+
_snapshot("ey->ions")
|
|
2472
2484
|
import numpy as np
|
|
2473
2485
|
t = np.asarray(time_h, float)
|
|
2474
2486
|
i_mA = np.asarray(current_mA, float)
|
|
@@ -2734,6 +2746,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax):
|
|
|
2734
2746
|
print("Canvas: only figure size will change; panel widths/gaps are not altered.")
|
|
2735
2747
|
line = input("New canvas size 'W H' (blank=cancel): ").strip()
|
|
2736
2748
|
if line:
|
|
2749
|
+
_snapshot("canvas-size")
|
|
2737
2750
|
try:
|
|
2738
2751
|
parts = line.split()
|
|
2739
2752
|
if len(parts) == 2:
|
|
@@ -166,6 +166,46 @@ def export_style_config(
|
|
|
166
166
|
bbox = ax.get_position()
|
|
167
167
|
frame_w_in = bbox.width * fw
|
|
168
168
|
frame_h_in = bbox.height * fh
|
|
169
|
+
|
|
170
|
+
# Build WASD state (20 parameters: 4 sides × 5 properties each)
|
|
171
|
+
def _get_spine_visible(which: str) -> bool:
|
|
172
|
+
sp = ax.spines.get(which)
|
|
173
|
+
try:
|
|
174
|
+
return bool(sp.get_visible()) if sp is not None else False
|
|
175
|
+
except Exception:
|
|
176
|
+
return False
|
|
177
|
+
|
|
178
|
+
wasd_state = {
|
|
179
|
+
'top': {
|
|
180
|
+
'spine': _get_spine_visible('top'),
|
|
181
|
+
'ticks': bool(tick_state.get('t_ticks', tick_state.get('tx', False))),
|
|
182
|
+
'minor': bool(tick_state.get('mtx', False)),
|
|
183
|
+
'labels': bool(tick_state.get('t_labels', tick_state.get('tx', False))),
|
|
184
|
+
'title': bool(getattr(ax, '_top_xlabel_on', False))
|
|
185
|
+
},
|
|
186
|
+
'bottom': {
|
|
187
|
+
'spine': _get_spine_visible('bottom'),
|
|
188
|
+
'ticks': bool(tick_state.get('b_ticks', tick_state.get('bx', True))),
|
|
189
|
+
'minor': bool(tick_state.get('mbx', False)),
|
|
190
|
+
'labels': bool(tick_state.get('b_labels', tick_state.get('bx', True))),
|
|
191
|
+
'title': bool(ax.get_xlabel())
|
|
192
|
+
},
|
|
193
|
+
'left': {
|
|
194
|
+
'spine': _get_spine_visible('left'),
|
|
195
|
+
'ticks': bool(tick_state.get('l_ticks', tick_state.get('ly', True))),
|
|
196
|
+
'minor': bool(tick_state.get('mly', False)),
|
|
197
|
+
'labels': bool(tick_state.get('l_labels', tick_state.get('ly', True))),
|
|
198
|
+
'title': bool(ax.get_ylabel())
|
|
199
|
+
},
|
|
200
|
+
'right': {
|
|
201
|
+
'spine': _get_spine_visible('right'),
|
|
202
|
+
'ticks': bool(tick_state.get('r_ticks', tick_state.get('ry', False))),
|
|
203
|
+
'minor': bool(tick_state.get('mry', False)),
|
|
204
|
+
'labels': bool(tick_state.get('r_labels', tick_state.get('ry', False))),
|
|
205
|
+
'title': bool(getattr(ax, '_right_ylabel_on', False))
|
|
206
|
+
},
|
|
207
|
+
}
|
|
208
|
+
|
|
169
209
|
cfg = {
|
|
170
210
|
"figure": {
|
|
171
211
|
"size": [fw, fh],
|
|
@@ -184,12 +224,12 @@ def export_style_config(
|
|
|
184
224
|
"family_chain": plt.rcParams.get("font.sans-serif"),
|
|
185
225
|
},
|
|
186
226
|
"ticks": {
|
|
187
|
-
"visibility": tick_state.copy(),
|
|
188
227
|
"x_major_width": axis_tick_width(ax.xaxis, "major"),
|
|
189
228
|
"x_minor_width": axis_tick_width(ax.xaxis, "minor"),
|
|
190
229
|
"y_major_width": axis_tick_width(ax.yaxis, "major"),
|
|
191
230
|
"y_minor_width": axis_tick_width(ax.yaxis, "minor"),
|
|
192
231
|
},
|
|
232
|
+
"wasd_state": wasd_state,
|
|
193
233
|
"spines": {
|
|
194
234
|
name: {
|
|
195
235
|
"linewidth": spn.get_linewidth(),
|
|
@@ -403,17 +443,88 @@ def apply_style_config(
|
|
|
403
443
|
|
|
404
444
|
# Tick visibility + widths
|
|
405
445
|
ticks_cfg = cfg.get("ticks", {})
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
changed_visibility = True
|
|
412
|
-
if changed_visibility:
|
|
446
|
+
|
|
447
|
+
# Try wasd_state first (version 2), fall back to visibility dict (version 1)
|
|
448
|
+
wasd = cfg.get("wasd_state", {})
|
|
449
|
+
if wasd:
|
|
450
|
+
# Apply WASD state (20 parameters)
|
|
413
451
|
try:
|
|
414
|
-
|
|
452
|
+
# Apply spines from wasd
|
|
453
|
+
for side in ('top', 'bottom', 'left', 'right'):
|
|
454
|
+
side_cfg = wasd.get(side, {})
|
|
455
|
+
if 'spine' in side_cfg and side in ax.spines:
|
|
456
|
+
ax.spines[side].set_visible(bool(side_cfg['spine']))
|
|
457
|
+
|
|
458
|
+
# Apply ticks and labels
|
|
459
|
+
top_cfg = wasd.get('top', {})
|
|
460
|
+
bot_cfg = wasd.get('bottom', {})
|
|
461
|
+
left_cfg = wasd.get('left', {})
|
|
462
|
+
right_cfg = wasd.get('right', {})
|
|
463
|
+
|
|
464
|
+
ax.tick_params(axis='x',
|
|
465
|
+
top=bool(top_cfg.get('ticks', False)),
|
|
466
|
+
bottom=bool(bot_cfg.get('ticks', True)),
|
|
467
|
+
labeltop=bool(top_cfg.get('labels', False)),
|
|
468
|
+
labelbottom=bool(bot_cfg.get('labels', True)))
|
|
469
|
+
ax.tick_params(axis='y',
|
|
470
|
+
left=bool(left_cfg.get('ticks', True)),
|
|
471
|
+
right=bool(right_cfg.get('ticks', False)),
|
|
472
|
+
labelleft=bool(left_cfg.get('labels', True)),
|
|
473
|
+
labelright=bool(right_cfg.get('labels', False)))
|
|
474
|
+
|
|
475
|
+
# Apply minor ticks
|
|
476
|
+
if top_cfg.get('minor') or bot_cfg.get('minor'):
|
|
477
|
+
from matplotlib.ticker import AutoMinorLocator, NullFormatter
|
|
478
|
+
ax.xaxis.set_minor_locator(AutoMinorLocator())
|
|
479
|
+
ax.xaxis.set_minor_formatter(NullFormatter())
|
|
480
|
+
ax.tick_params(axis='x', which='minor',
|
|
481
|
+
top=bool(top_cfg.get('minor', False)),
|
|
482
|
+
bottom=bool(bot_cfg.get('minor', False)),
|
|
483
|
+
labeltop=False, labelbottom=False)
|
|
484
|
+
|
|
485
|
+
if left_cfg.get('minor') or right_cfg.get('minor'):
|
|
486
|
+
from matplotlib.ticker import AutoMinorLocator, NullFormatter
|
|
487
|
+
ax.yaxis.set_minor_locator(AutoMinorLocator())
|
|
488
|
+
ax.yaxis.set_minor_formatter(NullFormatter())
|
|
489
|
+
ax.tick_params(axis='y', which='minor',
|
|
490
|
+
left=bool(left_cfg.get('minor', False)),
|
|
491
|
+
right=bool(right_cfg.get('minor', False)),
|
|
492
|
+
labelleft=False, labelright=False)
|
|
493
|
+
|
|
494
|
+
# Apply titles
|
|
495
|
+
ax._top_xlabel_on = bool(top_cfg.get('title', False))
|
|
496
|
+
ax._right_ylabel_on = bool(right_cfg.get('title', False))
|
|
497
|
+
|
|
498
|
+
# Update tick_state for consistency
|
|
499
|
+
tick_state['t_ticks'] = bool(top_cfg.get('ticks', False))
|
|
500
|
+
tick_state['t_labels'] = bool(top_cfg.get('labels', False))
|
|
501
|
+
tick_state['b_ticks'] = bool(bot_cfg.get('ticks', True))
|
|
502
|
+
tick_state['b_labels'] = bool(bot_cfg.get('labels', True))
|
|
503
|
+
tick_state['l_ticks'] = bool(left_cfg.get('ticks', True))
|
|
504
|
+
tick_state['l_labels'] = bool(left_cfg.get('labels', True))
|
|
505
|
+
tick_state['r_ticks'] = bool(right_cfg.get('ticks', False))
|
|
506
|
+
tick_state['r_labels'] = bool(right_cfg.get('labels', False))
|
|
507
|
+
tick_state['mtx'] = bool(top_cfg.get('minor', False))
|
|
508
|
+
tick_state['mbx'] = bool(bot_cfg.get('minor', False))
|
|
509
|
+
tick_state['mly'] = bool(left_cfg.get('minor', False))
|
|
510
|
+
tick_state['mry'] = bool(right_cfg.get('minor', False))
|
|
511
|
+
|
|
415
512
|
except Exception as e:
|
|
416
|
-
print(f"
|
|
513
|
+
print(f"Warning: Could not apply WASD tick visibility: {e}")
|
|
514
|
+
else:
|
|
515
|
+
# Fall back to old visibility dict
|
|
516
|
+
vis_cfg = ticks_cfg.get("visibility", {})
|
|
517
|
+
changed_visibility = False
|
|
518
|
+
for k, v in vis_cfg.items():
|
|
519
|
+
if k in tick_state and isinstance(v, bool):
|
|
520
|
+
tick_state[k] = v
|
|
521
|
+
changed_visibility = True
|
|
522
|
+
if changed_visibility:
|
|
523
|
+
try:
|
|
524
|
+
_ui_update_tick_visibility(ax, tick_state)
|
|
525
|
+
except Exception as e:
|
|
526
|
+
print(f"[DEBUG] Exception updating tick visibility: {e}")
|
|
527
|
+
|
|
417
528
|
|
|
418
529
|
xmaj = ticks_cfg.get("x_major_width")
|
|
419
530
|
xminr = ticks_cfg.get("x_minor_width")
|
|
@@ -250,7 +250,7 @@ def position_bottom_xlabel(ax, fig, tick_state: Dict[str, bool]):
|
|
|
250
250
|
pass
|
|
251
251
|
return
|
|
252
252
|
# Otherwise choose pad based on current tick label visibility
|
|
253
|
-
pad =
|
|
253
|
+
pad = 8 if bool(tick_state.get('b_labels', tick_state.get('bx', False))) else 6
|
|
254
254
|
try:
|
|
255
255
|
ax.xaxis.labelpad = pad
|
|
256
256
|
except Exception:
|
|
@@ -280,7 +280,7 @@ def position_left_ylabel(ax, fig, tick_state: Dict[str, bool]):
|
|
|
280
280
|
except Exception:
|
|
281
281
|
pass
|
|
282
282
|
return
|
|
283
|
-
pad =
|
|
283
|
+
pad = 8 if bool(tick_state.get('l_labels', tick_state.get('ly', False))) else 6
|
|
284
284
|
try:
|
|
285
285
|
ax.yaxis.labelpad = pad
|
|
286
286
|
except Exception:
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "batplot"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.2.0"
|
|
8
8
|
description = "Interactive plotting for XRD, PDF, and XAS data (.xye, .xy, .qye, .dat, .csv, .gr, .nor, .chik, .chir)"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Tian Dai", email = "tianda@uio.no" }
|
batplot-1.1.7/batplot/cli.py
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
"""CLI entry for batplot.
|
|
2
|
-
|
|
3
|
-
Clean entry point that delegates to mode handlers without import-time side effects.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
from __future__ import annotations
|
|
7
|
-
|
|
8
|
-
import sys
|
|
9
|
-
from typing import Optional
|
|
10
|
-
|
|
11
|
-
def main(argv: Optional[list] = None) -> int:
|
|
12
|
-
"""Main CLI entry point for batplot.
|
|
13
|
-
|
|
14
|
-
Args:
|
|
15
|
-
argv: Optional command line arguments (defaults to sys.argv)
|
|
16
|
-
|
|
17
|
-
Returns:
|
|
18
|
-
Exit code (0 for success, non-zero for error)
|
|
19
|
-
"""
|
|
20
|
-
# Import here to avoid side effects at module import time
|
|
21
|
-
if argv is not None:
|
|
22
|
-
# Temporarily replace sys.argv for argument parsing
|
|
23
|
-
old_argv = sys.argv
|
|
24
|
-
sys.argv = ['batplot'] + list(argv)
|
|
25
|
-
|
|
26
|
-
try:
|
|
27
|
-
# Import the main batplot function (now refactored to be safe)
|
|
28
|
-
from .batplot import batplot_main
|
|
29
|
-
return batplot_main()
|
|
30
|
-
finally:
|
|
31
|
-
if argv is not None:
|
|
32
|
-
sys.argv = old_argv
|
|
33
|
-
|
|
34
|
-
__all__ = ["main"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|