batplot 1.7.22__py3-none-any.whl → 1.7.23__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 CHANGED
@@ -1,5 +1,5 @@
1
1
  """batplot: Interactive plotting for battery data visualization."""
2
2
 
3
- __version__ = "1.7.22"
3
+ __version__ = "1.7.23"
4
4
 
5
5
  __all__ = ["__version__"]
batplot/args.py CHANGED
@@ -190,6 +190,7 @@ def _print_general_help() -> None:
190
190
  " (If you are not from UiO, send an email to sympa@kjemi.uio.no with the subject line \"subscribe batplot-lab@kjemi.uio.no your-name\")\n"
191
191
  " Kindly cite the pypi package page (https://pypi.org/project/batplot/) if the plot is used for publication\n"
192
192
  " Email: tianda@uio.no\n"
193
+ " Personal page: https://www.mn.uio.no/kjemi/english/people/aca/tianda/\n"
193
194
  )
194
195
  _print_help(msg)
195
196
 
@@ -1050,6 +1050,15 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
1050
1050
  # Horizontal offsets (relative to canvas center, in inches)
1051
1051
  cb_h_offset = getattr(cbar.ax, '_cb_h_offset_in', 0.0)
1052
1052
  ec_h_offset = getattr(ec_ax, '_ec_h_offset_in', 0.0) if ec_ax is not None else None
1053
+ # Colorbar tick/label positions (left/right)
1054
+ cb_ticks_left = True
1055
+ cb_label_left = True
1056
+ try:
1057
+ cb_ticks_left = any(getattr(tick, 'tick1line', None) and tick.tick1line.get_visible() for tick in cbar.ax.yaxis.get_major_ticks())
1058
+ # label position is stored on axis; capture current setting
1059
+ cb_label_left = (cbar.ax.yaxis.get_label_position() == 'left')
1060
+ except Exception:
1061
+ pass
1053
1062
  # Label pads (save current labelpad values to restore later)
