1
0
forked from IPKM/nmreval

BUGFIX: VFT;

change to src layout
This commit is contained in:
dominik 2022-10-20 17:23:15 +02:00
parent 89ce4bab9f
commit 8d148b639b
445 changed files with 1387 additions and 1920 deletions

View File

@ -2,7 +2,7 @@
import sys
import pathlib
sys.path.append(str(pathlib.Path().cwd().parent))
sys.path.append(str(pathlib.Path(__file__).parent.parent / 'src'))
from nmreval.configs import check_for_config
@ -15,8 +15,8 @@ check_for_config()
from nmreval.lib.logger import handle_exception
sys.excepthook = handle_exception
from nmreval.gui_qt import App
from nmreval.gui_qt.main.mainwindow import NMRMainWindow
from gui_qt import App
from gui_qt.main.mainwindow import NMRMainWindow
app = App([])

View File

@ -4,7 +4,7 @@
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= /autohome/dominik/miniconda3/bin/sphinx-build
SPHINXBUILD ?= # /autohome/dominik/miniconda3/bin/sphinx-build
SOURCEDIR = /autohome/dominik/nmreval/doc/source
BUILDDIR = /autohome/dominik/nmreval/doc/_build

View File

@ -1,16 +1,9 @@
"""
==========
T1 minimum
==========
================================
Example of apodization functions
================================
``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``
This file
"""
import numpy as np
import matplotlib.pyplot as plt

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

View File

@ -3,25 +3,36 @@
.. currentmodule:: {{ module }}
.. autoclass:: {{ objname }}
:exclude-members: {% for item in methods %}{%- if not item.startswith('_') or item in ['__call__'] %}{{ item }}, {% endif %}{%- endfor %}
{% block methods %}
{%- block methods %}
{% if methods %}
.. rubric:: {{ _('Methods') }}
{% for item in methods %}
.. automethod:: {{ item }}
{%- endfor %}
{% endif %}
{% endblock %}
{% block attributes %}
{% if attributes %}
.. rubric:: {{ _('Attributes') }}
.. rubric:: Methods
.. autosummary::
{% for item in attributes %}
~{{ name }}.{{ item }}
{%- endfor %}
:toctree:
{% for item in methods %}
{%- if not item.startswith('_') or item in ['__call__'] %} ~{{ name }}.{{ item }}
{% endif %}
{% endblock %}
{%- endfor %}
{%- endif %}
{%- endblock %}
{%- block attributes %}
{%- if attributes %}
.. rubric:: Properties
.. autosummary::
:toctree:
{% for item in attributes %}
{%- if not item.startswith('_') or item in ['__call__'] %} ~{{ name }}.{{ item }}
{% endif %}
{%- endfor %}
{%- endif %}
{%- endblock %}
.. _sphx_glr_backref_{{ fullname }}:
.. minigallery:: {{ objname }}
:add-heading:

View File

@ -1,5 +1,2 @@
.. automodule:: nmreval.distributions
:members:
:inherited-members:
:undoc-members:

View File

@ -11,3 +11,4 @@ Reference
models
distributions
nmr
math

View File

@ -12,7 +12,7 @@
#
import os
import sys
sys.path.append('/autohome/dominik/nmreval')
sys.path.append(os.path.abspath('../../src'))
import nmreval
@ -43,6 +43,9 @@ extensions = [
'sphinx.ext.viewcode',
'sphinx.ext.intersphinx',
'sphinx_gallery.gen_gallery',
'sphinx.ext.todo',
'sphinx.ext.autosectionlabel',
'sphinx.ext.mathjax',
]
# configuration for intersphinx
@ -56,7 +59,7 @@ intersphinx_mapping = {
# # autodoc options
autodoc_typehints = 'none'
autodoc_class_signature = 'separated'
# autodoc_class_signature = 'separated'
autoclass_content = 'class'
autodoc_member_order = 'groupwise'
#
@ -79,6 +82,7 @@ sphinx_gallery_conf = {
'min_reported_time': 10000000000,
'show_memory': False,
'show_signature': False,
'line_numbers': True,
}
# The suffix(es) of source filenames.
@ -151,15 +155,23 @@ todo_include_todos = False
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'pydata_sphinx_theme'
html_theme = 'sphinx_material' # 'sphinx_rtd_theme' # 'pydata_sphinx_theme'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {
'collapse_navigation': False,
'show_prev_next': False,
'navbar_end': ['navbar-icon-links.html', 'search-field.html'],
'nav_title': 'nmreval',
# 'base_url': 'https://chaos3.fkp.physik.tu-darmstadt.de/source/nmreval',
'repo_url': 'https://chaos3.fkp.physik.tu-darmstadt.de/source/nmreval',
'repo_name': 'Repo',
'html_minify': True,
'css_minify': True,
'master_doc': False,
'globaltoc_depth': 3,
'globaltoc_collapse': True,
'globaltoc_includehidden': True,
'heroes': {'index': 'Fun for the whole family!!!!'}
}
# Add any paths that contain custom themes here, relative to this directory.
@ -183,10 +195,10 @@ html_static_path = ['_static']
html_logo = '_static/logo.png'
# Custom sidebar templates, maps document names to template names.
html_sidebars = {'**': ['sidebar-nav-bs.html']}
# html_sidebars = {
# '**': ['localtoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html'],
# }
html_sidebars = {
"**": ["logo-text.html", "globaltoc.html", "localtoc.html", "searchbox.html"]
}
# If true, links to the reST sources are added to the pages.
html_show_sourcelink = False
@ -205,7 +217,7 @@ html_last_updated_fmt = ''
html_additional_pages = {}
# If false, no module index is generated.
html_domain_indices = False
html_domain_indices = True
# If false, no index is generated.
html_use_index = True
@ -214,10 +226,10 @@ html_use_index = True
html_split_index = False
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True
html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True
html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the

View File

@ -10,15 +10,15 @@ NMREval documentation
.. toctree::
:maxdepth: 1
install.rst
user_guide/index
gallery/index
api/index
Indices and tables
==================
Indices
=======
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
| :ref:`genindex`
| :ref:`modindex`

View File

