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 +1 -1
- batplot/batplot.py +43 -6
- batplot/converters.py +2 -1
- batplot/interactive.py +12 -15
- {batplot-1.8.6.dist-info → batplot-1.8.11.dist-info}/METADATA +1 -1
- {batplot-1.8.6.dist-info → batplot-1.8.11.dist-info}/RECORD +10 -10
- {batplot-1.8.6.dist-info → batplot-1.8.11.dist-info}/WHEEL +0 -0
- {batplot-1.8.6.dist-info → batplot-1.8.11.dist-info}/entry_points.txt +0 -0
- {batplot-1.8.6.dist-info → batplot-1.8.11.dist-info}/licenses/LICENSE +0 -0
- {batplot-1.8.6.dist-info → batplot-1.8.11.dist-info}/top_level.txt +0 -0
batplot/__init__.py
CHANGED
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
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
3085
|
-
|
|
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
|
-
#
|
|
3093
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
1817
|
-
#
|
|
1818
|
-
|
|
1819
|
-
|
|
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.
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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.
|
|
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.
|
|
72
|
-
batplot-1.8.
|
|
73
|
-
batplot-1.8.
|
|
74
|
-
batplot-1.8.
|
|
75
|
-
batplot-1.8.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|