1054
1063
  op_labelpads = {
1055
1064
  'x': getattr(ax.xaxis, 'labelpad', None),
@@ -1084,6 +1093,8 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
1084
1093
  'ec_visible': ec_visible,
1085
1094
  'cb_h_offset': float(cb_h_offset),
1086
1095
  'ec_h_offset': float(ec_h_offset) if ec_h_offset is not None else None,
1096
+ 'cb_ticks_left': cb_ticks_left,
1097
+ 'cb_label_left': cb_label_left,
1087
1098
  'op_labelpads': dict(op_labelpads),
1088
1099
  'ec_labelpads': dict(ec_labelpads) if ec_labelpads is not None else None,
1089
1100
  'op_title_offsets': {
@@ -1138,6 +1149,14 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
1138
1149
  _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)
1139
1150
  except Exception:
1140
1151
  pass
1152
+ # Colorbar tick/label side
1153
+ try:
1154
+ cb_ticks_left = snap.get('cb_ticks_left', True)
1155
+ cb_label_left = snap.get('cb_label_left', True)
1156
+ cbar.ax.yaxis.set_ticks_position('left' if cb_ticks_left else 'right')
1157
+ cbar.ax.yaxis.set_label_position('left' if cb_label_left else 'right')
1158
+ except Exception:
1159
+ pass
1141
1160
  # Labels
1142
1161
  try:
1143
1162
  op_l = snap.get('op_labels', {})
@@ -1170,6 +1189,14 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
1170
1189
  pass
1171
1190
  try:
1172
1191
  if snap.get('clim') is not None:
1192
+ # Detach built-in colorbar update to avoid artist removal errors; we redraw custom below.
1193
+ try:
1194
+ if hasattr(cbar, 'mappable'):
1195
+ cbar.mappable = None
1196
+ if hasattr(cbar, 'solids'):
1197
+ cbar.solids = None
1198
+ except Exception:
1199
+ pass
1173
1200
  lo, hi = snap['clim']; im.set_clim(float(lo), float(hi))
1174
1201
  except Exception:
1175
1202
  pass
@@ -1180,6 +1207,15 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
1180
1207
  cbar.update_normal(im)
1181
1208
  except Exception:
1182
1209
  pass
1210
+ # Restore colorbar side (ticks/label) and redraw custom colorbar to keep position
1211
+ try:
1212
+ cb_ticks_left = snap.get('cb_ticks_left', True)
1213
+ cb_label_left = snap.get('cb_label_left', True)
1214
+ cbar.ax.yaxis.set_ticks_position('left' if cb_ticks_left else 'right')
1215
+ cbar.ax.yaxis.set_label_position('left' if cb_label_left else 'right')
1216
+ _update_custom_colorbar(cbar.ax, im)
1217
+ except Exception:
1218
+ pass
1183
1219
  # EC axes
1184
1220
  try:
1185
1221
  if ec_ax is not None:
@@ -2840,7 +2876,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
2840
2876
  continue
2841
2877
  _snapshot("operando-xrange")
2842
2878
  ax.set_xlim(cur[0], new_upper)
2843
- _renormalize_to_visible()
2844
2879
  fig.canvas.draw_idle()
2845
2880
  print(f"Operando X range updated: {ax.get_xlim()[0]:.4g} {ax.get_xlim()[1]:.4g}")
2846
2881
  if line.lower() == 'w':
@@ -2860,7 +2895,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
2860
2895
  continue
2861
2896
  _snapshot("operando-xrange")
2862
2897
  ax.set_xlim(new_lower, cur[1])
2863
- _renormalize_to_visible()
2864
2898
  fig.canvas.draw_idle()
2865
2899
  print(f"Operando X range updated: {ax.get_xlim()[0]:.4g} {ax.get_xlim()[1]:.4g}")
2866
2900
  if line.lower() == 's':
@@ -2877,7 +2911,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
2877
2911
  orig_min = min(extent[0], extent[1])
2878
2912
  orig_max = max(extent[0], extent[1])
2879
2913
  ax.set_xlim(orig_min, orig_max)
2880
- _renormalize_to_visible()
2881
2914
  fig.canvas.draw_idle()
2882
2915
  print(f"Operando X range restored to original: {ax.get_xlim()[0]:.4g} {ax.get_xlim()[1]:.4g}")
2883
2916
  else:
@@ -2891,8 +2924,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
2891
2924
  try:
2892
2925
  lo, hi = map(float, line.split())
2893
2926
  ax.set_xlim(lo, hi)
2894
- # Re-normalize intensity to visible region
2895
- _renormalize_to_visible()
2896
2927
  fig.canvas.draw_idle()
2897
2928
  except Exception as e:
2898
2929
  print(f"Invalid range: {e}")
@@ -2918,7 +2949,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
2918
2949
  continue
2919
2950
  _snapshot("operando-yrange")
2920
2951
  ax.set_ylim(cur[0], new_upper)
2921
- _renormalize_to_visible()
2922
2952
  fig.canvas.draw_idle()
2923
2953
  print(f"Operando Y range updated: {ax.get_ylim()[0]:.4g} {ax.get_ylim()[1]:.4g}")
2924
2954
  if line.lower() == 'w':
@@ -2938,7 +2968,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
2938
2968
  continue
2939
2969
  _snapshot("operando-yrange")
2940
2970
  ax.set_ylim(new_lower, cur[1])
2941
- _renormalize_to_visible()
2942
2971
  fig.canvas.draw_idle()
2943
2972
  print(f"Operando Y range updated: {ax.get_ylim()[0]:.4g} {ax.get_ylim()[1]:.4g}")
2944
2973
  if line.lower() == 's':
@@ -2955,7 +2984,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
2955
2984
  orig_min = min(extent[2], extent[3])
2956
2985
  orig_max = max(extent[2], extent[3])
2957
2986
  ax.set_ylim(orig_min, orig_max)
2958
- _renormalize_to_visible()
2959
2987
  fig.canvas.draw_idle()
2960
2988
  print(f"Operando Y range restored to original: {ax.get_ylim()[0]:.4g} {ax.get_ylim()[1]:.4g}")
2961
2989
  else:
@@ -2969,8 +2997,6 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
2969
2997
  try:
2970
2998
  lo, hi = map(float, line.split())
2971
2999
  ax.set_ylim(lo, hi)
2972
- # Re-normalize intensity to visible region
2973
- _renormalize_to_visible()
2974
3000
  fig.canvas.draw_idle()
2975
3001
  except Exception as e:
2976
3002
  print(f"Invalid range: {e}")
batplot/session.py CHANGED
@@ -38,6 +38,7 @@ import matplotlib.pyplot as plt
38
38
  import numpy as np
39
39
 
40
40
  from .utils import _confirm_overwrite
41
+ from .color_utils import ensure_colormap
41
42
 
42
43
 
43
44
  def _current_tick_width(axis_obj, which: str):
@@ -831,8 +832,14 @@ def load_operando_session(filename: str):
831
832
  op = sess['operando']
832
833
  arr = _ma.masked_invalid(op['array'])
833
834
  extent = tuple(op['extent']) if op['extent'] is not None else None
835
+ cmap_name = op.get('cmap') or 'viridis'
836
+ try:
837
+ if not ensure_colormap(cmap_name):
838
+ cmap_name = 'viridis'
839
+ except Exception:
840
+ cmap_name = 'viridis'
834
841
  im = ax.imshow(arr, aspect='auto', origin=op.get('origin', 'upper'), extent=extent,
835
- cmap=op.get('cmap') or 'viridis', interpolation=op.get('interpolation', 'nearest'))
842
+ cmap=cmap_name, interpolation=op.get('interpolation', 'nearest'))
836
843
  if op.get('clim'):