@ -11,7 +11,8 @@ In general, time signals are calculated by integration of all orientations (see
.. math::
g(t) = \int f[\omega_\text{int}(\theta, \phi)t]\sin\theta\,\mathrm{d}\theta\,\mathrm{d}\phi
with :math:`f(\theta, \phi, t) = \cos[\omega_\text{int}(\theta, \phi) t]` or :math:`\exp[i\omega_\text{int}(\theta) t]` and fourier transform for a spectrum.
with :math:`f(\theta, \phi, t) = \cos[\omega_\text{int}(\theta, \phi) t]` or :math:`\exp[i\omega_\text{int}(\theta) t]`
and fourier transform for a spectrum.
However, summation over :math:`\theta`, :math:`\phi`, and calculating :math:`f(\theta, \phi, t)` for each orientation is time consuming.
Alternatively, if the orientations are equidistant in :math:`\cos\theta`, one can get to the spectrum directly by creating a histogram of :math:`\omega_\text{int}(\theta, \phi)`, thus circumventing a lot of calculations.

View File

@ -4,10 +4,6 @@
Fitting data
============
.. image:: ../_static/fit_dialog.png
:scale: 80%
:align: center
The picture gives an example of dialog to setup and start fits.
First, there is the possibiity to fit different functions, called models to differentiate from the functions inside each
model, to different data simultaneously.

View File

@ -1,11 +1,13 @@
==========
**********
User Guide
==========
**********
.. toctree::
:maxdepth: 2
read
gui/index
read/index
edit_signals
fit
shift_scale

View File

@ -1,19 +0,0 @@
.. _user_guide.read:
*************
Reading files
*************
Supported filetypes are
* Text files,
* DAMARIS HDF5 files,
* Grace images.
* HP alpha-analyzer EPS files
* NTNMR .tnt files
DAMARIS HDF files
=================
After scanning the selected file the program shows a list of the available data.

View File

@ -1,111 +0,0 @@
from typing import Union
import numpy as np
from scipy.integrate import simps
from scipy.special import gammaln
from .base import Distribution
class GGAlpha(Distribution):
name = r'General \Gamma (\alpha-process)'
parameter = [r'\alpha', r'\beta']
@staticmethod
def correlation(t, tau0, *args):
logtau0 = np.log(tau0)
logtau = np.linspace(logtau0-20, logtau0+20, num=4001)
taus = np.exp(logtau)
gtau = GGAlpha.distribution(taus, tau0, *args)
ret_val = np.array([simps(np.exp(-xvals/taus)*gtau, logtau) for xvals in t])
return ret_val
@staticmethod
def susceptibility(omega, tau0, *args):
logtau0 = np.log(tau0)
logtau = np.linspace(logtau0 - 20, logtau0 + 20, num=4001)
taus = np.exp(logtau)
gtau = GGAlpha.distribution(taus, tau0, *args)
ret_val = np.array([simps(1/(1+1j*xvals*taus) * gtau, logtau) for xvals in omega])
return ret_val
@staticmethod
def distribution(taus: Union[float, np.ndarray], tau: float, *args) -> Union[float, np.ndarray]:
alpha, beta = args
b_to_a = beta / alpha
norm = np.exp(gammaln(b_to_a) - b_to_a * np.log(b_to_a)) / alpha
t_to_t0 = taus / tau
ret_val = np.exp(-b_to_a * t_to_t0 ** alpha) * t_to_t0 ** beta
return ret_val / norm
class GGAlphaEW(Distribution):
name = r'General \Gamma (\alpha-process + EW)'
parameter = [r'\alpha', r'\beta']
@staticmethod
def correlation(t, tau0, *args):
logtau0 = np.log(tau0)
logtau = np.linspace(logtau0-20, logtau0+20, num=4001)
taus = np.exp(logtau)
gtau = GGAlphaEW.distribution(taus, tau0, *args)
# wir integrieren ueber lntau, nicht tau
ret_val = np.array([simps(np.exp(-xvals/taus)*gtau, logtau) for xvals in t])
return ret_val
@staticmethod
def susceptibility(omega, tau0, *args):
logtau0 = np.log(tau0)
logtau = np.linspace(logtau0 - 20, logtau0 + 20, num=4001)
taus = np.exp(logtau)
gtau = GGAlphaEW.distribution(taus, tau0, *args)
ret_val = np.array([simps(1/(1+1j*xvals*taus) * gtau, logtau) for xvals in omega])
return ret_val
@staticmethod
def distribution(tau: Union[float, np.ndarray], tau0: float, *args) -> Union[float, np.ndarray]:
alpha, beta, sigma, gamma = args
if gamma == beta:
return GGAlpha.distribution(tau, tau0, alpha, beta)
b_to_a = beta / alpha
g_to_a = gamma / alpha
t_to_t0 = tau / tau0
norm = (np.exp(gammaln(b_to_a)) + sigma**(gamma-beta) *
np.exp(gammaln(g_to_a) + (b_to_a-g_to_a)*np.log(b_to_a))) / np.exp(b_to_a*np.log(b_to_a)) / alpha
ret_val = np.exp(-b_to_a * t_to_t0**alpha) * t_to_t0**beta * (1 + (t_to_t0*sigma)**(gamma-beta))
return ret_val / norm
class GGBeta(Distribution):
name = r'General \Gamma (\beta-process)'
parameter = [r'\alpha', r'\beta']
@staticmethod
def correlation(t, tau0, *args):
logtau0 = np.log(tau0)
logtau = np.linspace(logtau0-20, logtau0+20, num=4001)
taus = np.exp(logtau)
gtau = GGBeta.distribution(taus, tau0, *args)
# wir integrieren ueber lntau, nicht tau
ret_val = np.array([simps(np.exp(-xvals/taus)*gtau, logtau) for xvals in t])
return ret_val
@staticmethod
def susceptibility(omega, tau0, *args):
logtau0 = np.log(tau0)
logtau = np.linspace(logtau0 - 20, logtau0 + 20, num=4001)
taus = np.exp(logtau)
gtau = GGBeta.distribution(taus, tau0, *args)
ret_val = np.array([simps(1/(1+1j*xvals*taus) * gtau, logtau) for xvals in omega])
return ret_val
@staticmethod
def distribution(tau: Union[float, np.ndarray], tau0: float, *args) -> Union[float, np.ndarray]:
a, b = args
norm = a * (1+b) * np.sin(np.pi*b/(1+b)) * b**(b/(1+b)) / np.pi
ret_val = b * (tau/tau0)**a + (tau/tau0)**(-a*b)
return norm / ret_val

View File

@ -1,189 +0,0 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'resources/_ui/fitcreationdialog.ui'
#
# Created by: PyQt5 UI code generator 5.12.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(614, 776)
self.verticalLayout_5 = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout_5.setContentsMargins(3, 3, 3, 3)
self.verticalLayout_5.setSpacing(3)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.groupBox = QtWidgets.QGroupBox(Dialog)
self.groupBox.setCheckable(True)
self.groupBox.setChecked(False)
self.groupBox.setObjectName("groupBox")
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.groupBox)
self.verticalLayout_7.setContentsMargins(3, 3, 3, 3)
self.verticalLayout_7.setSpacing(3)
self.verticalLayout_7.setObjectName("verticalLayout_7")
self.widget_2 = QtWidgets.QWidget(self.groupBox)
self.widget_2.setObjectName("widget_2")
self.gridLayout_2 = QtWidgets.QGridLayout(self.widget_2)
self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
self.gridLayout_2.setSpacing(3)
self.gridLayout_2.setObjectName("gridLayout_2")
self.name_lineedit = QtWidgets.QLineEdit(self.widget_2)
self.name_lineedit.setObjectName("name_lineedit")
self.gridLayout_2.addWidget(self.name_lineedit, 0, 1, 1, 1)
self.group_lineedit = QtWidgets.QLineEdit(self.widget_2)
self.group_lineedit.setObjectName("group_lineedit")
self.gridLayout_2.addWidget(self.group_lineedit, 1, 1, 1, 1)
self.group_label = QtWidgets.QLabel(self.widget_2)
self.group_label.setObjectName("group_label")
self.gridLayout_2.addWidget(self.group_label, 1, 0, 1, 1)
self.name_label = QtWidgets.QLabel(self.widget_2)
self.name_label.setObjectName("name_label")
self.gridLayout_2.addWidget(self.name_label, 0, 0, 1, 1)
self.lineEdit = QtWidgets.QLineEdit(self.widget_2)
self.lineEdit.setObjectName("lineEdit")
self.gridLayout_2.addWidget(self.lineEdit, 2, 1, 1, 1)
self.label_2 = QtWidgets.QLabel(self.widget_2)
self.label_2.setObjectName("label_2")
self.gridLayout_2.addWidget(self.label_2, 2, 0, 1, 1)
self.verticalLayout_7.addWidget(self.widget_2)
self.verticalLayout_5.addWidget(self.groupBox)
self.groupBox_2 = QtWidgets.QGroupBox(Dialog)
self.groupBox_2.setCheckable(True)
self.groupBox_2.setChecked(False)
self.groupBox_2.setObjectName("groupBox_2")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox_2)
self.verticalLayout_2.setContentsMargins(3, 3, 3, 3)
self.verticalLayout_2.setSpacing(3)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.widget_3 = QtWidgets.QWidget(self.groupBox_2)
self.widget_3.setObjectName("widget_3")
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.widget_3)
self.verticalLayout_8.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_8.setSpacing(3)
self.verticalLayout_8.setObjectName("verticalLayout_8")
self.tableWidget = QtWidgets.QTableWidget(self.widget_3)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.tableWidget.sizePolicy().hasHeightForWidth())
self.tableWidget.setSizePolicy(sizePolicy)
self.tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
self.tableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.tableWidget.setColumnCount(4)
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setRowCount(0)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
self.verticalLayout_8.addWidget(self.tableWidget)
self.parameter_button = QtWidgets.QToolButton(self.widget_3)
self.parameter_button.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
self.parameter_button.setAutoRaise(False)
self.parameter_button.setArrowType(QtCore.Qt.RightArrow)
self.parameter_button.setObjectName("parameter_button")
self.verticalLayout_8.addWidget(self.parameter_button)
self.verticalLayout_2.addWidget(self.widget_3)
self.verticalLayout_5.addWidget(self.groupBox_2)
self.groupBox_3 = QtWidgets.QGroupBox(Dialog)
self.groupBox_3.setCheckable(True)
self.groupBox_3.setChecked(False)
self.groupBox_3.setObjectName("groupBox_3")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.groupBox_3)
self.verticalLayout_3.setContentsMargins(3, 3, 3, 3)
self.verticalLayout_3.setSpacing(3)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.widget = QtWidgets.QWidget(self.groupBox_3)
self.widget.setObjectName("widget")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout_6.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_6.setSpacing(3)
self.verticalLayout_6.setObjectName("verticalLayout_6")
self.use_nuclei = QtWidgets.QCheckBox(self.widget)
self.use_nuclei.setObjectName("use_nuclei")
self.verticalLayout_6.addWidget(self.use_nuclei)
self.tabWidget = QtWidgets.QTabWidget(self.widget)
self.tabWidget.setTabPosition(QtWidgets.QTabWidget.West)
self.tabWidget.setTabsClosable(True)
self.tabWidget.setObjectName("tabWidget")
self.verticalLayout_6.addWidget(self.tabWidget)
self.selection_button = QtWidgets.QToolButton(self.widget)
self.selection_button.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
self.selection_button.setArrowType(QtCore.Qt.RightArrow)
self.selection_button.setObjectName("selection_button")
self.verticalLayout_6.addWidget(self.selection_button)
self.verticalLayout_3.addWidget(self.widget)
self.verticalLayout_5.addWidget(self.groupBox_3)
self.groupBox_4 = QtWidgets.QGroupBox(Dialog)
self.groupBox_4.setCheckable(True)
self.groupBox_4.setChecked(False)
self.groupBox_4.setObjectName("groupBox_4")
self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox_4)
self.verticalLayout.setObjectName("verticalLayout")
self.namespace_widget = QNamespaceWidget(self.groupBox_4)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.namespace_widget.sizePolicy().hasHeightForWidth())
self.namespace_widget.setSizePolicy(sizePolicy)
self.namespace_widget.setObjectName("namespace_widget")
self.verticalLayout.addWidget(self.namespace_widget)
self.verticalLayout_5.addWidget(self.groupBox_4)
self.frame_4 = QtWidgets.QFrame(Dialog)
self.frame_4.setObjectName("frame_4")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.frame_4)
self.verticalLayout_4.setContentsMargins(3, 3, 3, 3)
self.verticalLayout_4.setSpacing(3)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.label = QtWidgets.QLabel(self.frame_4)
self.label.setObjectName("label")
self.verticalLayout_4.addWidget(self.label)
self.plainTextEdit = CodeEditor(self.frame_4)
self.plainTextEdit.setObjectName("plainTextEdit")
self.verticalLayout_4.addWidget(self.plainTextEdit)
self.verticalLayout_5.addWidget(self.frame_4)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout_5.addWidget(self.buttonBox)
self.name_label.setBuddy(self.name_lineedit)
self.retranslateUi(Dialog)
self.buttonBox.accepted.connect(Dialog.accept)
self.buttonBox.rejected.connect(Dialog.reject)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.groupBox.setTitle(_translate("Dialog", "Description"))
self.group_label.setText(_translate("Dialog", "Group"))
self.name_label.setText(_translate("Dialog", "Name"))
self.label_2.setText(_translate("Dialog", "Equation"))
self.groupBox_2.setTitle(_translate("Dialog", "Variables"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("Dialog", "Variable"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("Dialog", "Name"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("Dialog", "Lower bound"))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("Dialog", "Upper bound"))
self.parameter_button.setText(_translate("Dialog", "Add parameter"))
self.groupBox_3.setTitle(_translate("Dialog", "Multiple choice part"))
self.use_nuclei.setText(_translate("Dialog", "Add gyromagnetic ratios"))
self.selection_button.setText(_translate("Dialog", "Add selection"))
self.groupBox_4.setTitle(_translate("Dialog", "Available namespace"))
self.label.setText(_translate("Dialog", "Function y = func(x)"))
from ..lib.codeeditor import CodeEditor
from ..lib.namespace import QNamespaceWidget

View File

@ -1,238 +0,0 @@
import re
import numexpr as ne
import numpy as np
from ..Qt import QtCore, QtWidgets
from .._py.fitcreationdialog import Ui_Dialog
_numexpr_funcs = []
for k, _ in ne.expressions.functions.items():
pat = k + r'\('
_numexpr_funcs.append((re.compile(pat), 'np.' + k + '('))
class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
classCreated = QtCore.pyqtSignal(object)
def __init__(self, parent=None):
super().__init__(parent=parent)
self.setupUi(self)
self.namespace_widget.make_namespace()
self.tableWidget.itemChanged.connect(self.update_function)
self.groupBox.toggled.connect(self.change_visibility)
self.groupBox_2.toggled.connect(self.change_visibility)
self.groupBox_3.toggled.connect(self.change_visibility)
self.groupBox_4.toggled.connect(self.change_visibility)
self.groupBox.setChecked(True)
def __call__(self, *args, **kwargs):
for w in [self.lineEdit_4, self.lineEdit, self.lineEdit_3, self.lineEdit_2,
self.parameterLineEdit, self.externalParametersLineEdit]:
w.clear()
def check(self):
self.name = self.name_lineedit.text()
self.group = self.group_lineedit.text()
self.eq = str(self.lineEdit.text())
self.p = str(self.parameterLineEdit.text()).split()
self.func = str(self.lineEdit_4.text())
self._func_string = ''
error = []
for k, v in [('Name', self.name), ('Group', self.group), ('Parameters', self.p), ('Function', self.func)]:
if not v:
error.append('Empty ' + str(k))
if self.name:
if self.name[0].isdigit():
error.append('Name starts with digit')
if self.p:
if set(self.p) & set(self.ext_p):
error.append('Duplicate entries: {}'.format(list(set(self.p) & set(self.ext_p))))
if self.p and self.func:
p_test = np.ones((len(self.p)+len(self.ext_p)))
_x = np.arange(2)
namespace = {'x': _x}
for i, pp in enumerate(p_test):
namespace[f'p_{i}'] = pp
self._func_string = self.func + ''
self._func_string = self._func_string.replace('[', '_').replace(']', '')
try:
ne.evaluate(self._func_string, local_dict=namespace)
except KeyError:
error.append(f'Incorrect evaluation {self.func}')
if error:
QtWidgets.QMessageBox().warning(self, 'Invalid entries', '\n'.join(error))
else:
return True
def accept(self):
self.confirm()
super().accept()
def confirm(self):
print(f' name = {self.name_lineedit.text()}')
group_type = self.group_lineedit.text()
if group_type:
print(f' group = "{group_type}"')
else:
print(' group = "User-defined"')
var = []
for row in range(self.tableWidget.rowCount()):
var.append(self.tableWidget.item(row, 1).text())
if var:
print(' params = [r"', end='')
print('", r"'.join(var) + '"]')
else:
print(' params = []')
print('\n@staticmethod')
print(self.label.text())
import inspect
for k, v in self.namespace_widget.namespace.flatten().items():
if inspect.isfunction(v):
print(k, inspect.getmodule(v))
print(k, [cc[1] for cc in inspect.getmembers(v) if cc[0] == '__qualname__'])
else:
print(k, v)
print(self.plainTextEdit.toPlainText())
@QtCore.pyqtSlot(name='on_parameter_button_clicked')
def add_variable(self):
self.tableWidget.blockSignals(True)
row = self.tableWidget.rowCount()
self.tableWidget.setRowCount(row+1)
self.tableWidget.setItem(row, 0, QtWidgets.QTableWidgetItem('p'+str(row)))
self.tableWidget.setItem(row, 1, QtWidgets.QTableWidgetItem('p_{'+str(row)+'}'))
self.tableWidget.setItem(row, 2, QtWidgets.QTableWidgetItem('--'))
self.tableWidget.setItem(row, 3, QtWidgets.QTableWidgetItem('--'))
self.tableWidget.blockSignals(False)
self.update_function(None)
@QtCore.pyqtSlot(name='on_selection_button_clicked')
def add_choice(self):
cnt = self.tabWidget.count()
self.tabWidget.addTab(ChoiceWidget(self), 'choice' + str(cnt))
self.tabWidget.setCurrentIndex(cnt)
def register(self):
i = 0
basename = self.name.replace(' ', '')
classname = basename
# while classname in _userfits:
# classname = basename + '_' + str(i)
# i += 1
c = register_class(classname, self.name, self.group, self.p, self.eq, self._func_string)
self.classCreated.emit(c)
return classname, c
def save(self, cname):
t = '\n# Created automatically\n' \
'class {cname:}(object):\n'\
' name = "{name:}"\n' \
' type = "{group:}"\n'\
' equation = "{eq:}"\n'\
' params = {p:}\n' \
' ext_params = {ep:}\n\n' \
' @staticmethod\n' \
' def func(p, x):\n' \
' return {func:}\n'
f_string = self.func
for pat, repl in _numexpr_funcs:
f_string = re.sub(pat, repl, f_string)
@QtCore.pyqtSlot(QtWidgets.QTableWidgetItem)
@QtCore.pyqtSlot(str)
def update_function(self, _):
var = []
for row in range(self.tableWidget.rowCount()):
var.append(self.tableWidget.item(row, 0).text())
if self.use_nuclei.isChecked():
var.append('nucleus=2.67522128e8')
# for row in range(self.selection_combobox.count()):
# var.append(self.selection_combobox.itemText(row) + '=')
self.label.setText('def func(x, ' + ', '.join(var) + '):')
def change_visibility(self):
sender = self.sender()
for gb in [self.groupBox, self.groupBox_2, self.groupBox_3, self.groupBox_4]:
gb.blockSignals(True)
gb.setChecked(sender == gb)
gb.blockSignals(False)
self.widget_2.setVisible(sender == self.groupBox)
self.widget_3.setVisible(sender == self.groupBox_2)
self.widget.setVisible(sender == self.groupBox_3)
self.namespace_widget.setVisible(sender == self.groupBox_4)
class ChoiceWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent=parent)
self._init_ui()
def _init_ui(self):
layout = QtWidgets.QGridLayout()
layout.setContentsMargins(3, 3, 3, 3)
layout.setHorizontalSpacing(6)
self.label = QtWidgets.QLabel('Name', parent=self)
layout.addWidget(self.label, 0, 0)
self.name_line = QtWidgets.QLineEdit(self)
layout.addWidget(self.name_line, 0, 1)
self.label_2 = QtWidgets.QLabel('Displayed name', parent=self)
layout.addWidget(self.label_2, 0, 2)
self.display_line = QtWidgets.QLineEdit(self)
layout.addWidget(self.display_line, 0, 3)
self.label_3 = QtWidgets.QLabel('Type', parent=self)
layout.addWidget(self.label_3)
self.types = QtWidgets.QComboBox(self)
self.types.addItems(['str', 'int', 'float'])
layout.addWidget(self.types)
self.add_button = QtWidgets.QPushButton('Add option')
layout.addWidget(self.add_button)
self.table = QtWidgets.QTableWidget(self)
self.table.setColumnCount(2)
self.table.setHorizontalHeaderLabels(['Name', 'Value'])
layout.addWidget(self.table, 2, 0, 1, 4)
self.setLayout(layout)
def register_class(cname, name, group, p, eq, func):
c = type(cname, (), {})
c.name = name
c.type = group
c.params = p
c.equation = eq
c.func = func_decorator(func)
return c
def func_decorator(f_string):
# we need this decorator because the result is used in a class
def wrapped_f(*args):
namespace = {'x': args[1]}
for i, pp in enumerate(args[0]):
namespace['p_{}'.format(i)] = pp
return ne.evaluate(f_string, local_dict=namespace)
return wrapped_f

View File

@ -1,357 +0,0 @@
import numpy as np
from scipy.integrate import trapz
from .orientations import zcw_spherical as crystallites
class Powder(object):
def __init__(self, n=100):
self.alpha, self.beta, self.wt = crystallites(n)
class Pake(object):
parameter = {'delta': 0., 'eta': 0., 'w_iso': 0.,
'x': None, 'y': None, 'half': False}
def __init__(self, samples=10000):
self.powder = Powder(n=samples)
self.dw = None
self.parameter = {}
self.GB = 1000
self.pw = 1e-6
self.legendre = 0
self.axial = 0
self.calc_prefactor()
def calc_prefactor(self):
"""
Calculates angular dependencies
Returns
-------
"""
self.legendre = 3 * np.square(np.cos(self.powder.beta)) - 1
self.axial = np.square(np.sin(self.powder.beta)) * np.cos(2 * self.powder.alpha)
def set_parameter(self, p, dw=None):
self.parameter['delta'] = p[0] * 1e3
self.parameter['eta'] = p[1]
self.GB = p[2] * 1e3
self.pw = p[3] * 1e-6
if len(p) == 5:
self.parameter['w_iso'] = p[4] * 1e3
if dw is not None:
self.dw = dw
@staticmethod
def _check_old_data(x, d, e, w, h):
if Pake.parameter['x'] is None:
return False
if Pake.parameter['w_iso'] == w and Pake.parameter['delta'] == d and \
Pake.parameter['eta'] == e and Pake.parameter['half'] == h and \
Pake.parameter['x'][0] == x[0] and Pake.parameter['x'][1] == x[1]:
return True
return False
def calc_timesignal(self, tt, p, half=False):
"""
Calculate time signal of pake spectrum
Parameters
----------
tt: time array
p: list of parameters [delta, eta, GB, omega_iso]
half: if False, Pake spectrum will be calculated, if True, chemical shift spectrum will be calculated
Returns
-------
timesignal
"""
_delta, _eta, _wiso = p
omega = 0.5 * _delta * (self.legendre - _eta * self.axial)
if half:
omega += _wiso
weight = self.powder.wt
if half:
fid_real = np.zeros_like(tt, dtype=float)
fid_imag = np.zeros_like(tt, dtype=float)
for k, v in zip(omega, weight):
pha = 2 * np.pi * k * tt
fid_real += (np.cos(pha)) * v
fid_imag += (np.sin(pha)) * v
fid = 1j * fid_imag
fid += fid_real
else:
fid = np.zeros_like(tt, dtype=float)
for k, v in zip(omega, weight):
fid += np.cos(2 * np.pi * k * tt) * v
return fid
@staticmethod
def calc_pulse(pw, f):
_phi = 2 * np.pi * f * pw
pulse = ((0.5 * np.pi * np.sin(np.sqrt(0.25 * np.pi ** 2 + 0.5 * _phi ** 2))) /
np.sqrt(0.25 * np.pi ** 2 + 0.25 * _phi ** 2)) ** 1
return pulse
def pake_spectrum(self, x, p=None, half=False):
if p is None:
_gb = self.GB
_pw = self.pw
try:
_delta = self.parameter['delta']
_eta = self.parameter['eta']
_wiso = self.parameter['w_iso']
except KeyError:
_delta = Pake.parameter['delta']
_eta = Pake.parameter['eta']
_wiso = Pake.parameter['w_iso']
else:
_delta = p[0] * 1e3
_eta = p[1]
_gb = p[2] * 1e3
_pw = p[3] * 1e-6
_wiso = p[4] * 1e3
# x is time
if abs(x[1] - x[0]) < 1:
if self.dw is None:
self.dw = x[1] - x[0]
t = x
nop = len(x)
isfreq = False
# x is frequency
else:
df = (x[1] - x[0])
if self.dw is None:
self.dw = 1 / (df * len(x))
if len(x) != 1 / (self.dw * df):
nop = int(1 / (self.dw * df))
else:
nop = len(x)
# avoid calculation for to much points
t = np.arange(0, min(8192, nop)) * self.dw
isfreq = True
new_data = self._check_old_data((nop, self.dw), _delta, _eta, _wiso, half)
if new_data:
fid = Pake.parameter['y'] + 0
Pake.parameter['delta'] = _delta
Pake.parameter['eta'] = _eta
Pake.parameter['w_iso'] = _wiso
Pake.parameter['x'] = (nop, self.dw)
Pake.parameter['half'] = half
self.GB = _gb
self.pw = _pw
fid = self.calc_timesignal(t, [_delta, _eta, _wiso], half=half)
Pake.parameter['y'] = fid + 0
fid *= np.exp(-(_gb * t) ** 2)
# add zeros to get desired signal length
if len(fid) != nop:
fid = np.append(fid, np.zeros((nop - len(fid))), axis=0)
spec = np.fft.fftshift(np.fft.fft(fid))
spec -= np.mean(spec[:10])
_f = np.fft.fftshift(np.fft.fftfreq(nop, d=self.dw))
# take finite pulse length into account
if _pw != 0:
pulse = self.calc_pulse(_pw, _f)
spec *= pulse
# shift pake spectrum by isotropic shift
if not half:
spec = np.roll(spec, int(self.dw * _wiso * nop))
# cut to original frequency range
if isfreq:
# mask = np.ma.masked_inside(_f, min(x), max(x)).mask
# spec = spec[mask]
spec = np.interp(x, _f, spec.real)
spec.real -= np.mean(spec.real[:10])
return spec.real / max(spec.real)
def pake(self, x, p=None):
return self.pake_spectrum(x, p=p)
def halfpake(self, x, p=None):
return self.pake_spectrum(x, p=p, half=True)
class SecondOrder(object):
parameter = {'c_q': 1e6, 'eta': 0.,
'x': None, 'y': None}
def __init__(self, samples=200000):
self.powder = Powder(n=samples)
self.dw = None
self.parameter = {}
self.GB = 1000
self.pw = 1e-6
self.legendre = 0
self.axial = 0
self.coupling = 1
self.larmor = 2 * np.pi * 100e6
def set_parameter(self, p, dw=None, larmor=None, spin=2.5):
self.parameter['c_q'] = 2 * np.pi * p[0] * 1e6
self.parameter['eta'] = p[1]
self.GB = p[2] * 1e3
if dw is not None:
self.dw = dw
if larmor is not None:
self.larmor = 2 * np.pi * larmor
self._calc_coupling(2 * np.pi * p[0] * 1e6, spin=spin)
def _calc_coupling(self, c_q, spin=2.5):
omega_q = c_q / (2 * spin * (2 * spin - 1))
self.coupling = 1.5 * omega_q ** 2 / self.larmor * (spin * (spin + 1) - 0.75)
def calc_omega(self, eta, delta):
self._calc_coupling(delta)
cos2phi = np.cos(2 * self.powder.alpha)
cos_theta_square = 0.5 + 0.5 * np.cos(2 * self.powder.beta)
prefactor_a = -3.375 + 2.25 * eta * cos2phi - 0.375 * (eta * cos2phi) ** 2
prefactor_b = 3.75 - 0.5 * eta ** 2 - 2 * eta * cos2phi + 0.75 * (eta * cos2phi) ** 2
prefactor_c = -0.375 + (eta ** 2) / 3. - 0.25 * eta * cos2phi - 0.375 * (eta * cos2phi) ** 2
ret_val = np.zeros_like(cos2phi)
ret_val += prefactor_a * cos_theta_square ** 2
ret_val += prefactor_b * cos_theta_square
ret_val += prefactor_c
return self.coupling * ret_val
def calc_timesignal(self, tt, p):
delta, eta = p
omega = self.calc_omega(eta, delta)
weight = self.powder.wt
fid_real = np.zeros_like(tt, dtype=float)
fid_imag = np.zeros_like(tt, dtype=float)
for o, w in zip(omega, weight):
pha = o * tt
co_pha = np.cos(pha)
si_pha = np.sin(pha)
fid_real += co_pha * w
fid_imag += si_pha * w
fid = 1j * fid_imag
fid += fid_real
return fid
def spectrum(self, x, p=None):
if p is None:
p = [self.parameter['c_q'], self.parameter['eta'], self.GB]
if abs(x[1] - x[0]) < 1:
if self.dw is None:
self.dw = x[1] - x[0]
t = x
nop = len(x)
isfreq = False
else:
df = (x[1] - x[0])
if self.dw is None:
self.dw = 1 / (df * len(x))
if len(x) != 1 / (self.dw * df):
nop = int(1 / (self.dw * df))
else:
nop = len(x)
t = np.arange(0, min(8192, nop)) * self.dw
isfreq = True
fid = self.calc_timesignal(t, p[:-1])
fid *= np.exp(-(p[-1] * t) ** 2)
if len(fid) != nop:
fid = np.append(fid, np.zeros((nop - len(fid))), axis=0)
spec = np.fft.fftshift(np.fft.fft(fid))
_f = np.fft.fftshift(np.fft.fftfreq(nop, d=self.dw))
if isfreq:
mask = np.ma.masked_inside(_f, min(x), max(x)).mask
spec = spec[mask]
return spec.real - np.mean(spec.real[:10])
def csa(x: np.ndarray, delta: float, eta: float, wiso: float, gb: float, sw: float):
dw = 1 / sw
a, b, _ = crystallites(200000)
bins = 0.5 * (x[1:] + x[:-1])
bins = np.hstack((np.array([0.5 * (-x[1] + 3 * x[0])]), bins, np.array([0.5 * (3 * x[-1] - x[-2])])))
omega = wiso + delta * 0.5 * (3 * np.cos(b) ** 2 - 1 - eta * np.square(np.sin(b)) * np.cos(2 * a))
s_left = np.histogram(omega, bins=bins)[0]
s = s_left
if gb != 0:
apd = np.exp(-4 * np.log(2) * (np.fft.fftshift(np.fft.fftfreq(len(x), d=dw)) / sw) ** 2) * \
2 * np.sqrt(np.log(2) / np.pi) / gb
ret_val = np.convolve(s, apd, mode='same')
else:
ret_val = s
return ret_val / trapz(ret_val, x)
def pake(p, x):
dw = 1/p[-1]
a, b, _ = crystallites(200000)
bins = 0.5 * (x[1:] + x[:-1])
bins = np.hstack((np.array([0.5 * (-x[1] + 3 * x[0])]), bins, np.array([0.5 * (3 * x[-1] - x[-2])])))
omega = p[0] * 0.5 * (3*np.cos(b)**2 - 1 - p[1] * np.square(np.sin(b)) * np.cos(2 * a))
s_left = np.histogram(omega, bins=bins)[0]
s_right = np.histogram(-omega, bins=bins)[0]
s = s_left + s_right
if p[2] != 0:
apd = np.exp(-4 * np.log(2) * (np.fft.fftshift(np.fft.fftfreq(len(x), d=dw)) / p[2]) ** 2) * \
2 * np.sqrt(np.log(2) / np.pi) / p[2]
ret_val = np.convolve(s, apd, mode='same')
else:
ret_val = s
return ret_val/trapz(ret_val, x)
def sec_order(p, x, spin=2.5):
dw = 1/p[-1]
a, b, _ = crystallites(200000)
bins = 0.5 * (x[1:] + x[:-1])
bins = np.hstack((np.array([0.5 * (-x[1] + 3 * x[0])]), bins, np.array([0.5 * (3 * x[-1] - x[-2])])))
omega_q = 2 * np.pi * p[0] / (2*spin * (2*spin - 1))
coupling = 1.5 * (omega_q**2 / (2 * np.pi *p[3])) * (spin*(spin + 1) - 0.75)
cos2phi = np.cos(2 * a)
cos_theta_square = 0.5+0.5*np.cos(2*b)
prefactor_a = -3.375 + 2.25*p[1] * cos2phi - 0.375 * (p[1] * cos2phi)**2
prefactor_b = 3.75 - 0.5 * p[1]**2 - 2*p[1]*cos2phi + 0.75 * (p[1]*cos2phi)**2
prefactor_c = -0.375 + (p[1]**2)/3. - 0.25*p[1]*cos2phi - 0.375 * (p[1]*cos2phi)**2
orient = np.zeros_like(cos2phi)
orient += prefactor_a * cos_theta_square ** 2
orient += prefactor_b * cos_theta_square
orient += prefactor_c
omega = coupling * orient
s = np.histogram(omega/(2*np.pi), bins=bins)[0]
if p[2] != 0:
apd = np.exp(-4 * np.log(2) * (np.fft.fftshift(np.fft.fftfreq(len(x), d=dw)) / p[2]) ** 2) * \
2 * np.sqrt(np.log(2) / np.pi) / p[2]
ret_val = np.convolve(s, apd, mode='same')
else:
ret_val = s
return ret_val / trapz(ret_val, x)

View File

@ -1,268 +0,0 @@
import numpy as np
from scipy.special import gammaln
from ..math.logfourier import logft
stepsize = 0.2 # 0.05
span1 = 20
span2 = 30
class GeneralGamma(object):
lower_b = 20
upper_b = 20
dx = 0.2
@staticmethod
def gga_dist(tau, tau0, alpha, beta):
b_to_a = beta / alpha
norm = np.exp(gammaln(b_to_a) - b_to_a * np.log(b_to_a)) / alpha
t_to_t0 = tau / tau0
ret_val = np.exp(-b_to_a * t_to_t0 ** alpha) * t_to_t0 ** beta
return ret_val / norm
@staticmethod
def gga_ew_dist(tau, tau0, alpha, beta, sigma, gamma):
if gamma == beta:
return GeneralGamma.gga_dist(tau, tau0, alpha, beta)
b_to_a = beta / alpha
g_to_a = gamma / alpha
t_to_t0 = tau / tau0
norm = (np.exp(gammaln(b_to_a)) + sigma**(gamma-beta) * np.exp(gammaln(g_to_a) + (b_to_a-g_to_a)*np.log(b_to_a))) / np.exp(b_to_a*np.log(b_to_a)) / alpha
ret_val = np.exp(-b_to_a * t_to_t0**alpha) * t_to_t0**beta * (1 + (t_to_t0*sigma)**(gamma-beta))
return ret_val / norm
@staticmethod
def ggb_dist(tau, tau0, a, b):
norm = a * (1+b) * np.sin(np.pi*b/(1+b)) * b**(b/(1+b)) / np.pi
ret_val = b * (tau/tau0)**a + (tau/tau0)**(-a*b)
return norm / ret_val
@staticmethod
def _gg_time(t, tau0, *args, **kwargs):
logtau = np.log(tau0)
steps = np.arange(logtau - GeneralGamma.lower_b, logtau + GeneralGamma.upper_b, GeneralGamma.dx)
taus = np.exp(steps)
ret_val = np.zeros_like(t)
dist = {'gga': GeneralGamma.gga_dist,
'gga_ew': GeneralGamma.gga_ew_dist,
'ggb': GeneralGamma.ggb_dist}[kwargs.pop('mode', 'gga')]
gtau = dist(taus, tau0, *args)
for i, xval in enumerate(t):
y = np.exp(- xval / taus)
y *= gtau
y = y[1:] + y[:-1]
ret_val[i] = np.sum(y) * GeneralGamma.dx / 2
return ret_val
@staticmethod
def ggaew_b_freq(f, tau0, alpha, beta, sigma, gamma, tau1, a, b, r, dec=5):
t = np.logspace(np.log10(1 / max(f)) - dec, np.log10(1 / min(f)) + dec, num=int(len(f) * (0.5 * dec)))
phi_a = GeneralGamma.ggaew(t, tau0, alpha, beta, sigma, gamma)
phi_b = GeneralGamma.ggb(t, tau1, a, b)
temp = phi_a * (1 - r + r * phi_b)
ret_val = logft(t, temp, new_x=2 * np.pi * f)[1].y
return ret_val * f * 2 * np.pi
@staticmethod
def gga_b_freq(f, tau0, alpha, beta, tau1, a, b, r, dec=5):
t = np.logspace(np.log10(1 / max(f)) - dec, np.log10(1 / min(f)) + dec, num=int(len(f) * (0.5 * dec)))
phi_a = GeneralGamma.gga(t, tau0, alpha, beta)
phi_b = GeneralGamma.ggb(t, tau1, a, b)
temp = phi_a * (1 - r + r * phi_b)
ret_val = logft(t, temp, new_x=2 * np.pi * f)[1].y
return ret_val * f * 2 * np.pi
@staticmethod
def gga(t, tau0, alpha, beta):
return GeneralGamma._gg_time(t, tau0, alpha, beta, mode='gga')
@staticmethod
def ggaew(t, tau0, alpha, beta, sigma, gamma):
return GeneralGamma._gg_time(t, tau0, alpha, beta, sigma, gamma, mode='gga_ew')
@staticmethod
def ggb(t, tau0, a, b):
return GeneralGamma._gg_time(t, tau0, a, b, mode='ggb')
@staticmethod
def ggaew_b(t, tau0, alpha, beta, sigma, gamma, tau1, a, b, r):
phi_a = GeneralGamma.ggaew(t, tau0, alpha, beta, sigma, gamma)
phi_b = GeneralGamma.ggb(t, tau1, a, b)
ret_val = phi_a * (1 - r + r * phi_b)
return ret_val
@staticmethod
def gga_b(t, tau0, alpha, beta, tau1, a, b, r):
phi_a = GeneralGamma.gga(t, tau0, alpha, beta)
phi_b = GeneralGamma.ggb(t, tau1, a, b)
ret_val = phi_a * (1 - r + r * phi_b)
return ret_val
class FitGG(object):
name = 'Alpha + Beta + EW'
type = 'Gamma-Functions'
equation = r'A*\Phi_{\alpha,EW} * [1 - C + C*\Phi_{\beta}] + B'
params = ['A', 'B',
r'\tau_{\alpha}', r'\alpha', r'\beta', '\sigma', '\gamma',
r'\tau_{\beta}', 'a', 'b', 'C']
@staticmethod
def func(p, x):
amp, base, tau0, alpha, beta, sigma, gamma, tau1, a, b, c = p
phi_a = GeneralGamma.ggaew(x, tau0, alpha, beta, sigma, gamma)
phi_b = GeneralGamma.ggb(x, tau1, a, b)
ret_val = amp * phi_a * (1 - c + c * phi_b) + base
return ret_val
# Definiere Funktionen #
def glntau1_td(ttime, tau, alpha, beta):
lnx = np.log(tau) + span1
intmin = np.log(tau) - span2
steps = np.arange(lnx, intmin, -stepsize)
explnx = np.exp(steps)
betatoalpha = beta / alpha
logtau = np.log(tau)
if betatoalpha > 80:
norm = np.exp(.5 * np.log(2 * np.pi / betatoalpha) - betatoalpha) / alpha
else:
norm = np.exp(gammaln(betatoalpha)) / alpha / np.power(betatoalpha, betatoalpha)
y = np.exp(-np.exp((steps - logtau) * alpha) * betatoalpha) * np.power(explnx / tau, beta) * np.exp(-ttime / explnx)
y = y[1:] + y[:-1]
intval = np.sum(y) / 2
intval = intval * stepsize / norm
return intval
def gga(t, tau0, alpha, beta):
logtau = np.log(tau0)
stepsize = 0.2
steps = np.arange(logtau - 20, logtau + 20, stepsize)
taus = np.exp(steps)/tau0
betatoalpha = beta / alpha
norm = np.exp(gammaln(betatoalpha) - betatoalpha*np.log(betatoalpha)) / alpha
ret_val = np.zeros_like(t)
gtau = np.exp(-taus ** alpha * betatoalpha) * taus ** beta
for i, xval in enumerate(t):
# exponent = -taus**alpha * betatoalpha - xval/taus/tau0
y = np.exp(- xval/taus/tau0)
y *= gtau
y = y[1:] + y[:-1]
ret_val[i] = np.sum(y) * stepsize / norm / 2
return ret_val
def ggaew(t, tau0, alpha, beta, sigma, gamma):
logtau = np.log(tau0)
stepsize = 0.2
steps = np.arange(logtau - 20, logtau + 20, stepsize)
taus = np.exp(steps) / tau0
q1 = beta / alpha
q2 = gamma / alpha
norm = (np.exp(gammaln(q1)) + sigma**(gamma-beta) * np.exp((q1-q2)*np.log(q1)) * np.exp(gammaln(q2))) / alpha / np.exp(q1*np.log(q1))
ret_val = np.empty_like(t)
gtau = np.exp(-taus**alpha * q1) * taus**beta * (1 + (taus*sigma)**(gamma-beta))
for i, xval in enumerate(t):
y = np.exp(-xval/taus/tau0)
y *= gtau
y = y[1:] + y[:-1]
ret_val[i] = np.sum(y) * stepsize / norm / 2
return ret_val
def ggaew_b(t, tau0, alpha, beta, sigma, gamma, tau1, a, b, r):
phi_a = ggaew(t, tau0, alpha, beta,sigma, gamma)
phi_b = ggb(t, tau1, a, b)
ret_val = phi_a * (1-r + r*phi_b)
return ret_val
def ggb(t, tau0, a, b):
logtau = np.log(tau0)
stepsize = 0.2
steps = np.arange(logtau - 20, logtau + 20, stepsize)
taus = np.exp(steps) / tau0
norm = np.pi / (a*(1+b)) / b**(b/(1+b)) / np.sin(np.pi*b / (1+b))
ret_val = np.empty_like(t)
gtau = 1. / (b * taus**a + taus**(-b*a))
for i, xval in enumerate(t):
y = np.exp(-xval / taus / tau0)
y *= gtau
y = y[1:] + y[:-1]
ret_val[i] = np.sum(y) * stepsize / norm / 2
return ret_val
def glntau2_td(ttime, tau, alpha, beta, sigma, gam):
intval = 0
lnx = np.log(tau) + span1
intmin = np.log(tau) - span2
steps = np.arange(lnx, intmin, -stepsize)
explnx = np.exp(steps)
logtau = np.log(tau)
q1 = beta / alpha
q2 = gam / alpha
if q2 > 80:
norm = (np.exp(.5 * np.log(2 * np.pi / q1) - q1) + np.power(sigma, alpha * (q2 - q1)) * np.power(q2 / q1,
-q2) * np.exp(
.5 * np.log(2 * np.PI / q2) - q2)) / alpha
elif q1 > 80:
norm = (np.exp(.5 * np.log(2 * np.pi / q1) - q1) + np.power(sigma, alpha * (q2 - q1)) * np.power(q2 / q1,
-q2) * np.exp(
gammaln(q2)) * np.power(q1, -q1)) / alpha
else:
norm = (np.exp(gammaln(q1)) + np.power(sigma, gam - beta) * np.power(q1, q1 - q2) * np.exp(gammaln(q2))) / (
alpha * np.power(q1, q1))
y = np.exp(-np.exp((steps - logtau) * alpha) * q1) * np.power(explnx / tau, beta) * (
1 + np.power(explnx * sigma / tau, gam - beta)) * np.exp(-ttime / explnx)
y = y[1:] + y[:-1]
intval = np.sum(y) / 2
intval = intval * stepsize / norm
return intval
def glnbeta_td(ttime, tau, a, b):
intval = 0
lnx = np.log(tau) + span1
intmin = np.log(tau) - span2
steps = np.arange(lnx, intmin, -stepsize)
explnx = np.exp(steps)
norm = np.pi / (a * (1 + b)) / np.power(b, b / (1. + b)) / np.sin(np.pi * b / (1. + b))
y = 1. / (b * np.power(explnx / tau, a) + np.power(explnx / tau, -(b * a))) * np.exp(-ttime / explnx)
y = y[1:] + y[:-1]
intval = np.sum(y) / 2
intval = intval * stepsize / norm
return intval
def g2(p, x):
ret_val = np.empty(np.shape(x))
for i, xval in enumerate(x):
# fkt1 = glntau2_td(xval, p[1], p[2], p[3], p[4], p[5])
# fkt1 = glntau1_td(xval, p[1], p[2], p[3])
fkt1 = glntau2_td(xval, p[1], p[2], p[3], p[4], p[5])
fkt2 = glnbeta_td(xval, p[6], p[7], p[8])
# ret_val[i] = (fkt1 * ((1 - p[4]) + p[4] * fkt2) * p[0]) + np.abs(p[9]) * np.exp(-(xval/p[10])**p[11]) + p[8]
ret_val[i] = fkt1 * (1-p[0] + p[0]*fkt2)
return ret_val
def g1(p, x):
ret_val = np.empty(np.shape(x))
for i, xval in enumerate(x):
# fkt1 = glntau1_td(xval,p[1],p[2],p[3])
fkt1 = glntau2_td(xval, p[1], p[2], p[3], p[11], p[12])
fkt2 = glnbeta_td(xval, p[5], p[6], p[7])
ret_val[i] = p[0] * (fkt1 * ((1 - p[4]) + p[4] * fkt2)) + np.abs(p[8]) * np.exp(-(xval / p[9]) ** p[10])
return ret_val

View File

@ -1,8 +1,8 @@
matplotlib
numpy
scipy
pyqt
h5py
pyqtgraph
bsddb3
h5py
pyqt

View File

@ -1,419 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>614</width>
<height>776</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Description</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>3</number>
</property>
<item row="0" column="1">
<widget class="QLineEdit" name="name_lineedit"/>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="group_lineedit"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="group_label">
<property name="text">
<string>Group</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="name_label">
<property name="text">
<string>Name</string>
</property>
<property name="buddy">
<cstring>name_lineedit</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="lineEdit"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Equation</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Variables</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QWidget" name="widget_3" native="true">
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTableWidget" name="tableWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="columnCount">
<number>4</number>
</property>
<column>
<property name="text">
<string>Variable</string>
</property>
</column>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Lower bound</string>
</property>
</column>
<column>
<property name="text">
<string>Upper bound</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QToolButton" name="parameter_button">
<property name="text">
<string>Add parameter</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
</property>
<property name="autoRaise">
<bool>false</bool>
</property>
<property name="arrowType">
<enum>Qt::RightArrow</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Multiple choice part</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="use_nuclei">
<property name="text">
<string>Add gyromagnetic ratios</string>
</property>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="tabPosition">
<enum>QTabWidget::West</enum>
</property>
<property name="tabsClosable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="selection_button">
<property name="text">
<string>Add selection</string>
</property>
<property name="toolButtonStyle">
<enum>Qt::ToolButtonTextBesideIcon</enum>
</property>
<property name="arrowType">
<enum>Qt::RightArrow</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Available namespace</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QNamespaceWidget" name="namespace_widget" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_4">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>3</number>
</property>
<property name="topMargin">
<number>3</number>
</property>
<property name="rightMargin">
<number>3</number>
</property>
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Function y = func(x)</string>
</property>
</widget>
</item>
<item>
<widget class="CodeEditor" name="plainTextEdit"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QNamespaceWidget</class>
<extends>QWidget</extends>
<header>..lib.namespace</header>
<container>1</container>
</customwidget>
<customwidget>
<class>CodeEditor</class>
<extends>QPlainTextEdit</extends>
<header>..lib.codeeditor</header>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>Dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,7 +1,7 @@
from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
# from PySide2 import QtCore, QtGui, QtWidgets
# from PySide2 import QtCore, QtGui, QtWidgets, QtPrintSupport
# QtCore.pyqtSignal = QtCore.Signal
# QtCore.pyqtProperty = QtCore.Property
# QtCore.pyqtSlot = QtCore.Slot

View File

@ -1,6 +1,7 @@
from nmreval.configs import read_configuration
from .Qt import QtWidgets
from .lib.styles import MyProxyStyle
from ..configs import read_configuration
class App(QtWidgets.QApplication):

View File

@ -0,0 +1,77 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'resources/_ui/fitcreationdialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(773, 633)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth())
Dialog.setSizePolicy(sizePolicy)
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
self.verticalLayout.setObjectName("verticalLayout")
self.splitter = QtWidgets.QSplitter(Dialog)
self.splitter.setOrientation(QtCore.Qt.Vertical)
self.splitter.setObjectName("splitter")
self.tabWidget = QtWidgets.QTabWidget(self.splitter)
self.tabWidget.setObjectName("tabWidget")
self.description_box = QtWidgets.QWidget()
self.description_box.setObjectName("description_box")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.description_box)
self.verticalLayout_2.setContentsMargins(3, 3, 3, 3)
self.verticalLayout_2.setSpacing(0)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.tabWidget.addTab(self.description_box, "")
self.args_box = QtWidgets.QWidget()
self.args_box.setObjectName("args_box")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.args_box)
self.verticalLayout_3.setContentsMargins(3, 3, 3, 3)
self.verticalLayout_3.setSpacing(0)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.tabWidget.addTab(self.args_box, "")
self.kwargs_box = QtWidgets.QWidget()
self.kwargs_box.setObjectName("kwargs_box")
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.kwargs_box)
self.verticalLayout_5.setObjectName("verticalLayout_5")
self.tabWidget.addTab(self.kwargs_box, "")
self.namespace_box = QtWidgets.QWidget()
self.namespace_box.setObjectName("namespace_box")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.namespace_box)
self.verticalLayout_6.setObjectName("verticalLayout_6")
self.tabWidget.addTab(self.namespace_box, "")
self.plainTextEdit = CodeEditor(self.splitter)
self.plainTextEdit.setEnabled(True)
self.plainTextEdit.setObjectName("plainTextEdit")
self.verticalLayout.addWidget(self.splitter)
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.buttonBox.setObjectName("buttonBox")
self.verticalLayout.addWidget(self.buttonBox)
self.retranslateUi(Dialog)
self.tabWidget.setCurrentIndex(0)
self.buttonBox.accepted.connect(Dialog.accept)
self.buttonBox.rejected.connect(Dialog.reject)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Create fit function"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.description_box), _translate("Dialog", "Description"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.args_box), _translate("Dialog", "Variables"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.kwargs_box), _translate("Dialog", "Multiple choice"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.namespace_box), _translate("Dialog", "Available Functions"))
from ..lib.codeeditor import CodeEditor

