batplot 1.7.24__py3-none-any.whl → 1.7.25__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.
@@ -2641,7 +2641,7 @@ def electrochem_interactive_menu(fig, ax, cycle_lines: Dict[int, Dict[str, Optio
2641
2641
  try:
2642
2642
  print("Tip: Use LaTeX/mathtext for special characters:")
2643
2643
  print(" Subscript: H$_2$O → H₂O | Superscript: m$^2$ → m²")
2644
- print(" Greek: $\\alpha$, $\\beta$ | Angstrom: $\\AA$ → Å")
2644
+ print(" Bullet: $\\bullet$ → • | Greek: $\\alpha$, $\\beta$ | Angstrom: $\\AA$ → Å")
2645
2645
  while True:
2646
2646
  print("Rename axis: x, y, both, q=back")
2647
2647
  sub = input("Rename> ").strip().lower()
batplot/interactive.py CHANGED
@@ -2179,7 +2179,7 @@ def interactive_menu(fig, ax, y_data_list, x_data_list, labels, orig_y,
2179
2179
  if mode == 'c':
2180
2180
  print("Tip: Use LaTeX/mathtext for special characters:")
2181
2181
  print(" Subscript: H$_2$O → H₂O | Superscript: m$^2$ → m²")
2182
- print(" Greek: $\\alpha$, $\\beta$ | Angstrom: $\\AA$ → Å")
2182
+ print(" Bullet: $\\bullet$ → • | Greek: $\\alpha$, $\\beta$ | Angstrom: $\\AA$ → Å")
2183
2183
  idx_in = input("Curve number to rename (q=cancel): ").strip()
2184
2184
  if not idx_in or idx_in.lower() == 'q':
2185
2185
  print("Canceled.")
@@ -4465,7 +4465,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
4465
4465
  print("Rename Operando Axes: x=rename X label, y=rename Y label, q=back")
4466
4466
  print("Tip: Use LaTeX/mathtext for special characters:")
4467
4467
  print(" Subscript: H$_2$O → H₂O | Superscript: m$^2$ → m²")
4468
- print(" Greek: $\\alpha$, $\\beta$ | Angstrom: $\\AA$ → Å")
4468
+ print(" Bullet: $\\bullet$ → • | Greek: $\\alpha$, $\\beta$ | Angstrom: $\\AA$ → Å")
4469
4469
  while True:
4470
4470
  sub = input("or> ").strip().lower()
4471
4471
  if not sub:
batplot/session.py CHANGED
@@ -2408,6 +2408,30 @@ def dump_cpc_session(
2408
2408
  if file_data and isinstance(file_data, list) and len(file_data) > 0:
2409
2409
  multi_files = []
2410
2410
  for f in file_data:
2411
+ def _marker_of(sc, default_val):
2412
+ try:
2413
+ m = getattr(sc, 'get_marker', lambda: default_val)()
2414
+ if m is None:
2415
+ return default_val
2416
+ return m
2417
+ except Exception:
2418
+ return default_val
2419
+ def _alpha_of(sc, default_val=None):
2420
+ try:
2421
+ a = sc.get_alpha()
2422
+ return float(a) if a is not None else default_val
2423
+ except Exception:
2424
+ return default_val
2425
+ def _visible_of(sc, default_val=True):
2426
+ try:
2427
+ return bool(sc.get_visible())
2428
+ except Exception:
2429
+ return default_val
2430
+ def _label_of(sc, default_val=""):
2431
+ try:
2432
+ return sc.get_label() or default_val
2433
+ except Exception:
2434
+ return default_val
2411
2435
  file_info = {
2412
2436
  'filename': f.get('filename', 'unknown'),
2413
2437
  'visible': f.get('visible', True),
@@ -2415,16 +2439,31 @@ def dump_cpc_session(
2415
2439
  'x': _np.array(_scatter_xy(f.get('sc_charge', sc_charge))[0]),
2416
2440
  'y': _np.array(_scatter_xy(f.get('sc_charge', sc_charge))[1]),
2417
2441
  'color': _color_of(f.get('sc_charge')),
2442
+ 'size': _size_of(f.get('sc_charge'), 32.0),
2443
+ 'alpha': _alpha_of(f.get('sc_charge')),
2444
+ 'marker': _marker_of(f.get('sc_charge'), 'o'),
2445
+ 'label': _label_of(f.get('sc_charge'), 'Charge capacity'),
2446
+ 'visible': _visible_of(f.get('sc_charge')),
2418
2447
  },
2419
2448
  'discharge': {
2420
2449
  'x': _np.array(_scatter_xy(f.get('sc_discharge', sc_discharge))[0]),
2421
2450
  'y': _np.array(_scatter_xy(f.get('sc_discharge', sc_discharge))[1]),
2422
2451
  'color': _color_of(f.get('sc_discharge')),
2452
+ 'size': _size_of(f.get('sc_discharge'), 32.0),
2453
+ 'alpha': _alpha_of(f.get('sc_discharge')),
2454
+ 'marker': _marker_of(f.get('sc_discharge'), 's'),
2455
+ 'label': _label_of(f.get('sc_discharge'), 'Discharge capacity'),
2456
+ 'visible': _visible_of(f.get('sc_discharge')),
2423
2457
  },
2424
2458
  'efficiency': {
2425
2459
  'x': _np.array(_scatter_xy(f.get('sc_eff', sc_eff))[0]),
2426
2460
  'y': _np.array(_scatter_xy(f.get('sc_eff', sc_eff))[1]),
2427
2461
  'color': _color_of(f.get('sc_eff')),
2462
+ 'size': _size_of(f.get('sc_eff'), 40.0),
2463
+ 'alpha': _alpha_of(f.get('sc_eff')),
2464
+ 'marker': _marker_of(f.get('sc_eff'), '^'),
2465
+ 'label': _label_of(f.get('sc_eff'), 'Coulombic efficiency'),
2466
+ 'visible': _visible_of(f.get('sc_eff')),
2428
2467
  }
2429
2468
  }
2430
2469
  multi_files.append(file_info)
@@ -2445,9 +2484,9 @@ def dump_cpc_session(
2445
2484
 
2446
2485
 
2447
2486
  def load_cpc_session(filename: str):
2448
- """Load a CPC session and reconstruct fig, axes, and scatter artists.
2487
+ """Load a CPC session and reconstruct fig, axes, scatter artists, and file_data.
2449
2488
 
2450
- Returns: (fig, ax, ax2, sc_charge, sc_discharge, sc_eff)
2489
+ Returns: (fig, ax, ax2, sc_charge, sc_discharge, sc_eff, file_data)
2451
2490
  """
2452
2491
  try:
2453
2492
  with open(filename, 'rb') as f:
@@ -2534,12 +2573,47 @@ def load_cpc_session(filename: str):
2534
2573
  except Exception:
2535
2574
  pass
2536
2575
  return sc
2537
- sc_charge = _mk_sc(ax, ch, 'o')
2538
- sc_discharge = _mk_sc(ax, dh, 'o')
2539
- # efficiency on ax2 with triangles
2540
- if 'marker' not in ef:
2541
- ef['marker'] = '^'
2542
- sc_eff = _mk_sc(ax2, ef, '^')
2576
+ # If multi_files exist, rebuild all files and pick the first as primary
2577
+ multi_files = sess.get('multi_files')
2578
+ file_data = []
2579
+ if multi_files and isinstance(multi_files, list) and len(multi_files) > 0:
2580
+ for idx, finfo in enumerate(multi_files):
2581
+ ch_info = finfo.get('charge', {})
2582
+ dh_info = finfo.get('discharge', {})
2583
+ ef_info = finfo.get('efficiency', {})
2584
+ sc_ch = _mk_sc(ax, ch_info, ch_info.get('marker', 'o') or 'o')
2585
+ sc_dh = _mk_sc(ax, dh_info, dh_info.get('marker', 's') or 's')
2586
+ eff_marker = ef_info.get('marker', '^') or '^'
2587
+ sc_ef = _mk_sc(ax2, ef_info, eff_marker)
2588
+ # Respect overall file visibility
2589
+ try:
2590
+ vis_file = bool(finfo.get('visible', True))
2591
+ except Exception:
2592
+ vis_file = True
2593
+ for sc_tmp in (sc_ch, sc_dh, sc_ef):
2594
+ try:
2595
+ sc_tmp.set_visible(sc_tmp.get_visible() and vis_file)
2596
+ except Exception:
2597
+ pass
2598
+ file_data.append({
2599
+ 'filename': finfo.get('filename', f'File {idx+1}'),
2600
+ 'visible': vis_file,
2601
+ 'sc_charge': sc_ch,
2602
+ 'sc_discharge': sc_dh,
2603
+ 'sc_eff': sc_ef,
2604
+ })
2605
+ # Use the first file as primary artists for interactive menu
2606
+ sc_charge = file_data[0]['sc_charge']
2607
+ sc_discharge = file_data[0]['sc_discharge']
2608
+ sc_eff = file_data[0]['sc_eff']
2609
+ else:
2610
+ # No multi-file info: fall back to single-file series
2611
+ sc_charge = _mk_sc(ax, ch, 'o')
2612
+ sc_discharge = _mk_sc(ax, dh, 's')
2613
+ if 'marker' not in ef:
2614
+ ef['marker'] = '^'
2615
+ sc_eff = _mk_sc(ax2, ef, '^')
2616
+ file_data = None
2543
2617
 
2544
2618
  # Restore spines state (version 2+)
2545
2619
  try:
@@ -2693,6 +2767,16 @@ def load_cpc_session(filename: str):
2693
2767
  ax2.tick_params(axis='y',
2694
2768
  right=wasd_state['right'].get('ticks', True),
2695
2769
  labelright=wasd_state['right'].get('labels', True))
2770
+ # Axis title visibility
2771
+ try:
2772
+ if 'bottom' in wasd_state:
2773
+ ax.xaxis.label.set_visible(bool(wasd_state['bottom'].get('title', True)))
2774
+ if 'left' in wasd_state:
2775
+ ax.yaxis.label.set_visible(bool(wasd_state['left'].get('title', True)))
2776
+ if 'right' in wasd_state:
2777
+ ax2.yaxis.label.set_visible(bool(wasd_state['right'].get('title', True)))
2778
+ except Exception:
2779
+ pass
2696
2780
 
2697
2781
  # Minor ticks
2698
2782
  if wasd_state.get('top', {}).get('minor') or wasd_state.get('bottom', {}).get('minor'):
@@ -2767,26 +2851,46 @@ def load_cpc_session(filename: str):
2767
2851
  try:
2768
2852
  handles1, labels1 = ax.get_legend_handles_labels()
2769
2853
  handles2, labels2 = ax2.get_legend_handles_labels()
2770
- if handles1 or handles2:
2771
- leg_meta = sess.get('legend', {})
2772
- xy_in = leg_meta.get('xy_in')
2854
+ # Filter visible handles only
2855
+ H, L = [], []
2856
+ for h, l in list(zip(handles1, labels1)) + list(zip(handles2, labels2)):
2857
+ try:
2858
+ if hasattr(h, 'get_visible') and not h.get_visible():
2859
+ continue
2860
+ except Exception:
2861
+ pass
2862
+ H.append(h); L.append(l)
2863
+ leg_meta = sess.get('legend', {})
2864
+ xy_in = leg_meta.get('xy_in')
2865
+ vis = bool(leg_meta.get('visible', True))
2866
+ if H and vis:
2773
2867
  if xy_in is not None:
2774
2868
  fw, fh = fig.get_size_inches()
2775
2869
  fx = 0.5 + float(xy_in[0]) / float(fw)
2776
2870
  fy = 0.5 + float(xy_in[1]) / float(fh)
2777
- ax.legend(handles1 + handles2, labels1 + labels2, loc='center', bbox_to_anchor=(fx, fy), bbox_transform=fig.transFigure, borderaxespad=1.0)
2871
+ leg = ax.legend(H, L, loc='center', bbox_to_anchor=(fx, fy), bbox_transform=fig.transFigure, borderaxespad=1.0)
2778
2872
  # persist inches on fig for interactive menu
2779
2873
  try:
2780
2874
  fig._cpc_legend_xy_in = (float(xy_in[0]), float(xy_in[1]))
2781
2875
  except Exception:
2782
2876
  pass
2783
2877
  else:
2784
- ax.legend(handles1 + handles2, labels1 + labels2, loc='best', borderaxespad=1.0)
2785
- # Apply visibility
2786
- vis = bool(leg_meta.get('visible', True))
2878
+ leg = ax.legend(H, L, loc='best', borderaxespad=1.0)
2879
+ # Always hide legend frame to match interactive export behavior
2880
+ try:
2881
+ if leg is not None:
2882
+ leg.set_frame_on(False)
2883
+ except Exception:
2884
+ pass
2885
+ else:
2886
+ try:
2887
+ fig._cpc_legend_xy_in = (float(xy_in[0]), float(xy_in[1])) if xy_in is not None else None
2888
+ except Exception:
2889
+ pass
2890
+ # ensure legend hidden
2787
2891
  leg = ax.get_legend()
2788
2892
  if leg is not None:
2789
- leg.set_visible(vis)
2893
+ leg.set_visible(False)
2790
2894
  except Exception:
2791
2895
  pass
2792
2896
  try:
@@ -2796,7 +2900,7 @@ def load_cpc_session(filename: str):
2796
2900
  fig.canvas.draw_idle()
2797
2901
  except Exception:
2798
2902
  pass
2799
- return fig, ax, ax2, sc_charge, sc_discharge, sc_eff
2903
+ return fig, ax, ax2, sc_charge, sc_discharge, sc_eff, file_data
2800
2904
  except Exception as e:
2801
2905
  import traceback
2802
2906
  print(f"Error loading CPC session: {e}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batplot
3
- Version: 1.7.24
3
+ Version: 1.7.25
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
@@ -1,28 +1,28 @@
1
- batplot/__init__.py,sha256=vcxX_RWa2zNjGw0VeGmJHavkp3EFX9_6FzqOzyahxOI,119
1
+ batplot/__init__.py,sha256=2qXM_ch4J6g2wG6kjsgmtes4tumgb-iIPYbAIvlfOM0,119
2
2
  batplot/args.py,sha256=6g1eHVsycDSAenwrXuCTcyuXCy_-30zy1lWtdguBG2s,34983
3
3
  batplot/batch.py,sha256=YQ7obCIqLCObwDbM7TXpOBh7g7BO95wZNsa2Fy84c6o,53858
4
- batplot/batplot.py,sha256=h960XKSmJ825DqI99Xnyomg_gaB0aFDUIKxkovm8BPQ,170691
4
+ batplot/batplot.py,sha256=8cSAOZphoecINZMpYuetq-rrSyg_zmRfV08VtvX4_B8,170723
5
5
  batplot/cif.py,sha256=JfHwNf3SHrcpALc_F5NjJmQ3lg71MBRSaIUJjGYPTx8,30120
6
6
  batplot/cli.py,sha256=ScDb2je8VQ0mz_z0SLCHEigiTuFPY5pb1snnzCouKms,5828
7
7
  batplot/color_utils.py,sha256=ow2ElqjIWFLRdrnLwQvrnfa3w3IEB0FodPFdoDQR_Dc,19990
8
8
  batplot/config.py,sha256=6nGY7fKN4T5KZUGQS2ArUBgEkLAL0j37XwG5SCVQgKA,6420
9
9
  batplot/converters.py,sha256=rR2WMPM0nR5E3eZI3gWbaJf_AfbdQx3urVSbJmZXNzo,8237
10
- batplot/cpc_interactive.py,sha256=zeMIoPt8fNEi-PcxkMf2PnU7k8owoU6SUfsruohIAsM,195690
11
- batplot/electrochem_interactive.py,sha256=ig9I-bQelTIRxSdXMppdA9RBqrR9vJ1lbkyNtwTC7-A,217226
12
- batplot/interactive.py,sha256=R9ipqK4ZN5wwe6L1mcvWt1TbmGXwPU87V5jm1BWvgeM,203584
10
+ batplot/cpc_interactive.py,sha256=90c-Rd9zcLIsL7mBb3gBDw4AnaWd9KnDtln9mhVKhNo,225252
11
+ batplot/electrochem_interactive.py,sha256=S7UmgZAMCD0sRGPW7xRxwOaHV5_vkuwxZSegWJHxJxI,217258
12
+ batplot/interactive.py,sha256=u0rDbxfjL3LHpAPUL3t6zUp94e-fJEA5_ApXTFfHflA,203616
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=wMuWMz96TeJcKp52iUEqsWy6_NTxAagva4NvCALG0GI,293064
16
+ batplot/operando_ec_interactive.py,sha256=a9OpAguBznUf9p642OyIzya-1AQJKWUO4pqjo7JNHEQ,293096
17
17
  batplot/plotting.py,sha256=hG2_EdDhF1Qpn1XfZKdCQ5-w_m9gUYFbr804UQ5QjsU,10841
18
18
  batplot/readers.py,sha256=kAI0AvYrdfGRZkvADJ4riN96IWtrH24aAoZpBtONTbw,112960
19
- batplot/session.py,sha256=fuUCRdZ2Trl_RKuFgF_m4BUfplhhzOHJ16vtetLC2T0,126312
19
+ batplot/session.py,sha256=1DxwzxnTD_w9nrUWi-aIsBd_3bgfo4xchQGe0nd71Dg,131533
20
20
  batplot/style.py,sha256=ZeRJ15fneSQqCYN_SGap-9Y2J8UkzRxYmf6qLJA6zMo,62058
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.24.dist-info/licenses/LICENSE,sha256=2PAnHeCiTfgI7aKZLWr0G56HI9fGKQ0CEbQ02H-yExQ,1065
25
+ batplot-1.7.25.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.24.dist-info/METADATA,sha256=dJA_9A2XGrZlSltD6KplJokAvn02C88tY4LYxc9A1mg,7407
49
- batplot-1.7.24.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
50
- batplot-1.7.24.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
51
- batplot-1.7.24.dist-info/top_level.txt,sha256=CgqK4RpsYnUFAcqO4bLOnEhCoPY4IPEGLPkiDlzLIxg,39
52
- batplot-1.7.24.dist-info/RECORD,,
48
+ batplot-1.7.25.dist-info/METADATA,sha256=AyVvcD6JyoG0Bl2AAvNtw0YVI9P6vHZAhqFJQQu-KYM,7407
49
+ batplot-1.7.25.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
50
+ batplot-1.7.25.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
51
+ batplot-1.7.25.dist-info/top_level.txt,sha256=CgqK4RpsYnUFAcqO4bLOnEhCoPY4IPEGLPkiDlzLIxg,39
52
+ batplot-1.7.25.dist-info/RECORD,,