837
844
  try:
838
845
  im.set_clim(*op['clim'])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batplot
3
- Version: 1.7.22
3
+ Version: 1.7.23
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-Expression: MIT
@@ -171,7 +171,9 @@ See [LICENSE](LICENSE)
171
171
 
172
172
  ## Author & Contact
173
173
 
174
- Tian Dai (tianda@uio.no)
174
+ Tian Dai
175
+ tianda@uio.no
175
176
  University of Oslo
177
+ https://www.mn.uio.no/kjemi/english/people/aca/tianda/
176
178
 
177
179
  **Subscribe for Updates**: Join batplot-lab@kjemi.uio.no for updates, feature announcements, and community feedback. If you are not from UiO, send an email to sympa@kjemi.uio.no with the exact subject line with your name: "subscribe batplot-lab@kjemi.uio.no your-name"
@@ -1,5 +1,5 @@
1
- batplot/__init__.py,sha256=49tgsxXciOUfTdUerVfqotJBtQQT93XXCs_pBD-1y2k,119
2
- batplot/args.py,sha256=T10bmG09tgMks6YvlurHECLvwl94zcvdGZKbc9SuXxQ,34899
1
+ batplot/__init__.py,sha256=vkOVAS6v23TnQZXUW0hx9pGUWLY7MUF__AXzrydzgBs,119
2
+ batplot/args.py,sha256=6g1eHVsycDSAenwrXuCTcyuXCy_-30zy1lWtdguBG2s,34983
3
3
  batplot/batch.py,sha256=YQ7obCIqLCObwDbM7TXpOBh7g7BO95wZNsa2Fy84c6o,53858
4
4
  batplot/batplot.py,sha256=h960XKSmJ825DqI99Xnyomg_gaB0aFDUIKxkovm8BPQ,170691
5
5
  batplot/cif.py,sha256=JfHwNf3SHrcpALc_F5NjJmQ3lg71MBRSaIUJjGYPTx8,30120
@@ -13,16 +13,16 @@ batplot/interactive.py,sha256=gAmfHLVu4dAC_-hpmpfJj8dyQTBbzRNweVODuQDIocw,196317
13
13
  batplot/manual.py,sha256=pbRI6G4Pm12pOW8LrOLWWu7IEOtqWN3tRHtgge50LlA,11556
14
14
  batplot/modes.py,sha256=qE2OsOQQKhwOWene5zxJeuuewTrZxubtahQuz5je7ok,37252
15
15
  batplot/operando.py,sha256=CdTZJa6Cr1wNczFEbwAido2mc7C_h1xxoQ5b045ktSk,28105
16
- batplot/operando_ec_interactive.py,sha256=FpBdtkYdLOa31teRnNZ5qn1fo4Xqrk3AaFwCbj32c3A,280504
16
+ batplot/operando_ec_interactive.py,sha256=snGzZBlgmXhvGupaMv-1Jvb9V7E3APMadYXKfQ4rZB4,281889
17
17
  batplot/plotting.py,sha256=hG2_EdDhF1Qpn1XfZKdCQ5-w_m9gUYFbr804UQ5QjsU,10841
