batplot 1.8.6__py3-none-any.whl → 1.8.11__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/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """batplot: Interactive plotting for battery data visualization."""
2
2
 
3
- __version__ = "1.8.6"
3
+ __version__ = "1.8.11"
4
4
 
5
5
  __all__ = ["__version__"]
batplot/batplot.py CHANGED
@@ -2763,7 +2763,17 @@ def batplot_main() -> int:
2763
2763
  any_cif = any(f.lower().endswith(".cif") for f in args.files)
2764
2764
  non_cif_count = sum(0 if f.lower().endswith('.cif') else 1 for f in args.files)
2765
2765
  cif_only = any_cif and non_cif_count == 0
2766
- any_lambda = any(":" in f for f in args.files) or args.wl is not None
2766
+ # Check for wavelength parameters (file:wl), but exclude Windows drive letters (C:\...)
2767
+ def has_wavelength_param(f):
2768
+ if ":" not in f:
2769
+ return False
2770
+ # Check if it's a Windows path (single letter followed by :\ or :/)
2771
+ if len(f) >= 2 and f[1] == ':' and len(f[0]) == 1 and f[0].isalpha():
2772
+ # This is a Windows drive letter, check after the drive path
2773
+ # Look for additional colons beyond the drive letter
2774
+ return ":" in f[2:]
2775
+ return True
2776
+ any_lambda = any(has_wavelength_param(f) for f in args.files) or args.wl is not None
2767
2777
 
2768
2778
  # Incompatibilities (no mixing of fundamentally different axis domains)
2769
2779
  if sum(bool(x) for x in (any_gr, any_nor, any_chik, any_chir, (any_qye or any_lambda or any_cif))) > 1:
@@ -2896,8 +2906,16 @@ def batplot_main() -> int:
2896
2906
 
2897
2907
  # Use data_files instead of args.files for processing
2898
2908
  for idx_file, file_entry in enumerate(data_files):
2909
+ # Handle Windows paths (C:\...) vs wavelength parameters (file:wl)
2910
+ # On Windows, check if first part is a single letter (drive letter)
2899
2911
  parts = file_entry.split(":")
2900
- fname = parts[0]
2912
+ if len(parts) > 1 and len(parts[0]) == 1 and parts[0].isalpha():
2913
+ # Windows drive letter detected (e.g., "C" from "C:\path")
2914
+ # Rejoin the first two parts as the filename
2915
+ fname = parts[0] + ":" + parts[1]
2916
+ parts = [fname] + parts[2:] # Reconstruct parts with full Windows path
2917
+ else:
2918
+ fname = parts[0]
2901
2919
  # Parse wavelength parameters: file:wl1 or file:wl1:wl2 or file.cif:wl
2902
2920
  wavelength_file = None
2903
2921
  original_wavelength = None # First wavelength (for Q conversion)
@@ -3081,16 +3099,35 @@ def batplot_main() -> int:
3081
3099
  # Step 2: Convert Q back to 2theta using second wavelength
3082
3100
  # Q = 4π sin(θ) / λ => sin(θ) = Qλ / (4π) => θ = arcsin(Qλ / (4π))
3083
3101
  sin_theta = Q * conversion_wavelength / (4 * np.pi)
3084
- # Clamp to valid range [-1, 1]
3085
- sin_theta = np.clip(sin_theta, -1.0, 1.0)
3102
+ # Check for physically impossible Q values (would require sin(θ) > 1)
3103
+ valid_mask = np.abs(sin_theta) <= 1.0
3104
+ if not np.all(valid_mask):
3105
+ # Some Q values are too high for the target wavelength
3106
+ n_invalid = np.sum(~valid_mask)
3107
+ q_max_possible = 4 * np.pi / conversion_wavelength
3108
+ print(f"Warning: {n_invalid} data points exceed Q_max={q_max_possible:.2f} Å⁻¹ for λ={conversion_wavelength} Å")
3109
+ print(f" Truncating data to physically accessible range.")
3110
+ # Truncate to valid range instead of clipping (which creates artificial data)
3111
+ x = x[valid_mask]
3112
+ y = y[valid_mask]
3113
+ sin_theta = sin_theta[valid_mask]
3086
3114
  theta_new_rad = np.arcsin(sin_theta)
