Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
5975c08fb2 | |||
47feebe22f | |||
11fe47bef1 | |||
f33643955b | |||
41353b9a54 |
@ -133,7 +133,7 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
if self.column_checkBox.isChecked() and self.line_spinBox.isEnabled():
|
if self.column_checkBox.isChecked() and self.line_spinBox.isEnabled():
|
||||||
header_line = self.reader.header[self.line_spinBox.value()-1]
|
header_line = self.reader.header[self.line_spinBox.value()-1]
|
||||||
header_line = header_line.strip('\n\t\r, ')
|
header_line = header_line.strip('\n\t\r, ')
|
||||||
header_line = re.sub(r'[\t ;,]+', ';', header_line)
|
header_line = re.sub(r'[\t, ;]+(?!\w*})', ';', header_line)
|
||||||
|
|
||||||
self.ascii_table.setHorizontalHeaderLabels(header_line.split(';'))
|
self.ascii_table.setHorizontalHeaderLabels(header_line.split(';'))
|
||||||
|
|
||||||
|
16
src/nmreval/clib/diffusion.c
Normal file
16
src/nmreval/clib/diffusion.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/* integrands used in quadrature integration with scipy's LowLevelCallables */
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
double anistropicDiffusion(double x, void *user_data) {
|
||||||
|
double *c = (double *)user_data;
|
||||||
|
|
||||||
|
double q = c[0];
|
||||||
|
double t = c[1];
|
||||||
|
double d_perp = c[2];
|
||||||
|
double d_par = c[3];
|
||||||
|
|
||||||
|
double cos_theta = cos(x);
|
||||||
|
double sin_theta = sin(x);
|
||||||
|
|
||||||
|
return exp(-q * q * t * (d_par * cos_theta * cos_theta + d_perp * sin_theta * sin_theta)) * sin_theta;
|
||||||
|
}
|
BIN
src/nmreval/clib/diffusion.so
Executable file
BIN
src/nmreval/clib/diffusion.so
Executable file
Binary file not shown.
@ -5,6 +5,17 @@ from ctypes import CDLL, c_double, c_void_p
|
|||||||
from ..lib.logger import logger
|
from ..lib.logger import logger
|
||||||
|
|
||||||
|
|
||||||
|
diffusion_lib = None
|
||||||
|
try:
|
||||||
|
diffusion_lib = CDLL(str(Path(__file__).parents[1] / 'clib' / 'diffusion.so'))
|
||||||
|
|
||||||
|
diffusion_lib.anistropicDiffusion.restype = c_double
|
||||||
|
diffusion_lib.anistropicDiffusion.argtypes = (c_double, c_void_p)
|
||||||
|
|
||||||
|
HAS_C_FUNCS = True
|
||||||
|
except OSError:
|
||||||
|
HAS_C_FUNCS = False
|
||||||
|
|
||||||
lib = None
|
lib = None
|
||||||
try:
|
try:
|
||||||
lib = CDLL(str(Path(__file__).parents[1] / 'clib' / 'integrate.so'))
|
lib = CDLL(str(Path(__file__).parents[1] / 'clib' / 'integrate.so'))
|
||||||
@ -39,10 +50,8 @@ try:
|
|||||||
lib.energyDistSuscImag.restype = c_double
|
lib.energyDistSuscImag.restype = c_double
|
||||||
lib.energyDistSuscImag.argtypes = (c_double, c_void_p)
|
lib.energyDistSuscImag.argtypes = (c_double, c_void_p)
|
||||||
|
|
||||||
|
|
||||||
HAS_C_FUNCS = True
|
HAS_C_FUNCS = True
|
||||||
logger.info('Use C functions')
|
logger.info('Use C functions')
|
||||||
except OSError:
|
except OSError:
|
||||||
HAS_C_FUNCS = False
|
HAS_C_FUNCS = False
|
||||||
logger.info('Use python functions')
|
logger.info('Use python functions')
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ class AsciiReader:
|
|||||||
with self.fname.open('r') as f:
|
with self.fname.open('r') as f:
|
||||||
for i, line in enumerate(islice(f, len(self.header)+len(self.lines), num_lines)):
|
for i, line in enumerate(islice(f, len(self.header)+len(self.lines), num_lines)):
|
||||||
line = line.strip('\n\t\r, ')
|
line = line.strip('\n\t\r, ')
|
||||||
line = re.sub(r'[\t ;,]+', ';', line)
|
line = re.sub(r'[\t, ;]+(?!\w*})', ';', line)
|
||||||
line = line.split(';')
|
line = line.split(';')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -146,10 +146,11 @@ class AsciiReader:
|
|||||||
raw_data = raw_data.reshape((1, *raw_data.shape))
|
raw_data = raw_data.reshape((1, *raw_data.shape))
|
||||||
|
|
||||||
if len(x) == 0 or raw_data.shape[2] == 1:
|
if len(x) == 0 or raw_data.shape[2] == 1:
|
||||||
_temp = np.zeros((raw_data.shape[0], raw_data.shape[1], raw_data.shape[2]+1))
|
raw_data = raw_data.reshape(raw_data.shape[0], raw_data.shape[2], raw_data.shape[1])
|
||||||
_temp[:, :, 0] = np.arange(raw_data.shape[1])
|
# _temp = np.zeros((raw_data.shape[0], raw_data.shape[2], raw_data.shape[1]))
|
||||||
_temp[:, :, 1:] = raw_data
|
# _temp[:, :, 0] = np.arange(raw_data.shape[1])
|
||||||
raw_data = _temp
|
# _temp[:, :, 1:] = raw_data
|
||||||
|
# raw_data = _temp
|
||||||
|
|
||||||
if y:
|
if y:
|
||||||
y = [i+1 for i in y]
|
y = [i+1 for i in y]
|
||||||
|
@ -302,15 +302,26 @@ class HdfReader(HdfNode):
|
|||||||
|
|
||||||
def make_signal(self, node, flag: str = 'fid', value: str = None, group: str = None):
|
def make_signal(self, node, flag: str = 'fid', value: str = None, group: str = None):
|
||||||
if value is None:
|
if value is None:
|
||||||
|
data_name = node.name
|
||||||
value = self._get_parameter_values(node, node.parameter)
|
value = self._get_parameter_values(node, node.parameter)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
|
data_name = f"{value}={node.parameter[value]}"
|
||||||
value = node.parameter[value]
|
value = node.parameter[value]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
print(node.title_parameter)
|
||||||
try:
|
try:
|
||||||
value = node.title_parameter[1][value]
|
temp = node
|
||||||
|
while value != temp.title_parameter[0][0]:
|
||||||
|
if temp.parent is None:
|
||||||
|
break
|
||||||
|
temp = temp.parent
|
||||||
|
|
||||||
|
value = temp.title_parameter[0][1]
|
||||||
|
data_name = temp.name
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print(f'{value} is not a valid key for {node.name}')
|
print(f'{value} is not a valid key for {node.name}')
|
||||||
|
data_name = node.name
|
||||||
value = None
|
value = None
|
||||||
|
|
||||||
if group is None:
|
if group is None:
|
||||||
@ -343,11 +354,11 @@ class HdfReader(HdfNode):
|
|||||||
dw = float(index['dwelltime'])
|
dw = float(index['dwelltime'])
|
||||||
if flag == 'fid':
|
if flag == 'fid':
|
||||||
x = np.arange(len(y)) * dw
|
x = np.arange(len(y)) * dw
|
||||||
ret = FID(x, y, name=node.name, value=value, group=group, filename=self.file.filename)
|
ret = FID(x, y, name=data_name, value=value, group=group, filename=self.file.filename)
|
||||||
|
|
||||||
elif flag == 'spectrum':
|
elif flag == 'spectrum':
|
||||||
x = np.linspace(-1/dw, 1/dw, num=len(y))
|
x = np.linspace(-1/dw, 1/dw, num=len(y))
|
||||||
ret = Spectrum(x, y, name=node.name, value=value, group=group, filename=self.file.filename)
|
ret = Spectrum(x, y, name=data_name, value=value, group=group, filename=self.file.filename)
|
||||||
else:
|
else:
|
||||||
raise ValueError(f'{flag} unknown, use `fid` or `spectrum`.')
|
raise ValueError(f'{flag} unknown, use `fid` or `spectrum`.')
|
||||||
|
|
||||||
|
@ -203,6 +203,31 @@ class Sinc:
|
|||||||
return c * np.sinc(((x-x0)/w)/np.pi)
|
return c * np.sinc(((x-x0)/w)/np.pi)
|
||||||
|
|
||||||
|
|
||||||
|
class Sigmoid:
|
||||||
|
type = 'Basic'
|
||||||
|
name = 'Sigmoid'
|
||||||
|
equation = 'C / [1 + exp(-a * (x - x_{0})] + y_{0}'
|
||||||
|
params = ['C', 'a', 'x_{0}', 'y_{0}']
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def func(x, c, a, x0, y0):
|
||||||
|
"""
|
||||||
|
Sigmoid function
|
||||||
|
|
||||||
|
.. math::
|
||||||
|
y = C / [1 + exp(-a * (x - x_0))] + y_0
|
||||||
|
|
||||||
|
Args:
|
||||||
|
x (array_like): Input values
|
||||||
|
c (float): Prefactor
|
||||||
|
a (float): Steepness of the sigmoid
|
||||||
|
x0 (float): x position of the sigmoid's midpoint
|
||||||
|
y0 (float): y position of the sigmoid's midpoint
|
||||||
|
|
||||||
|
"""
|
||||||
|
return c / (1 + np.exp(-a * (x - x0))) + y0
|
||||||
|
|
||||||
|
|
||||||
class Sine:
|
class Sine:
|
||||||
"""
|
"""
|
||||||
Wavy sine function
|
Wavy sine function
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
|
from ctypes import c_double, cast, c_void_p, pointer
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy import special as special
|
from scipy import special as special, LowLevelCallable
|
||||||
|
from scipy.integrate import quad
|
||||||
|
|
||||||
from ..utils import gamma
|
from ..utils import gamma
|
||||||
|
from nmreval.distributions.helper import HAS_C_FUNCS, diffusion_lib
|
||||||
|
|
||||||
|
|
||||||
class Diffusion:
|
class Diffusion:
|
||||||
@ -103,20 +107,36 @@ class AnisotropicDiffusion(object):
|
|||||||
tp = x
|
tp = x
|
||||||
relax = np.exp(-(tp/trel)**brel)*np.exp(-(tp/trel)**brel)
|
relax = np.exp(-(tp/trel)**brel)*np.exp(-(tp/trel)**brel)
|
||||||
|
|
||||||
q_squared = np.power(g * nucleus * tp, 2)
|
q = g * nucleus * tp
|
||||||
t = 2 * tp / 3 + tm
|
t = 2 * tp / 3 + tm
|
||||||
z = np.sqrt(q_squared * (d_par - d_perp) * t)
|
|
||||||
# Callaghan eq (6.89)
|
# Callaghan eq (6.89)
|
||||||
diffs = np.exp(-q_squared*t*d_perp) * special.erf(z) / z
|
if HAS_C_FUNCS:
|
||||||
|
# divide by 2 to normalize by integral sin(x), x=0..pi
|
||||||
|
diffusion_decay = AnisotropicDiffusion._integrate_c(q, t, d_perp, d_par) / 2
|
||||||
|
else:
|
||||||
|
z = np.sqrt(q**2 * (d_par - d_perp) * t)
|
||||||
|
diffusion_decay = np.exp(-q**2 * t * d_perp) * special.erf(z) / z
|
||||||
|
|
||||||
return m0 * diffs * relax
|
return m0 * diffusion_decay * relax
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _integrate_c(q, t, d_perp, d_par) -> np.ndarray:
|
||||||
|
diffusion_decay = np.zeros_like(t)
|
||||||
|
|
||||||
|
for (i, t_i) in enumerate(t):
|
||||||
|
c = (c_double * 4)(q, t_i, d_perp, d_par)
|
||||||
|
user_data = cast(pointer(c), c_void_p)
|
||||||
|
|
||||||
|
diffusion_decay[i] = quad(LowLevelCallable(diffusion_lib.anistropicDiffusion, user_data), 0, np.pi, epsabs=1e-13)[0]
|
||||||
|
|
||||||
|
return diffusion_decay
|
||||||
|
|
||||||
|
|
||||||
class Peschier:
|
class Peschier:
|
||||||
name = 'Diffusion + Cross-Relaxation'
|
name = 'Diffusion + Cross-Relaxation'
|
||||||
type = 'Diffusion'
|
type = 'Diffusion'
|
||||||
equation = r'Diffusion with cross-relax f(ast) \rightarrow s(low)'
|
equation = r'Diffusion with cross-relax f(ast) \rightarrow s(low)'
|
||||||
params = ['M_{0}', 'D', 'T_{1,f}', 'T_{1,s}', 'k', 'p_{f}', 't_{ev}', 'g']
|
params = ['M_{0}', 'D', 'T_{1f}', 'T_{1s}', 'k', 'p_{f}', 't_{ev}', 'g']
|
||||||
bounds = [(0, None), (0, None), (0, None), (0, None), (0, None), (0, None)]
|
bounds = [(0, None), (0, None), (0, None), (0, None), (0, None), (0, None)]
|
||||||
choices = [(r'\gamma', 'nucleus', gamma)]
|
choices = [(r'\gamma', 'nucleus', gamma)]
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ class TwoSatRecAbsolute:
|
|||||||
type = 'Relaxation'
|
type = 'Relaxation'
|
||||||
name = 'Two-step relaxation (abs. int)'
|
name = 'Two-step relaxation (abs. int)'
|
||||||
equation = r'M_{0} + \Sigma \DeltaM_{i}(1-exp(-(x/T_{1,i})^{\beta_{i}}))'
|
equation = r'M_{0} + \Sigma \DeltaM_{i}(1-exp(-(x/T_{1,i})^{\beta_{i}}))'
|
||||||
params = [r'\DeltaM_{1}', 'T_{1,1}', r'\beta_{1}', r'\DeltaM_{2}', 'T_{1,2}', r'\beta_{2}', 'M_{0}']
|
params = [r'\DeltaM_{1}', 'T_{11}', r'\beta_{1}', r'\DeltaM_{2}', 'T_{12}', r'\beta_{2}', 'M_{0}']
|
||||||
choices = [('Type', 'is_inv', {'Saturation': False, 'Inversion': True})]
|
choices = [('Type', 'is_inv', {'Saturation': False, 'Inversion': True})]
|
||||||
bounds = [(0, None), (0, None), (0, 1), (0, None), (0, None), (0, 1), (None, None)]
|
bounds = [(0, None), (0, None), (0, 1), (0, None), (0, None), (0, 1), (None, None)]
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ class TwoSatRecRelative:
|
|||||||
name = 'Two-step relaxation (rel. int)'
|
name = 'Two-step relaxation (rel. int)'
|
||||||
equation = r'M_{0} + \DeltaM[R(1-exp(-(x/T_{1,1})^{\beta_{1}})) + \n'\
|
equation = r'M_{0} + \DeltaM[R(1-exp(-(x/T_{1,1})^{\beta_{1}})) + \n'\
|
||||||
r'(1-R)(1-exp(-(x/T_{1,2})^{\beta_{2}}))]'
|
r'(1-R)(1-exp(-(x/T_{1,2})^{\beta_{2}}))]'
|
||||||
params = [r'\DeltaM', 'M_{0}', 'T_{1,1}', r'\beta_{1}', 'T_{1,2}', r'\beta_{2}', 'R']
|
params = [r'\DeltaM', 'M_{0}', 'T_{11}', r'\beta_{1}', 'T_{12}', r'\beta_{2}', 'R']
|
||||||
choices = [('Type', 'kind', {'Saturation': 'sat', 'Inversion': 'inv'})]
|
choices = [('Type', 'kind', {'Saturation': 'sat', 'Inversion': 'inv'})]
|
||||||
bounds = [(0, None), (None, None), (0, None), (0, 1), (0, None), (0, 1), (0, 1)]
|
bounds = [(0, None), (None, None), (0, None), (0, 1), (0, None), (0, 1), (0, 1)]
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user