18
18
  batplot/readers.py,sha256=kAI0AvYrdfGRZkvADJ4riN96IWtrH24aAoZpBtONTbw,112960
19
- batplot/session.py,sha256=5PVxu8Q7T6Fonq0zgvUD3SkoN-9QnlBa8l3_R02B_K0,120820
19
+ batplot/session.py,sha256=3oo0jimTEdK7HpcBb326F8iBCM_LKPwNaSnmqSKU92Y,121025
20
20
  batplot/style.py,sha256=wmg4D4LdunLU88YYzh9y2REwet6xc5Ox2naa1ZW2OlM,58276
21
21
  batplot/ui.py,sha256=MIY2x_ghCYxjdYhjMUZsMMnQEUBLgrIT37hfPGZf_cs,36320
22
22
  batplot/utils.py,sha256=3dBZALWiCu5c6uc5MBII7n8329BZjieTEw4qithTlow,33939
23
23
  batplot/version_check.py,sha256=OG4LuHo5-rSqLLHQo5nWbX9lbNq6NyxRdvVUUcJRBqQ,6219
24
24
  batplot/data/USER_MANUAL.md,sha256=VYPvNZt3Fy8Z4Izr2FnQBw9vEaFTPkybhHDnF-OuKws,17694
25
- batplot-1.7.22.dist-info/licenses/LICENSE,sha256=2PAnHeCiTfgI7aKZLWr0G56HI9fGKQ0CEbQ02H-yExQ,1065
25
+ batplot-1.7.23.dist-info/licenses/LICENSE,sha256=2PAnHeCiTfgI7aKZLWr0G56HI9fGKQ0CEbQ02H-yExQ,1065
26
26
  batplot_backup_20251121_223043/__init__.py,sha256=3s2DUQuTbWs65hoN9cQQ8IiJbaFJY8fNxiCpwRBYoOA,118
27
27
  batplot_backup_20251121_223043/args.py,sha256=OH-h84QhN-IhMS8sPAsSEqccHD3wpeMgmXa_fqv5xtg,21215
28
28
  batplot_backup_20251121_223043/batch.py,sha256=oI7PONJyciHDOqNPq-8fnOQMyn9CpAdVznKaEdsy0ig,48650
@@ -45,8 +45,8 @@ batplot_backup_20251121_223043/style.py,sha256=xg-tj6bEbFUVjjxYMokiLehS4tSfKanLI
45
45
  batplot_backup_20251121_223043/ui.py,sha256=K0XZWyiuBRNkFod9mgZyJ9CLN78GR1-hh6EznnIb5S8,31208
46
46
  batplot_backup_20251121_223043/utils.py,sha256=jydA0JxsCWWAudXEwSjlxTG17y2F8U6hIAukAzi1P0g,32526
47
47
  batplot_backup_20251121_223043/version_check.py,sha256=vlHkGkgUJcD_Z4KZmwonxZvKZh0MwHLaBSxaLPc66AQ,4555
48
- batplot-1.7.22.dist-info/METADATA,sha256=huY1GKnOrNjHphobQkIhbe94RtCDgTlwTNjmJRBQLIc,6137
49
- batplot-1.7.22.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
50
- batplot-1.7.22.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
51
- batplot-1.7.22.dist-info/top_level.txt,sha256=CgqK4RpsYnUFAcqO4bLOnEhCoPY4IPEGLPkiDlzLIxg,39
52
- batplot-1.7.22.dist-info/RECORD,,
48
+ batplot-1.7.23.dist-info/METADATA,sha256=9CLx5Pt0Lrcu3244DqSt7DjHP8zO9FfqsGh-nFmvtfs,6188
49
+ batplot-1.7.23.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
50
+ batplot-1.7.23.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
51
+ batplot-1.7.23.dist-info/top_level.txt,sha256=CgqK4RpsYnUFAcqO4bLOnEhCoPY4IPEGLPkiDlzLIxg,39
52
+ batplot-1.7.23.dist-info/RECORD,,