dev #297
@ -31,7 +31,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
self.t1calculator = RelaxationEvaluation()
|
self.t1calculator = RelaxationEvaluation()
|
||||||
|
|
||||||
self.sd_parameter = []
|
self.sd_parameter = []
|
||||||
self.sdmodels = [Debye, ColeCole, ColeDavidson, KWW, HavriliakNegami, LogGaussian]
|
self.sdmodels = [Debye, ColeCole, ColeDavidson, KWW, HavriliakNegami, LogGaussian, GGAlpha]
|
||||||
for i in self.sdmodels:
|
for i in self.sdmodels:
|
||||||
self.specdens_combobox.addItem(i.name)
|
self.specdens_combobox.addItem(i.name)
|
||||||
self.specdens_combobox.currentIndexChanged.connect(self.update_specdens)
|
self.specdens_combobox.currentIndexChanged.connect(self.update_specdens)
|
||||||
@ -51,8 +51,14 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
self.conv_y = QT1Widget.time_conversion[self.t1_combobox.currentIndex()]
|
self.conv_y = QT1Widget.time_conversion[self.t1_combobox.currentIndex()]
|
||||||
|
|
||||||
self.minimum = (1, np.inf)
|
self.minimum = (1, np.inf)
|
||||||
self.min_pos = PlotItem(x=np.array([]), y=np.array([]),
|
self.min_pos = PlotItem(
|
||||||
symbol='+', symbolBrush=mkBrush(color='r'), symbolPen=mkPen(color='r'), symbolSize=14)
|
x=np.array([]),
|
||||||
|
y=np.array([]),
|
||||||
|
symbol='+',
|
||||||
|
symbolBrush=mkBrush(color='r'),
|
||||||
|
symbolPen=mkPen(color='r'),
|
||||||
|
symbolSize=14,
|
||||||
|
)
|
||||||
self.parabola = PlotItem(x=np.array([]), y=np.array([]))
|
self.parabola = PlotItem(x=np.array([]), y=np.array([]))
|
||||||
|
|
||||||
self.lineEdit_2.setValidator(QtGui.QDoubleValidator())
|
self.lineEdit_2.setValidator(QtGui.QDoubleValidator())
|
||||||
@ -83,10 +89,10 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
right_b = min(np.argmin(y)+3, len(x)-1)
|
right_b = min(np.argmin(y)+3, len(x)-1)
|
||||||
|
|
||||||
self.lineEdit_2.blockSignals(True)
|
self.lineEdit_2.blockSignals(True)
|
||||||
self.lineEdit_2.setText('{:.2f}'.format(x[left_b]))
|
self.lineEdit_2.setText(f'{x[left_b]:.2f}')
|
||||||
self.lineEdit_2.blockSignals(False)
|
self.lineEdit_2.blockSignals(False)
|
||||||
self.lineEdit_3.blockSignals(True)
|
self.lineEdit_3.blockSignals(True)
|
||||||
self.lineEdit_3.setText('{:.2f}'.format(x[right_b]))
|
self.lineEdit_3.setText(f'{x[right_b]:.2f}')
|
||||||
self.lineEdit_3.blockSignals(False)
|
self.lineEdit_3.blockSignals(False)
|
||||||
|
|
||||||
self.t1calculator.set_data(x, y)
|
self.t1calculator.set_data(x, y)
|
||||||
@ -110,6 +116,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
|
|
||||||
if self.sdmodels[idx].parameter is not None:
|
if self.sdmodels[idx].parameter is not None:
|
||||||
for name in self.sdmodels[idx].parameter:
|
for name in self.sdmodels[idx].parameter:
|
||||||
|
print(name)
|
||||||
_temp = FormWidget(parent=self, name=name, fixable=True)
|
_temp = FormWidget(parent=self, name=name, fixable=True)
|
||||||
_temp.value = 1
|
_temp.value = 1
|
||||||
_temp.setChecked(True)
|
_temp.setChecked(True)
|
||||||
@ -133,7 +140,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
try:
|
try:
|
||||||
for i, v, in enumerate(values):
|
for i, v, in enumerate(values):
|
||||||
self.sd_parameter[i].blockSignals(True)
|
self.sd_parameter[i].blockSignals(True)
|
||||||
self.sd_parameter[i].value = '{:.3g}'.format(round(v, 3))
|
self.sd_parameter[i].value = f'{v:.3g}'
|
||||||
self.sd_parameter[i].blockSignals(False)
|
self.sd_parameter[i].blockSignals(False)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
@ -219,7 +226,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
self.update_model()
|
self.update_model()
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_interpol_combobox_currentIndexChanged')
|
@QtCore.pyqtSlot(int, name='on_interpol_combobox_currentIndexChanged')
|
||||||
def determine_minimum(self, idx):
|
def determine_minimum(self, idx: int):
|
||||||
if idx == 0:
|
if idx == 0:
|
||||||
self.checkBox_interpol.setChecked(False)
|
self.checkBox_interpol.setChecked(False)
|
||||||
self.checkBox_interpol.hide()
|
self.checkBox_interpol.hide()
|
||||||
@ -229,9 +236,10 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
self.checkBox_interpol.show()
|
self.checkBox_interpol.show()
|
||||||
self.frame.show()
|
self.frame.show()
|
||||||
try:
|
try:
|
||||||
m, i_func = self.t1calculator.calculate_t1_min(interpolate=idx,
|
m, i_func = self.t1calculator.calculate_t1_min(
|
||||||
trange=(float(self.lineEdit_2.text()),
|
interpolate=idx,
|
||||||
float(self.lineEdit_3.text())))
|
trange=(float(self.lineEdit_2.text()), float(self.lineEdit_3.text())),
|
||||||
|
)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
m, i_func = self.t1calculator.calculate_t1_min(interpolate=None)
|
m, i_func = self.t1calculator.calculate_t1_min(interpolate=None)
|
||||||
|
|
||||||
@ -273,11 +281,13 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
with busy_cursor():
|
with busy_cursor():
|
||||||
calc_stretching, mini = self.t1calculator.get_increase(height=self.minimum[1],
|
calc_stretching, mini = self.t1calculator.get_increase(
|
||||||
|
height=self.minimum[1],
|
||||||
idx=var_idx, mode=notfix,
|
idx=var_idx, mode=notfix,
|
||||||
omega=2*np.pi*self.frequency,
|
omega=2*np.pi*self.frequency,
|
||||||
dist_parameter=sd_args, prefactor=cp_args,
|
dist_parameter=sd_args, prefactor=cp_args,
|
||||||
coupling_kwargs=cp_kwargs)
|
coupling_kwargs=cp_kwargs
|
||||||
|
)
|
||||||
|
|
||||||
self.label_t1min.setText(f'{mini:.4g} s')
|
self.label_t1min.setText(f'{mini:.4g} s')
|
||||||
|
|
||||||
@ -292,9 +302,13 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
sd_args, _ = self.get_sd_values()
|
sd_args, _ = self.get_sd_values()
|
||||||
cp_args, cp_kwargs, _ = self.get_cp_values()
|
cp_args, cp_kwargs, _ = self.get_cp_values()
|
||||||
tau_mode = ['fit', 'peak', 'mean', 'logmean'][self.tau_combox.currentIndex()]
|
tau_mode = ['fit', 'peak', 'mean', 'logmean'][self.tau_combox.currentIndex()]
|
||||||
corr, opts = self.t1calculator.correlation_from_t1(omega=2*np.pi*self.frequency, dist_parameter=sd_args,
|
corr, opts = self.t1calculator.correlation_from_t1(
|
||||||
|
omega=2*np.pi*self.frequency,
|
||||||
|
dist_parameter=sd_args,
|
||||||
coupling_param=cp_args, coupling_kwargs=cp_kwargs,
|
coupling_param=cp_args, coupling_kwargs=cp_kwargs,
|
||||||
mode=tau_mode, interpolate=self.checkBox_interpol.isChecked())
|
mode=tau_mode,
|
||||||
|
interpolate=self.checkBox_interpol.isChecked()
|
||||||
|
)
|
||||||
|
|
||||||
name = self.name + '-' + str(self.t1calculator) + '('
|
name = self.name + '-' + str(self.t1calculator) + '('
|
||||||
name += ','.join([f'{a:.3g}' for a in sd_args])
|
name += ','.join([f'{a:.3g}' for a in sd_args])
|
||||||
@ -332,4 +346,4 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_graph_checkbox_stateChanged')
|
@QtCore.pyqtSlot(int, name='on_graph_checkbox_stateChanged')
|
||||||
def changed_state(self, checked):
|
def changed_state(self, checked):
|
||||||
self.graph_combobox.setEnabled(checked != QtCore.Qt.Checked)
|
self.graph_combobox.setEnabled(checked != QtCore.Qt.CheckState.Checked)
|
||||||
|
@ -26,3 +26,4 @@ from .coledavidson import ColeDavidson
|
|||||||
from .debye import Debye
|
from .debye import Debye
|
||||||
from .kww import KWW
|
from .kww import KWW
|
||||||
from .loggaussian import LogGaussian
|
from .loggaussian import LogGaussian
|
||||||
|
from .gengamma import GGAlpha
|
||||||
|
@ -20,10 +20,10 @@ class AbstractGG(Distribution, ABC):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def correlation(cls, t, tau0, *args):
|
def correlation(cls, t, tau0, *args):
|
||||||
tt = np.asanyarray(t)
|
tt = np.atleast_1d(t)
|
||||||
taus, ln_tau = AbstractGG._prepare_integration(tau0)
|
taus, ln_tau = AbstractGG._prepare_integration(tau0)
|
||||||
g_tau = cls.distribution(taus, tau0, *args)
|
g_tau = cls.distribution(taus, tau0, *args)
|
||||||
ret_val = np.array([simpson(np.exp(-t_i/taus) * g_tau, ln_tau) for t_i in tt])
|
ret_val = np.array([simpson(np.exp(-t_i/taus) * g_tau, ln_tau) for t_i in tt]).squeeze()
|
||||||
|
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
@ -32,11 +32,11 @@ class AbstractGG(Distribution, ABC):
|
|||||||
r"""
|
r"""
|
||||||
Calculate spectral density \int G(ln(tau) tau/(1+(w*tau)^2) dln(tau)
|
Calculate spectral density \int G(ln(tau) tau/(1+(w*tau)^2) dln(tau)
|
||||||
"""
|
"""
|
||||||
w = np.asanyarray(omega)
|
w = np.atleast_1d(omega)
|
||||||
taus, ln_tau = AbstractGG._prepare_integration(tau0)
|
taus, ln_tau = AbstractGG._prepare_integration(tau0)
|
||||||
g_tau = cls.distribution(taus, tau0, *args)
|
g_tau = cls.distribution(taus, tau0, *args)
|
||||||
|
|
||||||
ret_val = np.array([simpson(g_tau / (1 - 1j*w_i*taus), ln_tau) for w_i in w])
|
ret_val = np.array([simpson(g_tau / (1 - 1j*w_i*taus), ln_tau) for w_i in w]).squeeze()
|
||||||
|
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
@ -45,17 +45,23 @@ class AbstractGG(Distribution, ABC):
|
|||||||
r"""
|
r"""
|
||||||
Calculate spectral density \int G(ln(tau) tau/(1+(w*tau)^2) dln(tau)
|
Calculate spectral density \int G(ln(tau) tau/(1+(w*tau)^2) dln(tau)
|
||||||
"""
|
"""
|
||||||
w = np.asanyarray(omega)
|
w = np.atleast_1d(omega)
|
||||||
taus, ln_tau = AbstractGG._prepare_integration(tau0)
|
_t = np.atleast_1d(tau0)
|
||||||
g_tau = cls.distribution(taus, tau0, *args)
|
ret_val = np.zeros((w.size, _t.size))
|
||||||
|
|
||||||
ret_val = np.array([simpson(g_tau * taus / (1 + (w_i*taus)**2), ln_tau) for w_i in w])
|
for i, tau_i in enumerate(_t):
|
||||||
|
taus, ln_tau = AbstractGG._prepare_integration(tau_i)
|
||||||
|
g_tau = cls.distribution(taus, tau_i, *args)
|
||||||
|
|
||||||
return ret_val
|
ret_val[:, i] = np.array([simpson(g_tau * taus / (1 + (w_i*taus)**2), ln_tau) for w_i in w]).squeeze()
|
||||||
|
|
||||||
|
return ret_val.squeeze()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _prepare_integration(
|
def _prepare_integration(
|
||||||
tau0: float, limits: tuple[int, int] = (20, 20), num_steps: int = 4001
|
tau0: float,
|
||||||
|
limits: tuple[int, int] = (20, 20),
|
||||||
|
num_steps: int = 4001,
|
||||||
) -> tuple[np.ndarray, np.ndarray]:
|
) -> tuple[np.ndarray, np.ndarray]:
|
||||||
"""
|
"""
|
||||||
Create array of correlation times for integration over ln(tau)
|
Create array of correlation times for integration over ln(tau)
|
||||||
@ -77,8 +83,8 @@ class AbstractGG(Distribution, ABC):
|
|||||||
|
|
||||||
# noinspection PyMethodOverriding
|
# noinspection PyMethodOverriding
|
||||||
class GGAlpha(AbstractGG):
|
class GGAlpha(AbstractGG):
|
||||||
name = r'General \Gamma (\alpha)'
|
name = r'General Gamma (alpha)'
|
||||||
parameter = [r'\tau', r'\alpha', r'\beta']
|
parameter = [r'\alpha', r'\beta']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def distribution(taus: float | np.ndarray, tau: float, alpha: float, beta: float) -> float | np.ndarray:
|
def distribution(taus: float | np.ndarray, tau: float, alpha: float, beta: float) -> float | np.ndarray:
|
||||||
@ -92,8 +98,8 @@ class GGAlpha(AbstractGG):
|
|||||||
|
|
||||||
# noinspection PyMethodOverriding
|
# noinspection PyMethodOverriding
|
||||||
class GGAlphaEW(AbstractGG):
|
class GGAlphaEW(AbstractGG):
|
||||||
name = r'General \Gamma (\alpha + EW)'
|
name = r'General Gamma (alpha + EW)'
|
||||||
parameter = [r'\tau', r'\alpha', r'\beta', r'\sigma', r'\gamma']
|
parameter = [r'\alpha', r'\beta', r'\sigma', r'\gamma']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def distribution(tau: float | np.ndarray, tau0: float,
|
def distribution(tau: float | np.ndarray, tau0: float,
|
||||||
@ -117,8 +123,8 @@ class GGAlphaEW(AbstractGG):
|
|||||||
|
|
||||||
# noinspection PyMethodOverriding
|
# noinspection PyMethodOverriding
|
||||||
class GGBeta(AbstractGG):
|
class GGBeta(AbstractGG):
|
||||||
name = r'General \Gamma (\beta)'
|
name = r'General Gamma (beta)'
|
||||||
parameter = [r'\tau', 'a', 'b']
|
parameter = ['a', 'b']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def distribution(tau: float | np.ndarray, tau0: float, a: float, b: float) -> float | np.ndarray:
|
def distribution(tau: float | np.ndarray, tau0: float, a: float, b: float) -> float | np.ndarray:
|
||||||
|
@ -2,6 +2,7 @@ import numpy as np
|
|||||||
|
|
||||||
from ..distributions import *
|
from ..distributions import *
|
||||||
from ..distributions.energy import EnergyBarriers
|
from ..distributions.energy import EnergyBarriers
|
||||||
|
from ..distributions.gengamma import GGAlpha
|
||||||
from ..distributions.intermolecular import FFHS
|
from ..distributions.intermolecular import FFHS
|
||||||
from ..nmr.relaxation import Relaxation
|
from ..nmr.relaxation import Relaxation
|
||||||
from ..utils.constants import gamma
|
from ..utils.constants import gamma
|
||||||
@ -82,6 +83,13 @@ class FFHSFC(_AbstractFC):
|
|||||||
relax = Relaxation(distribution=FFHS)
|
relax = Relaxation(distribution=FFHS)
|
||||||
|
|
||||||
|
|
||||||
|
class GGAFC(_AbstractFC):
|
||||||
|
name = 'GG(alpha)'
|
||||||
|
params = _AbstractFC.params + [r'\alpha', r'\beta']
|
||||||
|
bounds = _AbstractFC.bounds + [(None, None), (None, None)]
|
||||||
|
relax = Relaxation(distribution=GGAlpha)
|
||||||
|
|
||||||
|
|
||||||
class EnergyFC(_AbstractFC):
|
class EnergyFC(_AbstractFC):
|
||||||
name = 'Energy distribution'
|
name = 'Energy distribution'
|
||||||
params = ['C', 'T'] + EnergyBarriers.parameter
|
params = ['C', 'T'] + EnergyBarriers.parameter
|
||||||
|
@ -525,7 +525,7 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
dist_parameter: tuple | list = None,
|
dist_parameter: tuple | list = None,
|
||||||
prefactor: tuple | list | float = None,
|
prefactor: tuple | list | float = None,
|
||||||
coupling_kwargs: dict = None,
|
coupling_kwargs: dict = None,
|
||||||
) -> None:
|
) -> tuple[float, float] :
|
||||||
"""
|
"""
|
||||||
Determine a single parameter from a T1 minimum.
|
Determine a single parameter from a T1 minimum.
|
||||||
It replaces the previously set value.
|
It replaces the previously set value.
|
||||||
|
Loading…
Reference in New Issue
Block a user