1
0
forked from IPKM/nmreval

Compare commits

...

2 Commits

Author SHA1 Message Date
f33643955b 304-fitparameter (#305)
fixes #304

Co-authored-by: Dominik Demuth <dominik.demuth@physik.tu-darmstadt.de>
Reviewed-on: IPKM/nmreval#305
2025-01-23 18:11:45 +00:00
41353b9a54 wide-line spectra handle missing x values better (#303)
see issue #302

Co-authored-by: Dominik Demuth <dominik.demuth@physik.tu-darmstadt.de>
Reviewed-on: IPKM/nmreval#303
2024-12-09 13:45:07 +00:00
6 changed files with 91 additions and 52 deletions

View File

@ -133,7 +133,7 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
if self.column_checkBox.isChecked() and self.line_spinBox.isEnabled():
header_line = self.reader.header[self.line_spinBox.value()-1]
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(';'))

View File

@ -542,7 +542,9 @@ class UpperManagement(QtCore.QObject):
elif fit_limits[0] == 'in':
inside = np.where((_x >= fit_limits[1][0]) & (_x <= fit_limits[1][1]))
else:
inside = np.where((_x < fit_limits[1][0]) | (_x > fit_limits[1][1]))
x_lim, _ = self.graphs[self.current_graph].ranges
inside_graph = (_x >= x_lim[0]) & (_x <= x_lim[1])
inside = np.where(((_x < fit_limits[1][0]) | (_x > fit_limits[1][1])) & inside_graph)
try:
if isinstance(we, str):

View File

@ -49,7 +49,7 @@ class AsciiReader:
with self.fname.open('r') as f:
for i, line in enumerate(islice(f, len(self.header)+len(self.lines), num_lines)):
line = line.strip('\n\t\r, ')
line = re.sub(r'[\t ;,]+', ';', line)
line = re.sub(r'[\t, ;]+(?!\w*})', ';', line)
line = line.split(';')
try:
@ -146,10 +146,11 @@ class AsciiReader:
raw_data = raw_data.reshape((1, *raw_data.shape))
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))
_temp[:, :, 0] = np.arange(raw_data.shape[1])
_temp[:, :, 1:] = raw_data
raw_data = _temp
raw_data = raw_data.reshape(raw_data.shape[0], raw_data.shape[2], raw_data.shape[1])
# _temp = np.zeros((raw_data.shape[0], raw_data.shape[2], raw_data.shape[1]))
# _temp[:, :, 0] = np.arange(raw_data.shape[1])
# _temp[:, :, 1:] = raw_data
# raw_data = _temp
if y:
y = [i+1 for i in y]

View File

@ -116,7 +116,7 @@ class Peschier:
name = 'Diffusion + Cross-Relaxation'
type = 'Diffusion'
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)]
choices = [(r'\gamma', 'nucleus', gamma)]

View File

@ -75,7 +75,7 @@ class TwoSatRecAbsolute:
type = 'Relaxation'
name = 'Two-step relaxation (abs. int)'
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})]
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)'
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}}))]'
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'})]
bounds = [(0, None), (None, None), (0, None), (0, 1), (0, None), (0, 1), (0, 1)]

View File

