klassez 0.2.0__tar.gz → 0.2.2.dev0__tar.gz
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.
- {klassez-0.2.0 → klassez-0.2.2.dev0}/PKG-INFO +1 -1
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/Spectra.py +36 -22
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/__init__.py +1 -1
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/anal.py +1 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/gui.py +8 -2
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/processing.py +147 -1
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez.egg-info/PKG-INFO +1 -1
- {klassez-0.2.0 → klassez-0.2.2.dev0}/LICENSE.txt +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/MANIFEST.in +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/README.md +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/docs/Makefile +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/docs/make.bat +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/docs/requirements.txt +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/config.py +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/figures.py +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/fit.py +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/misc.py +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/sim.py +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/tables/gamma.dic +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/tables/nuclei_jeol.dic +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/tables/xterm_colors +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez.egg-info/SOURCES.txt +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez.egg-info/dependency_links.txt +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez.egg-info/requires.txt +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez.egg-info/top_level.txt +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/pyproject.toml +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/setup.cfg +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T1_0.00.procs +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T1_10.00.procs +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T1_180.00.procs +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T1_90.00.procs +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T1_90.procs +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T2_10.00.procs +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T2_10.procs +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/acqus_1D +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/acqus_1D.fvf +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/acqus_1D.procs +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/acqus_2D +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/acqus_2D.procs +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/cnvg +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/fit_1D.py +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/read_process_1D.py +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/read_process_2D.py +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test.log +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test.py +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit.fvf +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit.ivf +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit_R1.png +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit_R2.png +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit_full.png +0 -0
- {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit_rhist.png +0 -0
|
@@ -2567,7 +2567,6 @@ class Pseudo_2D(Spectrum_2D):
|
|
|
2567
2567
|
# Then, baseline
|
|
2568
2568
|
procs['basl_c'] = None
|
|
2569
2569
|
procs['cal'] = 0
|
|
2570
|
-
procs['roll_ppm'] = None
|
|
2571
2570
|
return procs
|
|
2572
2571
|
|
|
2573
2572
|
def convdta(self, scaling=1):
|
|
@@ -2657,12 +2656,6 @@ class Pseudo_2D(Spectrum_2D):
|
|
|
2657
2656
|
self.freq_f1 = np.arange(self.S.shape[0]) # python numbering
|
|
2658
2657
|
self.ppm_f1 = np.arange(self.S.shape[0]) + 1 # human numbering
|
|
2659
2658
|
|
|
2660
|
-
# Align the spectrum
|
|
2661
|
-
if self.procs['roll_ppm'] is not None:
|
|
2662
|
-
for k, experiment in enumerate(self.S):
|
|
2663
|
-
roll_pt = int(self.procs['roll_ppm'][k] / misc.calcres(self.ppm_f2)) # Compute the circular shift in points
|
|
2664
|
-
self.S[k] = np.roll(experiment, roll_pt) # Apply it to each experiment
|
|
2665
|
-
|
|
2666
2659
|
self.integrals = {}
|
|
2667
2660
|
|
|
2668
2661
|
# Create empty dictionary where to save the projections
|
|
@@ -3189,18 +3182,21 @@ class Pseudo_2D(Spectrum_2D):
|
|
|
3189
3182
|
"""
|
|
3190
3183
|
super().qfil(which=which, u=u, s=s, from_procs=from_procs, SFO=self.acqus['SFO1'], O1P=self.acqus['o1p'])
|
|
3191
3184
|
|
|
3192
|
-
def align(self, lims=None, u_off=0.5, ref_idx=0):
|
|
3185
|
+
def align(self, lims=None, u_off=0.5, ref_idx=0, from_procs=True):
|
|
3193
3186
|
"""
|
|
3194
3187
|
Aligns the spectrum to a reference signal in the reference spectrum (default: first one).
|
|
3195
3188
|
|
|
3196
3189
|
Parameters
|
|
3197
3190
|
----------
|
|
3198
|
-
lims: tuple or None
|
|
3191
|
+
lims : tuple or None
|
|
3199
3192
|
Reference signal region, in ppm. If None, you can select it interactively.
|
|
3200
|
-
u_off: float
|
|
3193
|
+
u_off : float
|
|
3201
3194
|
Maximum displacement allowed, in ppm
|
|
3202
|
-
ref_idx: int
|
|
3195
|
+
ref_idx : int
|
|
3203
3196
|
Index of the spectrum to be used as a reference (python numbering)
|
|
3197
|
+
from_procs : bool
|
|
3198
|
+
If ``True``, read the values from ``self.procs`` and applies it.
|
|
3199
|
+
Else, it performs the whole process of calibration.
|
|
3204
3200
|
|
|
3205
3201
|
Returns
|
|
3206
3202
|
-------
|
|
@@ -3212,19 +3208,37 @@ class Pseudo_2D(Spectrum_2D):
|
|
|
3212
3208
|
|
|
3213
3209
|
:func:`klassez.processing.align`
|
|
3214
3210
|
"""
|
|
3215
|
-
# Get the region of the reference peak
|
|
3216
|
-
if lims is None:
|
|
3217
|
-
lims = gui.get_region(self.ppm_f2, self.rr[ref_idx], rev=True)
|
|
3218
|
-
# Align
|
|
3219
|
-
self.S, roll_pt, roll_ppm = processing.align(self.ppm_f2, self.S, lims, u_off, ref_idx)
|
|
3220
|
-
# Update the procs dictionary
|
|
3221
3211
|
if 'roll_ppm' not in self.procs.keys():
|
|
3222
3212
|
self.procs['roll_ppm'] = np.zeros(self.S.shape[0])
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3213
|
+
from_procs = False
|
|
3214
|
+
|
|
3215
|
+
if from_procs:
|
|
3216
|
+
data_roll = []
|
|
3217
|
+
for k, experiment in enumerate(self.S): # Loop over the experiments
|
|
3218
|
+
# Roll the spectra of the appropriate amount and append them to the list
|
|
3219
|
+
data_roll.append(processing.roll_dirac(experiment, self.ppm_f2, self.procs['roll_ppm'][k]))
|
|
3220
|
+
# Transform into array
|
|
3221
|
+
self.S = np.array(data_roll)
|
|
3222
|
+
print('Spectrum aligned from values in procs.', c='violet')
|
|
3223
|
+
else:
|
|
3224
|
+
# Get the region of the reference peak
|
|
3225
|
+
if lims is None:
|
|
3226
|
+
lims = gui.get_region(self.ppm_f2, self.rr, fig_title='Alignment Region Selection')
|
|
3227
|
+
|
|
3228
|
+
# Check on lims shape
|
|
3229
|
+
lims = np.squeeze(np.asarray(lims))
|
|
3230
|
+
arr_lims = np.asarray(lims)
|
|
3231
|
+
if len(arr_lims.shape) > 1:
|
|
3232
|
+
lims = arr_lims[0]
|
|
3233
|
+
print(f'More than one region selected. Using the first one: {lims}', c='yellow')
|
|
3234
|
+
|
|
3235
|
+
# Align
|
|
3236
|
+
self.S, roll_ppm = processing.align(self.ppm_f2, self.S, lims, u_off, ref_idx)
|
|
3237
|
+
|
|
3238
|
+
# Update the procs dictionary
|
|
3239
|
+
self.procs['roll_ppm'] = roll_ppm
|
|
3240
|
+
# Update the .procs file
|
|
3241
|
+
self.write_procs()
|
|
3228
3242
|
|
|
3229
3243
|
def basl(self, from_procs=False, phase=True):
|
|
3230
3244
|
"""
|
|
@@ -1429,6 +1429,7 @@ def write_igrl(filename, dic, indirect_scale=None, header=False):
|
|
|
1429
1429
|
n_dashes = 25 + 14 * n_spectra
|
|
1430
1430
|
|
|
1431
1431
|
# Open the file
|
|
1432
|
+
filename.parent.mkdir(parents=True, exist_ok=True)
|
|
1432
1433
|
f = filename.open('a', buffering=1)
|
|
1433
1434
|
|
|
1434
1435
|
# Info on the region to be fitted
|
|
@@ -2464,7 +2464,7 @@ def get_region(ppmscale, S, fig_title='Region Selector'):
|
|
|
2464
2464
|
----------
|
|
2465
2465
|
ppmscale : 1darray
|
|
2466
2466
|
The ppm scale of the spectrum
|
|
2467
|
-
S :
|
|
2467
|
+
S : ndarray
|
|
2468
2468
|
The spectrum to be trimmed
|
|
2469
2469
|
fig_title : str
|
|
2470
2470
|
Title for the interactive figure panel
|
|
@@ -2587,7 +2587,13 @@ def get_region(ppmscale, S, fig_title='Region Selector'):
|
|
|
2587
2587
|
plt.close()
|
|
2588
2588
|
|
|
2589
2589
|
# Draw the spectrum
|
|
2590
|
-
|
|
2590
|
+
if len(S.shape) == 1:
|
|
2591
|
+
ax.plot(ppmscale, S.real, c='tab:blue', lw=0.8) # Plot the data
|
|
2592
|
+
elif len(S.shape) == 2:
|
|
2593
|
+
for y in S.real:
|
|
2594
|
+
ax.plot(ppmscale, y, lw=0.8)
|
|
2595
|
+
else:
|
|
2596
|
+
raise ValueError('The given spectrum is more-than-2-dimensional.')
|
|
2591
2597
|
|
|
2592
2598
|
# Cosmetic stuff
|
|
2593
2599
|
ax.set_xlabel(r'$\delta\,$ /ppm')
|
|
@@ -2742,11 +2742,16 @@ def rpbc(data, split_imag=False, n=5, basl_method='huber', basl_thresh=0.2, basl
|
|
|
2742
2742
|
return y, p0, p1, c
|
|
2743
2743
|
|
|
2744
2744
|
|
|
2745
|
-
def
|
|
2745
|
+
def align_old(ppm_scale, data, lims, u_off=0.5, ref_idx=0):
|
|
2746
2746
|
"""
|
|
2747
2747
|
Performs the calibration of a pseudo-2D experiment by circular-shifting the spectra of an appropriate amount.
|
|
2748
2748
|
The target function aims to minimize the superimposition between a reference spectrum and the others using a brute-force method.
|
|
2749
2749
|
|
|
2750
|
+
.. error::
|
|
2751
|
+
|
|
2752
|
+
Old function!! Legacy
|
|
2753
|
+
|
|
2754
|
+
|
|
2750
2755
|
Parameters
|
|
2751
2756
|
----------
|
|
2752
2757
|
ppm_scale : 1darray
|
|
@@ -2838,6 +2843,103 @@ def align(ppm_scale, data, lims, u_off=0.5, ref_idx=0):
|
|
|
2838
2843
|
return data_roll, u_cal, u_cal_ppm
|
|
2839
2844
|
|
|
2840
2845
|
|
|
2846
|
+
def align(ppm_scale, data, lims, u_off=0.5, ref_idx=0):
|
|
2847
|
+
"""
|
|
2848
|
+
Performs the calibration of a pseudo-2D experiment by circular-shifting the spectra of an appropriate amount.
|
|
2849
|
+
The target function aims to minimize the superimposition between a reference spectrum and the others using a brute-force method.
|
|
2850
|
+
|
|
2851
|
+
Parameters
|
|
2852
|
+
----------
|
|
2853
|
+
ppm_scale : 1darray
|
|
2854
|
+
ppm scale of the spectrum to calibrate
|
|
2855
|
+
data : 2darray
|
|
2856
|
+
Complex-valued spectrum
|
|
2857
|
+
lims : tuple
|
|
2858
|
+
(ppm sx, ppm dx) of the calibration region
|
|
2859
|
+
u_off : float
|
|
2860
|
+
Maximum offset for the circular shift, in ppm
|
|
2861
|
+
ref_idx : int
|
|
2862
|
+
Index of the spectrum to be used as reference
|
|
2863
|
+
|
|
2864
|
+
Returns
|
|
2865
|
+
-------
|
|
2866
|
+
data_roll : 2darray
|
|
2867
|
+
Calibrated data
|
|
2868
|
+
u_cal_ppm : list
|
|
2869
|
+
Correction for the ppm scale of each experiment
|
|
2870
|
+
"""
|
|
2871
|
+
def f2min(param, s_ref, s, span_region):
|
|
2872
|
+
"""
|
|
2873
|
+
Cost function for the fit
|
|
2874
|
+
"""
|
|
2875
|
+
# Unpack the parameters
|
|
2876
|
+
par = param.valuesdict()
|
|
2877
|
+
|
|
2878
|
+
# References -> absolute value and its integral
|
|
2879
|
+
s_ref_abs = np.abs(s_ref)
|
|
2880
|
+
int_s_ref = processing.integral(s_ref_abs)
|
|
2881
|
+
|
|
2882
|
+
# Circular-shift the spectrum (first shift then abs)
|
|
2883
|
+
roll_s = np.abs(processing.roll_dirac(s, ppm_scale, par['u']))
|
|
2884
|
+
# Compute its integral
|
|
2885
|
+
int_roll_s = processing.integral(roll_s)
|
|
2886
|
+
|
|
2887
|
+
# Normalize the spectra in the calibration region
|
|
2888
|
+
A, _ = fit.fit_int(s_ref_abs, roll_s, q=0)
|
|
2889
|
+
roll_s *= A
|
|
2890
|
+
A_int, _ = fit.fit_int(int_s_ref, int_roll_s, q=0)
|
|
2891
|
+
int_roll_s *= A_int
|
|
2892
|
+
|
|
2893
|
+
# Compute the residuals
|
|
2894
|
+
res = s_ref_abs - roll_s
|
|
2895
|
+
int_res = int_s_ref - int_roll_s
|
|
2896
|
+
return np.concatenate([int_res[span_region], res[span_region]])
|
|
2897
|
+
|
|
2898
|
+
# Shallow copy
|
|
2899
|
+
data_in = deepcopy(data)
|
|
2900
|
+
|
|
2901
|
+
# Convert the ppm limits into points indeces
|
|
2902
|
+
sx = misc.ppmfind(ppm_scale, lims[0])[0]
|
|
2903
|
+
dx = misc.ppmfind(ppm_scale, lims[1])[0]
|
|
2904
|
+
# Calibration region
|
|
2905
|
+
cal_reg = slice(min(sx, dx), max(sx, dx), 1)
|
|
2906
|
+
|
|
2907
|
+
# Get the reference spectrum
|
|
2908
|
+
s_ref = data_in[ref_idx]
|
|
2909
|
+
|
|
2910
|
+
# Initialize the output variables
|
|
2911
|
+
u_cal_ppm = np.empty(data_in.shape[0]) # Shifts in ppm
|
|
2912
|
+
|
|
2913
|
+
# Make the parameters of the fit
|
|
2914
|
+
param = lmfit.Parameters()
|
|
2915
|
+
param.add('u', value=0., max=u_off, min=-u_off)
|
|
2916
|
+
for i, s_i in enumerate(data_in): # Loop over the experiments
|
|
2917
|
+
print(f'Alignment of transient {i+1:2d} of {len(data_in)}', end='\r', c='violet')
|
|
2918
|
+
# Fit
|
|
2919
|
+
minner = lmfit.Minimizer(f2min, param, fcn_args=(s_ref.real, s_i.real, cal_reg))
|
|
2920
|
+
result = minner.minimize(method='leastsq', max_nfev=5000, xtol=1e-5)
|
|
2921
|
+
|
|
2922
|
+
# Unpack the parameters and store them in the output variables
|
|
2923
|
+
popt = result.params.valuesdict()
|
|
2924
|
+
u_cal_ppm[i] = popt['u']
|
|
2925
|
+
# Initialize it for the next fit
|
|
2926
|
+
param['u'].set(value=popt['u'])
|
|
2927
|
+
print('\nDone.', c='violet')
|
|
2928
|
+
|
|
2929
|
+
# Correct the drift by subtracting the fit of the reference transient
|
|
2930
|
+
u_cal_ppm -= u_cal_ppm[ref_idx]
|
|
2931
|
+
|
|
2932
|
+
# Apply the correction
|
|
2933
|
+
data_roll = [] # Initialize output variable
|
|
2934
|
+
for i, experiment in enumerate(data_in): # Loop over the experiments
|
|
2935
|
+
# Roll the spectra of the appropriate amount and append them to the list
|
|
2936
|
+
data_roll.append(processing.roll_dirac(experiment, ppm_scale, u_cal_ppm[i]))
|
|
2937
|
+
# Transform into array
|
|
2938
|
+
data_roll = np.array(data_roll)
|
|
2939
|
+
|
|
2940
|
+
return data_roll, u_cal_ppm
|
|
2941
|
+
|
|
2942
|
+
|
|
2841
2943
|
def lp(data, pred=1, order=8, mode='b'):
|
|
2842
2944
|
"""
|
|
2843
2945
|
Apply linear prediction on the dataset.
|
|
@@ -4192,3 +4294,47 @@ def sl_bas(x, y, lims=None):
|
|
|
4192
4294
|
# Match the shape of y. Use always the left limit as anchor point
|
|
4193
4295
|
overlay_bas = [misc.sum_overlay(np.zeros_like(x), y_b, x[min(x_idx)], x) for y_b in bas]
|
|
4194
4296
|
return np.squeeze(np.array(overlay_bas))
|
|
4297
|
+
|
|
4298
|
+
|
|
4299
|
+
def roll_dirac(y, x, off=0, onfid=False):
|
|
4300
|
+
"""
|
|
4301
|
+
Perform a circular shift on ``y`` by convolution with a Dirac delta, centered at ``off`` in the ``x`` timescale.
|
|
4302
|
+
|
|
4303
|
+
Parameters
|
|
4304
|
+
----------
|
|
4305
|
+
y : ndarray
|
|
4306
|
+
Data to shift. The shift will be applied on the last dimension.
|
|
4307
|
+
x : 1darray
|
|
4308
|
+
Scale on which to consider ``off``.
|
|
4309
|
+
off : float
|
|
4310
|
+
Shift value on ``x``
|
|
4311
|
+
onfid : bool
|
|
4312
|
+
Set it to True if ``y`` is a FID. The shift then is done by multiplying, instead of convolving.
|
|
4313
|
+
|
|
4314
|
+
Returns
|
|
4315
|
+
-------
|
|
4316
|
+
y_roll : ndarray
|
|
4317
|
+
Shifted data
|
|
4318
|
+
"""
|
|
4319
|
+
# Compute required timescale
|
|
4320
|
+
sw = max(x) - min(x)
|
|
4321
|
+
dw = 1 / sw
|
|
4322
|
+
t = np.linspace(0, y.shape[-1] * dw, y.shape[-1])
|
|
4323
|
+
# Compute dirac delta in the time domain
|
|
4324
|
+
dirac_t = np.exp(-1j * 2 * np.pi * off * t)
|
|
4325
|
+
|
|
4326
|
+
# Make the data complex, if they are not already
|
|
4327
|
+
if np.iscomplexobj(y):
|
|
4328
|
+
y_cplx = deepcopy(y)
|
|
4329
|
+
else:
|
|
4330
|
+
y_cplx = processing.hilbert(y)
|
|
4331
|
+
|
|
4332
|
+
if onfid:
|
|
4333
|
+
# Just multply and return
|
|
4334
|
+
y_roll = y_cplx * dirac_t
|
|
4335
|
+
else:
|
|
4336
|
+
# Convolve y with the delta through IFT -> multiply -> FT
|
|
4337
|
+
y_t = processing.ift(y_cplx)
|
|
4338
|
+
y_t_roll = y_t * dirac_t
|
|
4339
|
+
y_roll = processing.ft(y_t_roll)
|
|
4340
|
+
return y_roll
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|