batplot 1.8.3__py3-none-any.whl → 1.8.5__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/session.py CHANGED
@@ -36,114 +36,71 @@ import os
36
36
 
37
37
  import matplotlib.pyplot as plt
38
38
  import numpy as np
39
- import sys
40
39
 
41
40
  from .utils import _confirm_overwrite
42
41
  from .color_utils import ensure_colormap
43
42
 
44
43
 
45
- def _get_package_versions():
46
- """Get versions of critical packages for compatibility checking.
44
+ def _try_extract_version_from_pickle(filename: str) -> Dict[str, str]:
45
+ """Try to extract package_versions from a pickle file even if it fails to fully load.
46
+
47
+ Note: This may not work if pickle.load() fails completely due to missing modules.
48
+ In that case, we can't extract version info, but we can still show current version.
47
49
 
48
50
  Returns:
49
- dict: Package name -> version string mapping
51
+ dict with package versions, or empty dict if extraction fails
50
52
  """
51
- versions = {}
52
- critical_packages = ['numpy', 'matplotlib', 'scipy']
53
-
54
- for pkg_name in critical_packages:
55
- try:
56
- mod = __import__(pkg_name)
57
- versions[pkg_name] = getattr(mod, '__version__', 'unknown')
58
- except ImportError:
59
- versions[pkg_name] = 'not_installed'
60
- except Exception:
61
- versions[pkg_name] = 'unknown'
62
-
63
- # Also track Python version
64
- versions['python'] = f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}"
65
-
66
- return versions
53
+ try:
54
+ with open(filename, 'rb') as f:
55
+ # Try to load the pickle
56
+ # This will fail if numpy._core is missing, but we try anyway
57
+ sess = pickle.load(f)
58
+ if isinstance(sess, dict):
59
+ return sess.get('package_versions', {})
60
+ except Exception:
61
+ # If loading fails completely (e.g., ModuleNotFoundError for numpy._core),
62
+ # we can't extract version info. This is expected in version mismatch cases.
63
+ pass
64
+ return {}
67
65
 
68
66
 
69
- def _check_package_compatibility(saved_versions, current_versions, filename):
70
- """Check if package versions are compatible and warn/error if not.
67
+ def _get_current_numpy_version() -> str:
68
+ """Get current numpy version, even if import fails.
69
+
70
+ Tries multiple methods:
71
+ 1. Direct import (fastest)
72
+ 2. pip show (works even if import fails)
73
+ 3. Returns 'unknown' if all fail
71
74
 
72
- Args:
73
- saved_versions: dict of package -> version from saved session
74
- current_versions: dict of package -> version currently installed
75
- filename: session filename for error messages
76
-
77
75
  Returns:
78
- bool: True if compatible (or can proceed), False if should abort
76
+ Version string or 'unknown'
79
77
  """