3087
3115
  x_plot = np.degrees(2 * theta_new_rad)
3088
3116
  elif use_2th and file_ext == ".qye" and wavelength_file:
3089
3117
  # Convert Q to 2theta for .qye files when wavelength is provided
3090
3118
  # Q = 4π sin(θ) / λ => sin(θ) = Qλ / (4π) => θ = arcsin(Qλ / (4π))
3091
3119
  sin_theta = x * wavelength_file / (4 * np.pi)
3092
- # Clamp to valid range [-1, 1]
3093
- sin_theta = np.clip(sin_theta, -1.0, 1.0)
3120
+ # Check for physically impossible Q values
3121
+ valid_mask = np.abs(sin_theta) <= 1.0
3122
+ if not np.all(valid_mask):
3123
+ n_invalid = np.sum(~valid_mask)
3124
+ q_max_possible = 4 * np.pi / wavelength_file
3125
+ print(f"Warning: {n_invalid} data points exceed Q_max={q_max_possible:.2f} Å⁻¹ for λ={wavelength_file} Å")
3126
+ print(f" Truncating data to physically accessible range.")
3127
+ # Truncate to valid range
3128
+ x = x[valid_mask]
3129
+ y = y[valid_mask]
3130
+ sin_theta = sin_theta[valid_mask]
3094
3131
  theta_rad = np.arcsin(sin_theta)
3095
3132
  x_plot = np.degrees(2 * theta_rad)
3096
3133
  elif use_Q and file_ext not in (".qye", ".gr", ".nor"):
batplot/converters.py CHANGED
@@ -224,7 +224,8 @@ def convert_xrd_data(filenames, from_param: str, to_param: str):
224
224
 
225
225
  # Save converted data
226
226
  try:
227
- np.savetxt(output_fname, out_data, fmt="% .6f", header=header)
227
+ # Use UTF-8 encoding to support Greek letters (θ) in headers on all platforms
228
+ np.savetxt(output_fname, out_data, fmt="% .6f", header=header, encoding='utf-8')
228
229
  print(f"Saved {output_fname}")
229
230
  except Exception as e:
230
231
  print(f"Error saving {output_fname}: {e}")
