batplot 1.8.4__py3-none-any.whl → 1.8.6__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.
batplot/session.py CHANGED
@@ -500,6 +500,30 @@ def dump_session(
500
500
  'orig_y': [np.array(a) for a in orig_y],
501
501
  'offsets': list(offsets_list),
502
502
  'labels': list(labels),
503
+ # Processed data (for smooth/reduce operations)
504
+ 'original_x_data_list': ([np.array(a) for a in getattr(fig, '_original_x_data_list', [])]
505
+ if hasattr(fig, '_original_x_data_list') else None),
506
+ 'original_y_data_list': ([np.array(a) for a in getattr(fig, '_original_y_data_list', [])]
507
+ if hasattr(fig, '_original_y_data_list') else None),
508
+ 'full_processed_x_data_list': ([np.array(a) for a in getattr(fig, '_full_processed_x_data_list', [])]
509
+ if hasattr(fig, '_full_processed_x_data_list') else None),
510
+ 'full_processed_y_data_list': ([np.array(a) for a in getattr(fig, '_full_processed_y_data_list', [])]
511
+ if hasattr(fig, '_full_processed_y_data_list') else None),
512
+ 'smooth_settings': (dict(getattr(fig, '_smooth_settings', {}))
513
+ if hasattr(fig, '_smooth_settings') else None),
514
+ 'last_smooth_settings': (dict(getattr(fig, '_last_smooth_settings', {}))
515
+ if hasattr(fig, '_last_smooth_settings') else None),
516
+ # Derivative data (for derivative operations)
517
+ 'pre_derivative_x_data_list': ([np.array(a) for a in getattr(fig, '_pre_derivative_x_data_list', [])]
518
+ if hasattr(fig, '_pre_derivative_x_data_list') else None),
519
+ 'pre_derivative_y_data_list': ([np.array(a) for a in getattr(fig, '_pre_derivative_y_data_list', [])]
520
+ if hasattr(fig, '_pre_derivative_y_data_list') else None),
521
+ 'pre_derivative_ylabel': (str(getattr(fig, '_pre_derivative_ylabel', ''))
522
+ if hasattr(fig, '_pre_derivative_ylabel') else None),
523
+ 'derivative_order': (int(getattr(fig, '_derivative_order', 0))
524
+ if hasattr(fig, '_derivative_order') else None),
525
+ 'derivative_reversed': (bool(getattr(fig, '_derivative_reversed', False))
526
+ if hasattr(fig, '_derivative_reversed') else None),
503
527
  'line_styles': [
504
528
  {
505
529
  'color': ln.get_color(),
@@ -540,6 +564,7 @@ def dump_session(
540
564
  'tick_state': dict(tick_state),
541
565
  'tick_widths': tick_widths,
542
566
  'tick_lengths': tick_lengths,
567
+ 'tick_direction': getattr(fig, '_tick_direction', 'out'),
543
568
  'font': {
544
569
  'size': plt.rcParams.get('font.size'),
545
570
  'chain': list(plt.rcParams.get('font.sans-serif', [])),
@@ -685,20 +710,34 @@ def dump_operando_session(
685
710
  def _capture_wasd_state(axis):
686
711
  ts = getattr(axis, '_saved_tick_state', {})
687
712
  wasd = {}
713
+ # Check if ylabel is positioned on right (typical for EC axis)
714
+ ylabel_on_right = False
715
+ try:
716
+ ylabel_on_right = (axis.yaxis.get_label_position() == 'right')
717
+ except Exception:
718
+ pass
719
+
688
720
  for side in ('top', 'bottom', 'left', 'right'):
689
721
  sp = axis.spines.get(side)
690
722
  prefix = {'top': 't', 'bottom': 'b', 'left': 'l', 'right': 'r'}[side]
691
- # For 'left' side ylabel: check if it's currently visible (has text)
692
- # If hidden but has stored text, the title state should be False (hidden)
723
+ # Title state logic
693
724
  if side == 'left':
694
- ylabel_text = axis.get_ylabel()
695
- title_state = bool(ylabel_text) # True only if currently visible with text
725
+ # If ylabel is positioned on right (EC axis), left has no title
726
+ if ylabel_on_right:
727
+ title_state = False
728
+ else:
729
+ ylabel_text = axis.get_ylabel()
730
+ title_state = bool(ylabel_text) # True only if currently visible with text
696
731
  elif side == 'bottom':
697
732
  title_state = bool(axis.get_xlabel())
698
733
  elif side == 'top':
699
734
  title_state = bool(getattr(axis, '_top_xlabel_on', False))
700
735
  elif side == 'right':
701
- title_state = bool(getattr(axis, '_right_ylabel_on', False))
736
+ # If ylabel is positioned on right (EC axis), check if ylabel is visible (not empty)
737
+ if ylabel_on_right:
738
+ title_state = bool(axis.get_ylabel()) # Empty string = hidden by user
739
+ else:
740
+ title_state = bool(getattr(axis, '_right_ylabel_on', False))
702
741
  else:
703
742
  title_state = False
704
743
 
@@ -925,6 +964,11 @@ def load_operando_session(filename: str):
925
964
  # Use standard DPI of 100 instead of saved DPI to avoid display-dependent issues
926
965
  # (Retina displays, Windows scaling, etc. can cause saved DPI to differ)
927
966
  fig = plt.figure(figsize=tuple(sess['figure']['size']), dpi=100)
967
+ # Seed last-session path so 'os' overwrite command is available immediately
968
+ try:
969
+ fig._last_session_save_path = os.path.abspath(filename)
970
+ except Exception:
971
+ pass
928
972
  # Disable automatic layout adjustments to preserve saved geometry
929
973
  try:
930
974
  fig.set_layout_engine('none')
@@ -1211,11 +1255,33 @@ def load_operando_session(filename: str):
1211
1255
  bottom=bool(ec_wasd.get('bottom', {}).get('ticks', True)),
1212
1256
  labeltop=bool(ec_wasd.get('top', {}).get('labels', False)),
1213
1257
  labelbottom=bool(ec_wasd.get('bottom', {}).get('labels', True)))
1258
+ # For EC: ticks and labels are on RIGHT by default, not left!
1259
+ # CRITICAL: EC y-axis defaults are: left=False, right=True (both ticks and labels)
1260
+ # Old sessions may have saved wrong values, so we need to sanitize them
1261
+
1262
+ # EC left side should ALWAYS be False (EC uses right side for y-axis)
1263
+ left_ticks = False
1264
+ left_labels = False
1265
+
1266
+ # EC right side should be True when ylabel is visible
1267
+ right_title = ec_wasd.get('right', {}).get('title', True)
1268
+
1269
+ # If right title is ON, ticks/labels should also be ON
1270
+ if right_title:
1271
+ right_ticks = True
1272
+ right_labels = True
1273
+ else:
1274
+ # Title is hidden - respect the saved tick/label state or use False
1275
+ right_ticks_val = ec_wasd.get('right', {}).get('ticks')
1276
+ right_labels_val = ec_wasd.get('right', {}).get('labels')
1277
+ right_ticks = bool(right_ticks_val) if right_ticks_val is not None else False
1278
+ right_labels = bool(right_labels_val) if right_labels_val is not None else False
1279
+
1214
1280
  ec_ax.tick_params(axis='y',
1215
- left=bool(ec_wasd.get('left', {}).get('ticks', True)),
1216
- right=bool(ec_wasd.get('right', {}).get('ticks', False)),
1217
- labelleft=bool(ec_wasd.get('left', {}).get('labels', True)),
1218
- labelright=bool(ec_wasd.get('right', {}).get('labels', False)))
1281
+ left=left_ticks,
1282
+ right=right_ticks,
1283
+ labelleft=left_labels,
1284
+ labelright=right_labels)
1219
1285
  # Apply minor ticks
1220
1286
  if ec_wasd.get('top', {}).get('minor') or ec_wasd.get('bottom', {}).get('minor'):
1221
1287
  ec_ax.xaxis.set_minor_locator(AutoMinorLocator())
@@ -1794,6 +1860,11 @@ def load_ec_session(filename: str):
1794
1860
  # Use standard DPI of 100 instead of saved DPI to avoid display-dependent issues
1795
1861
  # (Retina displays, Windows scaling, etc. can cause saved DPI to differ)
1796
1862
  fig = plt.figure(figsize=tuple(sess['figure']['size']), dpi=100)
1863
+ # Seed last-session path so 'os' overwrite command is available immediately
1864
+ try:
1865
+ fig._last_session_save_path = os.path.abspath(filename)
1866
+ except Exception:
1867
+ pass
1797
1868
  # Preserve saved geometry by disabling auto layout
1798
1869
  try:
1799
1870
  fig.set_layout_engine('none')
@@ -2693,6 +2764,11 @@ def load_cpc_session(filename: str):
2693
2764
  # Use standard DPI of 100 instead of saved DPI to avoid display-dependent issues
2694
2765
  # (Retina displays, Windows scaling, etc. can cause saved DPI to differ)
2695
2766
  fig = plt.figure(figsize=tuple(sess['figure']['size']), dpi=100)
2767
+ # Seed last-session path so 'os' overwrite command is available immediately
2768
+ try:
2769
+ fig._last_session_save_path = os.path.abspath(filename)
2770
+ except Exception:
2771
+ pass
2696
2772
  # Disable auto layout
2697
2773
  try:
2698
2774
  fig.set_layout_engine('none')
batplot/style.py CHANGED
@@ -8,6 +8,7 @@ from __future__ import annotations
8
8
  from typing import List, Dict, Any, Callable, Optional
9
9
  import json
10
10
  import importlib
11
+ import os
11
12
  import sys
12
13
  import numpy as np
13
14
  import matplotlib.pyplot as plt
@@ -451,7 +452,19 @@ def print_style_info(
451
452
  except Exception:
452
453
  pass
453
454
 
454
- # Omit CIF/HKL details from compact style print
455
+ # CIF hkl label visibility
456
+ if show_cif_hkl is not None:
457
+ print(f"CIF hkl labels: {'shown' if show_cif_hkl else 'hidden'}")
458
+ elif cif_tick_series:
459
+ # Try to read from __main__ module if not provided
460
+ try:
461
+ import sys
462
+ _bp_module = sys.modules.get('__main__')
463
+ if _bp_module is not None and hasattr(_bp_module, 'show_cif_hkl'):
464
+ hkl_state = bool(getattr(_bp_module, 'show_cif_hkl', False))
465
+ print(f"CIF hkl labels: {'shown' if hkl_state else 'hidden'}")
466
+ except Exception:
467
+ pass
455
468
 
456
469
  # Omit non-style global flags (mode/raw/autoscale/delta)
457
470
 
@@ -508,6 +521,7 @@ def export_style_config(
508
521
  base_path: Optional[str] = None,
509
522
  show_cif_titles: Optional[bool] = None,
510
523
  overwrite_path: Optional[str] = None,
524
+ force_kind: Optional[str] = None,
511
525
  ) -> Optional[str]:
512
526
  """Export style configuration after displaying a summary and prompting the user.
513
527
 
@@ -592,6 +606,8 @@ def export_style_config(
592
606
  "x_minor_width": axis_tick_width(ax.xaxis, "minor"),
593
607
  "y_major_width": axis_tick_width(ax.yaxis, "major"),
594
608
  "y_minor_width": axis_tick_width(ax.yaxis, "minor"),
609
+ "lengths": dict(getattr(fig, '_tick_lengths', {})),
610
+ "direction": getattr(fig, '_tick_direction', 'out'),
595
611
  },
596
612
  "wasd_state": wasd_state,
597
613
  "spines": {
@@ -670,6 +686,14 @@ def export_style_config(
670
686
  # Save CIF title visibility
671
687
  if show_cif_titles is not None:
672
688
  cfg["show_cif_titles"] = bool(show_cif_titles)
689
+ # Save CIF hkl label visibility (read from __main__ module if available)
690
+ try:
691
+ import sys
692
+ _bp_module = sys.modules.get('__main__')
693
+ if _bp_module is not None and hasattr(_bp_module, 'show_cif_hkl'):
694
+ cfg["show_cif_hkl"] = bool(getattr(_bp_module, 'show_cif_hkl', False))
695
+ except Exception:
696
+ pass
673
697
  if cif_tick_series:
674
698
  cfg["cif_ticks"] = [
675
699
  {"index": i, "color": color}
@@ -692,18 +716,36 @@ def export_style_config(
692
716
  if serialized_palettes:
693
717
  cfg['curve_palettes'] = serialized_palettes
694
718
 
695
- # If overwrite_path is provided, determine export type from existing file
719
+ # Store smooth settings (metadata only, not full arrays)
720
+ if hasattr(fig, '_smooth_settings'):
721
+ cfg['smooth_settings'] = dict(fig._smooth_settings)
722
+ if hasattr(fig, '_last_smooth_settings'):
723
+ cfg['last_smooth_settings'] = dict(fig._last_smooth_settings)
724
+ # Store derivative order (metadata only)
725
+ if hasattr(fig, '_derivative_order'):
726
+ cfg['derivative_order'] = int(fig._derivative_order)
727
+ if hasattr(fig, '_derivative_reversed'):
728
+ cfg['derivative_reversed'] = bool(fig._derivative_reversed)
729
+ # Note: We don't store original_x_data_list/original_y_data_list or pre_derivative data in style files
730
+ # as style files are for styling only, and the data would be specific
731
+ # to the dataset. Session files (pickle) store this data instead.
732
+
733
+ # If overwrite_path is provided, determine export type from existing file,
734
+ # unless the caller explicitly forces style-only or style+geometry.
696
735
  if overwrite_path:
697
- try:
698
- with open(overwrite_path, 'r', encoding='utf-8') as f:
699
- old_cfg = json.load(f)
700
- old_kind = old_cfg.get('kind', '')
701
- if old_kind == 'xy_style_geom':
702
- exp_choice = 'psg'
703
- else:
704
- exp_choice = 'ps'
705
- except Exception:
706
- exp_choice = 'ps' # Default to style-only if can't read
736
+ if force_kind in ('ps', 'psg'):
737
+ exp_choice = force_kind
738
+ else:
739
+ try:
740
+ with open(overwrite_path, 'r', encoding='utf-8') as f:
741
+ old_cfg = json.load(f)
742
+ old_kind = old_cfg.get('kind', '')
743
+ if old_kind == 'xy_style_geom':
744
+ exp_choice = 'psg'
745
+ else:
746
+ exp_choice = 'ps'
747
+ except Exception:
748
+ exp_choice = 'ps' # Default to style-only if can't read
707
749
  else:
708
750
  # Ask user for style-only or style+geometry
709
751
  print("\nExport options:")
@@ -873,6 +915,34 @@ def apply_style_config(
873
915
  print("Warning: Style/geometry file was saved without --ro; current plot was created with --ro.")
874
916
  print("Not applying style/geometry to avoid corrupting axis orientation.")
875
917
  return
918
+
919
+ # --- Style-import check messages (to debug y-axis / curve visibility after import)
920
+ # Disabled by default; set BATPLOT_STYLE_DEBUG=1 to enable. ---
921
+ _style_debug = os.environ.get("BATPLOT_STYLE_DEBUG", "0") == "1"
922
+ if _style_debug:
923
+ kind = cfg.get("kind", "")
924
+ has_geom = "geometry" in cfg and isinstance(cfg.get("geometry"), dict)
925
+ geom_ylim = cfg.get("geometry", {}).get("ylim") if has_geom else None
926
+ print("[style-import check] BEFORE applying style:")
927
+ print(f" kind={kind!r} has_geometry={has_geom} geom_ylim={geom_ylim}")
928
+ try:
929
+ xlim0, xlim1 = ax.get_xlim()
930
+ ylim0, ylim1 = ax.get_ylim()
931
+ print(f" ax xlim=({xlim0}, {xlim1}) ylim=({ylim0}, {ylim1})")
932
+ except Exception as e:
933
+ print(f" ax get_xlim/get_ylim failed: {e}")
934
+ nlines = len(ax.lines)
935
+ print(f" n_ax.lines={nlines} n_cfg.lines={len(cfg.get('lines', []))}")
936
+ if orig_y is not None:
937
+ print(f" len(orig_y)={len(orig_y)} len(offsets_list)={len(offsets_list) if offsets_list else 0}")
938
+ for i in range(nlines):
939
+ ln = ax.lines[i]
940
+ xd, yd = ln.get_data()
941
+ ymn = float(yd.min()) if yd.size else float("nan")
942
+ ymx = float(yd.max()) if yd.size else float("nan")
943
+ print(f" line[{i}] y_range=({ymn}, {ymx}) n_pts={len(yd)}")
944
+ # --- end check ---
945
+
876
946
  # Save current labelpad values BEFORE any style changes
877
947
  saved_xlabelpad = None
878
948
  saved_ylabelpad = None
@@ -921,6 +991,12 @@ def apply_style_config(
921
991
  fig.subplots_adjust(left=left, right=left + w_frac, bottom=bottom, top=bottom + h_frac)
922
992
  except Exception as e:
923
993
  print(f"[DEBUG] Exception in frame/axes fraction adjustment: {e}")
994
+ if _style_debug:
995
+ try:
996
+ ylim0, ylim1 = ax.get_ylim()
997
+ print(f"[style-import check] AFTER figure size/axes_frac: ax ylim=({ylim0}, {ylim1})")
998
+ except Exception:
999
+ pass
924
1000
  # Don't restore DPI from style - use system default to avoid display-dependent issues
925
1001
  # (Retina displays, Windows scaling, etc. can cause saved DPI to differ)
926
1002
 
@@ -1101,6 +1177,32 @@ def apply_style_config(
1101
1177
  ax.tick_params(axis="y", which="minor", width=yminr)
1102
1178
  except Exception as e:
1103
1179
  print(f"[DEBUG] Exception setting tick widths: {e}")
1180
+ # Tick lengths (t submenu)
1181
+ tick_lengths = ticks_cfg.get("lengths") or {}
1182
+ if isinstance(tick_lengths, dict):
1183
+ try:
1184
+ major_len = tick_lengths.get("major")
1185
+ minor_len = tick_lengths.get("minor")
1186
+ if major_len is not None:
1187
+ ax.tick_params(axis="both", which="major", length=float(major_len))
1188
+ if not hasattr(fig, '_tick_lengths'):
1189
+ fig._tick_lengths = {}
1190
+ fig._tick_lengths['major'] = float(major_len)
1191
+ if minor_len is not None:
1192
+ ax.tick_params(axis="both", which="minor", length=float(minor_len))
1193
+ if not hasattr(fig, '_tick_lengths'):
1194
+ fig._tick_lengths = {}
1195
+ fig._tick_lengths['minor'] = float(minor_len)
1196
+ except Exception as e:
1197
+ print(f"Warning: Could not restore tick lengths: {e}")
1198
+ # Tick direction (t submenu)
1199
+ tick_direction = ticks_cfg.get("direction")
1200
+ if tick_direction:
1201
+ try:
1202
+ setattr(fig, '_tick_direction', tick_direction)
1203
+ ax.tick_params(axis="both", which="both", direction=tick_direction)
1204
+ except Exception as e:
1205
+ print(f"Warning: Could not restore tick direction: {e}")
1104
1206
 
1105
1207
  # Spines
1106
1208
  for name, sp_dict in cfg.get("spines", {}).items():
@@ -1179,19 +1281,33 @@ def apply_style_config(
1179
1281
  except Exception:
1180
1282
  pass
1181
1283
  # Restore offset if available
1182
- if "offset" in entry and offsets_list is not None and orig_y is not None and x_data_list is not None:
1284
+ # Use current displayed y and current offset to get baseline, then apply file offset.
1285
+ # (orig_y can be wrong in stacked sessions—e.g. already offset—so we derive baseline here.)
1286
+ if "offset" in entry and offsets_list is not None and x_data_list is not None:
1183
1287
  try:
1184
1288
  offset_val = float(entry["offset"])
1185
- if idx < len(offsets_list):
1289
+ if idx < len(offsets_list) and idx < len(y_data_list) and idx < len(x_data_list):
1290
+ current_y = y_data_list[idx]
1291
+ current_offset = offsets_list[idx]
1292
+ baseline = current_y - current_offset
1293
+ y_with_offset = baseline + offset_val
1186
1294
  offsets_list[idx] = offset_val
1187
- # Reapply offset to the curve
1188
- if idx < len(orig_y) and idx < len(y_data_list) and idx < len(x_data_list):
1189
- y_norm = orig_y[idx]
1190
- y_with_offset = y_norm + offset_val
1191
- y_data_list[idx] = y_with_offset
1192
- ln.set_data(x_data_list[idx], y_with_offset)
1295
+ y_data_list[idx] = y_with_offset
1296
+ ln.set_data(x_data_list[idx], y_with_offset)
1297
+ if orig_y is not None and idx < len(orig_y):
1298
+ orig_y[idx] = np.asarray(baseline, dtype=float)
1299
+ if _style_debug:
1300
+ bmin, bmax = (float(baseline.min()), float(baseline.max())) if getattr(baseline, "size", 0) else (float("nan"), float("nan"))
1301
+ ymin, ymax = (float(y_with_offset.min()), float(y_with_offset.max())) if getattr(y_with_offset, "size", 0) else (float("nan"), float("nan"))
1302
+ print(f"[style-import check] line[{idx}] offset_from_file={offset_val} baseline=({bmin}, {bmax}) y_with_offset=({ymin}, {ymax})")
1193
1303
  except Exception as e:
1194
1304
  print(f"Warning: Could not restore offset for curve {idx+1}: {e}")
1305
+ if _style_debug:
1306
+ try:
1307
+ ylim0, ylim1 = ax.get_ylim()
1308
+ print(f"[style-import check] AFTER lines/offset restore: ax ylim=({ylim0}, {ylim1})")
1309
+ except Exception as e:
1310
+ print(f"[style-import check] AFTER lines: get_ylim failed: {e}")
1195
1311
  palette_cfg = cfg.get("curve_palettes", [])
1196
1312
  if palette_cfg:
1197
1313
  sanitized_history = []
@@ -1230,8 +1346,61 @@ def apply_style_config(
1230
1346
  setattr(_bp_module, 'show_cif_titles', bool(cfg["show_cif_titles"]))
1231
1347
  except Exception:
1232
1348
  pass
1349
+ # Restore CIF hkl label visibility
1350
+ if "show_cif_hkl" in cfg:
1351
+ try:
1352
+ _bp_module = sys.modules.get('__main__')
1353
+ if _bp_module is not None:
1354
+ setattr(_bp_module, 'show_cif_hkl', bool(cfg["show_cif_hkl"]))
1355
+ # Also update _bp object if available
1356
+ if cif_tick_series is not None:
1357
+ # Try to update via interactive menu's _bp object
1358
+ try:
1359
+ import sys
1360
+ _bp_obj = getattr(sys.modules.get('__main__'), '_bp', None)
1361
+ if _bp_obj is not None:
1362
+ setattr(_bp_obj, 'show_cif_hkl', bool(cfg["show_cif_hkl"]))
1363
+ except Exception:
1364
+ pass
1365
+ except Exception:
1366
+ pass
1367
+ # Restore smooth settings (metadata only, not full arrays)
1368
+ if "smooth_settings" in cfg:
1369
+ try:
1370
+ fig._smooth_settings = dict(cfg["smooth_settings"])
1371
+ except Exception:
1372
+ pass
1373
+ elif hasattr(fig, '_smooth_settings'):
1374
+ delattr(fig, '_smooth_settings')
1375
+ if "last_smooth_settings" in cfg:
1376
+ try:
1377
+ fig._last_smooth_settings = dict(cfg["last_smooth_settings"])
1378
+ except Exception:
1379
+ pass
1380
+ elif hasattr(fig, '_last_smooth_settings'):
1381
+ delattr(fig, '_last_smooth_settings')
1382
+ # Restore derivative order (metadata only)
1383
+ if "derivative_order" in cfg:
1384
+ try:
1385
+ order = int(cfg["derivative_order"])
1386
+ fig._derivative_order = order
1387
+ is_reversed = cfg.get("derivative_reversed", False)
1388
+ if "derivative_reversed" in cfg:
1389
+ fig._derivative_reversed = bool(cfg["derivative_reversed"])
1390
+ # Update y-axis label based on derivative order
1391
+ from .interactive import _update_ylabel_for_derivative
1392
+ current_ylabel = ax.get_ylabel() or ""
1393
+ new_ylabel = _update_ylabel_for_derivative(order, current_ylabel, is_reversed=is_reversed)
1394
+ ax.set_ylabel(new_ylabel)
1395
+ except Exception:
1396
+ pass
1397
+ elif hasattr(fig, '_derivative_order'):
1398
+ delattr(fig, '_derivative_order')
1399
+ # Note: We don't restore original_x_data_list/original_y_data_list or pre_derivative data from style files
1400
+ # as style files are for styling only, and the data would be specific
1401
+ # to the dataset. Session files (pickle) store this data instead.
1233
1402
  # Redraw CIF ticks after applying changes
1234
- if (cif_cfg and cif_tick_series is not None) or "show_cif_titles" in cfg:
1403
+ if (cif_cfg and cif_tick_series is not None) or "show_cif_titles" in cfg or "show_cif_hkl" in cfg:
1235
1404
  if hasattr(ax, "_cif_draw_func"):
1236
1405
  try:
1237
1406
  ax._cif_draw_func()
@@ -1338,11 +1507,19 @@ def apply_style_config(
1338
1507
  if 'xlim' in geom and isinstance(geom['xlim'], list) and len(geom['xlim']) == 2:
1339
1508
  ax.set_xlim(geom['xlim'][0], geom['xlim'][1])
1340
1509
  if 'ylim' in geom and isinstance(geom['ylim'], list) and len(geom['ylim']) == 2:
1510
+ if _style_debug:
1511
+ print(f"[style-import check] Applying geometry ylim=({geom['ylim'][0]}, {geom['ylim'][1]})")
1341
1512
  ax.set_ylim(geom['ylim'][0], geom['ylim'][1])
1342
1513
  print("Applied geometry (labels and limits)")
1343
1514
  except Exception as e:
1344
1515
  print(f"Warning: Could not apply geometry: {e}")
1345
1516
 
1517
+ if _style_debug:
1518
+ try:
1519
+ ylim0, ylim1 = ax.get_ylim()
1520
+ print(f"[style-import check] FINAL (before draw_idle): ax ylim=({ylim0}, {ylim1})")
1521
+ except Exception as e:
1522
+ print(f"[style-import check] FINAL get_ylim failed: {e}")
1346
1523
  try:
1347
1524
  fig.canvas.draw_idle()
1348
1525
  except Exception as e:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batplot
3
- Version: 1.8.4
3
+ Version: 1.8.6
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=A2c5RdJQEC4-Snfk1leoeq38dCyGoAxBuEvXo3Kb50A,118
2
- batplot/args.py,sha256=mrDjMURp_OQnXrAwl9WnE_FW4HJu940O7NmL9QWQnD4,35189
3
- batplot/batch.py,sha256=P2HNBYqrSzDr2fruYz8BFKwNFX6vdJpHDZpaG_hmEc8,55253
4
- batplot/batplot.py,sha256=IDnc-aGIMo1oMfXsQjU_koKqq2E9xXNn1Bm92xsmeYE,177109
1
+ batplot/__init__.py,sha256=Fy71HWPcaheFTg920KgEZ7reiHA27RQ-B6mxzpc8ZbI,118
2
+ batplot/args.py,sha256=DGTe2PKmJnI8Iq12QgO76V8lZvWhMOqY14gsyE5SgEs,37001
3
+ batplot/batch.py,sha256=hqLNvd88OLd0PLo_ot6JjC3FM6wwxCJ1jO2J63f9Zyg,55899
4
+ batplot/batplot.py,sha256=zD9kTLMKzYf73Ptn8jTOSeYZbxFzxlKxtrAE6bFHHNQ,187980
5
5
  batplot/cif.py,sha256=JfHwNf3SHrcpALc_F5NjJmQ3lg71MBRSaIUJjGYPTx8,30120
6
6
  batplot/cli.py,sha256=2-7NtxBlyOUfzHVwP7vZK7OZlyKyPVy-3daKN-MPWyU,6657
7
7
  batplot/color_utils.py,sha256=7InQLVo1XTg7sgAbltM2KeDSFJgr787YEaV9vJbIoWY,20460
8
8
  batplot/config.py,sha256=6nGY7fKN4T5KZUGQS2ArUBgEkLAL0j37XwG5SCVQgKA,6420
9
- batplot/converters.py,sha256=rR2WMPM0nR5E3eZI3gWbaJf_AfbdQx3urVSbJmZXNzo,8237
10
- batplot/cpc_interactive.py,sha256=qadWV2PaQMsqM16mSp5r1-WP7di0JCnzNI4RJy27alo,239616
11
- batplot/electrochem_interactive.py,sha256=8mFr5vtWb_ZDiJmZWXjkARq21D2GflT8-J2xvCGvDIc,222769
12
- batplot/interactive.py,sha256=5u2ulhTzRr7fA-INc5hfcz7xaHObnnigiXjrgdtE7XE,206728
9
+ batplot/converters.py,sha256=c4qhgN9zHUiBZhXVAdf0zGtPPoktD3JjMLkhjjYEwlk,9787
10
+ batplot/cpc_interactive.py,sha256=pPx6B8IN9YYnc7TWJnTV_2ZxcotCBXD29Db7G7ool-4,247355
11
+ batplot/electrochem_interactive.py,sha256=Ui1_E-oTNvk7bKossx1MyULNHosFMFnl2a_EAOE550E,225991
12
+ batplot/interactive.py,sha256=BTcr8ZtmWdID4uKiDA7KW72p9tfaC6sNhMZvhVA6py0,311985
13
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
14
+ batplot/modes.py,sha256=BajbnDzzYRD-FRr5Hoft0TyQ5CTWyggJjKa9yrM6iy4,37376
15
+ batplot/operando.py,sha256=h09xu1BsdR68YlzhWeUSypYX83DzjJABIQQS2noQzPI,29400
16
+ batplot/operando_ec_interactive.py,sha256=at0ZTk5jSLc2Tm5NEtXl8_neyFJayp8aSrtJEM3vIqc,326058
17
17
  batplot/plotting.py,sha256=hG2_EdDhF1Qpn1XfZKdCQ5-w_m9gUYFbr804UQ5QjsU,10841
18
18
  batplot/readers.py,sha256=kAI0AvYrdfGRZkvADJ4riN96IWtrH24aAoZpBtONTbw,112960
19
- batplot/session.py,sha256=sYhY3WH-Kks5SMO91kfGDkSs32SX_iFS62ZkUm3jwzY,142722
20
- batplot/style.py,sha256=jXtFaJR1aa6vIHupmDNqY2NY5Rgtw49UxF7cS4y8fCA,63375
19
+ batplot/session.py,sha256=6kVDR_7Lm6vUdxt9DaeI_UBV6uNqVaFqKveegrSaXyk,147407
20
+ batplot/style.py,sha256=RZKoRO77lxHZhxJ8q2mjEPJoCXvv8pYu-Z2-H-_YeoA,72826
21
21
  batplot/ui.py,sha256=ifpbK74juUzLMCt-sJGVaWtpDb1NMRJzs2YyiwwafzY,35302
22
22
  batplot/utils.py,sha256=LY2-Axr3DsQMTxuXe48vSjrLJKEnkzkZjdSFdQizbpg,37599
23
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.4.dist-info/licenses/LICENSE,sha256=2PAnHeCiTfgI7aKZLWr0G56HI9fGKQ0CEbQ02H-yExQ,1065
24
+ batplot/data/USER_MANUAL.md,sha256=w6pmDXoLINFkCWWh3zay7uNIxUaDxSOrocnPIZwu2uA,19542
25
+ batplot-1.8.6.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
@@ -68,8 +68,8 @@ batplot_backup_20251221_101150/style.py,sha256=ig1ozX4dhEsXf5JKaPZOvgVS3CWx-BTFS
68
68
  batplot_backup_20251221_101150/ui.py,sha256=ifpbK74juUzLMCt-sJGVaWtpDb1NMRJzs2YyiwwafzY,35302
69
69
  batplot_backup_20251221_101150/utils.py,sha256=LY2-Axr3DsQMTxuXe48vSjrLJKEnkzkZjdSFdQizbpg,37599
70
70
  batplot_backup_20251221_101150/version_check.py,sha256=ztTHwqgWd8OlS9PLLY5A_TabWxBASDA_-5yyN15PZC8,9996
71
- batplot-1.8.4.dist-info/METADATA,sha256=da51wuDhz7bqCTInJ_tjZzZy2wC6ujSfsrgYIi-GYgI,7175
72
- batplot-1.8.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
73
- batplot-1.8.4.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
74
- batplot-1.8.4.dist-info/top_level.txt,sha256=Z5Q4sAiT_FDqZqhlLsYn9avRTuFAEEf3AVfkswxOb18,70
75
- batplot-1.8.4.dist-info/RECORD,,
71
+ batplot-1.8.6.dist-info/METADATA,sha256=3vYzKlIUX7G_DynQgFBh-Weezl7GTs6u1a3vb2-Ir9w,7175
72
+ batplot-1.8.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
73
+ batplot-1.8.6.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
74
+ batplot-1.8.6.dist-info/top_level.txt,sha256=Z5Q4sAiT_FDqZqhlLsYn9avRTuFAEEf3AVfkswxOb18,70
75
+ batplot-1.8.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5