80
- if not saved_versions:
81
- # Old session file without version info - allow but warn
82
- print("Warning: Session file does not contain package version information.")
83
- print("This may cause compatibility issues. Consider recreating the session.")
84
- return True
85
-
86
- mismatches = []
87
- critical_mismatches = []
88
-
89
- for pkg in ['numpy', 'matplotlib', 'python']:
90
- saved_ver = saved_versions.get(pkg, 'unknown')
91
- current_ver = current_versions.get(pkg, 'unknown')
92
-
93
- if saved_ver == 'unknown' or current_ver == 'unknown':
94
- continue
95
-
96
- if saved_ver != current_ver:
97
- # Check for critical incompatibilities
98
- if pkg == 'numpy':
99
- # numpy 2.0+ uses _core, <2.0 doesn't - this is a breaking change
100
- try:
101
- saved_major = int(saved_ver.split('.')[0])
102
- current_major = int(current_ver.split('.')[0])
103
- if saved_major != current_major:
104
- critical_mismatches.append((pkg, saved_ver, current_ver))
105
- else:
106
- mismatches.append((pkg, saved_ver, current_ver))
107
- except (ValueError, IndexError):
108
- mismatches.append((pkg, saved_ver, current_ver))
109
- elif pkg == 'python':
110
- # Python major version changes are critical
111
- try:
112
- saved_major = int(saved_ver.split('.')[0])
113
- current_major = int(current_ver.split('.')[0])
114
- if saved_major != current_major:
115
- critical_mismatches.append((pkg, saved_ver, current_ver))
116
- else:
117
- mismatches.append((pkg, saved_ver, current_ver))
118
- except (ValueError, IndexError):
119
- mismatches.append((pkg, saved_ver, current_ver))
120
- else:
121
- mismatches.append((pkg, saved_ver, current_ver))
122
-
123
- if critical_mismatches:
124
- print(f"\nERROR: Critical package version mismatch detected for session: {filename}")
125
- print("The following packages have incompatible major version changes:")
126
- for pkg, saved, current in critical_mismatches:
127
- print(f" {pkg}: saved with {saved}, current is {current}")
128
- print("\nThis will likely cause pickle loading to fail.")
129
- print("Solutions:")
130
- print(" 1. Install matching package versions:")
131
- for pkg, saved, current in critical_mismatches:
132
- print(f" pip install '{pkg}=={saved}' # or use conda")
133
- print(" 2. Recreate the session from original data files")
134
- return False
78
+ # Method 1: Try direct import
79
+ try:
80
+ import numpy
81
+ return numpy.__version__
82
+ except Exception:
83
+ pass
135
84
 
136
- if mismatches:
137
- print(f"\nWarning: Package version differences detected for session: {filename}")
138
- print("Minor version differences may be okay, but proceed with caution:")
139
- for pkg, saved, current in mismatches:
140
- print(f" {pkg}: saved with {saved}, current is {current}")
141
- print("If you encounter errors, try matching the saved versions.")
142
- response = input("Continue loading session? (y/n): ").strip().lower()
143
- if response != 'y':
144
- return False
85
+ # Method 2: Try pip show
86
+ try:
87
+ import subprocess
88
+ import sys
89
+ result = subprocess.run(
90
+ [sys.executable, '-m', 'pip', 'show', 'numpy'],
91
+ capture_output=True,
92
+ text=True,
93
+ timeout=5,
94
+ check=False
95
+ )
96
+ if result.returncode == 0:
97
+ for line in result.stdout.split('\n'):
98
+ if line.startswith('Version:'):
99
+ return line.split(':', 1)[1].strip()
100
+ except Exception:
101
+ pass
145
102
 
146
- return True
103
+ return 'unknown'
147
104
 
148
105
 
149
106
  def _current_tick_width(axis_obj, which: str):
