batplot 1.8.0__py3-none-any.whl → 1.8.2__py3-none-any.whl
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.
Potentially problematic release.
This version of batplot might be problematic. Click here for more details.
- batplot/__init__.py +1 -1
- batplot/args.py +5 -3
- batplot/batplot.py +44 -4
- batplot/cpc_interactive.py +96 -3
- batplot/electrochem_interactive.py +28 -0
- batplot/interactive.py +18 -2
- batplot/modes.py +12 -12
- batplot/operando.py +2 -0
- batplot/operando_ec_interactive.py +112 -11
- batplot/session.py +35 -1
- batplot/utils.py +40 -0
- batplot/version_check.py +85 -6
- {batplot-1.8.0.dist-info → batplot-1.8.2.dist-info}/METADATA +1 -1
- batplot-1.8.2.dist-info/RECORD +75 -0
- {batplot-1.8.0.dist-info → batplot-1.8.2.dist-info}/top_level.txt +1 -0
- batplot_backup_20251221_101150/__init__.py +5 -0
- batplot_backup_20251221_101150/args.py +625 -0
- batplot_backup_20251221_101150/batch.py +1176 -0
- batplot_backup_20251221_101150/batplot.py +3589 -0
- batplot_backup_20251221_101150/cif.py +823 -0
- batplot_backup_20251221_101150/cli.py +149 -0
- batplot_backup_20251221_101150/color_utils.py +547 -0
- batplot_backup_20251221_101150/config.py +198 -0
- batplot_backup_20251221_101150/converters.py +204 -0
- batplot_backup_20251221_101150/cpc_interactive.py +4409 -0
- batplot_backup_20251221_101150/electrochem_interactive.py +4520 -0
- batplot_backup_20251221_101150/interactive.py +3894 -0
- batplot_backup_20251221_101150/manual.py +323 -0
- batplot_backup_20251221_101150/modes.py +799 -0
- batplot_backup_20251221_101150/operando.py +603 -0
- batplot_backup_20251221_101150/operando_ec_interactive.py +5487 -0
- batplot_backup_20251221_101150/plotting.py +228 -0
- batplot_backup_20251221_101150/readers.py +2607 -0
- batplot_backup_20251221_101150/session.py +2951 -0
- batplot_backup_20251221_101150/style.py +1441 -0
- batplot_backup_20251221_101150/ui.py +790 -0
- batplot_backup_20251221_101150/utils.py +1046 -0
- batplot_backup_20251221_101150/version_check.py +253 -0
- batplot-1.8.0.dist-info/RECORD +0 -52
- {batplot-1.8.0.dist-info → batplot-1.8.2.dist-info}/WHEEL +0 -0
- {batplot-1.8.0.dist-info → batplot-1.8.2.dist-info}/entry_points.txt +0 -0
- {batplot-1.8.0.dist-info → batplot-1.8.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -39,7 +39,7 @@ from .color_utils import (
|
|
|
39
39
|
resolve_color_token,
|
|
40
40
|
manage_user_colors,
|
|
41
41
|
)
|
|
42
|
-
from .utils import choose_style_file
|
|
42
|
+
from .utils import choose_style_file, convert_label_shortcuts
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
class _FilterIMKWarning:
|
|
@@ -376,6 +376,71 @@ def _update_custom_colorbar(cbar_ax, im=None, label=None, label_mode=None):
|
|
|
376
376
|
_draw_custom_colorbar(cbar_ax, im, label, label_mode)
|
|
377
377
|
|
|
378
378
|
|
|
379
|
+
def _safe_set_clim(im, vmin, vmax):
|
|
380
|
+
"""Safely set color limits without triggering matplotlib colorbar callbacks.
|
|
381
|
+
|
|
382
|
+
This wrapper around im.set_clim() prevents the NotImplementedError: cannot remove artist
|
|
383
|
+
error when using custom colorbars. The issue occurs because matplotlib's callback system
|
|
384
|
+
tries to update the colorbar when set_clim() is called, but our custom colorbar drawing
|
|
385
|
+
has already cleared the axes, causing the update to fail.
|
|
386
|
+
|
|
387
|
+
This function suppresses the callback traceback by redirecting stderr to a null device
|
|
388
|
+
during the set_clim() call, preventing matplotlib's callback system from printing
|
|
389
|
+
tracebacks to the terminal.
|
|
390
|
+
|
|
391
|
+
Args:
|
|
392
|
+
im: AxesImage object
|
|
393
|
+
vmin: Minimum value for color scale
|
|
394
|
+
vmax: Maximum value for color scale
|
|
395
|
+
"""
|
|
396
|
+
import sys
|
|
397
|
+
import os
|
|
398
|
+
from io import StringIO
|
|
399
|
+
|
|
400
|
+
# Create a null device for stderr redirection
|
|
401
|
+
class NullDevice:
|
|
402
|
+
def write(self, s):
|
|
403
|
+
pass
|
|
404
|
+
def flush(self):
|
|
405
|
+
pass
|
|
406
|
+
def close(self):
|
|
407
|
+
pass
|
|
408
|
+
|
|
409
|
+
# Suppress matplotlib's exception printing by redirecting stderr AND excepthook
|
|
410
|
+
old_stderr = sys.stderr
|
|
411
|
+
old_excepthook = sys.excepthook
|
|
412
|
+
null_dev = NullDevice()
|
|
413
|
+
|
|
414
|
+
# Create a no-op excepthook that suppresses all exceptions
|
|
415
|
+
def suppress_excepthook(exc_type, exc_value, exc_traceback):
|
|
416
|
+
# Only suppress if it's the specific error we're looking for
|
|
417
|
+
if exc_type == NotImplementedError and 'cannot remove artist' in str(exc_value).lower():
|
|
418
|
+
return # Suppress this specific exception
|
|
419
|
+
# For any other exception, use the original handler
|
|
420
|
+
old_excepthook(exc_type, exc_value, exc_traceback)
|
|
421
|
+
|
|
422
|
+
sys.stderr = null_dev
|
|
423
|
+
sys.excepthook = suppress_excepthook
|
|
424
|
+
|
|
425
|
+
try:
|
|
426
|
+
# Set the color limits - matplotlib's callback will try to print traceback
|
|
427
|
+
# but both stderr and excepthook are suppressed
|
|
428
|
+
im.set_clim(vmin, vmax)
|
|
429
|
+
# The operation succeeds; any tracebacks are suppressed
|
|
430
|
+
except NotImplementedError:
|
|
431
|
+
# Suppress the specific error - color limits were still updated successfully
|
|
432
|
+
pass
|
|
433
|
+
except Exception:
|
|
434
|
+
# For any other unexpected error, restore handlers and re-raise
|
|
435
|
+
sys.stderr = old_stderr
|
|
436
|
+
sys.excepthook = old_excepthook
|
|
437
|
+
raise
|
|
438
|
+
finally:
|
|
439
|
+
# Always restore both stderr and excepthook
|
|
440
|
+
sys.stderr = old_stderr
|
|
441
|
+
sys.excepthook = old_excepthook
|
|
442
|
+
|
|
443
|
+
|
|
379
444
|
def _detach_mpl_colorbar_callbacks(cbar, im) -> None:
|
|
380
445
|
"""Detach a Matplotlib Colorbar from its mappable callbacks.
|
|
381
446
|
|
|
@@ -737,7 +802,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
737
802
|
|
|
738
803
|
if intensity_max > intensity_min:
|
|
739
804
|
# Update color limits
|
|
740
|
-
im
|
|
805
|
+
_safe_set_clim(im, intensity_min, intensity_max)
|
|
741
806
|
|
|
742
807
|
# Update colorbar if available
|
|
743
808
|
try:
|
|
@@ -1111,7 +1176,10 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
1111
1176
|
clim = im.get_clim()
|
|
1112
1177
|
except Exception:
|
|
1113
1178
|
clim = None
|
|
1114
|
-
|
|
1179
|
+
# Get colormap name: first check if we stored it explicitly, otherwise try to get from colormap object
|
|
1180
|
+
cmap_name = getattr(im, '_operando_cmap_name', None)
|
|
1181
|
+
if cmap_name is None:
|
|
1182
|
+
cmap_name = getattr(im.get_cmap(), 'name', None)
|
|
1115
1183
|
# EC mode and caches (only if ec_ax exists)
|
|
1116
1184
|
if ec_ax is not None:
|
|
1117
1185
|
mode = getattr(ec_ax, '_ec_y_mode', 'time')
|
|
@@ -1325,12 +1393,15 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
1325
1393
|
cbar.solids = None
|
|
1326
1394
|
except Exception:
|
|
1327
1395
|
pass
|
|
1328
|
-
lo, hi = snap['clim']; im
|
|
1396
|
+
lo, hi = snap['clim']; _safe_set_clim(im, float(lo), float(hi))
|
|
1329
1397
|
except Exception:
|
|
1330
1398
|
pass
|
|
1331
1399
|
try:
|
|
1332
1400
|
if snap.get('cmap'):
|
|
1333
|
-
|
|
1401
|
+
cmap_name = snap['cmap']
|
|
1402
|
+
im.set_cmap(cmap_name)
|
|
1403
|
+
# Store the colormap name explicitly so it can be retrieved reliably when saving
|
|
1404
|
+
setattr(im, '_operando_cmap_name', cmap_name)
|
|
1334
1405
|
if cbar is not None:
|
|
1335
1406
|
_update_custom_colorbar(cbar.ax, im)
|
|
1336
1407
|
except Exception:
|
|
@@ -2023,8 +2094,10 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
2023
2094
|
continue
|
|
2024
2095
|
except ValueError:
|
|
2025
2096
|
print("Invalid input. Enter a number.")
|
|
2097
|
+
continue
|
|
2026
2098
|
except Exception as e:
|
|
2027
2099
|
print(f"Error: {e}")
|
|
2100
|
+
continue
|
|
2028
2101
|
elif sub == 'e':
|
|
2029
2102
|
if ec_ax is None:
|
|
2030
2103
|
print("EC panel not available.")
|
|
@@ -2042,10 +2115,13 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
2042
2115
|
continue
|
|
2043
2116
|
except ValueError:
|
|
2044
2117
|
print("Invalid input. Enter a number.")
|
|
2118
|
+
continue
|
|
2045
2119
|
except Exception as e:
|
|
2046
2120
|
print(f"Error: {e}")
|
|
2121
|
+
continue
|
|
2047
2122
|
else:
|
|
2048
2123
|
print("Invalid choice.")
|
|
2124
|
+
continue
|
|
2049
2125
|
elif choice != 'q':
|
|
2050
2126
|
print("Invalid choice")
|
|
2051
2127
|
else:
|
|
@@ -2107,10 +2183,13 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
2107
2183
|
continue
|
|
2108
2184
|
except ValueError:
|
|
2109
2185
|
print("Invalid input. Enter a number.")
|
|
2186
|
+
continue
|
|
2110
2187
|
except Exception as e:
|
|
2111
2188
|
print(f"Error: {e}")
|
|
2189
|
+
continue
|
|
2112
2190
|
else:
|
|
2113
2191
|
print("Invalid choice.")
|
|
2192
|
+
continue
|
|
2114
2193
|
elif choice != 'q':
|
|
2115
2194
|
print("Invalid choice")
|
|
2116
2195
|
fig.canvas.draw_idle()
|
|
@@ -3280,7 +3359,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
3280
3359
|
print("Invalid value, ignored.")
|
|
3281
3360
|
continue
|
|
3282
3361
|
_snapshot("operando-intensity-range")
|
|
3283
|
-
im
|
|
3362
|
+
_safe_set_clim(im, cur[0], new_upper)
|
|
3284
3363
|
try:
|
|
3285
3364
|
if cbar is not None:
|
|
3286
3365
|
_update_custom_colorbar(cbar.ax, im)
|
|
@@ -3306,7 +3385,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
3306
3385
|
print("Invalid value, ignored.")
|
|
3307
3386
|
continue
|
|
3308
3387
|
_snapshot("operando-intensity-range")
|
|
3309
|
-
im
|
|
3388
|
+
_safe_set_clim(im, new_lower, cur[1])
|
|
3310
3389
|
try:
|
|
3311
3390
|
if cbar is not None:
|
|
3312
3391
|
_update_custom_colorbar(cbar.ax, im)
|
|
@@ -3320,7 +3399,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
3320
3399
|
if line.lower() == 'a':
|
|
3321
3400
|
# Apply auto-normalization to visible data
|
|
3322
3401
|
if auto_available:
|
|
3323
|
-
im
|
|
3402
|
+
_safe_set_clim(im, auto_lo, auto_hi)
|
|
3324
3403
|
try:
|
|
3325
3404
|
if cbar is not None:
|
|
3326
3405
|
_update_custom_colorbar(cbar.ax, im)
|
|
@@ -3332,7 +3411,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
3332
3411
|
print("Auto-fit unavailable: no finite data in visible area")
|
|
3333
3412
|
else:
|
|
3334
3413
|
lo, hi = map(float, line.split())
|
|
3335
|
-
im
|
|
3414
|
+
_safe_set_clim(im, lo, hi)
|
|
3336
3415
|
try:
|
|
3337
3416
|
if cbar is not None:
|
|
3338
3417
|
_update_custom_colorbar(cbar.ax, im)
|
|
@@ -3381,6 +3460,15 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
3381
3460
|
print_menu()
|
|
3382
3461
|
elif cmd == 'oc':
|
|
3383
3462
|
# Change operando colormap (perceptually uniform suggestions)
|
|
3463
|
+
# Show current colormap if one is applied
|
|
3464
|
+
try:
|
|
3465
|
+
current_cmap = getattr(im, '_operando_cmap_name', None)
|
|
3466
|
+
if current_cmap is None:
|
|
3467
|
+
current_cmap = getattr(im.get_cmap(), 'name', None)
|
|
3468
|
+
if current_cmap:
|
|
3469
|
+
print(f"Current operando colormap: {current_cmap}")
|
|
3470
|
+
except Exception:
|
|
3471
|
+
pass
|
|
3384
3472
|
def _refresh_available():
|
|
3385
3473
|
return set(name.lower() for name in plt.colormaps())
|
|
3386
3474
|
available = _refresh_available()
|
|
@@ -3453,6 +3541,8 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
3453
3541
|
if reversed_choice:
|
|
3454
3542
|
palette_obj = palette_obj.reversed()
|
|
3455
3543
|
im.set_cmap(palette_obj)
|
|
3544
|
+
# Store the colormap name explicitly so it can be retrieved reliably when saving
|
|
3545
|
+
setattr(im, '_operando_cmap_name', choice)
|
|
3456
3546
|
try:
|
|
3457
3547
|
# Update custom colorbar with new colormap
|
|
3458
3548
|
if cbar is not None:
|
|
@@ -3489,7 +3579,10 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
3489
3579
|
cb_w_in, cb_gap_in, ec_gap_in, ec_w_in, ax_w_in, ax_h_in = _ensure_fixed_params(fig, ax, cbar.ax, ec_ax)
|
|
3490
3580
|
fam = plt.rcParams.get('font.sans-serif', [''])[0]
|
|
3491
3581
|
fsize = plt.rcParams.get('font.size', None)
|
|
3492
|
-
|
|
3582
|
+
# Get colormap name: first check if we stored it explicitly, otherwise try to get from colormap object
|
|
3583
|
+
cmap_name = getattr(im, '_operando_cmap_name', None)
|
|
3584
|
+
if cmap_name is None:
|
|
3585
|
+
cmap_name = getattr(im.get_cmap(), 'name', None)
|
|
3493
3586
|
cb_vis = bool(cbar.ax.get_visible())
|
|
3494
3587
|
ec_vis = bool(ec_ax.get_visible()) if ec_ax is not None else None
|
|
3495
3588
|
cb_label_text = str(getattr(cbar.ax, '_colorbar_label', cbar.ax.get_ylabel() or 'Intensity'))
|
|
@@ -4056,6 +4149,8 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
4056
4149
|
if cmap:
|
|
4057
4150
|
try:
|
|
4058
4151
|
im.set_cmap(cmap)
|
|
4152
|
+
# Store the colormap name explicitly so it can be retrieved reliably when saving
|
|
4153
|
+
setattr(im, '_operando_cmap_name', cmap)
|
|
4059
4154
|
if cbar is not None:
|
|
4060
4155
|
_update_custom_colorbar(cbar.ax, im)
|
|
4061
4156
|
except Exception:
|
|
@@ -4329,7 +4424,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
4329
4424
|
try:
|
|
4330
4425
|
intensity_range = op.get('intensity_range')
|
|
4331
4426
|
if intensity_range and isinstance(intensity_range, (list, tuple)) and len(intensity_range) == 2:
|
|
4332
|
-
im
|
|
4427
|
+
_safe_set_clim(im, float(intensity_range[0]), float(intensity_range[1]))
|
|
4333
4428
|
print(f"Applied intensity range: {intensity_range[0]:.4g} to {intensity_range[1]:.4g}")
|
|
4334
4429
|
except Exception as e:
|
|
4335
4430
|
print(f"Warning: Could not apply intensity range: {e}")
|
|
@@ -4623,6 +4718,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
4623
4718
|
print("Tip: Use LaTeX/mathtext for special characters:")
|
|
4624
4719
|
print(" Subscript: H$_2$O → H₂O | Superscript: m$^2$ → m²")
|
|
4625
4720
|
print(" Bullet: $\\bullet$ → • | Greek: $\\alpha$, $\\beta$ | Angstrom: $\\AA$ → Å")
|
|
4721
|
+
print(" Shortcuts: g{super(-1)} → g$^{\\mathrm{-1}}$ | Li{sub(2)}O → Li$_{\\mathrm{2}}$O")
|
|
4626
4722
|
while True:
|
|
4627
4723
|
sub = _safe_input("or> ").strip().lower()
|
|
4628
4724
|
if not sub:
|
|
@@ -4633,6 +4729,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
4633
4729
|
cur = ax.get_xlabel() or ''
|
|
4634
4730
|
lab = _safe_input(f"New operando X label (blank=cancel, current='{cur}'): ")
|
|
4635
4731
|
if lab:
|
|
4732
|
+
lab = convert_label_shortcuts(lab)
|
|
4636
4733
|
_snapshot("rename-op-x")
|
|
4637
4734
|
try:
|
|
4638
4735
|
ax.set_xlabel(lab)
|
|
@@ -4646,6 +4743,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
4646
4743
|
cur = ax.get_ylabel() or ''
|
|
4647
4744
|
lab = _safe_input(f"New operando Y label (blank=cancel, current='{cur}'): ")
|
|
4648
4745
|
if lab:
|
|
4746
|
+
lab = convert_label_shortcuts(lab)
|
|
4649
4747
|
_snapshot("rename-op-y")
|
|
4650
4748
|
try:
|
|
4651
4749
|
ax.set_ylabel(lab)
|
|
@@ -4675,6 +4773,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
4675
4773
|
print("Tip: Use LaTeX/mathtext for special characters:")
|
|
4676
4774
|
print(" Subscript: H$_2$O → H₂O | Superscript: m$^2$ → m²")
|
|
4677
4775
|
print(" Greek: $\\alpha$, $\\beta$ | Angstrom: $\\AA$ → Å")
|
|
4776
|
+
print(" Shortcuts: g{super(-1)} → g$^{\\mathrm{-1}}$ | Li{sub(2)}O → Li$_{\\mathrm{2}}$O")
|
|
4678
4777
|
while True:
|
|
4679
4778
|
sub = _safe_input("er> ").strip().lower()
|
|
4680
4779
|
if not sub:
|
|
@@ -4685,6 +4784,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
4685
4784
|
cur = ec_ax.get_xlabel() or ''
|
|
4686
4785
|
lab = _safe_input(f"New EC X label (blank=cancel, current='{cur}'): ")
|
|
4687
4786
|
if lab:
|
|
4787
|
+
lab = convert_label_shortcuts(lab)
|
|
4688
4788
|
_snapshot("rename-ec-x")
|
|
4689
4789
|
try:
|
|
4690
4790
|
ec_ax.set_xlabel(lab)
|
|
@@ -4697,6 +4797,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
|
|
|
4697
4797
|
cur = ec_ax.get_ylabel() or ''
|
|
4698
4798
|
lab = _safe_input(f"New EC Y label (blank=cancel, current='{cur}'): ")
|
|
4699
4799
|
if lab:
|
|
4800
|
+
lab = convert_label_shortcuts(lab)
|
|
4700
4801
|
_snapshot("rename-ec-y")
|
|
4701
4802
|
try:
|
|
4702
4803
|
ec_ax.set_ylabel(lab)
|
batplot/session.py
CHANGED
|
@@ -578,7 +578,10 @@ def dump_operando_session(
|
|
|
578
578
|
# Use masked arrays to preserve NaNs if present
|
|
579
579
|
data = _np.array(arr) # preserves mask where possible
|
|
580
580
|
extent = tuple(map(float, im.get_extent())) if hasattr(im, 'get_extent') else None
|
|
581
|
-
|
|
581
|
+
# Get colormap name: first check if we stored it explicitly, otherwise try to get from colormap object
|
|
582
|
+
cmap_name = getattr(im, '_operando_cmap_name', None)
|
|
583
|
+
if cmap_name is None:
|
|
584
|
+
cmap_name = getattr(im.get_cmap(), 'name', None)
|
|
582
585
|
clim = tuple(map(float, im.get_clim())) if hasattr(im, 'get_clim') else None
|
|
583
586
|
origin = getattr(im, 'origin', 'upper')
|
|
584
587
|
interpolation = getattr(im, 'get_interpolation', lambda: None)() or 'nearest'
|
|
@@ -870,6 +873,8 @@ def load_operando_session(filename: str):
|
|
|
870
873
|
cmap_name = 'viridis'
|
|
871
874
|
im = ax.imshow(arr, aspect='auto', origin=op.get('origin', 'upper'), extent=extent,
|
|
872
875
|
cmap=cmap_name, interpolation=op.get('interpolation', 'nearest'))
|
|
876
|
+
# Store the colormap name explicitly so it can be retrieved reliably when saving
|
|
877
|
+
setattr(im, '_operando_cmap_name', cmap_name)
|
|
873
878
|
if op.get('clim'):
|
|
874
879
|
try:
|
|
875
880
|
im.set_clim(*op['clim'])
|
|
@@ -1315,6 +1320,18 @@ def load_operando_session(filename: str):
|
|
|
1315
1320
|
elif ec_h_offset is not None:
|
|
1316
1321
|
# EC panel doesn't exist but offset was saved - ignore it
|
|
1317
1322
|
pass
|
|
1323
|
+
|
|
1324
|
+
# Apply layout with loaded offsets to ensure visual position matches saved position
|
|
1325
|
+
# This must happen after all offsets and geometry parameters are set
|
|
1326
|
+
try:
|
|
1327
|
+
from .operando_ec_interactive import _apply_group_layout_inches, _ensure_fixed_params
|
|
1328
|
+
# Get current geometry parameters (which should match what was just loaded)
|
|
1329
|
+
cb_w_i, cb_gap_i, ec_gap_i, ec_w_i, ax_w_i, ax_h_i = _ensure_fixed_params(fig, ax, cbar_ax, ec_ax)
|
|
1330
|
+
# Apply layout with loaded offsets (offsets are already set as attributes above)
|
|
1331
|
+
_apply_group_layout_inches(fig, ax, cbar_ax, ec_ax, ax_w_i, ax_h_i, cb_w_i, cb_gap_i, ec_gap_i, ec_w_i)
|
|
1332
|
+
except Exception:
|
|
1333
|
+
# If layout application fails, continue - better to have a slightly wrong layout than crash
|
|
1334
|
+
pass
|
|
1318
1335
|
except Exception:
|
|
1319
1336
|
pass
|
|
1320
1337
|
|
|
@@ -2811,6 +2828,23 @@ def load_cpc_session(filename: str):
|
|
|
2811
2828
|
ax2.yaxis.set_minor_locator(AutoMinorLocator())
|
|
2812
2829
|
ax2.yaxis.set_minor_formatter(NullFormatter())
|
|
2813
2830
|
ax2.tick_params(axis='y', which='minor', right=True)
|
|
2831
|
+
# Store tick_state on axes for interactive menu
|
|
2832
|
+
tick_state = {}
|
|
2833
|
+
for side_key, prefix in [('top', 't'), ('bottom', 'b'), ('left', 'l'), ('right', 'r')]:
|
|
2834
|
+
s = wasd_state.get(side_key, {})
|
|
2835
|
+
tick_state[f'{prefix}_ticks'] = bool(s.get('ticks', side_key in ('bottom', 'left')))
|
|
2836
|
+
tick_state[f'{prefix}_labels'] = bool(s.get('labels', side_key in ('bottom', 'left')))
|
|
2837
|
+
tick_state[f'm{prefix}x' if prefix in 'tb' else f'm{prefix}y'] = bool(s.get('minor', False))
|
|
2838
|
+
# Legacy keys
|
|
2839
|
+
tick_state['bx'] = tick_state.get('b_ticks', True)
|
|
2840
|
+
tick_state['tx'] = tick_state.get('t_ticks', False)
|
|
2841
|
+
tick_state['ly'] = tick_state.get('l_ticks', True)
|
|
2842
|
+
tick_state['ry'] = tick_state.get('r_ticks', True) # CPC has right axis
|
|
2843
|
+
tick_state['mbx'] = tick_state.get('mbx', False)
|
|
2844
|
+
tick_state['mtx'] = tick_state.get('mtx', False)
|
|
2845
|
+
tick_state['mly'] = tick_state.get('mly', False)
|
|
2846
|
+
tick_state['mry'] = tick_state.get('mry', False)
|
|
2847
|
+
ax._saved_tick_state = tick_state
|
|
2814
2848
|
except Exception:
|
|
2815
2849
|
pass
|
|
2816
2850
|
|
batplot/utils.py
CHANGED
|
@@ -540,6 +540,46 @@ def list_files_in_subdirectory(extensions: tuple, file_type: str, base_path: str
|
|
|
540
540
|
return sorted(files, key=lambda x: x[0])
|
|
541
541
|
|
|
542
542
|
|
|
543
|
+
def convert_label_shortcuts(text: str) -> str:
|
|
544
|
+
"""Convert shortcut syntax to LaTeX format for labels.
|
|
545
|
+
|
|
546
|
+
Converts {super(...)} and {sub(...)} shortcuts to LaTeX superscript/subscript format.
|
|
547
|
+
This allows easier input of mathematical notation without typing full LaTeX.
|
|
548
|
+
|
|
549
|
+
Args:
|
|
550
|
+
text: Label text that may contain {super(...)} or {sub(...)} shortcuts
|
|
551
|
+
|
|
552
|
+
Returns:
|
|
553
|
+
Text with shortcuts converted to LaTeX format (uses \\mathrm{} to prevent italic rendering).
|
|
554
|
+
|
|
555
|
+
Examples:
|
|
556
|
+
>>> convert_label_shortcuts("g{super(-1)}")
|
|
557
|
+
"g$^{\\mathrm{-1}}$"
|
|
558
|
+
>>> convert_label_shortcuts("Li{sub(2)}FeSeO")
|
|
559
|
+
"Li$_{\\mathrm{2}}$FeSeO"
|
|
560
|
+
>>> convert_label_shortcuts("H{sub(2)}O")
|
|
561
|
+
"H$_{\\mathrm{2}}$O"
|
|
562
|
+
"""
|
|
563
|
+
if not text:
|
|
564
|
+
return text
|
|
565
|
+
|
|
566
|
+
import re
|
|
567
|
+
|
|
568
|
+
# Convert {super(...)} to $^{\mathrm{...}}$ to prevent italic rendering
|
|
569
|
+
# Pattern matches {super(anything inside)}
|
|
570
|
+
# Use \mathrm{} to ensure non-italic rendering unless explicitly specified
|
|
571
|
+
# Need to escape backslashes in replacement string for LaTeX commands
|
|
572
|
+
text = re.sub(r'\{super\(([^)]+)\)\}', r'$^{\\mathrm{\1}}$', text)
|
|
573
|
+
|
|
574
|
+
# Convert {sub(...)} to $_{\mathrm{...}}$ to prevent italic rendering
|
|
575
|
+
# Pattern matches {sub(anything inside)}
|
|
576
|
+
# Use \mathrm{} to ensure non-italic rendering unless explicitly specified
|
|
577
|
+
# Need to escape backslashes in replacement string for LaTeX commands
|
|
578
|
+
text = re.sub(r'\{sub\(([^)]+)\)\}', r'$_{\\mathrm{\1}}$', text)
|
|
579
|
+
|
|
580
|
+
return text
|
|
581
|
+
|
|
582
|
+
|
|
543
583
|
def normalize_label_text(text: str) -> str:
|
|
544
584
|
"""Normalize axis label text for proper matplotlib rendering.
|
|
545
585
|
|
batplot/version_check.py
CHANGED
|
@@ -53,6 +53,54 @@ import time
|
|
|
53
53
|
from pathlib import Path
|
|
54
54
|
from typing import Optional, Tuple
|
|
55
55
|
|
|
56
|
+
# ====================================================================================
|
|
57
|
+
# UPDATE INFO CONFIGURATION
|
|
58
|
+
# ====================================================================================
|
|
59
|
+
# Edit this section to customize update notification messages and add update info.
|
|
60
|
+
#
|
|
61
|
+
# HOW TO USE:
|
|
62
|
+
# ----------
|
|
63
|
+
# When releasing a new version, edit the UPDATE_INFO dictionary below to include
|
|
64
|
+
# information about what's new or important in the update. This information will
|
|
65
|
+
# be displayed to users when they run batplot and a newer version is available.
|
|
66
|
+
#
|
|
67
|
+
# EXAMPLE:
|
|
68
|
+
# --------
|
|
69
|
+
# UPDATE_INFO = {
|
|
70
|
+
# 'custom_message': "This update includes important bug fixes and new features.",
|
|
71
|
+
# 'update_notes': [
|
|
72
|
+
# "- Fixed colormap preservation issue in session files",
|
|
73
|
+
# "- Improved legend positioning when toggling visibility",
|
|
74
|
+
# "- Added superscript/subscript shortcuts for labels",
|
|
75
|
+
# "- Enhanced version check notifications"
|
|
76
|
+
# ],
|
|
77
|
+
# 'show_update_notes': True,
|
|
78
|
+
# }
|
|
79
|
+
#
|
|
80
|
+
# To disable custom messages, set 'custom_message' to None.
|
|
81
|
+
# To disable update notes, set 'update_notes' to None or an empty list [].
|
|
82
|
+
# ====================================================================================
|
|
83
|
+
|
|
84
|
+
UPDATE_INFO = {
|
|
85
|
+
# Custom message to include in update notification
|
|
86
|
+
# Set to None or empty string to disable
|
|
87
|
+
# This will be displayed as an additional line in the update message box
|
|
88
|
+
'custom_message': "This update includes important bug fixes", # Example: "This update includes important bug fixes."
|
|
89
|
+
|
|
90
|
+
# Additional notes about the update (list of strings)
|
|
91
|
+
# Set to None or empty list [] to disable
|
|
92
|
+
# Each item in the list will be displayed as a separate line
|
|
93
|
+
'update_notes': None, # Example: ["- Fixed colormap preservation issue", "- Improved legend positioning"]
|
|
94
|
+
|
|
95
|
+
# Whether to show update notes if provided
|
|
96
|
+
# Set to False to hide update notes even if they are defined
|
|
97
|
+
'show_update_notes': True,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# ====================================================================================
|
|
101
|
+
# END OF UPDATE INFO CONFIGURATION
|
|
102
|
+
# ====================================================================================
|
|
103
|
+
|
|
56
104
|
|
|
57
105
|
def get_cache_file() -> Path:
|
|
58
106
|
"""Get the path to the version check cache file."""
|
|
@@ -160,12 +208,43 @@ def _print_update_message(current: str, latest: str) -> None:
|
|
|
160
208
|
current: Current version
|
|
161
209
|
latest: Latest available version
|
|
162
210
|
"""
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
211
|
+
# Calculate box width (minimum 68, expand if needed for longer messages)
|
|
212
|
+
box_width = 68
|
|
213
|
+
custom_msg = UPDATE_INFO.get('Fixed some bugs')
|
|
214
|
+
update_notes = UPDATE_INFO.get('update_notes')
|
|
215
|
+
show_notes = UPDATE_INFO.get('show_update_notes', True)
|
|
216
|
+
|
|
217
|
+
# Calculate required width based on content
|
|
218
|
+
max_line_len = 68 # Default minimum width
|
|
219
|
+
if custom_msg:
|
|
220
|
+
max_line_len = max(max_line_len, len(custom_msg) + 4)
|
|
221
|
+
if update_notes and show_notes:
|
|
222
|
+
for note in update_notes:
|
|
223
|
+
max_line_len = max(max_line_len, len(note) + 4)
|
|
224
|
+
# Ensure box width is at least the calculated width
|
|
225
|
+
box_width = max(68, min(max_line_len, 100)) # Cap at 100 for readability
|
|
226
|
+
|
|
227
|
+
print(f"\n\033[93m╭{'─' * box_width}╮\033[0m")
|
|
228
|
+
print(f"\033[93m│\033[0m \033[1mA new version of batplot is available!\033[0m" + " " * max(0, box_width - 34) + "\033[93m│\033[0m")
|
|
229
|
+
print(f"\033[93m│\033[0m Current: \033[91m{current}\033[0m → Latest: \033[92m{latest}\033[0m" + " " * max(0, box_width - 20 - len(current) - len(latest)) + "\033[93m│\033[0m")
|
|
230
|
+
|
|
231
|
+
# Add custom message if provided
|
|
232
|
+
if custom_msg and custom_msg.strip():
|
|
233
|
+
# Truncate if too long to fit in box
|
|
234
|
+
msg = custom_msg[:box_width - 6] if len(custom_msg) > box_width - 6 else custom_msg
|
|
235
|
+
print(f"\033[93m│\033[0m {msg}" + " " * max(0, box_width - len(msg) - 4) + "\033[93m│\033[0m")
|
|
236
|
+
|
|
237
|
+
# Add update notes if provided
|
|
238
|
+
if update_notes and show_notes and isinstance(update_notes, list):
|
|
239
|
+
for note in update_notes:
|
|
240
|
+
if note and note.strip():
|
|
241
|
+
# Truncate if too long to fit in box
|
|
242
|
+
note_text = note[:box_width - 6] if len(note) > box_width - 6 else note
|
|
243
|
+
print(f"\033[93m│\033[0m {note_text}" + " " * max(0, box_width - len(note_text) - 4) + "\033[93m│\033[0m")
|
|
244
|
+
|
|
245
|
+
print(f"\033[93m│\033[0m Update with: \033[96mpip install --upgrade batplot\033[0m" + " " * max(0, box_width - 34) + "\033[93m│\033[0m")
|
|
246
|
+
print(f"\033[93m│\033[0m To disable this check: \033[96mexport BATPLOT_NO_VERSION_CHECK=1\033[0m" + " " * max(0, box_width - 45) + "\033[93m│\033[0m")
|
|
247
|
+
print(f"\033[93m╰{'─' * box_width}╯\033[0m\n")
|
|
169
248
|
|
|
170
249
|
|
|
171
250
|
if __name__ == '__main__':
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: batplot
|
|
3
|
-
Version: 1.8.
|
|
3
|
+
Version: 1.8.2
|
|
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
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
batplot/__init__.py,sha256=cmYE6SKId-NqANj2k5EUEXFUnzP58FNBG7XRF6CLfgQ,118
|
|
2
|
+
batplot/args.py,sha256=mrDjMURp_OQnXrAwl9WnE_FW4HJu940O7NmL9QWQnD4,35189
|
|
3
|
+
batplot/batch.py,sha256=YQ7obCIqLCObwDbM7TXpOBh7g7BO95wZNsa2Fy84c6o,53858
|
|
4
|
+
batplot/batplot.py,sha256=Avb0Txs-VaG1UU-bL-7HWnZf_8RS_n-KTnZz9O_3GPA,174374
|
|
5
|
+
batplot/cif.py,sha256=JfHwNf3SHrcpALc_F5NjJmQ3lg71MBRSaIUJjGYPTx8,30120
|
|
6
|
+
batplot/cli.py,sha256=ScDb2je8VQ0mz_z0SLCHEigiTuFPY5pb1snnzCouKms,5828
|
|
7
|
+
batplot/color_utils.py,sha256=7InQLVo1XTg7sgAbltM2KeDSFJgr787YEaV9vJbIoWY,20460
|
|
8
|
+
batplot/config.py,sha256=6nGY7fKN4T5KZUGQS2ArUBgEkLAL0j37XwG5SCVQgKA,6420
|
|
9
|
+
batplot/converters.py,sha256=rR2WMPM0nR5E3eZI3gWbaJf_AfbdQx3urVSbJmZXNzo,8237
|
|
10
|
+
batplot/cpc_interactive.py,sha256=r70RVu75QAPEWkK_bR4c3MWDXNSwHYxOAYGEVf0TgUg,238755
|
|
11
|
+
batplot/electrochem_interactive.py,sha256=ti7V8BoAxUk4BD_vDRKAu5ydlHMl75htLvdVYFUUVsw,221778
|
|
12
|
+
batplot/interactive.py,sha256=2hQrvV-7VEz0cscIb3Bc7qQ9MpRxP4hjZ6raEnpl5yg,206779
|
|
13
|
+
batplot/manual.py,sha256=pbRI6G4Pm12pOW8LrOLWWu7IEOtqWN3tRHtgge50LlA,11556
|
|
14
|
+
batplot/modes.py,sha256=qE2OsOQQKhwOWene5zxJeuuewTrZxubtahQuz5je7ok,37252
|
|
15
|
+
batplot/operando.py,sha256=p2Ug1mFUQxaU702cTBGgJKb3_v1C2p3LLUwfXaVBpPY,28311
|
|
16
|
+
batplot/operando_ec_interactive.py,sha256=8GQ47-I8SLTS88sFEk8m3vDxFEjSfD3hao62Qke7SxA,305137
|
|
17
|
+
batplot/plotting.py,sha256=hG2_EdDhF1Qpn1XfZKdCQ5-w_m9gUYFbr804UQ5QjsU,10841
|
|
18
|
+
batplot/readers.py,sha256=kAI0AvYrdfGRZkvADJ4riN96IWtrH24aAoZpBtONTbw,112960
|
|
19
|
+
batplot/session.py,sha256=WuBZR-HKDr4VlqjwynyK8gCkx6xLoHzNaGBH948p9jU,135638
|
|
20
|
+
batplot/style.py,sha256=ig1ozX4dhEsXf5JKaPZOvgVS3CWx-BTFSc3vfAH3Y-E,62274
|
|
21
|
+
batplot/ui.py,sha256=ifpbK74juUzLMCt-sJGVaWtpDb1NMRJzs2YyiwwafzY,35302
|
|
22
|
+
batplot/utils.py,sha256=LY2-Axr3DsQMTxuXe48vSjrLJKEnkzkZjdSFdQizbpg,37599
|
|
23
|
+
batplot/version_check.py,sha256=--U_74DKgHbGtVdBsg9DfUJ10S5-OMXT-rzaYjK0JBc,9997
|
|
24
|
+
batplot/data/USER_MANUAL.md,sha256=VYPvNZt3Fy8Z4Izr2FnQBw9vEaFTPkybhHDnF-OuKws,17694
|
|
25
|
+
batplot-1.8.2.dist-info/licenses/LICENSE,sha256=2PAnHeCiTfgI7aKZLWr0G56HI9fGKQ0CEbQ02H-yExQ,1065
|
|
26
|
+
batplot_backup_20251121_223043/__init__.py,sha256=3s2DUQuTbWs65hoN9cQQ8IiJbaFJY8fNxiCpwRBYoOA,118
|
|
27
|
+
batplot_backup_20251121_223043/args.py,sha256=OH-h84QhN-IhMS8sPAsSEqccHD3wpeMgmXa_fqv5xtg,21215
|
|
28
|
+
batplot_backup_20251121_223043/batch.py,sha256=oI7PONJyciHDOqNPq-8fnOQMyn9CpAdVznKaEdsy0ig,48650
|
|
29
|
+
batplot_backup_20251121_223043/batplot.py,sha256=cJOqfqEWd3vW4prlt0i2Ih6BqopnjFiRP_fAxCMHcds,157883
|
|
30
|
+
batplot_backup_20251121_223043/cif.py,sha256=MeMHq7GvFwrFwpASD4XkqbHVBiBrJxmG112IPThfbZo,17564
|
|
31
|
+
batplot_backup_20251121_223043/cli.py,sha256=lq-0MSCHouGm1qXMYFlI2YMwAMZZSPQxhfMrR8-vdTM,2622
|
|
32
|
+
batplot_backup_20251121_223043/color_utils.py,sha256=jQzsR1Q2cfn7luIdK5aMW4BZhIKb5Q_Q9NfmiUk0AwA,8467
|
|
33
|
+
batplot_backup_20251121_223043/config.py,sha256=MKtmMiQrY9WmghEpcdyBwpiT-Xl3SwLVZTt0DhuB7Yc,1939
|
|
34
|
+
batplot_backup_20251121_223043/converters.py,sha256=O7zvCNTztrXXSxJtm2GZkseYt4agidA6URSCugh953I,3090
|
|
35
|
+
batplot_backup_20251121_223043/cpc_interactive.py,sha256=Z8Sil20F8ibhZUFm1s2oKWGr_tDFwbPBCvEzfb3xADQ,157886
|
|
36
|
+
batplot_backup_20251121_223043/electrochem_interactive.py,sha256=FxFuq7945tIZJWWxdXkh8ZGzyCV5u8khVIr9bFCtKTw,173915
|
|
37
|
+
batplot_backup_20251121_223043/interactive.py,sha256=dAntE1WkAC2pf50wK-jOLmO-t3BOt9NgtgrFmyM_0ac,181928
|
|
38
|
+
batplot_backup_20251121_223043/modes.py,sha256=s4eUHfbl-uORt9kR7Rl56xvirMkPXSsU_dVVv8PrOSE,24698
|
|
39
|
+
batplot_backup_20251121_223043/operando.py,sha256=SABx1BQguoXXsG5PFAbp_CMvAz9vDA3JKRa4lcKGCm0,22980
|
|
40
|
+
batplot_backup_20251121_223043/operando_ec_interactive.py,sha256=k9_r70OKqclJQUOT3c_W2DxXfkF9qVRCcUxo-QuTwsI,261415
|
|
41
|
+
batplot_backup_20251121_223043/plotting.py,sha256=fwzcdKQcHZDamtJj33zfs--Kwc81KoMhn91EQ8Vkeq8,4157
|
|
42
|
+
batplot_backup_20251121_223043/readers.py,sha256=O1CbGE5sedFn1TvCAvIB39Y6zCqcBt3ehvIkf0b6rYw,78339
|
|
43
|
+
batplot_backup_20251121_223043/session.py,sha256=CzzDZw_7rb8r2seVZZbP6dLoDl8nhhViKgB-qaT5-5s,111705
|
|
44
|
+
batplot_backup_20251121_223043/style.py,sha256=xg-tj6bEbFUVjjxYMokiLehS4tSfKanLIQKtly3cAP0,51318
|
|
45
|
+
batplot_backup_20251121_223043/ui.py,sha256=K0XZWyiuBRNkFod9mgZyJ9CLN78GR1-hh6EznnIb5S8,31208
|
|
46
|
+
batplot_backup_20251121_223043/utils.py,sha256=jydA0JxsCWWAudXEwSjlxTG17y2F8U6hIAukAzi1P0g,32526
|
|
47
|
+
batplot_backup_20251121_223043/version_check.py,sha256=vlHkGkgUJcD_Z4KZmwonxZvKZh0MwHLaBSxaLPc66AQ,4555
|
|
48
|
+
batplot_backup_20251221_101150/__init__.py,sha256=AjJgj7OxrIM-uNCR6JvGnRjpVNZgCUbmj0VE_BpFFF8,118
|
|
49
|
+
batplot_backup_20251221_101150/args.py,sha256=mrDjMURp_OQnXrAwl9WnE_FW4HJu940O7NmL9QWQnD4,35189
|
|
50
|
+
batplot_backup_20251221_101150/batch.py,sha256=YQ7obCIqLCObwDbM7TXpOBh7g7BO95wZNsa2Fy84c6o,53858
|
|
51
|
+
batplot_backup_20251221_101150/batplot.py,sha256=40lU1nY1NqeAOpzNG_vLF_L34COKhiA19pMpbvA3SJc,171885
|
|
52
|
+
batplot_backup_20251221_101150/cif.py,sha256=JfHwNf3SHrcpALc_F5NjJmQ3lg71MBRSaIUJjGYPTx8,30120
|
|
53
|
+
batplot_backup_20251221_101150/cli.py,sha256=ScDb2je8VQ0mz_z0SLCHEigiTuFPY5pb1snnzCouKms,5828
|
|
54
|
+
batplot_backup_20251221_101150/color_utils.py,sha256=7InQLVo1XTg7sgAbltM2KeDSFJgr787YEaV9vJbIoWY,20460
|
|
55
|
+
batplot_backup_20251221_101150/config.py,sha256=6nGY7fKN4T5KZUGQS2ArUBgEkLAL0j37XwG5SCVQgKA,6420
|
|
56
|
+
batplot_backup_20251221_101150/converters.py,sha256=rR2WMPM0nR5E3eZI3gWbaJf_AfbdQx3urVSbJmZXNzo,8237
|
|
57
|
+
batplot_backup_20251221_101150/cpc_interactive.py,sha256=HrrjaB8-CNYUitgl5zWMNvWQLZfxyFAtpSm67qoi-nE,238235
|
|
58
|
+
batplot_backup_20251221_101150/electrochem_interactive.py,sha256=ti7V8BoAxUk4BD_vDRKAu5ydlHMl75htLvdVYFUUVsw,221778
|
|
59
|
+
batplot_backup_20251221_101150/interactive.py,sha256=uerVR-56g2Ur8qDZ-cXffPbpYMQXEXiMNXCxyWZZ8k0,206259
|
|
60
|
+
batplot_backup_20251221_101150/manual.py,sha256=pbRI6G4Pm12pOW8LrOLWWu7IEOtqWN3tRHtgge50LlA,11556
|
|
61
|
+
batplot_backup_20251221_101150/modes.py,sha256=Utfal5IaV8rfoNyNFziUZpqRlpZAWJdiTc45DY-FJE8,37300
|
|
62
|
+
batplot_backup_20251221_101150/operando.py,sha256=p2Ug1mFUQxaU702cTBGgJKb3_v1C2p3LLUwfXaVBpPY,28311
|
|
63
|
+
batplot_backup_20251221_101150/operando_ec_interactive.py,sha256=TMB6rDpeolX0CgE2V7tWC24ffJrnbJomQSnTsTd8CNQ,305121
|
|
64
|
+
batplot_backup_20251221_101150/plotting.py,sha256=hG2_EdDhF1Qpn1XfZKdCQ5-w_m9gUYFbr804UQ5QjsU,10841
|
|
65
|
+
batplot_backup_20251221_101150/readers.py,sha256=kAI0AvYrdfGRZkvADJ4riN96IWtrH24aAoZpBtONTbw,112960
|
|
66
|
+
batplot_backup_20251221_101150/session.py,sha256=05JsVi0ygMzOxVRRZ4klhE5Eh6eE6QxKR8p7_j6slBI,134429
|
|
67
|
+
batplot_backup_20251221_101150/style.py,sha256=ig1ozX4dhEsXf5JKaPZOvgVS3CWx-BTFSc3vfAH3Y-E,62274
|
|
68
|
+
batplot_backup_20251221_101150/ui.py,sha256=ifpbK74juUzLMCt-sJGVaWtpDb1NMRJzs2YyiwwafzY,35302
|
|
69
|
+
batplot_backup_20251221_101150/utils.py,sha256=LY2-Axr3DsQMTxuXe48vSjrLJKEnkzkZjdSFdQizbpg,37599
|
|
70
|
+
batplot_backup_20251221_101150/version_check.py,sha256=ztTHwqgWd8OlS9PLLY5A_TabWxBASDA_-5yyN15PZC8,9996
|
|
71
|
+
batplot-1.8.2.dist-info/METADATA,sha256=ZNkBWCjEFRJVKuq1FtQ9JCovRWnEm3lmqWs8eYsvMzU,7406
|
|
72
|
+
batplot-1.8.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
73
|
+
batplot-1.8.2.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
|
|
74
|
+
batplot-1.8.2.dist-info/top_level.txt,sha256=Z5Q4sAiT_FDqZqhlLsYn9avRTuFAEEf3AVfkswxOb18,70
|
|
75
|
+
batplot-1.8.2.dist-info/RECORD,,
|