batplot/interactive.py CHANGED
@@ -1590,6 +1590,12 @@ def interactive_menu(fig, ax, y_data_list, x_data_list, labels, orig_y,
1590
1590
  plt.rcParams['font.size'] = snap["font_size"]
1591
1591
  except Exception:
1592
1592
  pass
1593
+ # Apply restored font settings to all existing text objects
1594
+ # This ensures labels, tick labels, etc. update to match restored font size/family
1595
+ try:
1596
+ sync_fonts()
1597
+ except Exception:
1598
+ pass
1593
1599
 
1594
1600
  # Figure size & dpi
1595
1601
  if snap.get("fig_size") and isinstance(snap["fig_size"], (list, tuple)) and len(snap["fig_size"])==2:
@@ -1813,22 +1819,13 @@ def interactive_menu(fig, ax, y_data_list, x_data_list, labels, orig_y,
1813
1819
  except Exception:
1814
1820
  pass
1815
1821
 
1816
- # Recalculate y_data_list from orig_y and offsets_list to ensure consistency
1817
- # Ensure lists have the same length before assigning
1818
- max_len = max(len(orig_y), len(y_data_list), len(offsets_list))
1819
- while len(orig_y) < max_len:
1820
- orig_y.append(np.array([]))
1821
- while len(y_data_list) < max_len:
1822
- y_data_list.append(np.array([]))
1823
- while len(offsets_list) < max_len:
1824
- offsets_list.append(0.0)
1825
- for i in range(len(orig_y)):
1826
- if i < len(offsets_list):
1827
- y_data_list[i] = orig_y[i] + offsets_list[i]
1828
- else:
1829
- y_data_list[i] = orig_y[i].copy() if orig_y[i].size > 0 else np.array([])
1822
+ # DON'T recalculate y_data_list - trust the snapshotted data to avoid offset drift
1823
+ # The snapshot already captured the correct y_data_list with offsets applied.
1824
+ # Recalculating from orig_y + offsets_list can introduce floating-point errors
1825
+ # or inconsistencies if the data underwent transformations (normalize, etc.)
1830
1826
 
1831
- # Update line data with restored values
1827
+ # Update line data with restored values from snapshot
1828
+ # This ensures line visual data matches the snapshotted data lists exactly
1832
1829
  for i in range(min(len(ax.lines), len(x_data_list), len(y_data_list))):
1833
1830
  try:
1834
1831
  ax.lines[i].set_data(x_data_list[i], y_data_list[i])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: batplot
3
- Version: 1.8.6
3
+ Version: 1.8.11
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,15 +1,15 @@
1
- batplot/__init__.py,sha256=Fy71HWPcaheFTg920KgEZ7reiHA27RQ-B6mxzpc8ZbI,118
1
+ batplot/__init__.py,sha256=XfA6rl6BPWzT0v4kl1_Zl94wmGALHRaHjeHPTbvpPL4,119
2
2
  batplot/args.py,sha256=DGTe2PKmJnI8Iq12QgO76V8lZvWhMOqY14gsyE5SgEs,37001
3
3
  batplot/batch.py,sha256=hqLNvd88OLd0PLo_ot6JjC3FM6wwxCJ1jO2J63f9Zyg,55899
4
- batplot/batplot.py,sha256=zD9kTLMKzYf73Ptn8jTOSeYZbxFzxlKxtrAE6bFHHNQ,187980
4
+ batplot/batplot.py,sha256=7gZNxkkm85uhZn4ZjP_h_SimXrNcp4Ldc10MCPQMOQk,190241
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=c4qhgN9zHUiBZhXVAdf0zGtPPoktD3JjMLkhjjYEwlk,9787
9
+ batplot/converters.py,sha256=o9tSuFmTK7VOdg-VMquPJbAyhP_vnBYcIWJF7wSA3HE,9896
10
10
  batplot/cpc_interactive.py,sha256=pPx6B8IN9YYnc7TWJnTV_2ZxcotCBXD29Db7G7ool-4,247355
11
11
  batplot/electrochem_interactive.py,sha256=Ui1_E-oTNvk7bKossx1MyULNHosFMFnl2a_EAOE550E,225991
12
- batplot/interactive.py,sha256=BTcr8ZtmWdID4uKiDA7KW72p9tfaC6sNhMZvhVA6py0,311985
12
+ batplot/interactive.py,sha256=Xk8N5FAC0bJMxBlw4V6Ne18QLQtaihJuqWZyVokIvCM,311953
13
13
  batplot/manual.py,sha256=pbRI6G4Pm12pOW8LrOLWWu7IEOtqWN3tRHtgge50LlA,11556
14
14
  batplot/modes.py,sha256=BajbnDzzYRD-FRr5Hoft0TyQ5CTWyggJjKa9yrM6iy4,37376
15
15
  batplot/operando.py,sha256=h09xu1BsdR68YlzhWeUSypYX83DzjJABIQQS2noQzPI,29400
@@ -22,7 +22,7 @@ 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
24
  batplot/data/USER_MANUAL.md,sha256=w6pmDXoLINFkCWWh3zay7uNIxUaDxSOrocnPIZwu2uA,19542
25
- batplot-1.8.6.dist-info/licenses/LICENSE,sha256=2PAnHeCiTfgI7aKZLWr0G56HI9fGKQ0CEbQ02H-yExQ,1065
25
+ batplot-1.8.11.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.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,,
71
+ batplot-1.8.11.dist-info/METADATA,sha256=ulk0HpgMaqViA4UK0DLrg4zYnL_1UmyCtzK5Z7sm1zs,7176
72
+ batplot-1.8.11.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
73
+ batplot-1.8.11.dist-info/entry_points.txt,sha256=73GgH3Zs-qGIvgiyQLgGsSW-ryOwPPKHveOW6TDIR5Q,82
74
+ batplot-1.8.11.dist-info/top_level.txt,sha256=Z5Q4sAiT_FDqZqhlLsYn9avRTuFAEEf3AVfkswxOb18,70
75
+ batplot-1.8.11.dist-info/RECORD,,