batplot 1.7.24__py3-none-any.whl → 1.7.26__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.

@@ -1684,6 +1684,13 @@ def electrochem_interactive_menu(fig, ax, cycle_lines: Dict[int, Dict[str, Optio
1684
1684
  if not already_confirmed and os.path.exists(target):
1685
1685
  target = _confirm_overwrite(target)
1686
1686
  if target:
1687
+ # Save current legend position before export (savefig can change layout)
1688
+ saved_legend_pos = None
1689
+ try:
1690
+ saved_legend_pos = getattr(fig, '_ec_legend_xy_in', None)
1691
+ except Exception:
1692
+ pass
1693
+
1687
1694
  # If exporting SVG, make background transparent for PowerPoint
1688
1695
  _, ext2 = os.path.splitext(target)
1689
1696
  ext2 = ext2.lower()
@@ -1727,6 +1734,15 @@ def electrochem_interactive_menu(fig, ax, cycle_lines: Dict[int, Dict[str, Optio
1727
1734
  fig.savefig(target, bbox_inches='tight')
1728
1735
  print(f"Exported figure to {target}")
1729
1736
  fig._last_figure_export_path = target
1737
+
1738
+ # Restore legend position after savefig (which may have changed layout)
1739
+ if saved_legend_pos is not None:
1740
+ try:
1741
+ fig._ec_legend_xy_in = saved_legend_pos
1742
+ _rebuild_legend(ax)
1743
+ fig.canvas.draw_idle()
1744
+ except Exception:
1745
+ pass
1730
1746
  except Exception as e:
1731
1747
  print(f"Export failed: {e}")
1732
1748
  except Exception as e:
@@ -2641,7 +2657,7 @@ def electrochem_interactive_menu(fig, ax, cycle_lines: Dict[int, Dict[str, Optio
2641
2657
  try:
2642
2658
  print("Tip: Use LaTeX/mathtext for special characters:")
2643
2659
  print(" Subscript: H$_2$O → H₂O | Superscript: m$^2$ → m²")
2644
- print(" Greek: $\\alpha$, $\\beta$ | Angstrom: $\\AA$ → Å")
2660
+ print(" Bullet: $\\bullet$ → • | Greek: $\\alpha$, $\\beta$ | Angstrom: $\\AA$ → Å")
2645
2661
  while True:
2646
2662
  print("Rename axis: x, y, both, q=back")
2647
2663
  sub = input("Rename> ").strip().lower()
@@ -3283,8 +3299,10 @@ def electrochem_interactive_menu(fig, ax, cycle_lines: Dict[int, Dict[str, Optio
3283
3299
  continue
3284
3300
  elif key == 'f':
3285
3301
  # Font submenu with numbered options
3302
+ cur_family = plt.rcParams.get('font.sans-serif', [''])[0]
3303
+ cur_size = plt.rcParams.get('font.size', None)
3286
3304
  while True:
3287
- print("\nFont menu: f=font family, s=size, q=back")
3305
+ print(f"\nFont menu (current: family='{cur_family}', size={cur_size}): f=font family, s=size, q=back")
3288
3306
  sub = input("Font> ").strip().lower()
3289
3307
  if not sub:
3290
3308
  continue
@@ -3298,7 +3316,7 @@ def electrochem_interactive_menu(fig, ax, cycle_lines: Dict[int, Dict[str, Optio
3298
3316
  for i, font in enumerate(fonts, 1):
3299
3317
  print(f" {i}: {font}")
3300
3318
  print("Or enter custom font name directly.")
3301
- choice = input("Font family (number or name): ").strip()
3319
+ choice = input(f"Font family (current: '{cur_family}', number or name): ").strip()
3302
3320
  if not choice:
3303
3321
  continue
3304
3322
  # Check if it's a number
batplot/interactive.py CHANGED
@@ -963,7 +963,7 @@ def interactive_menu(fig, ax, y_data_list, x_data_list, labels, orig_y,
963
963
  txt = ax.text(1.0, 1.0, "",
964
964
  ha='right', va='bottom',
965
965
  transform=ax.transAxes,
966
- fontsize=max(9, int(0.6 * plt.rcParams.get('font.size', 12))),
966
+ fontsize=max(9, int(0.6 * plt.rcParams.get('font.size', 16))),
967
967
  color='0.15',
968
968
  bbox=dict(boxstyle='round,pad=0.25', fc='white', ec='0.7', alpha=0.8))
969
969
 
@@ -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.")
@@ -3130,15 +3130,18 @@ def interactive_menu(fig, ax, y_data_list, x_data_list, labels, orig_y,
3130
3130
  except Exception as e:
3131
3131
  print(f"Error setting widths: {e}")
3132
3132
  elif key == 'f':
3133
+ cur_family = plt.rcParams.get('font.sans-serif', [''])[0]
3134
+ cur_size = plt.rcParams.get('font.size', None)
3133
3135
  while True:
3134
- subkey = input(colorize_prompt("Font submenu (s=size, f=family, q=return): ")).strip().lower()
3136
+ subkey = input(colorize_prompt(f"Font submenu (current: family='{cur_family}', size={cur_size}) - s=size, f=family, q=return: ")).strip().lower()
3135
3137
  if subkey == 'q':
3136
3138
  break
3137
3139
  if subkey == '':
3138
3140
  continue
3139
3141
  if subkey == 's':
3140
3142
  try:
3141
- fs = input("Enter new font size (q=cancel): ").strip()
3143
+ cur_size = plt.rcParams.get('font.size', None)
3144
+ fs = input(f"Enter new font size (current: {cur_size}, q=cancel): ").strip()
3142
3145
  if not fs or fs.lower() == 'q':
3143
3146
  print("Canceled.")
3144
3147
  else:
@@ -3153,13 +3156,14 @@ def interactive_menu(fig, ax, y_data_list, x_data_list, labels, orig_y,
3153
3156
  print(f"Error changing font size: {e}")
3154
3157
  elif subkey == 'f':
3155
3158
  try:
3159
+ cur_family = plt.rcParams.get('font.sans-serif', [''])[0]
3156
3160
  print("Common publication fonts:")
3157
3161
  print(" 1) Arial")
3158
3162
  print(" 2) Helvetica")
3159
3163
  print(" 3) Times New Roman")
3160
3164
  print(" 4) STIXGeneral")
3161
3165
  print(" 5) DejaVu Sans")
3162
- ft_raw = input("Enter font number or family name (q=cancel): ").strip()
3166
+ ft_raw = input(f"Enter font number or family name (current: '{cur_family}', q=cancel): ").strip()
3163
3167
  if not ft_raw or ft_raw.lower() == 'q':
3164
3168
  print("Canceled.")
3165
3169
  else:
@@ -1553,7 +1553,7 @@ def operando_ec_interactive_menu(fig, ax, im, cbar, ec_ax, file_paths=None):
1553
1553
  # Create text annotations for coordinates
1554
1554
  coord_text = fig.text(0.02, 0.98, '', transform=fig.transFigure,
1555
1555
  verticalalignment='top',
1556
- fontsize=max(9, int(0.6 * mpl_plt.rcParams.get('font.size', 12))),
1556
+ fontsize=max(9, int(0.6 * mpl_plt.rcParams.get('font.size', 16))),
1557
1557
  color='0.15',
1558
1558
  bbox=dict(boxstyle='round,pad=0.25', fc='white', ec='0.7', alpha=0.8))
1559
1559
  except Exception as e:
@@ -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,54 @@ 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
+ # Use same spacing parameters as _legend_no_frame for consistent legend appearance
2872
+ leg = ax.legend(H, L, loc='center', bbox_to_anchor=(fx, fy), bbox_transform=fig.transFigure,
2873
+ handlelength=1.0, handletextpad=0.35, labelspacing=0.25,
2874
+ borderaxespad=0.5, borderpad=0.3, columnspacing=0.6,
2875
+ labelcolor='linecolor', frameon=False)
2778
2876
  # persist inches on fig for interactive menu
2779
2877
  try:
2780
2878
  fig._cpc_legend_xy_in = (float(xy_in[0]), float(xy_in[1]))
2781
2879
  except Exception:
2782
2880
  pass
2783
2881
  else:
2784
- ax.legend(handles1 + handles2, labels1 + labels2, loc='best', borderaxespad=1.0)
2785
- # Apply visibility
2786
- vis = bool(leg_meta.get('visible', True))
2882
+ # Use same spacing parameters as _legend_no_frame for consistent legend appearance
2883
+ leg = ax.legend(H, L, loc='best',
2884
+ handlelength=1.0, handletextpad=0.35, labelspacing=0.25,
2885
+ borderaxespad=0.5, borderpad=0.3, columnspacing=0.6,
2886
+ labelcolor='linecolor', frameon=False)
2887
+ # Ensure legend frame is off (redundant but safe)
2888
+ try:
2889
+ if leg is not None:
2890
+ leg.set_frame_on(False)
2891
+ except Exception:
2892
+ pass
2893
+ else:
2894
+ try:
2895
+ fig._cpc_legend_xy_in = (float(xy_in[0]), float(xy_in[1])) if xy_in is not None else None
2896
+ except Exception:
2897
+ pass
2898
+ # ensure legend hidden
2787
2899
  leg = ax.get_legend()
2788
2900
  if leg is not None:
2789
- leg.set_visible(vis)
2901
+ leg.set_visible(False)
2790
2902
  except Exception:
2791
2903
  pass
2792
2904
  try:
@@ -2796,7 +2908,7 @@ def load_cpc_session(filename: str):
2796
2908
  fig.canvas.draw_idle()
2797
2909
  except Exception:
2798
2910
  pass
2799
- return fig, ax, ax2, sc_charge, sc_discharge, sc_eff
2911
+ return fig, ax, ax2, sc_charge, sc_discharge, sc_eff, file_data
2800
2912
  except Exception as e:
2801
2913
  import traceback
2802
2914
  print(f"Error loading CPC session: {e}")
batplot/ui.py CHANGED
@@ -611,7 +611,7 @@ def resize_plot_frame(fig, ax, y_data_list: List, label_text_objects: List, args
611
611
  ax_bbox = ax.get_position()
612
612
  cur_ax_w_in = ax_bbox.width * fig_w_in
613
613
  cur_ax_h_in = ax_bbox.height * fig_h_in
614
- print(f"Current canvas (fixed): {fig_w_in:.2f} x {fig_h_in:.2f} in")
614
+ print(f"Current canvas: {fig_w_in:.2f} x {fig_h_in:.2f} in")
615
615
  print(f"Current plot frame: {cur_ax_w_in:.2f} x {cur_ax_h_in:.2f} in (W x H)")
616
616
  try:
617
617
  spec = input("Enter new plot frame size (e.g. '6 4', '6x4', 'w=6 h=4', 'scale=1.2', single width, q=back): ").strip().lower()
@@ -651,16 +651,9 @@ def resize_plot_frame(fig, ax, y_data_list: List, label_text_objects: List, args
651
651
  print("Could not parse specification.")
652
652
  continue
653
653
  req_w_in, req_h_in = new_w_in, new_h_in
654
- min_margin_frac = 0.05
655
- max_w_in = fig_w_in * (1 - 2 * min_margin_frac)
656
- max_h_in = fig_h_in * (1 - 2 * min_margin_frac)
657
- if new_w_in > max_w_in:
658
- print(f"Requested width {new_w_in:.2f} exceeds max {max_w_in:.2f}; clamped.")
659
- new_w_in = max_w_in
660
- if new_h_in > max_h_in:
661
- print(f"Requested height {new_h_in:.2f} exceeds max {max_h_in:.2f}; clamped.")
662
- new_h_in = max_h_in
663
- min_ax_in = 0.25
654
+ # Apply exact requested size without any clamping
655
+ # Only enforce minimum size to prevent division by zero
656
+ min_ax_in = 0.01
664
657
  new_w_in = max(min_ax_in, new_w_in)
665
658
  new_h_in = max(min_ax_in, new_h_in)
666
659
  tol = 1e-3
@@ -676,33 +669,24 @@ def resize_plot_frame(fig, ax, y_data_list: List, label_text_objects: List, args
676
669
  lm, bm, rm, tm = fig._last_user_margins
677
670
  fig.subplots_adjust(left=lm, bottom=bm, right=rm, top=tm)
678
671
  update_labels_func(ax, y_data_list, label_text_objects, args.stack)
679
- if not ensure_text_visibility(fig, ax, label_text_objects, check_only=True):
680
- fig.canvas.draw_idle()
681
- print(f"Plot frame unchanged ({new_w_in:.2f} x {new_h_in:.2f} in); layout preserved.")
682
- continue
672
+ fig.canvas.draw_idle()
673
+ print(f"Plot frame unchanged ({new_w_in:.2f} x {new_h_in:.2f} in); layout preserved.")
674
+ continue
683
675
  left = (1 - w_frac) / 2
684
676
  right = left + w_frac
685
677
  bottom = (1 - h_frac) / 2
686
678
  top = bottom + h_frac
687
- left = max(min_margin_frac, left)
688
- bottom = max(min_margin_frac, bottom)
689
- right = min(1 - min_margin_frac, right)
690
- top = min(1 - min_margin_frac, top)
691
- if right - left < 0.05 or top - bottom < 0.05:
692
- print("Requested frame too small after safety clamps; aborting.")
693
- else:
694
- fig.subplots_adjust(left=left, right=right, bottom=bottom, top=top)
679
+ # Apply exact size without margin clamping
680
+ fig.subplots_adjust(left=left, right=right, bottom=bottom, top=top)
695
681
  update_labels_func(ax, y_data_list, label_text_objects, args.stack)
696
- ensure_text_visibility(fig, ax, label_text_objects)
682
+ # Store the final size (exactly as requested, no text visibility adjustments)
697
683
  sp = fig.subplotpars
698
- fig._last_user_axes_inches = (((sp.right - sp.left) * fig_w_in), ((sp.top - sp.bottom) * fig_h_in))
684
+ fig._last_user_axes_inches = (new_w_in, new_h_in)
699
685
  fig._last_user_margins = (sp.left, sp.bottom, sp.right, sp.top)
700
686
  final_w_in = (sp.right - sp.left) * fig_w_in
701
687
  final_h_in = (sp.top - sp.bottom) * fig_h_in
702
- if requesting_full_canvas:
703
- print(f"Requested full-canvas frame. Canvas remains {fig_w_in:.2f} x {fig_h_in:.2f} in; frame now {final_w_in:.2f} x {final_h_in:.2f} in (maximum with minimum margins {min_margin_frac*100:.0f}%).")
704
- else:
705
- print(f"Plot frame set to {final_w_in:.2f} x {final_h_in:.2f} in inside fixed canvas {fig_w_in:.2f} x {fig_h_in:.2f} in.")
688
+ # Show the requested size (which is what was applied)
689
+ print(f"Plot frame set to {req_w_in:.2f} x {req_h_in:.2f} in inside canvas {fig_w_in:.2f} x {fig_h_in:.2f} in.")
706
690
  except KeyboardInterrupt:
707
691
  print("Canceled.")
708
692
  return
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batplot
3
- Version: 1.7.24
3
+ Version: 1.7.26
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=l-iAn_Q1KA7sJv2vOZzjjw4K2UWfntwGpQk9Z3lyuRw,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=40lU1nY1NqeAOpzNG_vLF_L34COKhiA19pMpbvA3SJc,171885
5
5
  batplot/cif.py,sha256=JfHwNf3SHrcpALc_F5NjJmQ3lg71MBRSaIUJjGYPTx8,30120
6
6
  batplot/cli.py,sha256=ScDb2je8VQ0mz_z0SLCHEigiTuFPY5pb1snnzCouKms,5828
7
- batplot/color_utils.py,sha256=ow2ElqjIWFLRdrnLwQvrnfa3w3IEB0FodPFdoDQR_Dc,19990
7
+ batplot/color_utils.py,sha256=7InQLVo1XTg7sgAbltM2KeDSFJgr787YEaV9vJbIoWY,20460
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=YGt-TLfO5W_YyUdIInfW6y6bZxQJyfeGX7JGBv1kNbs,232634
11
+ batplot/electrochem_interactive.py,sha256=n_Jc9shH4LIL3r6z3MXnx02ZddMKZoh4dg25hHhfJRw,218297
12
+ batplot/interactive.py,sha256=johjaK8Er1y3rc5Cvg0C3Lv8Cqf2IliOyYrSnSrCzW4,203997
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=BOFj1E7H7b1wW0_pNwYCf7e2E70HemYzl1UjHihxB68,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=FEWYHu1XUIrWxD3an5m7HB57pHst2CHgJ_brAmCBk38,132199
20
20
  batplot/style.py,sha256=ZeRJ15fneSQqCYN_SGap-9Y2J8UkzRxYmf6qLJA6zMo,62058
21
- batplot/ui.py,sha256=MIY2x_ghCYxjdYhjMUZsMMnQEUBLgrIT37hfPGZf_cs,36320
21
+ batplot/ui.py,sha256=ifpbK74juUzLMCt-sJGVaWtpDb1NMRJzs2YyiwwafzY,35302
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.26.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.26.dist-info/METADATA,sha256=nuvFZX39gTf0X-Dxff9jzQur4tLBTpRPuE55CPiYEdA,7407
49
+ batplot-1.7.26.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
50
+ batplot-1.7.26.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
51
+ batplot-1.7.26.dist-info/top_level.txt,sha256=CgqK4RpsYnUFAcqO4bLOnEhCoPY4IPEGLPkiDlzLIxg,39
52
+ batplot-1.7.26.dist-info/RECORD,,