spinlab 0.0.0__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.
- spinlab/__init__.py +27 -0
- spinlab/analysis/__init__.py +6 -0
- spinlab/analysis/hydration.py +555 -0
- spinlab/analysis/peaks.py +249 -0
- spinlab/analysis/relaxation_fit.py +29 -0
- spinlab/analysis/simulate_enhancement_profiles.py +109 -0
- spinlab/config/__init__.py +0 -0
- spinlab/config/config.py +81 -0
- spinlab/constants/__init__.py +5 -0
- spinlab/constants/constants.py +27 -0
- spinlab/constants/mrProperties.py +236 -0
- spinlab/constants/radicalProperties.py +147 -0
- spinlab/core/__init__.py +5 -0
- spinlab/core/base.py +1268 -0
- spinlab/core/coord.py +225 -0
- spinlab/core/data.py +335 -0
- spinlab/core/ufunc.py +67 -0
- spinlab/core/util.py +159 -0
- spinlab/fitting/__init__.py +3 -0
- spinlab/fitting/general.py +106 -0
- spinlab/io/__init__.py +19 -0
- spinlab/io/bes3t.py +453 -0
- spinlab/io/cnsi.py +139 -0
- spinlab/io/delta.py +523 -0
- spinlab/io/h5.py +215 -0
- spinlab/io/load.py +334 -0
- spinlab/io/load_csv.py +98 -0
- spinlab/io/logs.py +84 -0
- spinlab/io/mat.py +153 -0
- spinlab/io/power.py +109 -0
- spinlab/io/prospa.py +340 -0
- spinlab/io/random.py +36 -0
- spinlab/io/rs2d.py +111 -0
- spinlab/io/save.py +52 -0
- spinlab/io/specman.py +358 -0
- spinlab/io/tnmr.py +178 -0
- spinlab/io/topspin.py +625 -0
- spinlab/io/vna.py +76 -0
- spinlab/io/vnmrj.py +236 -0
- spinlab/io/winepr.py +205 -0
- spinlab/math/__init__.py +6 -0
- spinlab/math/lineshape.py +142 -0
- spinlab/math/pulses.py +255 -0
- spinlab/math/relaxation.py +133 -0
- spinlab/math/window.py +161 -0
- spinlab/plotting/__init__.py +9 -0
- spinlab/plotting/colors.py +9 -0
- spinlab/plotting/general.py +285 -0
- spinlab/plotting/image.py +68 -0
- spinlab/plotting/stack_plot.py +69 -0
- spinlab/processing/__init__.py +12 -0
- spinlab/processing/align.py +76 -0
- spinlab/processing/apodization.py +96 -0
- spinlab/processing/average.py +28 -0
- spinlab/processing/conversion.py +247 -0
- spinlab/processing/fft.py +182 -0
- spinlab/processing/helpers.py +577 -0
- spinlab/processing/integration.py +130 -0
- spinlab/processing/interpolation.py +70 -0
- spinlab/processing/offset.py +133 -0
- spinlab/processing/phase.py +508 -0
- spinlab/reporting/__init__.py +1 -0
- spinlab/version.py +1 -0
- spinlab/widgets/__init__.py +4 -0
- spinlab/widgets/align_widget.py +77 -0
- spinlab/widgets/phase_widget.py +118 -0
- spinlab-0.0.0.dist-info/METADATA +56 -0
- spinlab-0.0.0.dist-info/RECORD +71 -0
- spinlab-0.0.0.dist-info/WHEEL +5 -0
- spinlab-0.0.0.dist-info/licenses/LICENSE.txt +21 -0
- spinlab-0.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import numpy as _np
|
|
2
|
+
import scipy.signal as _spsig
|
|
3
|
+
import spinlab as _sl
|
|
4
|
+
import warnings
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def find_peaks(
|
|
8
|
+
data,
|
|
9
|
+
dims="f2",
|
|
10
|
+
normalize=True,
|
|
11
|
+
regions=None,
|
|
12
|
+
height=0.5,
|
|
13
|
+
threshold=None,
|
|
14
|
+
distance=None,
|
|
15
|
+
prominence=None,
|
|
16
|
+
width=None,
|
|
17
|
+
wlen=None,
|
|
18
|
+
rel_height=0.5,
|
|
19
|
+
plateau_size=None,
|
|
20
|
+
):
|
|
21
|
+
"""Find peaks in spectrum
|
|
22
|
+
|
|
23
|
+
Find peaks in spectrum (sldata object) and returns peak index, chemical shift (ppm), peak height, peak width (Hz) and peak width height. The function uses the SciPy functions "find_peaks" and "peak_widths".
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
data (SpinData): Data object
|
|
27
|
+
dims (str): Dimension to find peaks
|
|
28
|
+
regions (None, list): List of tuples defining the region to find peaks
|
|
29
|
+
normalize (boolean): Normalize data to a maximum value of 1. Default is True
|
|
30
|
+
height (float or numpy.array): Optionally, height of peaks. If an array is supplied, the first element is minimum and the second is maximum
|
|
31
|
+
threshold (float or numpy.array): Optionally, threshold of minimum peak height to be counted. If an array is supplied, the first element is minimum and the second is maximum
|
|
32
|
+
distance (float): Optionally, minimal horizontal distance in samples between peaks. Smaller peaks are removed first until the condition is fulfilled for all remaining peaks.
|
|
33
|
+
prominence (float or numpy.array): Optionally, prominence of peaks. If an array is supplied, the first element is minimum and the second is maximum
|
|
34
|
+
width (float or numpy.array): Optionally, width of peaks. If an array is supplied, the first element is minimum and the second is maximum
|
|
35
|
+
wlen (int): Optionally, for calculating the peaks prominences. Only valid if prominence is given
|
|
36
|
+
rel_height (float): Optionally, relative height at which peak width is measured. Default is 0.5 for FWHH
|
|
37
|
+
plateau_size (float or numpy.array): Optionally, size of the flat top of peaks in samples. If an array is supplied, the first element is minimum and the second is maximum
|
|
38
|
+
peak_info (boolean): If True print output to terminal
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
data (SpinData): nd array of peak index, peak width and relative peak height. The linewidth is returned in (Hz), based on the spectrometer frequency
|
|
42
|
+
|
|
43
|
+
Examples:
|
|
44
|
+
Find peaks in entire data region:
|
|
45
|
+
|
|
46
|
+
>>> peak_list = sl.find_peaks(data)
|
|
47
|
+
|
|
48
|
+
Find peaks with an amplitude > 0.01 (after normalization):
|
|
49
|
+
|
|
50
|
+
>>> peak_list = sl.find_peaks(data, peak_height = 0.05)
|
|
51
|
+
|
|
52
|
+
Find peaks with an amplitude > 500 (data not normalized):
|
|
53
|
+
|
|
54
|
+
>>> peak_list = sl.find_peaks(data, peak_height = 500, normalize = False)
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
if len(data.dims) == 2:
|
|
59
|
+
data_list = []
|
|
60
|
+
second_dim = data.dims[-1]
|
|
61
|
+
second_coord = data.coords[second_dim]
|
|
62
|
+
for i in range(len(second_coord)):
|
|
63
|
+
sub_data = data[second_dim, i].sum(second_dim)
|
|
64
|
+
data_list.append(
|
|
65
|
+
find_peaks(
|
|
66
|
+
sub_data,
|
|
67
|
+
dims,
|
|
68
|
+
normalize,
|
|
69
|
+
regions=regions,
|
|
70
|
+
height=height,
|
|
71
|
+
threshold=threshold,
|
|
72
|
+
distance=distance,
|
|
73
|
+
prominence=prominence,
|
|
74
|
+
width=width,
|
|
75
|
+
wlen=wlen,
|
|
76
|
+
rel_height=rel_height,
|
|
77
|
+
plateau_size=plateau_size,
|
|
78
|
+
)
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# data_list, second_coord = _peak_list_checker(
|
|
82
|
+
# data_list, second_coord, second_dim
|
|
83
|
+
# )
|
|
84
|
+
|
|
85
|
+
return _sl.concat(
|
|
86
|
+
data_list, dim=second_dim, coord=second_coord, casting="unsafe"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
elif len(data.dims) == 1:
|
|
90
|
+
out = data.copy()
|
|
91
|
+
out.attrs["experiment_type"] = "peak_list"
|
|
92
|
+
out.attrs["data_type"] = "peak_list"
|
|
93
|
+
|
|
94
|
+
resolution = _np.sum(_np.diff(out.coords)) / _np.size(out.coords)
|
|
95
|
+
frequency = out.attrs["nmr_frequency"]
|
|
96
|
+
|
|
97
|
+
coords = out.coords[dims]
|
|
98
|
+
append_index = 0
|
|
99
|
+
|
|
100
|
+
if regions:
|
|
101
|
+
out = out[dims, regions]
|
|
102
|
+
append_index = _np.where(coords == out.coords[dims][0])[0][0]
|
|
103
|
+
|
|
104
|
+
if normalize == True:
|
|
105
|
+
out = _sl.normalize(out)
|
|
106
|
+
|
|
107
|
+
# In the case of the negative peaks
|
|
108
|
+
real_array = out.values.real
|
|
109
|
+
max_value = _np.max(real_array)
|
|
110
|
+
min_value = _np.min(real_array)
|
|
111
|
+
if _np.abs(max_value) < _np.abs(min_value):
|
|
112
|
+
out.values *= -1
|
|
113
|
+
|
|
114
|
+
peak_index, _ = _spsig.find_peaks(
|
|
115
|
+
out.values,
|
|
116
|
+
height=height,
|
|
117
|
+
threshold=threshold,
|
|
118
|
+
distance=distance,
|
|
119
|
+
prominence=prominence,
|
|
120
|
+
width=width,
|
|
121
|
+
wlen=wlen,
|
|
122
|
+
rel_height=rel_height,
|
|
123
|
+
plateau_size=plateau_size,
|
|
124
|
+
)
|
|
125
|
+
peak_width_height = _spsig.peak_widths(
|
|
126
|
+
out.values.real, peaks=peak_index, rel_height=rel_height
|
|
127
|
+
)
|
|
128
|
+
peak_width = peak_width_height[0] * resolution * 1e-6 * frequency
|
|
129
|
+
peak_width_height = peak_width_height[1]
|
|
130
|
+
|
|
131
|
+
peak_index = [x + append_index for x in peak_index]
|
|
132
|
+
peak_values = [data.values.real[x] for x in peak_index]
|
|
133
|
+
peak_shift = [coords[int(x)] for x in peak_index]
|
|
134
|
+
|
|
135
|
+
out.values = _np.vstack(
|
|
136
|
+
(peak_index, peak_shift, peak_values, peak_width, peak_width_height)
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
out = _sl.update_axis(
|
|
140
|
+
out, dim=0, new_dims="peak_info", start_stop=(0, len(out.values) - 1)
|
|
141
|
+
)
|
|
142
|
+
out.coords.append(dim="index", coord=_np.arange(0, len(peak_index), 1))
|
|
143
|
+
|
|
144
|
+
proc_attr_name = "peak_list"
|
|
145
|
+
proc_parameters = {
|
|
146
|
+
"dims": dims,
|
|
147
|
+
"normalize": normalize,
|
|
148
|
+
"regions": regions,
|
|
149
|
+
"height": height,
|
|
150
|
+
"threshold": threshold,
|
|
151
|
+
"distance": distance,
|
|
152
|
+
"prominence": prominence,
|
|
153
|
+
"width": width,
|
|
154
|
+
"wlen": wlen,
|
|
155
|
+
"rel_height": rel_height,
|
|
156
|
+
"plateau_size": plateau_size,
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
out.add_proc_attrs(proc_attr_name, proc_parameters)
|
|
160
|
+
|
|
161
|
+
return out
|
|
162
|
+
|
|
163
|
+
else:
|
|
164
|
+
raise ValueError("The function only works with 1d or 2d datasets")
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def peak_info(data):
|
|
168
|
+
"""
|
|
169
|
+
Print peak list in human readable form
|
|
170
|
+
|
|
171
|
+
Function to print the peak list in a human readable form. You first have to run find_peaks to create a sldata object that includes a peak list.
|
|
172
|
+
|
|
173
|
+
Args:
|
|
174
|
+
data (SpinData): SpinData object created by find_peaks
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
Output (str): Peak list table
|
|
178
|
+
"""
|
|
179
|
+
|
|
180
|
+
if data.attrs["experiment_type"] != "peak_list":
|
|
181
|
+
print("Peak list required as input")
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
if len(data.dims) == 3:
|
|
185
|
+
dim = data.dims[-1]
|
|
186
|
+
coord = data.coords[dim]
|
|
187
|
+
for i in range(len(coord)):
|
|
188
|
+
sub_data = data[dim, i].sum(dim)
|
|
189
|
+
print("Dim: %s, Dim Index: %d, Dim Value: %0.01f" % (dim, i, coord[i]))
|
|
190
|
+
print("--------------------------------------------")
|
|
191
|
+
peak_info(sub_data)
|
|
192
|
+
|
|
193
|
+
elif len(data.dims) == 2:
|
|
194
|
+
for peak_number in range(len(data.coords["index"])):
|
|
195
|
+
values = data["index", peak_number].sum("index").values
|
|
196
|
+
if any(_np.isnan(values)):
|
|
197
|
+
print("Peak #%d Information Not Available." % (peak_number + 1))
|
|
198
|
+
else:
|
|
199
|
+
print(
|
|
200
|
+
"Peak #%d: Index: %5d, Shift (ppm): %0.02f, Height : %4.2f, Width (Hz): %4.2f, Width Height: %2.2f"
|
|
201
|
+
% (
|
|
202
|
+
peak_number + 1,
|
|
203
|
+
values[0],
|
|
204
|
+
values[1],
|
|
205
|
+
values[2],
|
|
206
|
+
values[3],
|
|
207
|
+
values[4],
|
|
208
|
+
)
|
|
209
|
+
)
|
|
210
|
+
print("--------------------------------------------")
|
|
211
|
+
else:
|
|
212
|
+
raise ValueError("The function only works with 1d or 2d datasets")
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def _peak_list_checker(peak_list, coord, dim):
|
|
216
|
+
"""
|
|
217
|
+
Check peak list before concat. It will remove the inconsistent peak data from list.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
peak_list (list): list of peak data
|
|
221
|
+
coord (numpy.array): an array of coord
|
|
222
|
+
dim (str): the dim for concat
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
new_peak_list (list): concat-able list of peak data
|
|
226
|
+
new_coord (numpy.array): a new array of coord
|
|
227
|
+
"""
|
|
228
|
+
|
|
229
|
+
ref = peak_list[-1]
|
|
230
|
+
ref_shape = _np.shape(ref)
|
|
231
|
+
new_peak_list = [peak for peak in peak_list if _np.shape(peak) == ref_shape]
|
|
232
|
+
new_coord = _np.array(
|
|
233
|
+
[
|
|
234
|
+
coord[i]
|
|
235
|
+
for i in range(len(peak_list))
|
|
236
|
+
if _np.shape(peak_list[i]) == ref_shape
|
|
237
|
+
]
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
if new_peak_list != peak_list:
|
|
241
|
+
print("In dim %s, the following datasets are removed." % dim)
|
|
242
|
+
for i in range(len(peak_list)):
|
|
243
|
+
if peak_list[i] not in new_peak_list:
|
|
244
|
+
print(
|
|
245
|
+
"Index: %i, Value: %0.01f, Number of Peaks Found: %i"
|
|
246
|
+
% (i, coord[i], len(peak_list[i].coords[1]))
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
return new_peak_list, new_coord
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Modules which provide function to analyse relaxation measurements]"""
|
|
2
|
+
|
|
3
|
+
import numpy as _np
|
|
4
|
+
from ..fitting import fit
|
|
5
|
+
from ..math import *
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def inversion_recovery_fit(integrals):
|
|
9
|
+
# Estimate an initial guess from experimental data
|
|
10
|
+
|
|
11
|
+
initial_guess = (2.0, -4000, 4000)
|
|
12
|
+
|
|
13
|
+
fit_results = fit(relaxation.t1, integrals.real, dim="t1", p0=initial_guess)
|
|
14
|
+
|
|
15
|
+
# fit returns dictionary with results
|
|
16
|
+
|
|
17
|
+
print(fit_results)
|
|
18
|
+
|
|
19
|
+
# print(fit_results['fit'])
|
|
20
|
+
|
|
21
|
+
# fit = out['fit']
|
|
22
|
+
# popt = out['popt']
|
|
23
|
+
# err = out['err']
|
|
24
|
+
|
|
25
|
+
# T1 = popt['popt',0]
|
|
26
|
+
# M_0 = popt['popt',1]
|
|
27
|
+
# M_inf = popt['popt',2]
|
|
28
|
+
|
|
29
|
+
# return out
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Modules to calculate Spin enhancement profiles"""
|
|
2
|
+
|
|
3
|
+
import numpy as _np
|
|
4
|
+
from scipy import optimize
|
|
5
|
+
import spinlab as _sl
|
|
6
|
+
import warnings
|
|
7
|
+
from ..constants import constants
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def sim_sl_profile(
|
|
11
|
+
data,
|
|
12
|
+
B0,
|
|
13
|
+
nucleus="1H",
|
|
14
|
+
sl_process="SE",
|
|
15
|
+
add_details=False,
|
|
16
|
+
remove_background=True,
|
|
17
|
+
normalize=True,
|
|
18
|
+
integrate=True,
|
|
19
|
+
):
|
|
20
|
+
"""Simulate Spin enhancment profile
|
|
21
|
+
|
|
22
|
+
Simulate Spin enhancement profile based on the EPR spectrum. For more details:
|
|
23
|
+
|
|
24
|
+
Banerjee, D., D. Shimon, A. Feintuch, S. Vega, and D. Goldfarb. “The Interplay between the Solid Effect and the Cross Effect Mechanisms in Solid State (1)(3)C Spin at 95 GHz Using Trityl Radicals.” Journal of Magnetic Resonance 230 (May 2013): 212–19.
|
|
25
|
+
https://doi.org/10.1016/j.jmr.2013.02.010.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
data (Spindata): EPR spectrum
|
|
29
|
+
B0 (float): Field position for the Spin experiment in (T)
|
|
30
|
+
nucleus (int): Nucleus for Spin experiment
|
|
31
|
+
sl_process (int): Select Spin mechanism, SE - Solid Effect, CE/TM - Cross-Effect/Thermal Mixing
|
|
32
|
+
add_details (boolean): Add individual spectra to proc_attrs. Default is False
|
|
33
|
+
remove_background (boolean): Remove 0th order background from EPR spectrum. Default is True
|
|
34
|
+
normalize (boolean): Normalize EPR spectrum to maximum amplitude of 1. Default is True
|
|
35
|
+
integrate (boolean): Integrate EPR spectrum. Default is True
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
data (Spindata): Simulated Spin enhancement profile
|
|
39
|
+
|
|
40
|
+
.. math::
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
out = data.copy()
|
|
44
|
+
|
|
45
|
+
# Some error checks:
|
|
46
|
+
if out.attrs.get("experiment_type") == None:
|
|
47
|
+
print("Error: Key experiment_type not present")
|
|
48
|
+
return
|
|
49
|
+
|
|
50
|
+
if out.attrs["experiment_type"] != "epr_spectrum":
|
|
51
|
+
print("Error: EPR spectrum required as input.")
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
if len(out.dims) > 1:
|
|
55
|
+
print("Error: This function requires a 1D EPR spectrum as input.")
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
if remove_background == True:
|
|
59
|
+
out = _sl.remove_background(out, dim="B0", deg=0) # Remove background
|
|
60
|
+
|
|
61
|
+
if normalize == True:
|
|
62
|
+
out = _sl.normalize(out)
|
|
63
|
+
|
|
64
|
+
if integrate == True:
|
|
65
|
+
out = _sl.cumulative_integrate(out, dim="B0") # Calculate cumsum
|
|
66
|
+
|
|
67
|
+
## Calculate number of points to shift
|
|
68
|
+
slLarmorFrequency = _sl.mr_properties(nucleus, B0) # Nuclear Larmor Frequency
|
|
69
|
+
slLarmorFrequency_G = slLarmorFrequency / (
|
|
70
|
+
1000 * _sl.mr_properties("0e") / 2 / pi
|
|
71
|
+
) # Nuclear Larmor Frequency in [G]
|
|
72
|
+
deltaB0_G = (out.coords["B0"][1] - out.coords["B0"][0]) * 10
|
|
73
|
+
points_to_shift = round(slLarmorFrequency_G / deltaB0_G)
|
|
74
|
+
|
|
75
|
+
## Shift EPR spectra using mumpy's roll function
|
|
76
|
+
EPRdataPos = out.copy()
|
|
77
|
+
EPRdataPos.values = _np.roll(EPRdataPos.values, points_to_shift)
|
|
78
|
+
|
|
79
|
+
EPRdataNeg = out.copy()
|
|
80
|
+
EPRdataNeg.values = _np.roll(out.values, (-1) * points_to_shift)
|
|
81
|
+
EPRdataNeg.values = (-1) * EPRdataNeg.values
|
|
82
|
+
|
|
83
|
+
if sl_process == "SE":
|
|
84
|
+
out = EPRdataPos + EPRdataNeg
|
|
85
|
+
elif sl_process == "CE/TM":
|
|
86
|
+
out = out.values * (EPRdataPos + EPRdataNeg)
|
|
87
|
+
|
|
88
|
+
proc_attr_name = "sim_sl_profile"
|
|
89
|
+
proc_parameters = {
|
|
90
|
+
"nucleus": nucleus,
|
|
91
|
+
"sl_process": sl_process,
|
|
92
|
+
"remove_background": remove_background,
|
|
93
|
+
"normalize": normalize,
|
|
94
|
+
"integrate": integrate,
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
out.add_proc_attrs(proc_attr_name, proc_parameters)
|
|
98
|
+
|
|
99
|
+
if add_details == True:
|
|
100
|
+
sim_data = _np.array([out.values, EPRdataNeg.values, EPRdataPos.values])
|
|
101
|
+
|
|
102
|
+
proc_attr_name = "sim_sl_profile"
|
|
103
|
+
proc_parameters = {
|
|
104
|
+
"sim_data": sim_data,
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
out.add_proc_attrs(proc_attr_name, proc_parameters)
|
|
108
|
+
|
|
109
|
+
return out
|
|
File without changes
|
spinlab/config/config.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""
|
|
2
|
+
global config
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import configparser
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
import warnings
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _escape_split(s, delim=",", escape="\\"):
|
|
15
|
+
tokens = []
|
|
16
|
+
previous_escape = False
|
|
17
|
+
subtoken = ""
|
|
18
|
+
for k in range(len(s)):
|
|
19
|
+
if s[k] == delim and (not previous_escape):
|
|
20
|
+
if len(subtoken) > 0:
|
|
21
|
+
tokens.append(subtoken)
|
|
22
|
+
subtoken = "" # reset subtoken
|
|
23
|
+
else:
|
|
24
|
+
# ESCAPE DELIM -> DELIM
|
|
25
|
+
if previous_escape and s[k] != escape and s[k] == delim:
|
|
26
|
+
subtoken = subtoken[:-1] + s[k]
|
|
27
|
+
else:
|
|
28
|
+
# add to subtoken
|
|
29
|
+
subtoken += s[k]
|
|
30
|
+
# set previous_escape flag:
|
|
31
|
+
# If for current char is escape (True and s[k]=='\\') and previous_escape is False -> set it to True
|
|
32
|
+
# If for current char is escape (True and s[k]=='\\') and previous_escape is True -> case of '\\\\' -> escaping an escape character -> set it back to False
|
|
33
|
+
# if current char is no escape character -> set it to false
|
|
34
|
+
previous_escape = (not previous_escape) and (s[k] == escape)
|
|
35
|
+
if len(subtoken) > 0:
|
|
36
|
+
tokens.append(subtoken)
|
|
37
|
+
return tokens
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _kwarg_converter(s: str):
|
|
41
|
+
tokens = _escape_split(s, ",", escape="\\")
|
|
42
|
+
args = []
|
|
43
|
+
kwargs = {}
|
|
44
|
+
for k in tokens:
|
|
45
|
+
subtokens = _escape_split(k, "=", escape="\\")
|
|
46
|
+
if len(subtokens) == 1:
|
|
47
|
+
args.append(subtokens[0])
|
|
48
|
+
else:
|
|
49
|
+
kwargs[subtokens[0].strip()] = subtokens[1].strip()
|
|
50
|
+
return args, kwargs
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _get_sl_config(configname="spinlab.cfg"):
|
|
54
|
+
config = configparser.ConfigParser(
|
|
55
|
+
converters={
|
|
56
|
+
"list": lambda x: list(x.strip("[").strip("]").split(",")),
|
|
57
|
+
"args_kwargs": _kwarg_converter,
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
# define three possible locations:
|
|
62
|
+
spinlab_current_config = Path.cwd() / configname
|
|
63
|
+
spinlab_home_config = Path.home() / configname
|
|
64
|
+
|
|
65
|
+
spinlab_cfg_folder = str(
|
|
66
|
+
Path(__file__).parent
|
|
67
|
+
) # / configname #.with_name("config"))
|
|
68
|
+
spinlab_global_config = Path(spinlab_cfg_folder) / configname
|
|
69
|
+
|
|
70
|
+
config_read_list = [
|
|
71
|
+
spinlab_global_config,
|
|
72
|
+
spinlab_home_config,
|
|
73
|
+
spinlab_current_config,
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
# user defined takes precedence
|
|
77
|
+
config.read(config_read_list)
|
|
78
|
+
return config
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
SpinLAB_CONFIG = _get_sl_config()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from scipy.constants import mu_0, c, pi, epsilon_0, hbar, h, N_A, m_e, eV
|
|
2
|
+
from scipy.constants import e as e_charge
|
|
3
|
+
|
|
4
|
+
from scipy.constants import physical_constants as pc
|
|
5
|
+
|
|
6
|
+
e_gyro = pc["electron gyromag. ratio in MHz/T"][0]
|
|
7
|
+
p_gyro = pc["proton gyromag. ratio in MHz/T"][0]
|
|
8
|
+
mub = pc["Bohr magneton"][0]
|
|
9
|
+
mub_Hz = pc["Bohr magneton in Hz/T"][0]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"mu_0",
|
|
14
|
+
"c",
|
|
15
|
+
"pi",
|
|
16
|
+
"epsilon_0",
|
|
17
|
+
"hbar",
|
|
18
|
+
"h",
|
|
19
|
+
"N_A",
|
|
20
|
+
"m_e",
|
|
21
|
+
"e_charge",
|
|
22
|
+
"e_gyro",
|
|
23
|
+
"p_gyro",
|
|
24
|
+
"eV",
|
|
25
|
+
"mub",
|
|
26
|
+
"mub_Hz",
|
|
27
|
+
]
|