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.
Files changed (51) hide show
  1. {klassez-0.2.0 → klassez-0.2.2.dev0}/PKG-INFO +1 -1
  2. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/Spectra.py +36 -22
  3. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/__init__.py +1 -1
  4. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/anal.py +1 -0
  5. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/gui.py +8 -2
  6. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/processing.py +147 -1
  7. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez.egg-info/PKG-INFO +1 -1
  8. {klassez-0.2.0 → klassez-0.2.2.dev0}/LICENSE.txt +0 -0
  9. {klassez-0.2.0 → klassez-0.2.2.dev0}/MANIFEST.in +0 -0
  10. {klassez-0.2.0 → klassez-0.2.2.dev0}/README.md +0 -0
  11. {klassez-0.2.0 → klassez-0.2.2.dev0}/docs/Makefile +0 -0
  12. {klassez-0.2.0 → klassez-0.2.2.dev0}/docs/make.bat +0 -0
  13. {klassez-0.2.0 → klassez-0.2.2.dev0}/docs/requirements.txt +0 -0
  14. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/config.py +0 -0
  15. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/figures.py +0 -0
  16. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/fit.py +0 -0
  17. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/misc.py +0 -0
  18. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/sim.py +0 -0
  19. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/tables/gamma.dic +0 -0
  20. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/tables/nuclei_jeol.dic +0 -0
  21. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez/tables/xterm_colors +0 -0
  22. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez.egg-info/SOURCES.txt +0 -0
  23. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez.egg-info/dependency_links.txt +0 -0
  24. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez.egg-info/requires.txt +0 -0
  25. {klassez-0.2.0 → klassez-0.2.2.dev0}/klassez.egg-info/top_level.txt +0 -0
  26. {klassez-0.2.0 → klassez-0.2.2.dev0}/pyproject.toml +0 -0
  27. {klassez-0.2.0 → klassez-0.2.2.dev0}/setup.cfg +0 -0
  28. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T1_0.00.procs +0 -0
  29. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T1_10.00.procs +0 -0
  30. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T1_180.00.procs +0 -0
  31. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T1_90.00.procs +0 -0
  32. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T1_90.procs +0 -0
  33. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T2_10.00.procs +0 -0
  34. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/T2_10.procs +0 -0
  35. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/acqus_1D +0 -0
  36. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/acqus_1D.fvf +0 -0
  37. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/acqus_1D.procs +0 -0
  38. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/acqus_2D +0 -0
  39. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/acqus_2D.procs +0 -0
  40. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/cnvg +0 -0
  41. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/fit_1D.py +0 -0
  42. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/read_process_1D.py +0 -0
  43. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/read_process_2D.py +0 -0
  44. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test.log +0 -0
  45. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test.py +0 -0
  46. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit.fvf +0 -0
  47. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit.ivf +0 -0
  48. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit_R1.png +0 -0
  49. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit_R2.png +0 -0
  50. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit_full.png +0 -0
  51. {klassez-0.2.0 → klassez-0.2.2.dev0}/test/test_1D_fit_rhist.png +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: klassez
3
- Version: 0.2.0
3
+ Version: 0.2.2.dev0
4
4
  Summary: A collection of functions for NMR data handling
5
5
  Author: Letizia Fiorucci
6
6
  Author-email: Francesco Bruno <bruno@cerm.unifi.it>
@@ -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
- if self.procs['roll_ppm'] is None:
3224
- self.procs['roll_ppm'] = np.zeros(self.S.shape[0])
3225
- self.procs['roll_ppm'] += roll_ppm
3226
- # Update the .procs file
3227
- self.write_procs()
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
  """
@@ -17,4 +17,4 @@ from .config import CM, CM_2D, COLORS, cron, safe_kws, textcolor, _print, cprint
17
17
 
18
18
  print = cprint
19
19
 
20
- __version__ = "0.2.0"
20
+ __version__ = "0.2.2.dev0"
@@ -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 : 1darray
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
- ax.plot(ppmscale, S.real, c='tab:blue', lw=0.8) # Plot the data
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 align(ppm_scale, data, lims, u_off=0.5, ref_idx=0):
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: klassez
3
- Version: 0.2.0
3
+ Version: 0.2.2.dev0
4
4
  Summary: A collection of functions for NMR data handling
5
5
  Author: Letizia Fiorucci
6
6
  Author-email: Francesco Bruno <bruno@cerm.unifi.it>
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