BUGFIX: VFT;
change to src layout
This commit is contained in:
1 parent
89ce4bab9f
commit
8d148b639b
445 files changed
+1387
-1920
No files matched your search
+3
-3
@@ -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([])
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
|
||||
@@ -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 |
@@ -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:
|
||||
@@ -1,5 +1,2 @@
|
||||
.. automodule:: nmreval.distributions
|
||||
:members:
|
||||
:inherited-members:
|
||||
:undoc-members:
|
||||
|
||||
@@ -11,3 +11,4 @@ Reference
|
||||
models
|
||||
distributions
|
||||
nmr
|
||||
math
|
||||
+25
-13
@@ -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
|
||||
|
||||
@@ -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`
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
==========
|
||||
**********
|
||||
User Guide
|
||||
==========
|
||||
**********
|
||||
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
read
|
||||
gui/index
|
||||
read/index
|
||||
edit_signals
|
||||
fit
|
||||
shift_scale
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
matplotlib
|
||||
numpy
|
||||
scipy
|
||||
pyqt
|
||||
h5py
|
||||
pyqtgraph
|
||||
bsddb3
|
||||
h5py
|
||||
pyqt
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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):
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -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]
|
||||
|
||||
Loaded 100 of 445 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user