forked from IPKM/nmreval
save fit parameter and agr; more doc
This commit is contained in:
parent
ef81030213
commit
73e4a2b4d9
@ -5,8 +5,8 @@
|
|||||||
# from the environment for the first two.
|
# from the environment for the first two.
|
||||||
SPHINXOPTS ?=
|
SPHINXOPTS ?=
|
||||||
SPHINXBUILD ?= /autohome/dominik/miniconda3/bin/sphinx-build
|
SPHINXBUILD ?= /autohome/dominik/miniconda3/bin/sphinx-build
|
||||||
SOURCEDIR = /autohome/dominik/nmreval/docs/source
|
SOURCEDIR = /autohome/dominik/nmreval/doc/source
|
||||||
BUILDDIR = /autohome/dominik/nmreval/docs/build
|
BUILDDIR = /autohome/dominik/nmreval/doc/_build
|
||||||
|
|
||||||
# Put it first so that "make" without argument is like "make help".
|
# Put it first so that "make" without argument is like "make help".
|
||||||
help:
|
help:
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
"""
|
"""
|
||||||
=======================
|
==========
|
||||||
Spin-lattice relaxation
|
T1 minimum
|
||||||
=======================
|
==========
|
||||||
|
|
||||||
Example for
|
``RelaxationEvaluation`` is used to get width parameter from a T1 minimum.
|
||||||
|
As a subclass of ``Relaxation`` it can also be used to calculate Relaxation times.
|
||||||
|
The basic steps are:
|
||||||
|
|
||||||
|
* Determine a T1 minimum with `nmreval.nmr.RelaxationEvaluation.calculate_t1_min`
|
||||||
|
* Calculate width parameter of a spectral density/coupling constants/... with
|
||||||
|
``RelaxationEvaluation.get_increase``
|
||||||
|
* Calculate correlation times from these values with ``RelaxationEvaluation.correlation_from_t1``
|
||||||
"""
|
"""
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from matplotlib import pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
from nmreval.distributions import ColeDavidson
|
from nmreval.distributions import ColeDavidson
|
||||||
from nmreval.nmr import Relaxation, RelaxationEvaluation
|
from nmreval.nmr import Relaxation, RelaxationEvaluation
|
||||||
@ -20,7 +27,7 @@ temperature = 1000/inv_temp
|
|||||||
# spectral density parameter
|
# spectral density parameter
|
||||||
ea = 0.45
|
ea = 0.45
|
||||||
tau = 1e-21 * np.exp(ea / kB / temperature)
|
tau = 1e-21 * np.exp(ea / kB / temperature)
|
||||||
gamma_cd = 0.1
|
gamma_cd = 0.4
|
||||||
|
|
||||||
# interaction parameter
|
# interaction parameter
|
||||||
omega = 2*np.pi*46e6
|
omega = 2*np.pi*46e6
|
||||||
@ -28,40 +35,57 @@ delta = 120e3
|
|||||||
eta = 0
|
eta = 0
|
||||||
|
|
||||||
r = Relaxation()
|
r = Relaxation()
|
||||||
r.set_distribution(ColeDavidson) # the only parameter that has to be set beforehand
|
r.set_distribution(ColeDavidson) # the only parameter that set beforehand
|
||||||
|
|
||||||
t1_values = r.t1(omega, tau, gamma_cd, mode='bpp',
|
t1_values = r.t1(omega, tau, gamma_cd, mode='bpp',
|
||||||
prefactor=Quadrupolar.relax(delta, eta))
|
prefactor=Quadrupolar.relax(delta, eta))
|
||||||
# add noise
|
# add noise
|
||||||
rng = np.random.default_rng(123456789)
|
rng = np.random.default_rng()
|
||||||
noisy = (rng.random(t1_values.size)-0.5) * 0.5 * t1_values + t1_values
|
noisy = (rng.random(t1_values.size)-0.5) * 0.5 * t1_values + t1_values
|
||||||
|
|
||||||
# set parameter and data
|
ax_t1 = plt.figure().add_subplot()
|
||||||
|
ax_t1.semilogy(inv_temp, t1_values, label='Calculated T1')
|
||||||
|
ax_t1.semilogy(inv_temp, noisy, 'o', label='Noise')
|
||||||
|
ax_t1.legend()
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
|
# Actual evaluation starts here
|
||||||
|
# setting necessary parameter
|
||||||
r_eval = RelaxationEvaluation()
|
r_eval = RelaxationEvaluation()
|
||||||
r_eval.set_distribution(ColeDavidson)
|
r_eval.set_distribution(ColeDavidson)
|
||||||
r_eval.set_coupling(Quadrupolar, (delta, eta))
|
r_eval.set_coupling(Quadrupolar, (delta, eta))
|
||||||
r_eval.data(temperature, noisy)
|
r_eval.set_data(temperature, noisy)
|
||||||
r_eval.omega = omega
|
r_eval.omega = omega
|
||||||
|
|
||||||
|
# Find a T1 minumum
|
||||||
t1_min_data, _ = r_eval.calculate_t1_min() # second argument is None
|
t1_min_data, _ = r_eval.calculate_t1_min() # second argument is None
|
||||||
t1_min_inter, line = r_eval.calculate_t1_min(interpolate=1, trange=(160, 195), use_log=True)
|
t1_min_inter, line = r_eval.calculate_t1_min(interpolate=1, trange=(160, 195), use_log=True)
|
||||||
|
|
||||||
fig, ax = plt.subplots()
|
ax_min = plt.figure().add_subplot()
|
||||||
ax.semilogy(1000/t1_min_data[0], t1_min_data[1], 'rx', label='Data minimum')
|
ax_min.semilogy(inv_temp, noisy, 'o', label='Data')
|
||||||
ax.semilogy(1000/t1_min_inter[0], t1_min_inter[1], 'r+', label='Parabola')
|
ax_min.semilogy(1000/line[0], line[1], '--')
|
||||||
ax.semilogy(1000/line[0], line[1])
|
ax_min.semilogy(1000/t1_min_data[0], t1_min_data[1], 'C2X',label='Data minimum')
|
||||||
|
ax_min.semilogy(1000/t1_min_inter[0], t1_min_inter[1], 'C3P',label='Parabola')
|
||||||
|
ax_min.set_xlim(4.5, 7)
|
||||||
|
ax_min.set_ylim(1e-3, 1e-1)
|
||||||
|
ax_min.legend()
|
||||||
|
|
||||||
|
# Vary the first (and for Cole-Davidson, only) parameter of the spectral density
|
||||||
found_gamma, found_height = r_eval.get_increase(t1_min_inter[1], idx=0, mode='distribution')
|
found_gamma, found_height = r_eval.get_increase(t1_min_inter[1], idx=0, mode='distribution')
|
||||||
print(found_gamma)
|
print(f'Minimum at {found_height} for {found_gamma}; input is {gamma_cd}')
|
||||||
|
|
||||||
plt.axhline(found_height)
|
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
#%%
|
##################################################################################
|
||||||
# Now we found temperature and height of the minimum we can calculate the correlation time
|
# Calculation of correlation times uses previously parameter for spectral density
|
||||||
|
# and prefactor
|
||||||
|
|
||||||
plt.semilogy(1000/temperature, tau)
|
tau_from_t1, opts = r_eval.correlation_from_t1(mode='mean')
|
||||||
tau_from_t1, opts = r_eval.correlation_from_t1()
|
print(f'Used options: {opts}')
|
||||||
print(opts)
|
|
||||||
plt.semilogy(1000/tau_from_t1[:, 0], tau_from_t1[:, 1], 'o')
|
ax_tau = plt.figure().add_subplot()
|
||||||
|
ax_tau.semilogy(inv_temp, tau*gamma_cd, label='Original input')
|
||||||
|
ax_tau.semilogy(1000/tau_from_t1[:, 0], tau_from_t1[:, 1], 'o', label='Calculated')
|
||||||
|
ax_tau.legend()
|
||||||
plt.show()
|
plt.show()
|
||||||
|
@ -1,179 +0,0 @@
|
|||||||
:orphan:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _sphx_glr_gallery:
|
|
||||||
|
|
||||||
.. examples-index:
|
|
||||||
|
|
||||||
.. _gallery:
|
|
||||||
|
|
||||||
========
|
|
||||||
Examples
|
|
||||||
========
|
|
||||||
|
|
||||||
This page contains example plots. Click on any image to see the full image and source code.
|
|
||||||
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<div class="sphx-glr-clear"></div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _sphx_glr_gallery_distribution:
|
|
||||||
|
|
||||||
.. _distribution_examples:
|
|
||||||
|
|
||||||
.. _distribution-examples-index:
|
|
||||||
|
|
||||||
Distribution of correlation times
|
|
||||||
=================================
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<div class="sphx-glr-thumbcontainer" tooltip="Example for KWW distributions">
|
|
||||||
|
|
||||||
.. only:: html
|
|
||||||
|
|
||||||
.. figure:: /gallery/distribution/images/thumb/sphx_glr_plot_KWW_thumb.png
|
|
||||||
:alt: Kohlrausch-Williams-Watts
|
|
||||||
|
|
||||||
:ref:`sphx_glr_gallery_distribution_plot_KWW.py`
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
/gallery/distribution/plot_KWW
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<div class="sphx-glr-thumbcontainer" tooltip="Example for Cole-Cole distributions">
|
|
||||||
|
|
||||||
.. only:: html
|
|
||||||
|
|
||||||
.. figure:: /gallery/distribution/images/thumb/sphx_glr_plot_ColeCole_thumb.png
|
|
||||||
:alt: Cole-Cole
|
|
||||||
|
|
||||||
:ref:`sphx_glr_gallery_distribution_plot_ColeCole.py`
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
/gallery/distribution/plot_ColeCole
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<div class="sphx-glr-thumbcontainer" tooltip="Example for Log-Gaussian distributions">
|
|
||||||
|
|
||||||
.. only:: html
|
|
||||||
|
|
||||||
.. figure:: /gallery/distribution/images/thumb/sphx_glr_plot_LogGaussian_thumb.png
|
|
||||||
:alt: Log-Gaussian
|
|
||||||
|
|
||||||
:ref:`sphx_glr_gallery_distribution_plot_LogGaussian.py`
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
/gallery/distribution/plot_LogGaussian
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<div class="sphx-glr-thumbcontainer" tooltip="Example for Cole-Davidson distributions">
|
|
||||||
|
|
||||||
.. only:: html
|
|
||||||
|
|
||||||
.. figure:: /gallery/distribution/images/thumb/sphx_glr_plot_ColeDavidson_thumb.png
|
|
||||||
:alt: Cole-Davidson
|
|
||||||
|
|
||||||
:ref:`sphx_glr_gallery_distribution_plot_ColeDavidson.py`
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
/gallery/distribution/plot_ColeDavidson
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<div class="sphx-glr-thumbcontainer" tooltip="Example for Havriliak-Negami distributions">
|
|
||||||
|
|
||||||
.. only:: html
|
|
||||||
|
|
||||||
.. figure:: /gallery/distribution/images/thumb/sphx_glr_plot_HavriliakNegami_thumb.png
|
|
||||||
:alt: Havriliak-Negami
|
|
||||||
|
|
||||||
:ref:`sphx_glr_gallery_distribution_plot_HavriliakNegami.py`
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
/gallery/distribution/plot_HavriliakNegami
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<div class="sphx-glr-clear"></div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _sphx_glr_gallery_nmr:
|
|
||||||
|
|
||||||
.. _nmr_examples:
|
|
||||||
|
|
||||||
.. _nmr-examples-index:
|
|
||||||
|
|
||||||
NMR specifics
|
|
||||||
=============
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<div class="sphx-glr-thumbcontainer" tooltip="Example for">
|
|
||||||
|
|
||||||
.. only:: html
|
|
||||||
|
|
||||||
.. figure:: /gallery/nmr/images/thumb/sphx_glr_plot_RelaxationEvaluation_thumb.png
|
|
||||||
:alt: Spin-lattice relaxation
|
|
||||||
|
|
||||||
:ref:`sphx_glr_gallery_nmr_plot_RelaxationEvaluation.py`
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
/gallery/nmr/plot_RelaxationEvaluation
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<div class="sphx-glr-clear"></div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
'/autohome/dominik/nmreval/doc/_build/html/index.html', (0, 6969)
|
|
||||||
'/autohome/dominik/nmreval/doc/_build/html/_static/documentation_options.js', (7168, 364)
|
|
||||||
'/autohome/dominik/nmreval/doc/_build/html/searchindex.js', (7680, 29280)
|
|
Binary file not shown.
@ -1,3 +0,0 @@
|
|||||||
'/autohome/dominik/nmreval/doc/_build/html/index.html', (0, 6969)
|
|
||||||
'/autohome/dominik/nmreval/doc/_build/html/_static/documentation_options.js', (7168, 364)
|
|
||||||
'/autohome/dominik/nmreval/doc/_build/html/searchindex.js', (7680, 29280)
|
|
@ -485,7 +485,7 @@ class PointContainer(ExperimentContainer):
|
|||||||
}
|
}
|
||||||
|
|
||||||
if sym_kwargs['symbol'] is None and line_kwargs['style'] is None:
|
if sym_kwargs['symbol'] is None and line_kwargs['style'] is None:
|
||||||
if len(self._data) > 1000:
|
if len(self._data) > 500:
|
||||||
line_kwargs['style'] = LineStyle.Solid
|
line_kwargs['style'] = LineStyle.Solid
|
||||||
sym_kwargs['symbol'] = SymbolStyle.No
|
sym_kwargs['symbol'] = SymbolStyle.No
|
||||||
else:
|
else:
|
||||||
|
@ -138,8 +138,6 @@ class ConversionDialog(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
src_sets.append((set_id_real, set_id_imag, graph_id, type_idx))
|
src_sets.append((set_id_real, set_id_imag, graph_id, type_idx))
|
||||||
|
|
||||||
print(src_sets)
|
|
||||||
|
|
||||||
self.convertSets.emit(src_sets)
|
self.convertSets.emit(src_sets)
|
||||||
|
|
||||||
return src_sets
|
return src_sets
|
||||||
|
@ -124,7 +124,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
|||||||
self.data_parameter[idx].blockSignals(False)
|
self.data_parameter[idx].blockSignals(False)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(str, object)
|
@QtCore.pyqtSlot(str, object)
|
||||||
def change_global_choice(self, argname, value):
|
def change_global_choice(self, _, value):
|
||||||
idx = self.global_parameter.index(self.sender())
|
idx = self.global_parameter.index(self.sender())
|
||||||
self.glob_values[idx] = value
|
self.glob_values[idx] = value
|
||||||
if self.data_values[self.comboBox.currentData()][idx] is None:
|
if self.data_values[self.comboBox.currentData()][idx] is None:
|
||||||
@ -242,6 +242,8 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
|||||||
else:
|
else:
|
||||||
if p_i is None:
|
if p_i is None:
|
||||||
kw_p.update(g.value)
|
kw_p.update(g.value)
|
||||||
|
elif isinstance(p_i, dict):
|
||||||
|
kw_p.update(p_i)
|
||||||
else:
|
else:
|
||||||
kw_p[g.argname] = p_i
|
kw_p[g.argname] = p_i
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
|
|
||||||
# reconnect "Export..." in context menu to our function
|
# reconnect "Export..." in context menu to our function
|
||||||
self.scene.contextMenu[0].disconnect()
|
self.scene.contextMenu[0].disconnect()
|
||||||
self.scene.contextMenu[0].triggered.connect(self.export)
|
self.scene.contextMenu[0].triggered.connect(self.export_dialog)
|
||||||
|
|
||||||
def _init_gui(self):
|
def _init_gui(self):
|
||||||
self.setWindowTitle('Graph ' + str(next(QGraphWindow.counter)))
|
self.setWindowTitle('Graph ' + str(next(QGraphWindow.counter)))
|
||||||
@ -515,7 +515,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
(item in self.graphic.items() or other_item in self.graphic.items()):
|
(item in self.graphic.items() or other_item in self.graphic.items()):
|
||||||
self.legend.addItem(item, convert(item.opts.get('name', ''), old='tex', new='html'))
|
self.legend.addItem(item, convert(item.opts.get('name', ''), old='tex', new='html'))
|
||||||
|
|
||||||
def export(self):
|
def export_dialog(self):
|
||||||
filters = 'All files (*.*);;AGR (*.agr);;SVG (*.svg);;PDF (*.pdf)'
|
filters = 'All files (*.*);;AGR (*.agr);;SVG (*.svg);;PDF (*.pdf)'
|
||||||
for imgformat in QtGui.QImageWriter.supportedImageFormats():
|
for imgformat in QtGui.QImageWriter.supportedImageFormats():
|
||||||
str_format = imgformat.data().decode('utf-8')
|
str_format = imgformat.data().decode('utf-8')
|
||||||
@ -524,6 +524,9 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
outfile, _ = QtWidgets.QFileDialog.getSaveFileName(self, caption='Export graphic', filter=filters,
|
outfile, _ = QtWidgets.QFileDialog.getSaveFileName(self, caption='Export graphic', filter=filters,
|
||||||
options=QtWidgets.QFileDialog.DontConfirmOverwrite)
|
options=QtWidgets.QFileDialog.DontConfirmOverwrite)
|
||||||
if outfile:
|
if outfile:
|
||||||
|
self.export(outfile)
|
||||||
|
|
||||||
|
def export(self, outfile: str):
|
||||||
_, suffix = os.path.splitext(outfile)
|
_, suffix = os.path.splitext(outfile)
|
||||||
if suffix == '':
|
if suffix == '':
|
||||||
QtWidgets.QMessageBox.warning(self, 'No file extension',
|
QtWidgets.QMessageBox.warning(self, 'No file extension',
|
||||||
@ -566,7 +569,6 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
from ..io.exporters import PDFPrintExporter
|
from ..io.exporters import PDFPrintExporter
|
||||||
PDFPrintExporter(self.graphic).export(outfile)
|
PDFPrintExporter(self.graphic).export(outfile)
|
||||||
|
|
||||||
|
|
||||||
elif suffix == '.svg':
|
elif suffix == '.svg':
|
||||||
from pyqtgraph.exporters import SVGExporter
|
from pyqtgraph.exporters import SVGExporter
|
||||||
SVGExporter(self.scene).export(outfile)
|
SVGExporter(self.scene).export(outfile)
|
||||||
@ -591,8 +593,6 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
if item_dic:
|
if item_dic:
|
||||||
dic['items'].append(item_dic)
|
dic['items'].append(item_dic)
|
||||||
|
|
||||||
print(dic)
|
|
||||||
|
|
||||||
return dic
|
return dic
|
||||||
|
|
||||||
def get_state(self) -> dict:
|
def get_state(self) -> dict:
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import pathlib
|
||||||
|
|
||||||
from ..Qt import QtWidgets, QtCore
|
from ..Qt import QtWidgets, QtCore
|
||||||
|
|
||||||
|
|
||||||
@ -74,15 +78,45 @@ class SaveDirectoryDialog(_FileDialog):
|
|||||||
self.setOption(QtWidgets.QFileDialog.DontConfirmOverwrite, False)
|
self.setOption(QtWidgets.QFileDialog.DontConfirmOverwrite, False)
|
||||||
self.setAcceptMode(QtWidgets.QFileDialog.AcceptSave)
|
self.setAcceptMode(QtWidgets.QFileDialog.AcceptSave)
|
||||||
|
|
||||||
|
lay = self.layout()
|
||||||
|
|
||||||
self.label = QtWidgets.QLabel(self)
|
self.label = QtWidgets.QLabel(self)
|
||||||
self.label.setTextFormat(QtCore.Qt.RichText)
|
self.label.setTextFormat(QtCore.Qt.RichText)
|
||||||
self.label.setText('Use <b><label></b> as placeholder in filename. (e.g. <i>t1_<label>.dat</i>)')
|
self.label.setText('Use <b><label></b> as placeholder in filename. (e.g. <i>t1_<label>.dat</i>)')
|
||||||
self.layout().addWidget(self.label, self.layout().rowCount(), 0, 1, self.layout().columnCount())
|
lay.addWidget(self.label, lay.rowCount(), 0, 1, lay.columnCount())
|
||||||
|
|
||||||
|
line = QtWidgets.QFrame(self)
|
||||||
|
line.setFrameShape(line.HLine)
|
||||||
|
line.setFrameShadow(line.Sunken)
|
||||||
|
lay.addWidget(line, lay.rowCount(), 0, 1, lay.columnCount())
|
||||||
|
|
||||||
|
h_layout = QtWidgets.QHBoxLayout()
|
||||||
|
h_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
h_layout.setSpacing(3)
|
||||||
|
|
||||||
self.checkBox = QtWidgets.QCheckBox(self)
|
self.checkBox = QtWidgets.QCheckBox(self)
|
||||||
self.checkBox.setChecked(True)
|
self.checkBox.setChecked(True)
|
||||||
self.checkBox.setText('Replace spaces with underscore')
|
self.checkBox.setText('Replace spaces with _')
|
||||||
self.layout().addWidget(self.checkBox, self.layout().rowCount(), 0, 1, self.layout().columnCount())
|
h_layout.addWidget(self.checkBox)
|
||||||
|
|
||||||
|
self.agr_cb = QtWidgets.QCheckBox(self)
|
||||||
|
self.agr_cb.setChecked(True)
|
||||||
|
self.agr_cb.setText('Save graph as Grace file')
|
||||||
|
h_layout.addWidget(self.agr_cb)
|
||||||
|
|
||||||
|
self.fit_cb = QtWidgets.QCheckBox(self)
|
||||||
|
self.fit_cb.setChecked(True)
|
||||||
|
self.fit_cb.setText('Save fit parameter')
|
||||||
|
h_layout.addWidget(self.fit_cb)
|
||||||
|
|
||||||
|
lay.addLayout(h_layout, lay.rowCount(), 0, 1, lay.columnCount())
|
||||||
|
|
||||||
self.setWindowTitle('Save')
|
self.setWindowTitle('Save')
|
||||||
self.setNameFilters(['All files (*.*)', 'Session file (*.nmr)', 'Text file (*.dat)', 'HDF file (*.h5)', 'Grace files (*.agr)'])
|
self.setNameFilters(['All files (*.*)', 'Session file (*.nmr)', 'Text file (*.dat)',
|
||||||
|
'HDF file (*.h5)', 'Grace files (*.agr)'])
|
||||||
|
|
||||||
|
def save_file(self) -> pathlib.Path | None:
|
||||||
|
outfile = self.selectedFiles()
|
||||||
|
if outfile:
|
||||||
|
return pathlib.Path(outfile[0])
|
||||||
|
return
|
||||||
|
@ -193,6 +193,8 @@ class SelectionWidget(QtWidgets.QWidget):
|
|||||||
|
|
||||||
@value.setter
|
@value.setter
|
||||||
def value(self, val):
|
def value(self, val):
|
||||||
|
if isinstance(val, dict):
|
||||||
|
val = list(val.values())[0]
|
||||||
key = [k for k, v in self.options.items() if v == val][0]
|
key = [k for k, v in self.options.items() if v == val][0]
|
||||||
self.comboBox.setCurrentIndex(self.comboBox.findText(key))
|
self.comboBox.setCurrentIndex(self.comboBox.findText(key))
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ class PlotItem(PlotDataItem):
|
|||||||
|
|
||||||
if opts['symbol'] is None:
|
if opts['symbol'] is None:
|
||||||
item_dic['symbol'] = SymbolStyle.No
|
item_dic['symbol'] = SymbolStyle.No
|
||||||
item_dic['symbolcolor'] = Colors.Black
|
item_dic['symbolcolor'] = None
|
||||||
else:
|
else:
|
||||||
item_dic['symbol'] = SymbolStyle.from_str(opts['symbol'])
|
item_dic['symbol'] = SymbolStyle.from_str(opts['symbol'])
|
||||||
item_dic['symbolcolor'] = opts['symbolcolor']
|
item_dic['symbolcolor'] = opts['symbolcolor']
|
||||||
@ -354,9 +354,16 @@ class PlotItem(PlotDataItem):
|
|||||||
item_dic['linewidth'] = pen.widthF()
|
item_dic['linewidth'] = pen.widthF()
|
||||||
else:
|
else:
|
||||||
item_dic['linestyle'] = LineStyle.No
|
item_dic['linestyle'] = LineStyle.No
|
||||||
item_dic['linecolor'] = item_dic['symbolcolor']
|
item_dic['linecolor'] = None
|
||||||
item_dic['linewidth'] = 0.0
|
item_dic['linewidth'] = 0.0
|
||||||
|
|
||||||
|
if item_dic['linecolor'] is None and item_dic['symbolcolor'] is None:
|
||||||
|
item_dic['symbolcolor'] = Colors.Black.rgb()
|
||||||
|
elif item_dic['linecolor'] is None:
|
||||||
|
item_dic['linecolor'] = item_dic['symbolcolor']
|
||||||
|
elif item_dic['symbolcolor'] is None:
|
||||||
|
item_dic['symbolcolor'] = item_dic['linecolor']
|
||||||
|
|
||||||
return item_dic
|
return item_dic
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import pathlib
|
import pathlib
|
||||||
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
|
|
||||||
@ -249,11 +250,20 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
|
|
||||||
mode = save_dialog.exec()
|
mode = save_dialog.exec()
|
||||||
if mode == QtWidgets.QDialog.Accepted:
|
if mode == QtWidgets.QDialog.Accepted:
|
||||||
path = save_dialog.selectedFiles()
|
savefile = save_dialog.save_file()
|
||||||
selected_filter = save_dialog.selectedNameFilter()
|
selected_filter = save_dialog.selectedNameFilter()
|
||||||
|
|
||||||
if path:
|
if savefile is not None:
|
||||||
self.management.save(path[0], selected_filter)
|
use_underscore = save_dialog.checkBox.isChecked()
|
||||||
|
self.management.save(savefile, selected_filter, strip_spaces=use_underscore)
|
||||||
|
|
||||||
|
param_outfile = re.sub('[_\s-]?<label>[_\s-]?', '', savefile.stem)
|
||||||
|
|
||||||
|
if save_dialog.agr_cb.isChecked():
|
||||||
|
self.current_graph_widget.export(savefile.with_name(param_outfile + '.agr'))
|
||||||
|
|
||||||
|
if save_dialog.fit_cb.isChecked():
|
||||||
|
self.management.save_fit_parameter(savefile.with_name(param_outfile + '.dat'))
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
@QtCore.pyqtSlot(list)
|
@QtCore.pyqtSlot(list)
|
||||||
@ -266,7 +276,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_actionExportGraphic_triggered')
|
@QtCore.pyqtSlot(name='on_actionExportGraphic_triggered')
|
||||||
def export_graphic(self):
|
def export_graphic(self):
|
||||||
self.current_graph_widget.export()
|
self.current_graph_widget.export_dialog()
|
||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_actionNew_window_triggered')
|
@QtCore.pyqtSlot(name='on_actionNew_window_triggered')
|
||||||
def new_graph(self):
|
def new_graph(self):
|
||||||
@ -304,7 +314,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(str)
|
@QtCore.pyqtSlot(str)
|
||||||
def remove_graph(self, gid: str):
|
def remove_graph(self, gid: str):
|
||||||
print(gid, self.current_graph_widget)
|
|
||||||
self.datawidget.remove_item(gid)
|
self.datawidget.remove_item(gid)
|
||||||
w = None
|
w = None
|
||||||
for w in self.area.subWindowList():
|
for w in self.area.subWindowList():
|
||||||
@ -655,7 +664,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(str)
|
@QtCore.pyqtSlot(str)
|
||||||
def delete_data(self, sid):
|
def delete_data(self, sid):
|
||||||
print('remove', sid)
|
|
||||||
if self.valuewidget.shown_set == sid:
|
if self.valuewidget.shown_set == sid:
|
||||||
self.tabWidget.setCurrentIndex(0)
|
self.tabWidget.setCurrentIndex(0)
|
||||||
|
|
||||||
@ -765,7 +773,8 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
|
|
||||||
def _select_fitwidget(self, onoff: bool, block_window: bool):
|
def _select_fitwidget(self, onoff: bool, block_window: bool):
|
||||||
if self.current_graph_widget is not None:
|
if self.current_graph_widget is not None:
|
||||||
print('select', self.current_graph_widget.id)
|
pass
|
||||||
|
|
||||||
if onoff:
|
if onoff:
|
||||||
if self.management.active_sets:
|
if self.management.active_sets:
|
||||||
self.fit_dialog.connected_figure = self.management.current_graph
|
self.fit_dialog.connected_figure = self.management.current_graph
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import pathlib
|
import pathlib
|
||||||
import re
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
@ -260,7 +262,6 @@ class UpperManagement(QtCore.QObject):
|
|||||||
@QtCore.pyqtSlot(str)
|
@QtCore.pyqtSlot(str)
|
||||||
def delete_sets(self, rm_sets: list = None):
|
def delete_sets(self, rm_sets: list = None):
|
||||||
rm_graphs = []
|
rm_graphs = []
|
||||||
print(rm_sets)
|
|
||||||
|
|
||||||
if rm_sets is None:
|
if rm_sets is None:
|
||||||
rm_sets = self.graphs[self.current_graph].sets + [self.current_graph]
|
rm_sets = self.graphs[self.current_graph].sets + [self.current_graph]
|
||||||
@ -489,9 +490,6 @@ class UpperManagement(QtCore.QObject):
|
|||||||
|
|
||||||
f_id = self.add(fit, color=color, src=k)
|
f_id = self.add(fit, color=color, src=k)
|
||||||
|
|
||||||
if subplots:
|
|
||||||
print('subplots')
|
|
||||||
|
|
||||||
f_id_list.append(f_id)
|
f_id_list.append(f_id)
|
||||||
data_k.set_fits(f_id)
|
data_k.set_fits(f_id)
|
||||||
gid = data_k.graph
|
gid = data_k.graph
|
||||||
@ -516,7 +514,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
|
|
||||||
self.newData.emit(p_id_list, graph_id)
|
self.newData.emit(p_id_list, graph_id)
|
||||||
|
|
||||||
def save_fit_parameter(self, fname: str, fit_sets: List[str] = None):
|
def save_fit_parameter(self, fname: str | pathlib.Path, fit_sets: List[str] = None):
|
||||||
if fit_sets is None:
|
if fit_sets is None:
|
||||||
fit_sets = [s for (s, _) in self.active_sets]
|
fit_sets = [s for (s, _) in self.active_sets]
|
||||||
|
|
||||||
@ -1009,7 +1007,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
def append(self, idx: str):
|
def append(self, idx: str):
|
||||||
self.data[idx].add([0.0, 0.0, 0.0])
|
self.data[idx].add([0.0, 0.0, 0.0])
|
||||||
|
|
||||||
def save(self, outpath: str, extension: str, strip_spaces=False):
|
def save(self, outpath: str | pathlib.Path, extension: str, strip_spaces=False):
|
||||||
path = pathlib.Path(outpath)
|
path = pathlib.Path(outpath)
|
||||||
suffix = path.suffix
|
suffix = path.suffix
|
||||||
|
|
||||||
@ -1030,7 +1028,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
real_outnames = []
|
real_outnames = []
|
||||||
for set_id, set_name in self.active_sets:
|
for set_id, set_name in self.active_sets:
|
||||||
full_name = path.stem
|
full_name = path.stem
|
||||||
if '<label>' in outpath:
|
if '<label>' in full_name:
|
||||||
full_name = full_name.replace('<label>', convert(set_name, old='tex', new='str'))
|
full_name = full_name.replace('<label>', convert(set_name, old='tex', new='str'))
|
||||||
|
|
||||||
data_i = self.data[set_id]
|
data_i = self.data[set_id]
|
||||||
|
@ -87,7 +87,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
self.lineEdit_3.setText('{:.2f}'.format(x[right_b]))
|
self.lineEdit_3.setText('{:.2f}'.format(x[right_b]))
|
||||||
self.lineEdit_3.blockSignals(False)
|
self.lineEdit_3.blockSignals(False)
|
||||||
|
|
||||||
self.t1calculator.data(x, y)
|
self.t1calculator.set_data(x, y)
|
||||||
|
|
||||||
self.determine_minimum(self.interpol_combobox.currentIndex())
|
self.determine_minimum(self.interpol_combobox.currentIndex())
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -159,7 +159,6 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
_temp.valueChanged.connect(self.update_coupling_parameter)
|
_temp.valueChanged.connect(self.update_coupling_parameter)
|
||||||
_temp.stateChanged.connect(self.update_coupling_parameter)
|
_temp.stateChanged.connect(self.update_coupling_parameter)
|
||||||
self.cp_parameter.append(_temp)
|
self.cp_parameter.append(_temp)
|
||||||
print(self.cp_parameter)
|
|
||||||
|
|
||||||
if self.coupling[idx].choice is not None:
|
if self.coupling[idx].choice is not None:
|
||||||
for (name, kw_name, opts) in self.coupling[idx].choice:
|
for (name, kw_name, opts) in self.coupling[idx].choice:
|
||||||
|
@ -112,8 +112,7 @@ class BDSReader:
|
|||||||
warnings.warn('Number of set temperatures does not match number of data points')
|
warnings.warn('Number of set temperatures does not match number of data points')
|
||||||
|
|
||||||
_y = np.array(_y).reshape((actual_temps_length, freq_values_length, 9))
|
_y = np.array(_y).reshape((actual_temps_length, freq_values_length, 9))
|
||||||
print(_y.shape)
|
|
||||||
print(f.tell())
|
|
||||||
# last 3 entries are zero, save only 6
|
# last 3 entries are zero, save only 6
|
||||||
# Z.imag*omega), Z.real, meas.time, meas. temp., ac voltage, dc voltage
|
# Z.imag*omega), Z.real, meas.time, meas. temp., ac voltage, dc voltage
|
||||||
self.y = np.transpose(_y[:, :, :6], (2, 0, 1))
|
self.y = np.transpose(_y[:, :, :6], (2, 0, 1))
|
||||||
|
@ -450,7 +450,6 @@ class GraceGraph(GraceProperties):
|
|||||||
self.idx = idx
|
self.idx = idx
|
||||||
|
|
||||||
def set_limits(self, x=None, y=None):
|
def set_limits(self, x=None, y=None):
|
||||||
print(x, y)
|
|
||||||
for i, line in enumerate(self):
|
for i, line in enumerate(self):
|
||||||
m = self._RE_ENTRY.match(line)
|
m = self._RE_ENTRY.match(line)
|
||||||
if m and m.group('key') == 'world':
|
if m and m.group('key') == 'world':
|
||||||
@ -702,10 +701,3 @@ def _convert_to_str(value):
|
|||||||
return ', '.join(map(str, value))
|
return ', '.join(map(str, value))
|
||||||
else:
|
else:
|
||||||
return str(value)
|
return str(value)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
agr = GraceEditor('/autohome/dominik/nmreval/testdata/02_relax_2.agr')
|
|
||||||
import pprint
|
|
||||||
pprint.pprint(agr.graphs)
|
|
||||||
agr.graphs[0].set_property(title='"asdasdasd"')
|
|
||||||
|
@ -4,9 +4,10 @@ Relaxation
|
|||||||
|
|
||||||
Classes to calculate spin-lattice and spin-spin relaxation, as well as to evaluate T1 data and calculate correlation times
|
Classes to calculate spin-lattice and spin-spin relaxation, as well as to evaluate T1 data and calculate correlation times
|
||||||
"""
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Optional, Tuple, Type, Union
|
from typing import Any, Tuple, Type
|
||||||
from warnings import warn
|
from warnings import warn
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@ -42,8 +43,8 @@ class Relaxation:
|
|||||||
else:
|
else:
|
||||||
return super().__repr__()
|
return super().__repr__()
|
||||||
|
|
||||||
def set_coupling(self, coupling: Union[float, Type[Coupling]],
|
def set_coupling(self, coupling: float | Type[Coupling],
|
||||||
parameter: Union[tuple, list] = None, keywords: dict = None):
|
parameter: tuple | list = None, keywords: dict = None):
|
||||||
|
|
||||||
if parameter is not None:
|
if parameter is not None:
|
||||||
self.coup_parameter = parameter
|
self.coup_parameter = parameter
|
||||||
@ -61,7 +62,7 @@ class Relaxation:
|
|||||||
else:
|
else:
|
||||||
raise ValueError(f'`coupling` is not number or of type `Coupling`, found {coupling!r}')
|
raise ValueError(f'`coupling` is not number or of type `Coupling`, found {coupling!r}')
|
||||||
|
|
||||||
def set_distribution(self, dist: Type[Distribution], parameter: Union[tuple, list] = None, keywords: dict = None):
|
def set_distribution(self, dist: Type[Distribution], parameter: tuple | list = None, keywords: dict = None):
|
||||||
self.distribution = dist
|
self.distribution = dist
|
||||||
|
|
||||||
if parameter is not None:
|
if parameter is not None:
|
||||||
@ -71,7 +72,7 @@ class Relaxation:
|
|||||||
self._dist_kw = keywords
|
self._dist_kw = keywords
|
||||||
|
|
||||||
def t1(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
def t1(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
||||||
mode: str = 'bpp', **kwargs) -> Union[np.ndarray, float]:
|
mode: str = 'bpp', **kwargs) -> np.ndarray | float:
|
||||||
r"""
|
r"""
|
||||||
Convenience function
|
Convenience function
|
||||||
|
|
||||||
@ -109,7 +110,7 @@ class Relaxation:
|
|||||||
|
|
||||||
def t1_dipolar(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any, inverse: bool = True,
|
def t1_dipolar(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any, inverse: bool = True,
|
||||||
prefactor: float = None, omega_coup: ArrayLike = None,
|
prefactor: float = None, omega_coup: ArrayLike = None,
|
||||||
gamma_coup: str = None, gamma_obs: str = None) -> Union[np.ndarray, float]:
|
gamma_coup: str = None, gamma_obs: str = None) -> np.ndarray | float:
|
||||||
r"""Calculate T1 under heteronuclear dipolar coupling.
|
r"""Calculate T1 under heteronuclear dipolar coupling.
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
@ -162,7 +163,7 @@ class Relaxation:
|
|||||||
return rate
|
return rate
|
||||||
|
|
||||||
def t1_bpp(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
def t1_bpp(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
||||||
inverse: bool = True, prefactor: float = None) -> Union[np.ndarray, float]:
|
inverse: bool = True, prefactor: float = None) -> np.ndarray | float:
|
||||||
r"""Calculate T1 under homonuclear dipolar coupling or quadrupolar coupling.
|
r"""Calculate T1 under homonuclear dipolar coupling or quadrupolar coupling.
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
@ -197,7 +198,7 @@ class Relaxation:
|
|||||||
return rate
|
return rate
|
||||||
|
|
||||||
def t1_csa(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
def t1_csa(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
||||||
inverse: bool = True, prefactor: float = None) -> Union[np.ndarray, float]:
|
inverse: bool = True, prefactor: float = None) -> np.ndarray | float:
|
||||||
r"""Calculate T1 under chemical shift anisotropy.
|
r"""Calculate T1 under chemical shift anisotropy.
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
@ -234,7 +235,7 @@ class Relaxation:
|
|||||||
return rate
|
return rate
|
||||||
|
|
||||||
def t1q(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
def t1q(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
||||||
inverse: bool = True, prefactor: float = None) -> Union[np.ndarray, float]:
|
inverse: bool = True, prefactor: float = None) -> np.ndarray | float:
|
||||||
r"""Calculate T1q for homonuclear dipolar coupling or quadrupolar coupling (I=1).
|
r"""Calculate T1q for homonuclear dipolar coupling or quadrupolar coupling (I=1).
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
@ -305,7 +306,7 @@ class Relaxation:
|
|||||||
return rate
|
return rate
|
||||||
|
|
||||||
def t2(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
def t2(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
||||||
mode: str = 'bpp', **kwargs) -> Union[np.ndarray, float]:
|
mode: str = 'bpp', **kwargs) -> np.ndarray | float:
|
||||||
r"""
|
r"""
|
||||||
Convenience function
|
Convenience function
|
||||||
|
|
||||||
@ -342,7 +343,7 @@ class Relaxation:
|
|||||||
return self.t2_csa(omega, tau, *specdens_args, **kwargs)
|
return self.t2_csa(omega, tau, *specdens_args, **kwargs)
|
||||||
|
|
||||||
def t2_bpp(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
def t2_bpp(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
||||||
inverse: bool = True, prefactor: float = None) -> Union[np.ndarray, float]:
|
inverse: bool = True, prefactor: float = None) -> np.ndarray | float:
|
||||||
r"""Calculate T2 under homonuclear dipolar coupling or quadrupolar coupling.
|
r"""Calculate T2 under homonuclear dipolar coupling or quadrupolar coupling.
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
@ -379,7 +380,7 @@ class Relaxation:
|
|||||||
|
|
||||||
def t2_dipolar(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
def t2_dipolar(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
||||||
inverse: bool = True, prefactor: float = None, omega_coup: ArrayLike = None,
|
inverse: bool = True, prefactor: float = None, omega_coup: ArrayLike = None,
|
||||||
gamma_coup: str = None, gamma_obs: str = None) -> Union[np.ndarray, float]:
|
gamma_coup: str = None, gamma_obs: str = None) -> np.ndarray | float:
|
||||||
r"""Calculate T2 under heteronuclear dipolar coupling.
|
r"""Calculate T2 under heteronuclear dipolar coupling.
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
@ -435,7 +436,7 @@ class Relaxation:
|
|||||||
return rate
|
return rate
|
||||||
|
|
||||||
def t2_csa(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
def t2_csa(self, omega: ArrayLike, tau: ArrayLike, *specdens_args: Any,
|
||||||
inverse: bool = True, prefactor: float = None) -> Union[np.ndarray, float]:
|
inverse: bool = True, prefactor: float = None) -> np.ndarray | float:
|
||||||
r"""Calculate T1 under chemical shift anisotropy.
|
r"""Calculate T1 under chemical shift anisotropy.
|
||||||
|
|
||||||
.. math::
|
.. math::
|
||||||
@ -471,7 +472,7 @@ class Relaxation:
|
|||||||
|
|
||||||
|
|
||||||
class RelaxationEvaluation(Relaxation):
|
class RelaxationEvaluation(Relaxation):
|
||||||
def __init__(self, distribution=None):
|
def __init__(self, distribution: Type[Distribution] = None):
|
||||||
super().__init__(distribution=distribution)
|
super().__init__(distribution=distribution)
|
||||||
self.t1min = (np.nan, np.nan)
|
self.t1min = (np.nan, np.nan)
|
||||||
self._interpolate = None
|
self._interpolate = None
|
||||||
@ -481,7 +482,15 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
self.x = None
|
self.x = None
|
||||||
self.y = None
|
self.y = None
|
||||||
|
|
||||||
def data(self, temp, t1):
|
def set_data(self, temp: ArrayLike, t1: ArrayLike):
|
||||||
|
"""
|
||||||
|
Set data for evaluation.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
temp (array-like): Temperature values
|
||||||
|
t1 (array-like): T1 values
|
||||||
|
|
||||||
|
"""
|
||||||
temp = np.asanyarray(temp)
|
temp = np.asanyarray(temp)
|
||||||
t1 = np.asanyarray(t1)
|
t1 = np.asanyarray(t1)
|
||||||
sortidx = temp.argsort()
|
sortidx = temp.argsort()
|
||||||
@ -490,10 +499,11 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
self.calculate_t1_min()
|
self.calculate_t1_min()
|
||||||
|
|
||||||
def get_increase(self, height: float = None, idx: int = 0, mode: str = None, omega: float = None,
|
def get_increase(self, height: float = None, idx: int = 0, mode: str = None, omega: float = None,
|
||||||
dist_parameter: Union[tuple, list] = None, prefactor: Union[tuple, list, float] = None,
|
dist_parameter: tuple | list = None, prefactor: tuple | list | float = None,
|
||||||
coupling_kwargs: dict = None):
|
coupling_kwargs: dict = None):
|
||||||
"""
|
"""
|
||||||
Determine a single parameter from a T1 minimum
|
Determine a single parameter from a T1 minimum.
|
||||||
|
It replaces the previously set value.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
height (float, optional): Height of T1 minimum
|
height (float, optional): Height of T1 minimum
|
||||||
@ -501,14 +511,16 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
idx (int): Default is 0.
|
idx (int): Default is 0.
|
||||||
omega (float, optional): Larmor frequency (in 1/s)
|
omega (float, optional): Larmor frequency (in 1/s)
|
||||||
dist_parameter (tuple, optional):
|
dist_parameter (tuple, optional):
|
||||||
prefactor (tuple, float, optional):
|
prefactor (tuple, float, optional): Prefactor for
|
||||||
coupling_kwargs (dict, optional):
|
coupling_kwargs (dict, optional): Keyword arguments for coupling, replacing old values
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
A tuple of the value of varied parameter, or nan if nothing was varied
|
||||||
|
and the minimum height calculated for given parameters.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
stretching = mini = np.nan
|
stretching = minimon = np.nan
|
||||||
if height is None:
|
if height is None:
|
||||||
height = self.t1min[1]
|
height = self.t1min[1]
|
||||||
|
|
||||||
@ -605,6 +617,7 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
stretching = t1_no_coup / height
|
stretching = t1_no_coup / height
|
||||||
|
prefactor = stretching
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError('Use `distribution` or `coupling` to set parameter')
|
raise ValueError('Use `distribution` or `coupling` to set parameter')
|
||||||
@ -617,13 +630,30 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
self.prefactor = self.coupling.relax(*self.coup_parameter, **self.coup_kw)
|
self.prefactor = self.coupling.relax(*self.coup_parameter, **self.coup_kw)
|
||||||
else:
|
else:
|
||||||
self.prefactor = prefactor
|
self.prefactor = prefactor
|
||||||
mini = np.min(self.t1(omega, np.logspace(*tau_lims, num=1001), *self.dist_parameter,
|
minimon = np.min(self.t1(omega, np.logspace(*tau_lims, num=1001), *self.dist_parameter,
|
||||||
prefactor=self.prefactor))
|
prefactor=self.prefactor))
|
||||||
|
|
||||||
return stretching, mini
|
return stretching, minimon
|
||||||
|
|
||||||
def calculate_t1_min(self, interpolate: int = None, trange: Tuple[float, float] = None, use_log: bool = False) -> \
|
def calculate_t1_min(self, interpolate: int = None, trange: Tuple[float, float] = None, use_log: bool = False) -> \
|
||||||
Tuple[Tuple[float, float], Optional[Tuple[np.ndarray, np.ndarray]]]:
|
Tuple[Tuple[float, float], Tuple[np.ndarray, np.ndarray] | None]:
|
||||||
|
"""
|
||||||
|
Determine a minimum position for given T1 data
|
||||||
|
|
||||||
|
Args:
|
||||||
|
interpolate (int, optional):
|
||||||
|
* 0 or None: No interpolation, minimum is data minimum
|
||||||
|
* 1: Interpolation with a parabola
|
||||||
|
* 2: Interpolation with a cubic spline
|
||||||
|
* 3: Interpolation with Akima spline (less wiggly than cubic)
|
||||||
|
trange (tuple): Range (left border, range border) of interpolation in K.
|
||||||
|
Interpolation without a given range uses two points left and right of minimum value.
|
||||||
|
use_log (bool): Default is `True`.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The minimum position (`T_min`, `T1_min`)
|
||||||
|
|
||||||
|
"""
|
||||||
min_index = np.argmin(self.y)
|
min_index = np.argmin(self.y)
|
||||||
t1_min = (self.x[min_index], self.y[min_index])
|
t1_min = (self.x[min_index], self.y[min_index])
|
||||||
parabola = None
|
parabola = None
|
||||||
@ -674,9 +704,25 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
return t1_min, parabola
|
return t1_min, parabola
|
||||||
|
|
||||||
def correlation_from_t1(self, mode: str = 'raw', interpolate: bool = False, omega: float = None,
|
def correlation_from_t1(self, mode: str = 'raw', interpolate: bool = False, omega: float = None,
|
||||||
dist_parameter: Union[float, list, tuple] = None, prefactor: Union[float, tuple, list] = None,
|
dist_parameter: list | tuple = None, prefactor: float = None,
|
||||||
coupling_param: list = None, coupling_kwargs: dict = None) -> Tuple[np.ndarray, dict]:
|
coupling_param: list = None, coupling_kwargs: dict = None) -> Tuple[np.ndarray, dict]:
|
||||||
|
"""
|
||||||
|
Calculate correlation times from set T1 data.
|
||||||
|
Optional arguments overwrite previousliy set parameter.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mode (str, {`raw`, `mean`, `logmean`, `max`}): Type of correlation time. Default is `raw`.
|
||||||
|
interpolate (bool): If ``True`` and T1 minimum was determined by nterpolation,
|
||||||
|
T1 on interpolated line instead of measured value is used. Default is `False`.
|
||||||
|
omega (float, optional): Larmor frequency (in 1/s)
|
||||||
|
dist_parameter (list, optional): List of parameter of spectral density
|
||||||
|
prefactor (float, optional): Prefactor of T1 calculation, will
|
||||||
|
coupling_param (list, optional): Parameter for coupling constant, ignored if `prefactor`is given.
|
||||||
|
coupling_kwargs (dict, optional): Keyword arguments for coupling constant, ignored if `prefactor`is given.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
if self.x is None:
|
if self.x is None:
|
||||||
raise ValueError('Temperature is not set')
|
raise ValueError('Temperature is not set')
|
||||||
|
|
||||||
@ -694,6 +740,7 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
|
|
||||||
if coupling_param is None:
|
if coupling_param is None:
|
||||||
prefactor = self.prefactor
|
prefactor = self.prefactor
|
||||||
|
coupling_param = self.coup_parameter
|
||||||
else:
|
else:
|
||||||
prefactor = self.coupling.relax(*coupling_param, **coupling_kwargs)
|
prefactor = self.coupling.relax(*coupling_param, **coupling_kwargs)
|
||||||
|
|
||||||
@ -711,7 +758,7 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
base_taus = np.logspace(-10, -7, num=1001)
|
base_taus = np.logspace(-10, -7, num=1001)
|
||||||
min_tau = base_taus[np.argmin(self.t1(omega, base_taus, *dist_parameter, prefactor=prefactor))]
|
min_tau = base_taus[np.argmin(self.t1(omega, base_taus, *dist_parameter, prefactor=prefactor))]
|
||||||
|
|
||||||
taus = np.geomspace(min_tau, 100. * min_tau, num=501)
|
taus = np.geomspace(min_tau, 100. * min_tau, num=1001)
|
||||||
current_t1 = self.t1(omega, taus, *dist_parameter, prefactor=prefactor)
|
current_t1 = self.t1(omega, taus, *dist_parameter, prefactor=prefactor)
|
||||||
|
|
||||||
for i in range(1, len(slow_t1) + 1):
|
for i in range(1, len(slow_t1) + 1):
|
||||||
@ -722,7 +769,7 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
t1_i = self._interpolate(slow_temp[-i])
|
t1_i = self._interpolate(slow_temp[-i])
|
||||||
|
|
||||||
if np.min(current_t1) > t1_i:
|
if np.min(current_t1) > t1_i:
|
||||||
warn('Correlation time could not be calculated')
|
warn(f'Value {t1_i} below set minimum, wonky correlation time')
|
||||||
correlation_times[offset - i] = taus[0]
|
correlation_times[offset - i] = taus[0]
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -738,7 +785,7 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
fast_t1 = self.y[fast_idx]
|
fast_t1 = self.y[fast_idx]
|
||||||
fast_temp = self.x[fast_idx]
|
fast_temp = self.x[fast_idx]
|
||||||
|
|
||||||
taus = np.geomspace(0.01 * min_tau, min_tau, num=501)
|
taus = np.geomspace(0.01 * min_tau, min_tau, num=1001)
|
||||||
current_t1 = self.t1(omega, taus, *dist_parameter, prefactor=prefactor)
|
current_t1 = self.t1(omega, taus, *dist_parameter, prefactor=prefactor)
|
||||||
|
|
||||||
for i in range(len(fast_t1)):
|
for i in range(len(fast_t1)):
|
||||||
@ -750,7 +797,7 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
|
|
||||||
if current_t1[-1] > t1_i:
|
if current_t1[-1] > t1_i:
|
||||||
correlation_times[offset + i] = taus[-1]
|
correlation_times[offset + i] = taus[-1]
|
||||||
warn(f'Correlation time for {correlation_times[offset + i]} could not be calculated')
|
warn(f'Value {t1_i} below set minimum, wonky correlation time')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
cross_idx = np.where(np.diff(np.sign(current_t1 - t1_i)))[0]
|
cross_idx = np.where(np.diff(np.sign(current_t1 - t1_i)))[0]
|
||||||
@ -763,11 +810,10 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
correlation_times[offset + i] = (taus[cross_idx + 1] * lamb + (1 - lamb) * taus[cross_idx])[0]
|
correlation_times[offset + i] = (taus[cross_idx + 1] * lamb + (1 - lamb) * taus[cross_idx])[0]
|
||||||
|
|
||||||
opts = {'distribution': (self.distribution.name, dist_parameter),
|
opts = {'distribution': (self.distribution.name, dist_parameter),
|
||||||
'frequency': omega / 2 / np.pi}
|
'frequency': omega / 2 / np.pi,
|
||||||
|
'prefactor': self.prefactor}
|
||||||
if self.coupling is not None:
|
if self.coupling is not None:
|
||||||
opts['coupling'] = (self.coupling.name, self.prefactor, coupling_param, coupling_kwargs)
|
opts['coupling'] = (self.coupling.name, coupling_param, coupling_kwargs)
|
||||||
else:
|
|
||||||
opts['coupling'] = (self.prefactor,)
|
|
||||||
|
|
||||||
return np.c_[self.x, self.distribution.mean_value(correlation_times, *dist_parameter, mode=mode)], opts
|
return np.c_[self.x, self.distribution.mean_value(correlation_times, *dist_parameter, mode=mode)], opts
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user