@ -3,11 +3,42 @@ try:
from scipy.integrate import simpson
except ImportError:
from scipy.integrate import simps as simpson
from numpy import pi
from ..math.orientations import zcw_spherical as crystallites
__all__ = ['CSA', 'Pake', 'SecCentralLine']
def _make_broadening(x: np.ndarray, sigma: float, mode: str):
dx = x[1] - x[0]
_x = np.arange(len(x)) * dx
_x -= 0.5 * _x[-1]
if mode == 'l':
apd = 2 * sigma / (4*_x**2 + sigma**2) / np.pi
else:
ln2 = np.log(2)
apd = np.exp(-4*ln2 * (_x/sigma)**2) * 2 * np.sqrt(ln2/np.pi) / sigma
return apd
def _make_bins(x: np.ndarray) -> np.ndarray:
bins = 0.5 * (x[1:] + x[:-1])
return np.r_[0.5 * (-x[1] + 3 * x[0]), bins, 0.5 * (3 * x[-1] - x[-2])]
def _make_x(x: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
_x = x
dx = x[1:] - x[:-1]
dx = np.min(dx)
width = x[-1] - x[0]
_x = np.arange(width/dx - 1) * dx + x[0]
bins = (_x[1:] + _x[:-1]) / 2
bins = np.r_[_x[0]-dx/2, bins, _x[-1] + dx/2]
return _x, bins
class Pake:
type = 'Spectrum'
name = 'Pake'
@ -17,38 +48,39 @@ class Pake:
choices = [('Broadening', 'broad', {'Gaussian': 'g', 'Lorentzian': 'l'})]
@staticmethod
def func(x, c, delta, eta, sigma, t_pulse, broad='g'):
def func(
x: np.ndarray,
c: float,
delta: float,
eta: float,
sigma: float,
t_pulse: float,
broad: str = 'g',
) -> np.ndarray:
a, b, _ = crystallites(100000)
bins = 0.5 * (x[1:] + x[:-1])
bins = np.r_[0.5*(3*x[0]-x[1]), bins, 0.5*(3*x[-1]-x[-2])]
omega = delta * 0.5 * (3*np.cos(b)**2 - 1 - eta * np.sin(b)**2 * np.cos(2*a))
x_used, bins = _make_x(x)
s_left = np.histogram(omega, bins=bins)[0]
s_right = np.histogram(-omega, bins=bins)[0]
s = s_left + s_right
if sigma != 0:
_x = np.arange(len(x))*(x[1]-x[0])
_x -= 0.5*_x[-1]
if broad == 'l':
apd = 2 * sigma / (4 * _x**2 + sigma**2) / pi
else:
apd = np.exp(-4 * np.log(2) * (_x/sigma)**2) * 2 * np.sqrt(np.log(2) / pi) / sigma
apd = _make_broadening(x_used, sigma, broad)
ret_val = np.convolve(s, apd, mode='same')
else:
ret_val = s
omega_1 = pi/2/t_pulse
attn = omega_1 * np.sin(t_pulse*np.sqrt(omega_1**2+0.5*(2*pi*x)**2)) / \
np.sqrt(omega_1**2+(np.pi*x)**2)
omega_1 = np.pi/2/t_pulse
attn = omega_1 * np.sin(t_pulse*np.sqrt(omega_1**2 + 0.5*(2*np.pi*x_used)**2)) / np.sqrt(omega_1**2 + (np.pi*x_used)**2)
ret_val *= attn
ret_val /= simpson(y=ret_val, x=x_used)
return c * ret_val / simpson(ret_val, x)
if x_used.size == x.size:
return c * ret_val
else:
return c * np.interp(x=x, xp=x_used, fp=ret_val)
class CSA:
@ -60,28 +92,29 @@ class CSA:
choices = [('Broadening', 'broad', {'Gaussian': 'g', 'Lorentzian': 'l'})]
@staticmethod
def func(x, c, delta, eta, w_iso, sigma, broad='g'):
def func(
x: np.ndarray,
c: float,
delta: float,
eta: float,
w_iso: float,
sigma: float,
broad: str = 'g',
) -> np.ndarray:
a, b, _ = crystallites(100000)
bins = 0.5 * (x[1:] + x[:-1])
bins = np.r_[0.5*(-x[1] + 3*x[0]), bins, 0.5*(3*x[-1] - x[-2])]
omega = w_iso + delta * 0.5 * (3*np.cos(b)**2 - 1 - eta * np.sin(b)**2 * np.cos(2*a))
s_left = np.histogram(omega, bins=bins)[0]
s = s_left
s = np.histogram(omega, bins=_make_bins(x))[0]
if sigma != 0:
_x = np.arange(len(x)) * (x[1] - x[0])
_x -= 0.5 * _x[-1]
if broad == 'l':
apd = 2 * sigma / (4*_x**2 + sigma**2) / pi
else:
apd = np.exp(-4 * np.log(2) * (_x / sigma) ** 2) * 2 * np.sqrt(np.log(2) / pi) / sigma
print(len(s))
apd = _make_broadening(x, sigma, broad)
ret_val = np.convolve(s, apd, mode='same')
else:
ret_val = s
return c * ret_val / simpson(ret_val, x)
return c * ret_val / simpson(y=ret_val, x=x)
class SecCentralLine:
@ -94,10 +127,18 @@ class SecCentralLine:
('Broadening', 'broad', {'Gaussian': 'g', 'Lorentzian': 'l'})]
@staticmethod
def func(x, c, cq, eta, f_iso, gb, f_l, spin=2.5, broad='g'):
def func(
x: np.ndarray,
c: float,
cq: float,
eta: float,
f_iso: float,
gb: float,
f_l: float,
spin: float = 2.5,
broad: str = 'g',
) -> np.ndarray:
a, b, _ = crystallites(200000)
bins = 0.5 * (x[1:] + x[:-1])
bins = np.r_[0.5*(-x[1] + 3*x[0]), bins, 0.5*(3*x[-1] - x[-2])]
# coupling constant
omega_q = 2 * np.pi * cq / (2*spin*(2*spin-1))
@ -116,17 +157,12 @@ class SecCentralLine:
orient += prefactor_c
omega = 2*np.pi*f_iso + coupling * orient
s = np.histogram(omega / (2*np.pi), bins=bins)[0]
s = np.histogram(omega / (2*np.pi), bins=_make_bins(x))[0]
if gb != 0:
_x = np.arange(len(x)) * (x[1]-x[0])
_x -= 0.5*_x[-1]
if broad == 'l':
apd = 2*gb / (4*_x**2 + gb**2) / np.pi
else:
apd = np.exp(-4*np.log(2) * (_x/gb)**2) * 2 * np.sqrt(np.log(2)/np.pi) / gb
apd = _make_broadening(x, gb, broad)
ret_val = np.convolve(s, apd, mode='same')
else:
ret_val = s
return c * ret_val / simpson(ret_val, x)
return c * ret_val / simpson(y=ret_val, x=x)