View File

@ -310,5 +310,5 @@ class Ui_shift_dialog(object):
self.overwrite_checkbox.setText(_translate("shift_dialog", "Overwrite data"))
self.data_newgraph.setText(_translate("shift_dialog", "New graph"))
self.values_newgraph.setText(_translate("shift_dialog", "New graph"))
from ..lib.utils import SciSpinBox
from ..lib.spinboxes import SciSpinBox
from pyqtgraph import PlotWidget

View File

@ -1,3 +1,4 @@
from __future__ import annotations
from collections import OrderedDict
from itertools import cycle
from typing import Any
@ -5,14 +6,14 @@ from typing import Any
import numpy as np
from pyqtgraph import mkPen
from ...data.points import Points
from ...data.signals import Signal
from ...utils.text import convert
from ...data.bds import BDS
from ...lib.colors import BaseColor, TUColors
from ...lib.lines import LineStyle
from ...lib.symbols import SymbolStyle, symbolcycle
from ...data.nmr import Spectrum, FID
from nmreval.data.points import Points
from nmreval.data.signals import Signal
from nmreval.utils.text import convert
from nmreval.data.bds import BDS
from nmreval.lib.colors import BaseColor, TUColors
from nmreval.lib.lines import LineStyle
from nmreval.lib.symbols import SymbolStyle, symbolcycle
from nmreval.data.nmr import Spectrum, FID
from ..Qt import QtCore, QtGui
from ..io.exporters import GraceExporter
@ -254,7 +255,7 @@ class ExperimentContainer(QtCore.QObject):
def has_fits(self):
return len(self._fits) != 0
def set_fits(self, value: str or list, replace: bool = False):
def set_fits(self, value: str | list, replace: bool = False):
if isinstance(value, str):
value = [value]

Some files were not shown because too many files have changed in this diff Show More