@@ -536,17 +493,37 @@ def dump_session(
536
493
  wasd_state = _capture_wasd_state(ax)
537
494
 
538
495
  try:
539
- # Get current package versions for compatibility checking
540
- package_versions = _get_package_versions()
541
-
542
496
  sess = {
543
497
  'version': 3,
544
- 'package_versions': package_versions, # Track versions for compatibility checking
545
498
  'x_data': [np.array(a) for a in x_data_list],
546
499
  'y_data': [np.array(a) for a in y_data_list],
547
500
  'orig_y': [np.array(a) for a in orig_y],
548
501
  'offsets': list(offsets_list),
549
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),
550
527
  'line_styles': [
551
528
  {
552
529
  'color': ln.get_color(),
@@ -863,13 +840,9 @@ def dump_operando_session(
863
840
  cb_h_offset = getattr(cbar.ax, '_cb_h_offset_in', 0.0)
864
841
  ec_h_offset = getattr(ec_ax, '_ec_h_offset_in', 0.0) if ec_ax is not None else None
865
842
 
866
- # Get current package versions for compatibility checking
867
- package_versions = _get_package_versions()
868
-
869
843
  sess = {
870
844
  'kind': 'operando_ec',
871
845
  'version': 2,
872
- 'package_versions': package_versions, # Track versions for compatibility checking
873
846
  'figure': {'size': (fig_w, fig_h), 'dpi': dpi},
874
847
  'layout_inches': {
875
848
  'cb_w_in': cb_w_in,
@@ -937,22 +910,33 @@ def load_operando_session(filename: str):
937
910
  except ModuleNotFoundError as e:
938
911
  # Handle numpy._core and other module import errors
939
912
  if '_core' in str(e) or 'numpy' in str(e).lower():
913
+ # Try to extract version info before the error
914
+ saved_versions = _try_extract_version_from_pickle(filename)
915
+ current_numpy = _get_current_numpy_version()
916
+
917
+ saved_numpy = saved_versions.get('numpy', 'unknown')
918
+
940
919
  print(f"\nERROR: NumPy version mismatch detected when loading: {filename}")
941
920
  print("This session was saved with a different NumPy version.")
921
+ print()
922
+ print(f"Session was saved with: NumPy {saved_numpy}")
923
+ print(f"Currently installed: NumPy {current_numpy}")
924
+ print()
942
925
  print("The error 'No module named numpy._core' indicates:")
943
926
  print(" - Session saved with NumPy 2.0+ but loading with NumPy <2.0, OR")
944
927
  print(" - Session saved with NumPy <2.0 but loading with NumPy 2.0+")
945
- print("\nSolutions:")
946
- print(" 1. Check NumPy version: python3 -c 'import numpy; print(numpy.__version__)'")
947
- print(" 2. Install matching version:")
948
- print(" - If session was saved with NumPy 2.0+: pip install 'numpy>=2.0'")
949
- print(" - If session was saved with NumPy <2.0: pip install 'numpy<2.0'")
950
- print(" 3. Recreate the session from original data files")
928
+ print()
929
+ print("Solutions:")
930
+ if saved_numpy != 'unknown':
931
+ print(f" 1. Install matching version: pip install 'numpy=={saved_numpy}'")
932
+ else:
933
+ print(" 1. Try installing NumPy <2.0: pip install 'numpy<2.0'")
934
+ print(" OR try installing NumPy 2.0+: pip install 'numpy>=2.0'")
935
+ print(" 2. Recreate the session from original data files")
951
936
  else:
952
937
  print(f"\nERROR: Module import error when loading: {filename}")
953
938
  print(f"Error: {e}")
954
939
  print("This usually indicates a package version mismatch.")
955
- print("Try installing matching package versions or recreate the session.")
956
940
  return None
957
941
  except Exception as e:
958
942
  print(f"Failed to load session: {e}")
@@ -961,12 +945,6 @@ def load_operando_session(filename: str):
961
945
  if not isinstance(sess, dict) or sess.get('kind') != 'operando_ec':
962
946
  print("Not an operando+EC session file.")
963
947
  return None
964
-
965
- # Check package version compatibility
966
- saved_versions = sess.get('package_versions', {})
967
- current_versions = _get_package_versions()
968
- if not _check_package_compatibility(saved_versions, current_versions, filename):
969
- return None
970
948
 
971
949
  # Use standard DPI of 100 instead of saved DPI to avoid display-dependent issues
972
950
  # (Retina displays, Windows scaling, etc. can cause saved DPI to differ)
@@ -1746,13 +1724,9 @@ def dump_ec_session(
1746
1724
  legend_xy_in = (float(xy[0]), float(xy[1]))
1747
1725
  except Exception:
1748
1726
  legend_xy_in = None
1749
- # Get current package versions for compatibility checking
1750
- package_versions = _get_package_versions()
1751
-
1752
1727
  sess = {
1753
1728
  'kind': 'ec_gc',
1754
1729
  'version': 2,
1755
- 'package_versions': package_versions, # Track versions for compatibility checking
1756
1730
  'figure': {'size': (fig_w, fig_h), 'dpi': dpi},
1757
1731
  'axis': axis,
1758
1732
  'subplot_margins': subplot_margins,
@@ -1805,22 +1779,33 @@ def load_ec_session(filename: str):
1805
1779
  except ModuleNotFoundError as e:
1806
1780
  # Handle numpy._core and other module import errors
1807
1781
  if '_core' in str(e) or 'numpy' in str(e).lower():
1782
+ # Try to extract version info before the error
1783
+ saved_versions = _try_extract_version_from_pickle(filename)
1784
+ current_numpy = _get_current_numpy_version()
1785
+
1786
+ saved_numpy = saved_versions.get('numpy', 'unknown')
1787
+
1808
1788
  print(f"\nERROR: NumPy version mismatch detected when loading: {filename}")
1809
1789
  print("This session was saved with a different NumPy version.")
1790
+ print()
1791
+ print(f"Session was saved with: NumPy {saved_numpy}")
1792
+ print(f"Currently installed: NumPy {current_numpy}")
1793
+ print()
1810
1794
  print("The error 'No module named numpy._core' indicates:")
1811
1795
  print(" - Session saved with NumPy 2.0+ but loading with NumPy <2.0, OR")
1812
1796
  print(" - Session saved with NumPy <2.0 but loading with NumPy 2.0+")
1813
- print("\nSolutions:")
1814
- print(" 1. Check NumPy version: python3 -c 'import numpy; print(numpy.__version__)'")
1815
- print(" 2. Install matching version:")
1816
- print(" - If session was saved with NumPy 2.0+: pip install 'numpy>=2.0'")
1817
- print(" - If session was saved with NumPy <2.0: pip install 'numpy<2.0'")
1818
- print(" 3. Recreate the session from original data files")
1797
+ print()
1798
+ print("Solutions:")
1799
+ if saved_numpy != 'unknown':
1800
+ print(f" 1. Install matching version: pip install 'numpy=={saved_numpy}'")
1801
+ else:
1802
+ print(" 1. Try installing NumPy <2.0: pip install 'numpy<2.0'")
1803
+ print(" OR try installing NumPy 2.0+: pip install 'numpy>=2.0'")
1804
+ print(" 2. Recreate the session from original data files")
1819
1805
  else:
1820
1806
  print(f"\nERROR: Module import error when loading: {filename}")
1821
1807
  print(f"Error: {e}")
1822
1808
  print("This usually indicates a package version mismatch.")
1823
- print("Try installing matching package versions or recreate the session.")
1824
1809
  return None
1825
1810
  except Exception as e:
1826
1811
  print(f"Failed to load EC session: {e}")
@@ -1829,12 +1814,6 @@ def load_ec_session(filename: str):
1829
1814
  if not isinstance(sess, dict) or sess.get('kind') != 'ec_gc':
1830
1815
  print("Not an EC GC session file.")
1831
1816
  return None
1832
-
1833
- # Check package version compatibility
1834
- saved_versions = sess.get('package_versions', {})
1835
- current_versions = _get_package_versions()
1836
- if not _check_package_compatibility(saved_versions, current_versions, filename):
1837
- return None
1838
1817
 
1839
1818
  # Use standard DPI of 100 instead of saved DPI to avoid display-dependent issues
1840
1819
  # (Retina displays, Windows scaling, etc. can cause saved DPI to differ)
@@ -2539,13 +2518,9 @@ def dump_cpc_session(
2539
2518
  'right_y': float(getattr(ax2, '_right_ylabel_manual_offset_y_pts', 0.0) or 0.0),
2540
2519
  }
2541
2520
 
2542
- # Get current package versions for compatibility checking
2543
- package_versions = _get_package_versions()
2544
-
2545
2521
  meta = {
2546
2522
  'kind': 'cpc',
2547
2523
  'version': 2, # Incremented version for new format
2548
- 'package_versions': package_versions, # Track versions for compatibility checking
2549
2524
  'figure': {
2550
2525
  'size': (fig_w, fig_h),
2551
2526
  'dpi': dpi,
@@ -2704,22 +2679,33 @@ def load_cpc_session(filename: str):
2704
2679
  except ModuleNotFoundError as e:
2705
2680
  # Handle numpy._core and other module import errors
2706
2681
  if '_core' in str(e) or 'numpy' in str(e).lower():
2682
+ # Try to extract version info before the error
2683
+ saved_versions = _try_extract_version_from_pickle(filename)
2684
+ current_numpy = _get_current_numpy_version()
2685
+
2686
+ saved_numpy = saved_versions.get('numpy', 'unknown')
2687
+
2707
2688
  print(f"\nERROR: NumPy version mismatch detected when loading: {filename}")
2708
2689
  print("This session was saved with a different NumPy version.")
2690
+ print()
2691
+ print(f"Session was saved with: NumPy {saved_numpy}")
2692
+ print(f"Currently installed: NumPy {current_numpy}")
2693
+ print()
2709
2694
  print("The error 'No module named numpy._core' indicates:")
2710
2695
  print(" - Session saved with NumPy 2.0+ but loading with NumPy <2.0, OR")
2711
2696
  print(" - Session saved with NumPy <2.0 but loading with NumPy 2.0+")
2712
- print("\nSolutions:")
2713
- print(" 1. Check NumPy version: python3 -c 'import numpy; print(numpy.__version__)'")
2714
- print(" 2. Install matching version:")
2715
- print(" - If session was saved with NumPy 2.0+: pip install 'numpy>=2.0'")
2716
- print(" - If session was saved with NumPy <2.0: pip install 'numpy<2.0'")
2717
- print(" 3. Recreate the session from original data files")
2697
+ print()
2698
+ print("Solutions:")
2699
+ if saved_numpy != 'unknown':
2700
+ print(f" 1. Install matching version: pip install 'numpy=={saved_numpy}'")
2701
+ else:
2702
+ print(" 1. Try installing NumPy <2.0: pip install 'numpy<2.0'")
2703
+ print(" OR try installing NumPy 2.0+: pip install 'numpy>=2.0'")
2704
+ print(" 2. Recreate the session from original data files")
2718
2705
  else:
2719
2706
  print(f"\nERROR: Module import error when loading: {filename}")
2720
2707
  print(f"Error: {e}")
2721
2708
  print("This usually indicates a package version mismatch.")
2722
- print("Try installing matching package versions or recreate the session.")
2723
2709
  return None
2724
2710
  except Exception as e:
2725
2711
  print(f"Failed to load session: {e}")
@@ -2727,12 +2713,6 @@ def load_cpc_session(filename: str):
2727
2713
  if not isinstance(sess, dict) or sess.get('kind') != 'cpc':
2728
2714
  print("Not a CPC session file.")
2729
2715
  return None
2730
-
2731
- # Check package version compatibility
2732
- saved_versions = sess.get('package_versions', {})
2733
- current_versions = _get_package_versions()
2734
- if not _check_package_compatibility(saved_versions, current_versions, filename):
2735
- return None
2736
2716
  try:
2737
2717
  # Use standard DPI of 100 instead of saved DPI to avoid display-dependent issues
2738
2718
  # (Retina displays, Windows scaling, etc. can cause saved DPI to differ)
batplot/style.py CHANGED
@@ -451,7 +451,19 @@ def print_style_info(
451
451
  except Exception:
452
452
  pass
453
453
 
454
- # Omit CIF/HKL details from compact style print
454
+ # CIF hkl label visibility
455
+ if show_cif_hkl is not None:
456
+ print(f"CIF hkl labels: {'shown' if show_cif_hkl else 'hidden'}")
457
+ elif cif_tick_series:
458
+ # Try to read from __main__ module if not provided
459
+ try:
460
+ import sys
461
+ _bp_module = sys.modules.get('__main__')
462
+ if _bp_module is not None and hasattr(_bp_module, 'show_cif_hkl'):
463
+ hkl_state = bool(getattr(_bp_module, 'show_cif_hkl', False))
464
+ print(f"CIF hkl labels: {'shown' if hkl_state else 'hidden'}")
465
+ except Exception:
466
+ pass
455
467
 
456
468
  # Omit non-style global flags (mode/raw/autoscale/delta)
457
469
 
@@ -670,6 +682,14 @@ def export_style_config(
670
682
  # Save CIF title visibility
671
683
  if show_cif_titles is not None:
672
684
  cfg["show_cif_titles"] = bool(show_cif_titles)
685
+ # Save CIF hkl label visibility (read from __main__ module if available)
686
+ try:
687
+ import sys
688
+ _bp_module = sys.modules.get('__main__')
689
+ if _bp_module is not None and hasattr(_bp_module, 'show_cif_hkl'):
690
+ cfg["show_cif_hkl"] = bool(getattr(_bp_module, 'show_cif_hkl', False))
691
+ except Exception:
692
+ pass
673
693
  if cif_tick_series:
674
694
  cfg["cif_ticks"] = [
675
695
  {"index": i, "color": color}
@@ -692,6 +712,20 @@ def export_style_config(
692
712
  if serialized_palettes:
693
713
  cfg['curve_palettes'] = serialized_palettes
694
714
 
715
+ # Store smooth settings (metadata only, not full arrays)
716
+ if hasattr(fig, '_smooth_settings'):
717
+ cfg['smooth_settings'] = dict(fig._smooth_settings)
718
+ if hasattr(fig, '_last_smooth_settings'):
719
+ cfg['last_smooth_settings'] = dict(fig._last_smooth_settings)
720
+ # Store derivative order (metadata only)
721
+ if hasattr(fig, '_derivative_order'):
722
+ cfg['derivative_order'] = int(fig._derivative_order)
723
+ if hasattr(fig, '_derivative_reversed'):
724
+ cfg['derivative_reversed'] = bool(fig._derivative_reversed)
725
+ # Note: We don't store original_x_data_list/original_y_data_list or pre_derivative data in style files
726
+ # as style files are for styling only, and the data would be specific
727
+ # to the dataset. Session files (pickle) store this data instead.
728
+
695
729
  # If overwrite_path is provided, determine export type from existing file
696
730
  if overwrite_path:
697
731
  try:
@@ -1230,8 +1264,61 @@ def apply_style_config(
1230
1264
  setattr(_bp_module, 'show_cif_titles', bool(cfg["show_cif_titles"]))
1231
1265
  except Exception:
1232
1266
  pass
1267
+ # Restore CIF hkl label visibility
1268
+ if "show_cif_hkl" in cfg:
1269
+ try:
1270
+ _bp_module = sys.modules.get('__main__')
1271
+ if _bp_module is not None:
1272
+ setattr(_bp_module, 'show_cif_hkl', bool(cfg["show_cif_hkl"]))
1273
+ # Also update _bp object if available
1274
+ if cif_tick_series is not None:
1275
+ # Try to update via interactive menu's _bp object
1276
+ try:
1277
+ import sys
1278
+ _bp_obj = getattr(sys.modules.get('__main__'), '_bp', None)
1279
+ if _bp_obj is not None:
1280
+ setattr(_bp_obj, 'show_cif_hkl', bool(cfg["show_cif_hkl"]))
1281
+ except Exception:
1282
+ pass
1283
+ except Exception:
1284
+ pass
1285
+ # Restore smooth settings (metadata only, not full arrays)
1286
+ if "smooth_settings" in cfg:
1287
+ try:
1288
+ fig._smooth_settings = dict(cfg["smooth_settings"])
1289
+ except Exception:
1290
+ pass
1291
+ elif hasattr(fig, '_smooth_settings'):
1292
+ delattr(fig, '_smooth_settings')
1293
+ if "last_smooth_settings" in cfg:
1294
+ try:
1295
+ fig._last_smooth_settings = dict(cfg["last_smooth_settings"])
1296
+ except Exception:
1297
+ pass
1298
+ elif hasattr(fig, '_last_smooth_settings'):
1299
+ delattr(fig, '_last_smooth_settings')
1300
+ # Restore derivative order (metadata only)
1301
+ if "derivative_order" in cfg:
1302
+ try:
1303
+ order = int(cfg["derivative_order"])
1304
+ fig._derivative_order = order
1305
+ is_reversed = cfg.get("derivative_reversed", False)
1306
+ if "derivative_reversed" in cfg:
1307
+ fig._derivative_reversed = bool(cfg["derivative_reversed"])
1308
+ # Update y-axis label based on derivative order
1309
+ from .interactive import _update_ylabel_for_derivative
1310
+ current_ylabel = ax.get_ylabel() or ""
1311
+ new_ylabel = _update_ylabel_for_derivative(order, current_ylabel, is_reversed=is_reversed)
1312
+ ax.set_ylabel(new_ylabel)
1313
+ except Exception:
1314
+ pass
1315
+ elif hasattr(fig, '_derivative_order'):
1316
+ delattr(fig, '_derivative_order')
1317
+ # Note: We don't restore original_x_data_list/original_y_data_list or pre_derivative data from style files
1318
+ # as style files are for styling only, and the data would be specific
1319
+ # to the dataset. Session files (pickle) store this data instead.
1233
1320
  # Redraw CIF ticks after applying changes
1234
- if (cif_cfg and cif_tick_series is not None) or "show_cif_titles" in cfg:
1321
+ if (cif_cfg and cif_tick_series is not None) or "show_cif_titles" in cfg or "show_cif_hkl" in cfg:
1235
1322
  if hasattr(ax, "_cif_draw_func"):
1236
1323
  try:
1237
1324
  ax._cif_draw_func()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batplot
3
- Version: 1.8.3
3
+ Version: 1.8.5
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
@@ -31,20 +31,15 @@ Project-URL: Issues, https://github.com/TianDai1729/batplot/issues
31
31
  Classifier: Programming Language :: Python
32
32
  Classifier: Programming Language :: Python :: 3
33
33
  Classifier: Programming Language :: Python :: 3 :: Only
34
- Classifier: Programming Language :: Python :: 3.8
35
- Classifier: Programming Language :: Python :: 3.9
36
- Classifier: Programming Language :: Python :: 3.10
37
- Classifier: Programming Language :: Python :: 3.11
38
- Classifier: Programming Language :: Python :: 3.12
39
34
  Classifier: Programming Language :: Python :: 3.13
40
35
  Classifier: Operating System :: OS Independent
41
36
  Classifier: Intended Audience :: Science/Research
42
37
  Classifier: Topic :: Scientific/Engineering :: Visualization
43
- Requires-Python: >=3.7
38
+ Requires-Python: <3.14,>=3.13
44
39
  Description-Content-Type: text/markdown
45
40
  License-File: LICENSE
46
- Requires-Dist: numpy
47
- Requires-Dist: matplotlib
41
+ Requires-Dist: numpy==2.3.4
42
+ Requires-Dist: matplotlib==3.10.7
48
43
  Requires-Dist: rich>=10.0.0
49
44
  Requires-Dist: openpyxl>=3.0.0
50
45
  Dynamic: license-file
@@ -1,28 +1,28 @@
1
- batplot/__init__.py,sha256=RAScNSaXpWIGw1hbfjWc2RDcKAf-ftvoSfY-3DOZTF0,118
2
- batplot/args.py,sha256=mrDjMURp_OQnXrAwl9WnE_FW4HJu940O7NmL9QWQnD4,35189
3
- batplot/batch.py,sha256=P2HNBYqrSzDr2fruYz8BFKwNFX6vdJpHDZpaG_hmEc8,55253
4
- batplot/batplot.py,sha256=Yd6wyMTRgu65BY9ousd_3Zxoauce99vYqzeSgqhxv8U,177164
1
+ batplot/__init__.py,sha256=6mfbpfSzbSfjCLrvmBzBMKmDyiFSBUJlcB8Qqv6o26s,118
2
+ batplot/args.py,sha256=DGTe2PKmJnI8Iq12QgO76V8lZvWhMOqY14gsyE5SgEs,37001
3
+ batplot/batch.py,sha256=hqLNvd88OLd0PLo_ot6JjC3FM6wwxCJ1jO2J63f9Zyg,55899
4
+ batplot/batplot.py,sha256=-mAf1aW7bniyfQ5DCorqyOr-OcRtUgRtq6TZHKk5xCU,184599
5
5
  batplot/cif.py,sha256=JfHwNf3SHrcpALc_F5NjJmQ3lg71MBRSaIUJjGYPTx8,30120
6
- batplot/cli.py,sha256=ScDb2je8VQ0mz_z0SLCHEigiTuFPY5pb1snnzCouKms,5828
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=-9etN342VqLbY9pLP7cyBcSzgVHuWpDwEZHkXzShl7E,240683
11
+ batplot/electrochem_interactive.py,sha256=a3ocYQEfi0FsiMq9B4_0GY97td00e8uyzlHc3Sr6EKE,225211
12
+ batplot/interactive.py,sha256=b-0xeza_Rs4S59ve-pyWVq_-FvTpqDIy1tu4M3tT3Eg,300447
13
13
  batplot/manual.py,sha256=pbRI6G4Pm12pOW8LrOLWWu7IEOtqWN3tRHtgge50LlA,11556
14
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
15
+ batplot/operando.py,sha256=h09xu1BsdR68YlzhWeUSypYX83DzjJABIQQS2noQzPI,29400
16
+ batplot/operando_ec_interactive.py,sha256=YExiuKn-qQksW3YFYCTpvumuCit4cc4YiiaSRWGa0og,317833
17
17
  batplot/plotting.py,sha256=hG2_EdDhF1Qpn1XfZKdCQ5-w_m9gUYFbr804UQ5QjsU,10841
18
18
  batplot/readers.py,sha256=kAI0AvYrdfGRZkvADJ4riN96IWtrH24aAoZpBtONTbw,112960
19
- batplot/session.py,sha256=5eZLJHE66wtZPwNsnR1I2iyEvxY3cLTl3aY7HNxpX6U,145772
20
- batplot/style.py,sha256=jXtFaJR1aa6vIHupmDNqY2NY5Rgtw49UxF7cS4y8fCA,63375
19
+ batplot/session.py,sha256=sgcJyCj00lOhmIRdDxGSqu2vEpOm7WSFZzLXxukYNL0,144936
20
+ batplot/style.py,sha256=3XnWlU9aTb1b-aiq5BQOuAREE5nOEYZ0b75v_LS0xDM,67790
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.3.dist-info/licenses/LICENSE,sha256=2PAnHeCiTfgI7aKZLWr0G56HI9fGKQ0CEbQ02H-yExQ,1065
24
+ batplot/data/USER_MANUAL.md,sha256=w6pmDXoLINFkCWWh3zay7uNIxUaDxSOrocnPIZwu2uA,19542
25
+ batplot-1.8.5.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.3.dist-info/METADATA,sha256=BNWy96koh0Pcj9CDJYuJ6Xp44krYa8Wg9SM1T4qhYhA,7406
72
- batplot-1.8.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
73
- batplot-1.8.3.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
74
- batplot-1.8.3.dist-info/top_level.txt,sha256=Z5Q4sAiT_FDqZqhlLsYn9avRTuFAEEf3AVfkswxOb18,70
75
- batplot-1.8.3.dist-info/RECORD,,
71
+ batplot-1.8.5.dist-info/METADATA,sha256=WTflN9nVzAXg4xPnjpjfJeRNhuyUaXaJKBLyjhjVxko,7175
72
+ batplot-1.8.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
73
+ batplot-1.8.5.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
74
+ batplot-1.8.5.dist-info/top_level.txt,sha256=Z5Q4sAiT_FDqZqhlLsYn9avRTuFAEEf3AVfkswxOb18,70
75
+ batplot-1.8.5.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