15 Commits

Author SHA1 Message Date
35e89176be datawidget.py: raise AttributeError manually if item is graph, was not always raised; maybe problem of #52 2023-04-27 12:13:20 +02:00
4e0ff4eddd replace semicolon and commas with spaces in csv; closes #23 2023-03-24 11:03:50 +01:00
de9464ef9f Update 'src/gui_qt/lib/utils.py' 2023-03-17 13:16:24 +00:00
466a63990d Update 'src/gui_qt/lib/utils.py'
logger added to zsync download
2023-03-17 13:15:44 +00:00
8690cb222e ignore errors due to wrong encoding in agr files (#22)
Co-authored-by: Dominik Demuth <dominik.demuth@physik.tu-darmstadt.de>
Reviewed-on: #22
2023-03-16 18:49:44 +00:00
28c15ff565 extrapolate_fit (#21)
New sets with arbitrary x range can be created from fit results

Co-authored-by: Dominik Demuth <dominik.demuth@physik.tu-darmstadt.de>
Reviewed-on: #21
2023-03-12 19:37:10 +00:00
1601f1455c use same value in widget and multimodel to count parameter 2023-03-01 19:27:03 +01:00
b73d6f08b8 asciireader.py avoid IndexError if file has no header 2023-03-01 19:27:03 +01:00
5577adabec AppImage path was incorrect in upload script.
fixes #17
2023-02-07 07:57:56 +01:00
57ecff478b silence curl in upload script 2023-02-07 01:03:05 +01:00
2229b2905a fixes #16 2023-02-07 00:47:27 +01:00
60c93f6bc9 changed the repository path 2023-02-06 20:38:04 +01:00
626804783e Merge remote-tracking branch 'origin/master' 2023-02-06 20:20:09 +01:00
a182d55b98 Add 'LICE' 2023-02-06 20:19:41 +01:00
ee2a91813c Add 'LICE' 2023-02-06 19:13:45 +00:00
19 changed files with 439 additions and 176 deletions

View File

@ -87,6 +87,6 @@ AppDir:
command: ./AppRun
AppImage:
update-information: 'zsync|https://gitea.pkm.physik.tu-darmstadt.de/api/packages/IPKM-Public/generic/NMReval/latest/NMReval-latest-x86_64.Appimage.zsync'
update-information: 'zsync|https://gitea.pkm.physik.tu-darmstadt.de/api/packages/IPKM/generic/NMReval/latest/NMReval-latest-x86_64.Appimage.zsync'
sign-key: 976AC9D78688B628B00D4944D319B98C2D6CE5D3
arch: x86_64

13
LICENSE Normal file
View File

@ -0,0 +1,13 @@
BSD 3-Clause License
Copyright (c) 2023 Dominik Demuth.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file './resources/_ui/fitresult.ui'
# Form implementation generated from reading ui file '/autohome/dominik/nmreval-gitea/src/resources/_ui/fitresult.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
# Created by: PyQt5 UI code generator 5.15.7
#
# 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.
@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(817, 584)
Dialog.resize(864, 649)
self.gridLayout = QtWidgets.QGridLayout(Dialog)
self.gridLayout.setObjectName("gridLayout")
self.sets_comboBox = ElideComboBox(Dialog)
@ -51,6 +51,21 @@ class Ui_Dialog(object):
self.gridLayout_2.setContentsMargins(3, 3, 3, 3)
self.gridLayout_2.setSpacing(3)
self.gridLayout_2.setObjectName("gridLayout_2")
self.extrapolate_box = QtWidgets.QCheckBox(self.groupBox)
self.extrapolate_box.setObjectName("extrapolate_box")
self.gridLayout_2.addWidget(self.extrapolate_box, 1, 0, 1, 1)
self.parameter_checkbox = QtWidgets.QCheckBox(self.groupBox)
self.parameter_checkbox.setObjectName("parameter_checkbox")
self.gridLayout_2.addWidget(self.parameter_checkbox, 0, 5, 1, 1)
self.graph_comboBox = QtWidgets.QComboBox(self.groupBox)
self.graph_comboBox.setEnabled(False)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.graph_comboBox.sizePolicy().hasHeightForWidth())
self.graph_comboBox.setSizePolicy(sizePolicy)
self.graph_comboBox.setObjectName("graph_comboBox")
self.gridLayout_2.addWidget(self.graph_comboBox, 1, 6, 1, 1)
self.graph_checkBox = QtWidgets.QCheckBox(self.groupBox)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
@ -59,22 +74,44 @@ class Ui_Dialog(object):
self.graph_checkBox.setSizePolicy(sizePolicy)
self.graph_checkBox.setChecked(True)
self.graph_checkBox.setObjectName("graph_checkBox")
self.gridLayout_2.addWidget(self.graph_checkBox, 1, 1, 1, 1)
self.graph_comboBox = QtWidgets.QComboBox(self.groupBox)
self.graph_comboBox.setEnabled(False)
self.graph_comboBox.setObjectName("graph_comboBox")
self.gridLayout_2.addWidget(self.graph_comboBox, 1, 2, 1, 1)
self.gridLayout_2.addWidget(self.graph_checkBox, 1, 5, 1, 1)
self.minx_line = QtWidgets.QLineEdit(self.groupBox)
self.minx_line.setEnabled(False)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.minx_line.sizePolicy().hasHeightForWidth())
self.minx_line.setSizePolicy(sizePolicy)
self.minx_line.setObjectName("minx_line")
self.gridLayout_2.addWidget(self.minx_line, 1, 1, 1, 1)
self.line_2 = QtWidgets.QFrame(self.groupBox)
self.line_2.setFrameShape(QtWidgets.QFrame.VLine)
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line_2.setObjectName("line_2")
self.gridLayout_2.addWidget(self.line_2, 0, 4, 2, 1)
self.maxx_line = QtWidgets.QLineEdit(self.groupBox)
self.maxx_line.setEnabled(False)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.maxx_line.sizePolicy().hasHeightForWidth())
self.maxx_line.setSizePolicy(sizePolicy)
self.maxx_line.setObjectName("maxx_line")
self.gridLayout_2.addWidget(self.maxx_line, 1, 2, 1, 1)
self.numx_line = QtWidgets.QLineEdit(self.groupBox)
self.numx_line.setEnabled(False)
self.numx_line.setObjectName("numx_line")
self.gridLayout_2.addWidget(self.numx_line, 1, 3, 1, 1)
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.curve_checkbox = QtWidgets.QCheckBox(self.groupBox)
self.curve_checkbox.setChecked(True)
self.curve_checkbox.setObjectName("curve_checkbox")
self.gridLayout_2.addWidget(self.curve_checkbox, 0, 0, 1, 1)
self.horizontalLayout.addWidget(self.curve_checkbox)
self.partial_checkBox = QtWidgets.QCheckBox(self.groupBox)
self.partial_checkBox.setObjectName("partial_checkBox")
self.gridLayout_2.addWidget(self.partial_checkBox, 1, 0, 1, 1)
self.parameter_checkbox = QtWidgets.QCheckBox(self.groupBox)
self.parameter_checkbox.setChecked(True)
self.parameter_checkbox.setObjectName("parameter_checkbox")
self.gridLayout_2.addWidget(self.parameter_checkbox, 0, 1, 1, 1)
self.horizontalLayout.addWidget(self.partial_checkBox)
self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 4)
self.gridLayout.addWidget(self.groupBox, 5, 0, 1, 2)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setSpacing(3)
@ -91,40 +128,38 @@ class Ui_Dialog(object):
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
self.line.setObjectName("line")
self.gridLayout.addWidget(self.line, 3, 0, 1, 2)
self.stack = QtWidgets.QToolBox(Dialog)
self.stack = QtWidgets.QTabWidget(Dialog)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.stack.sizePolicy().hasHeightForWidth())
self.stack.setSizePolicy(sizePolicy)
self.stack.setObjectName("stack")
self.page = QtWidgets.QWidget()
self.page.setGeometry(QtCore.QRect(0, 0, 399, 346))
self.page.setObjectName("page")
self.gridLayout_3 = QtWidgets.QGridLayout(self.page)
self.stackPage1 = QtWidgets.QWidget()
self.stackPage1.setObjectName("stackPage1")
self.gridLayout_3 = QtWidgets.QGridLayout(self.stackPage1)
self.gridLayout_3.setContentsMargins(3, 3, 3, 3)
self.gridLayout_3.setSpacing(3)
self.gridLayout_3.setObjectName("gridLayout_3")
self.logy_box = QtWidgets.QCheckBox(self.page)
self.logy_box = QtWidgets.QCheckBox(self.stackPage1)
self.logy_box.setLayoutDirection(QtCore.Qt.RightToLeft)
self.logy_box.setObjectName("logy_box")
self.gridLayout_3.addWidget(self.logy_box, 2, 1, 1, 1)
self.logx_box = QtWidgets.QCheckBox(self.page)
self.logx_box = QtWidgets.QCheckBox(self.stackPage1)
self.logx_box.setLayoutDirection(QtCore.Qt.RightToLeft)
self.logx_box.setObjectName("logx_box")
self.gridLayout_3.addWidget(self.logx_box, 2, 0, 1, 1)
self.graphicsView = GraphicsLayoutWidget(self.page)
self.graphicsView = GraphicsLayoutWidget(self.stackPage1)
self.graphicsView.setObjectName("graphicsView")
self.gridLayout_3.addWidget(self.graphicsView, 0, 0, 1, 2)
self.stack.addItem(self.page, "")
self.page_2 = QtWidgets.QWidget()
self.page_2.setGeometry(QtCore.QRect(0, 0, 399, 346))
self.page_2.setObjectName("page_2")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.page_2)
self.stack.addTab(self.stackPage1, "")
self.stackPage2 = QtWidgets.QWidget()
self.stackPage2.setObjectName("stackPage2")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.stackPage2)
self.verticalLayout_2.setContentsMargins(3, 3, 3, 3)
self.verticalLayout_2.setSpacing(3)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.stats_tableWidget = QtWidgets.QTableWidget(self.page_2)
self.stats_tableWidget = QtWidgets.QTableWidget(self.stackPage2)
self.stats_tableWidget.setFrameShape(QtWidgets.QFrame.Box)
self.stats_tableWidget.setGridStyle(QtCore.Qt.NoPen)
self.stats_tableWidget.setColumnCount(1)
@ -133,15 +168,14 @@ class Ui_Dialog(object):
self.stats_tableWidget.horizontalHeader().setVisible(False)
self.stats_tableWidget.horizontalHeader().setSortIndicatorShown(True)
self.verticalLayout_2.addWidget(self.stats_tableWidget)
self.stack.addItem(self.page_2, "")
self.page_3 = QtWidgets.QWidget()
self.page_3.setGeometry(QtCore.QRect(0, 0, 399, 346))
self.page_3.setObjectName("page_3")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.page_3)
self.stack.addTab(self.stackPage2, "")
self.stackPage3 = QtWidgets.QWidget()
self.stackPage3.setObjectName("stackPage3")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.stackPage3)
self.verticalLayout_3.setContentsMargins(3, 3, 3, 3)
self.verticalLayout_3.setSpacing(3)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.corr_tableWidget = QtWidgets.QTableWidget(self.page_3)
self.corr_tableWidget = QtWidgets.QTableWidget(self.stackPage3)
self.corr_tableWidget.setFrameShape(QtWidgets.QFrame.Box)
self.corr_tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.corr_tableWidget.setGridStyle(QtCore.Qt.NoPen)
@ -159,28 +193,34 @@ class Ui_Dialog(object):
self.corr_tableWidget.horizontalHeader().setStretchLastSection(True)
self.corr_tableWidget.verticalHeader().setVisible(False)
self.verticalLayout_3.addWidget(self.corr_tableWidget)
self.stack.addItem(self.page_3, "")
self.stack.addTab(self.stackPage3, "")
self.gridLayout.addWidget(self.stack, 0, 1, 3, 1)
self.retranslateUi(Dialog)
self.stack.setCurrentIndex(0)
self.stack.layout().setSpacing(0)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Fit results"))
self.groupBox.setTitle(_translate("Dialog", "Output"))
self.graph_checkBox.setText(_translate("Dialog", "New graph"))
self.extrapolate_box.setToolTip(_translate("Dialog", "Extrapolates only main function"))
self.extrapolate_box.setText(_translate("Dialog", "Extrapolate curves"))
self.parameter_checkbox.setText(_translate("Dialog", "Plot parameter"))
self.graph_checkBox.setText(_translate("Dialog", "New graph for parameter"))
self.minx_line.setToolTip(_translate("Dialog", "Leave empty to start at lowest point"))
self.minx_line.setPlaceholderText(_translate("Dialog", "min x"))
self.maxx_line.setToolTip(_translate("Dialog", "Leave empty to start at highest point"))
self.maxx_line.setPlaceholderText(_translate("Dialog", "max x"))
self.numx_line.setPlaceholderText(_translate("Dialog", "# pts"))
self.curve_checkbox.setText(_translate("Dialog", "Plot fit curve"))
self.partial_checkBox.setText(_translate("Dialog", "Plot partial functions"))
self.parameter_checkbox.setText(_translate("Dialog", "Plot parameter"))
self.reject_fit_checkBox.setText(_translate("Dialog", "Reject this fit"))
self.del_prev_checkBox.setText(_translate("Dialog", "Delete previous fits"))
self.logy_box.setText(_translate("Dialog", "logarithmic y axis"))
self.logx_box.setText(_translate("Dialog", "logarithmic x axis"))
self.stack.setItemText(self.stack.indexOf(self.page), _translate("Dialog", "Plot"))
self.stack.setItemText(self.stack.indexOf(self.page_2), _translate("Dialog", "Statistics"))
self.stack.setTabText(self.stack.indexOf(self.stackPage1), _translate("Dialog", "Plot"))
self.stack.setTabText(self.stack.indexOf(self.stackPage2), _translate("Dialog", "Statistics"))
item = self.corr_tableWidget.horizontalHeaderItem(0)
item.setText(_translate("Dialog", "Parameter 1"))
item = self.corr_tableWidget.horizontalHeaderItem(1)
@ -189,6 +229,6 @@ class Ui_Dialog(object):
item.setText(_translate("Dialog", "Corr."))
item = self.corr_tableWidget.horizontalHeaderItem(3)
item.setText(_translate("Dialog", "Partial Corr."))
self.stack.setItemText(self.stack.indexOf(self.page_3), _translate("Dialog", "Correlations"))
self.stack.setTabText(self.stack.indexOf(self.stackPage3), _translate("Dialog", "Correlations"))
from ..lib.forms import ElideComboBox
from pyqtgraph import GraphicsLayoutWidget

View File

@ -553,7 +553,9 @@ class FitContainer(ExperimentContainer):
setattr(self, n, getattr(data, n))
def _init_plot(self, **kwargs):
color = kwargs.get('color', (0, 0, 0))
color = kwargs.get('color')
if color is None:
color = kwargs.get('linecolor', (0, 0, 0))
if isinstance(color, BaseColor):
color = color.rgb()
@ -605,7 +607,7 @@ class SignalContainer(ExperimentContainer):
linecolor = kwargs.get('linecolor', color)
if symcolor is None and linecolor is None:
color = next(self.colors)
color = next(self.colors) if color is None else color
symcolor = color
linecolor = color
elif symcolor is None:

View File

@ -17,6 +17,7 @@ class DataTree(QtWidgets.QTreeWidget):
moveItem = QtCore.pyqtSignal(list, str, str, int) # items, from, to, new row
copyItem = QtCore.pyqtSignal(list, str)
saveFits = QtCore.pyqtSignal(list)
extendFits = QtCore.pyqtSignal(list)
def __init__(self, parent=None):
super().__init__(parent=parent)
@ -341,6 +342,9 @@ class DataTree(QtWidgets.QTreeWidget):
_id = item.data(0, QtCore.Qt.UserRole)
if _id in ids:
try:
if item.parent() is None:
raise AttributeError
idx = item.parent().indexOfChild(item)
item.parent().takeChild(idx)
if _id in self._checked_sets:
@ -387,6 +391,10 @@ class DataTree(QtWidgets.QTreeWidget):
for c in available_cycles.keys():
col_menu.addAction(c)
action = menu.exec(evt.globalPos())
if action is None:
return
graphs = []
items = []
for i in self.selectedIndexes():
@ -395,7 +403,6 @@ class DataTree(QtWidgets.QTreeWidget):
items.append(self.itemFromIndex(i))
graphs.append(self.itemFromIndex(i).data(0, QtCore.Qt.UserRole))
action = menu.exec(evt.globalPos())
if action == del_action:
for gid in graphs:
self.management.delete_graph(gid)
@ -414,8 +421,7 @@ class DataTree(QtWidgets.QTreeWidget):
del_action = menu.addAction('Exterminate sets')
cp_action = menu.addAction('Replicate sets')
cat_action = menu.addAction('Join us!')
plt_action = None
save_action = None
plt_action = save_action = extend_action = None
menu.addSeparator()
col_menu = menu.addMenu('Color cycle')
for c in available_cycles.keys():
@ -446,6 +452,7 @@ class DataTree(QtWidgets.QTreeWidget):
menu.addSeparator()
plt_action = menu.addAction('Plot fit parameter')
save_action = menu.addAction('Save fit parameter')
extend_action = menu.addAction('Extrapolate fit')
action = menu.exec(evt.globalPos())
@ -469,6 +476,9 @@ class DataTree(QtWidgets.QTreeWidget):
elif action == save_action:
self.saveFits.emit(s)
elif action == extend_action:
self.extendFits.emit(s)
elif action.parent() == col_menu:
self.management.set_cycle(s, action.text())

View File

@ -4,7 +4,6 @@ from functools import reduce
from itertools import count, cycle
from operator import add
from string import ascii_letters
from typing import Dict, List, Tuple
import numpy as np
from pyqtgraph import mkPen
@ -144,7 +143,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
self._complex[self._current_model] = self.functionwidget.get_complex_state()
self._func_list[self._current_model] = self.functionwidget.get_parameter_list()
def load(self, ids: List[str]):
def load(self, ids: list[str]):
"""
Add name and id of dataset to list.
"""
@ -216,7 +215,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
self.model_frame.hide()
def _prepare(self, model: list, function_use: list = None,
parameter: dict = None, add_idx: bool = False, cnt: int = 0) -> Tuple[dict, int]:
parameter: dict = None, add_idx: bool = False, cnt: int = 0) -> tuple[dict, int]:
if parameter is None:
parameter = {'parameter': {}, 'lb': (), 'ub': (), 'var': [],
'glob': {'idx': [], 'p': [], 'var': [], 'lb': [], 'ub': []},
@ -241,6 +240,8 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
parameter['links'] += links
parameter['color'] += [f['color']]
cnt = f['cnt']
for p_k, v_k in p.items():
if add_idx:
kw_k = {f'{k}_{cnt}': v for k, v in v_k[1].items()}
@ -450,7 +451,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
return self.preview_lines
def set_parameter(self, parameter: Dict[str, FitResult]):
def set_parameter(self, parameter: dict[str, FitResult]):
# which data uses which model
data = self.data_table.collect_data(default=self.default_combobox.currentData())
@ -468,7 +469,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
self.set_parameter_iter(None, mean_parameter, self.models[fitted_model])
def set_parameter_iter(self, fit_id: str | None, param: List[float], functions: List, cnt: int = 0):
def set_parameter_iter(self, fit_id: str | None, param: list[float], functions: list, cnt: int = 0):
for model_p in functions:
if model_p['active']:
cnt += self.param_widgets[model_p['cnt']].set_parameter(fit_id, param[cnt:])

View File

@ -11,7 +11,7 @@ from ..lib.pg_objects import PlotItem
class QFitResult(QtWidgets.QDialog, Ui_Dialog):
closed = QtCore.pyqtSignal(dict, list, str, bool, dict)
closed = QtCore.pyqtSignal(dict, list, str, bool, bool, list)
redoFit = QtCore.pyqtSignal(dict)
def __init__(self, results: list, management, parent=None):
@ -20,10 +20,17 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
self._management = management
self.maxx_line.setValidator(QtGui.QDoubleValidator())
self.minx_line.setValidator(QtGui.QDoubleValidator())
self.numx_line.setValidator(QtGui.QIntValidator())
self.extrapolate_box.stateChanged.connect(lambda x: self.maxx_line.setEnabled(x))
self.extrapolate_box.stateChanged.connect(lambda x: self.minx_line.setEnabled(x))
self.extrapolate_box.stateChanged.connect(lambda x: self.numx_line.setEnabled(x))
self._prevs = {}
self._models = {}
for (res, parts) in results:
for res in results:
idx = res.idx
data_k = management.data[idx]
@ -36,8 +43,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
for fit in data_k.get_fits():
self._prevs[idx].append((fit.name, fit.statistics, fit.nobs-fit.nvar))
self._results = {res.idx: res for (res, _) in results}
self._parts = {res.idx: parts for (res, parts) in results}
self._results = {res.idx: res for res in results}
self._opts = [(False, False) for _ in range(len(self._results))]
self.residplot = self.graphicsView.addPlot(row=0, col=0)
@ -273,12 +279,75 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
plot_fits = self.curve_checkbox.isChecked()
if self.partial_checkBox.checkState() == QtCore.Qt.Checked:
self.closed.emit(self._results, self._opts, graph, plot_fits, self._parts)
else:
self.closed.emit(self._results, self._opts, graph, plot_fits, {})
parts = self.partial_checkBox.checkState() == QtCore.Qt.Checked
extrapolate = [None, None, None]
if self.extrapolate_box.isChecked():
try:
extrapolate[0] = float(self.minx_line.text())
except TypeError:
pass
try:
extrapolate[1] = float(self.maxx_line.text())
except TypeError:
pass
try:
extrapolate[2] = int(self.numx_line.text())
except TypeError:
pass
self.closed.emit(self._results, self._opts, graph, plot_fits, parts, extrapolate)
self.accept()
else:
self.reject()
class FitExtension(QtWidgets.QDialog):
def __init__(self, parent=None):
super().__init__(parent=parent)
gridLayout = QtWidgets.QGridLayout(self)
self.label = QtWidgets.QLabel('Minimum value')
gridLayout.addWidget(self.label, 0, 0, 1, 1)
self.min_line = QtWidgets.QLineEdit()
self.min_line.setValidator(QtGui.QDoubleValidator())
gridLayout.addWidget(self.min_line, 0, 1, 1, 1)
self.label_2 = QtWidgets.QLabel('Maximum value')
gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
self.max_line = QtWidgets.QLineEdit()
self.max_line.setValidator(QtGui.QDoubleValidator())
gridLayout.addWidget(self.max_line, 1, 1, 1, 1)
self.label_3 = QtWidgets.QLabel('Number of pts.')
gridLayout.addWidget(self.label_3, 2, 0, 1, 1)
self.num_pts = QtWidgets.QLineEdit()
self.num_pts.setValidator(QtGui.QIntValidator())
gridLayout.addWidget(self.num_pts, 2, 1, 1, 1)
self.buttonBox = QtWidgets.QDialogButtonBox()
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
gridLayout.addWidget(self.buttonBox, 3, 0, 1, 2)
self.setLayout(gridLayout)
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.reject)
@property
def values(self):
try:
xmin = float(self.min_line.text())
xmax = float(self.max_line.text())
nums = int(self.num_pts.text())
except TypeError:
return None
return xmin, xmax, nums

View File

@ -113,7 +113,7 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
@QtCore.pyqtSlot(int, name='on_line_spinBox_valueChanged')
def set_column_names(self, _):
self.ascii_table.setHorizontalHeaderLabels(map(str, range(1, self.ascii_table.columnCount() + 1)))
if self.column_checkBox.isChecked():
if self.column_checkBox.isChecked() and self.line_spinBox.isEnabled():
header_line = self.reader.header[self.line_spinBox.value()-1]
self.ascii_table.setHorizontalHeaderLabels(header_line.split())

View File

@ -1,3 +1,5 @@
import numpy as np
from nmreval.lib.lines import LineStyle
from nmreval.lib.symbols import SymbolStyle
from nmreval.data.points import Points
@ -90,6 +92,7 @@ class QGraceReader(QtWidgets.QDialog, Ui_Dialog):
label = self._reader.get_property(*key, 'legend').replace('"', '')
# label = self._reader.graphs[key[0]].sets[key[1]]['legend'].replace('"', '')
sd = s.data
sd = np.atleast_2d(sd)
if s.type == 'xydy':
data.append(Points(x=sd[:, 0], y=sd[:, 1], y_err=sd[:, 2], name=label))
else:

View File

@ -233,8 +233,10 @@ class Updater:
response = requests.get(url_zsync)
if response.status_code == requests.codes['\o/']:
zsync_file = response.content
except Exception as e:
pass
else:
logger.error(f'Request for zsync returned code {response.statuse_code}')
except Exception:
logger.exception('Download of zsync failed')
if zsync_file is not None:
for line in zsync_file.split(b'\n'):

View File

@ -11,10 +11,10 @@ from pyqtgraph import ViewBox
from nmreval.configs import *
from .management import UpperManagement
from ..Qt import QtCore, QtGui, QtPrintSupport, QtWidgets
from ..Qt import QtGui, QtPrintSupport
from ..data.shift_graphs import QShift
from ..data.signaledit import QApodDialog, QBaselineDialog, QPhasedialog
from ..fit.result import QFitResult
from ..fit.result import FitExtension, QFitResult
from ..graphs.graphwindow import QGraphWindow
from ..graphs.movedialog import QMover
from ..io.fcbatchreader import QFCReader
@ -164,6 +164,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.datawidget.startShowProperty.connect(self.management.get_properties)
self.datawidget.propertyChanged.connect(self.management.update_property)
self.datawidget.tree.saveFits.connect(self.save_fit_parameter)
self.datawidget.tree.extendFits.connect(self.extend_fit)
self.management.newData.connect(self.show_new_data)
self.management.newGraph.connect(self.new_graph)
@ -907,10 +908,10 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
res_dialog.redoFit.connect(self.management.redo_fits)
res_dialog.show()
@QtCore.pyqtSlot(dict, list, str, bool, dict)
def accepts_fit(self, res: dict, opts: list, param_graph: str, show_fit: bool, parts: dict) -> None:
@QtCore.pyqtSlot(dict, list, str, bool, bool, list)
def accepts_fit(self, res: dict, opts: list, param_graph: str, show_fit: bool, parts: bool, extrapolate: list) -> None:
self.fit_dialog.set_parameter(res)
self.management.make_fits(res, opts, param_graph, show_fit, parts)
self.management.make_fits(res, opts, param_graph, show_fit, parts, extrapolate)
@QtCore.pyqtSlot(name='on_actionFunction_editor_triggered')
def edit_models(self):
@ -922,6 +923,16 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.editor.setWindowModality(QtCore.Qt.ApplicationModal)
self.editor.show()
@QtCore.pyqtSlot(list)
def extend_fit(self, sets: list):
w = FitExtension(self)
res = w.exec()
print(res)
if res:
p = w.values
x = linspace(p[0], p[1], num=p[2])
self.management.extend_fits(sets, x)
@QtCore.pyqtSlot(name='on_action_create_fit_function_triggered')
def open_fitmodel_wizard(self):
from ..fit.function_creation_dialog import QUserFitCreator
@ -931,7 +942,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
helper.show()
@QtCore.pyqtSlot(name='on_actionShift_triggered')
def shift_dialog(self):
s = QShift(self)

View File

@ -4,6 +4,8 @@ import pathlib
import re
import uuid
import numpy as np
from nmreval.fit import data as fit_d
from nmreval.fit.model import Model
from nmreval.fit.result import FitResult
@ -482,7 +484,7 @@ class UpperManagement(QtCore.QObject):
parameter[set_id] = (new_values, set_parameter[1])
self.start_fit(*self.__fit_options)
def make_fits(self, res: dict, opts: list, param_graph: str, show_fit: bool, parts: dict) -> None:
def make_fits(self, res: dict, opts: list, param_graph: str, show_fit: bool, parts: bool, extrapolate: list) -> None:
"""
Args:
@ -491,6 +493,7 @@ class UpperManagement(QtCore.QObject):
param_graph: None if no parameter to plot, '' for new graph, or id of existig graph
show_fit: plot fit curve?
parts: key is that of original data, value is list of subplots
extrapolate:
"""
f_id_list = []
@ -503,6 +506,26 @@ class UpperManagement(QtCore.QObject):
if reject:
continue
if not all(e is None for e in extrapolate):
spacefunc = np.geomspace if fit.islog else np.linspace
xmin = fit.x.min()
xmax = fit.x.max()
len_data = len(fit.x_data)
num_pts = 20*len_data-9 if len_data < 51 else 3*len_data
if extrapolate[0] is not None:
xmin = extrapolate[0]
if extrapolate[1] is not None:
xmax = extrapolate[1]
if extrapolate[2] is not None:
num_pts = extrapolate[2]
_x = spacefunc(xmin, xmax, num=num_pts)
fit = fit.with_new_x(_x)
data_k = self.data[k]
if delete_prev:
tobedeleted.extend([f.id for f in data_k.get_fits()])
@ -527,18 +550,16 @@ class UpperManagement(QtCore.QObject):
f_id_list.append(f_id)
data_k.set_fits(f_id)
if parts:
color_scheme = available_cycles['colorblind']
for subfunc, col in zip(fit.sub(fit.x), cycle(color_scheme)):
subfunc.value = data_k.value
subfunc.group = data_k.group
subfunc.name += data_name
sub_f_id = self.add(subfunc, color=col, linestyle=LineStyle.Dashed, symbol=SymbolStyle.No)
f_id_list.append(sub_f_id)
gid = data_k.graph
if k in parts and show_fit:
color_scheme = available_cycles['colorblind']
for subfunc, col in zip(parts[k], cycle(color_scheme)):
subfunc.value = data_k.value
subfunc.group = data_k.group
subfunc.name += data_name
sub_f_id = self.add(subfunc, color=col, linestyle=LineStyle.Dashed, symbol=SymbolStyle.No)
f_id_list.append(sub_f_id)
self.delete_sets(tobedeleted)
if accepted and (param_graph != '-1'):
@ -546,6 +567,27 @@ class UpperManagement(QtCore.QObject):
self.newData.emit(f_id_list, gid)
def extend_fits(self, set_id: list, x_range: np.ndarray):
graphs = {}
for sid in set_id:
data = self[sid]
fit = data.copy(full=True, keep_color=True)
fit.data = fit.data.with_new_x(x_range)
graph_id = data.graph
if graph_id not in graphs:
graphs[graph_id] = []
graphs[graph_id].append(self.add(fit))
color_scheme = available_cycles['colorblind']
for subfunc, col in zip(fit.data.sub(fit.x), cycle(color_scheme)):
subfunc.value = fit.value
subfunc.group = fit.group
graphs[graph_id].append(self.add(subfunc, color=col, linestyle=LineStyle.Dashed, symbol=SymbolStyle.No))
for k, v in graphs.items():
self.newData.emit(v, k)
def make_fit_parameter(self, fit_sets: list[str | FitResult], graph_id: str = None):
fit_dict = self._collect_fit_parameter(fit_sets)

View File

@ -29,7 +29,7 @@ class ModelFactory:
right_cnt = None
else:
right = func['func']
right_cnt = func['pos']
right_cnt = func['cnt']
if left is None:
left = right

View File

@ -126,12 +126,12 @@ class Model(object):
kwargs = self.fun_kwargs
if not self.is_multi:
return [self.func(p, x, **kwargs)]
return []
else:
return list(self._int_iter(x, *p, *self.fun_args, **kwargs))
def sub_name(self):
if not self.is_multi:
return [self.name]
return []
else:
return list(self._iter_name())

View File

@ -9,6 +9,7 @@ import numpy as np
from scipy.stats import f as fdist
from scipy.interpolate import interp1d
from ._meta import MultiModel
from .parameter import Parameter
from ..data.points import Points
from ..data.signals import Signal
@ -17,7 +18,7 @@ from ..utils.text import convert
class FitResultCreator:
@staticmethod
def make_from_session(x_orig: np.ndarray, y_orig: np.ndarray, idx: int, kwargs: dict[Any]) -> (dict, list):
def make_from_session(x_orig: np.ndarray, y_orig: np.ndarray, idx: int, kwargs: dict[Any]) -> FitResult:
params = OrderedDict()
for key, pbest, err in zip(kwargs['pnames'], kwargs['parameter'], kwargs['error']):
@ -37,10 +38,10 @@ class FitResultCreator:
stats = FitResultCreator.calc_statistics(resid, _y)
return FitResult(kwargs['x'], kwargs['y'], x_orig, y_orig, params, dict(kwargs['choice']), resid, 0, 0,
kwargs['name'], stats, idx), []
kwargs['name'], stats, idx)
@staticmethod
def make_with_model(model, x_orig, y_orig, p, fun_kwargs, idx, nobs, nvar, corr, pcorr) -> (dict, list):
def make_with_model(model, x_orig, y_orig, p, fun_kwargs, idx, nobs, nvar, corr, pcorr) -> FitResult:
if np.all(x_orig > 0) and (np.max(x_orig) > 100 * np.min(x_orig)):
islog = True
else:
@ -48,7 +49,7 @@ class FitResultCreator:
if len(x_orig) < 51:
if islog:
_x = np.logspace(np.log10(np.min(x_orig)), np.log10(np.max(x_orig)), num=10*x_orig.size-9)
_x = np.geomspace(np.min(x_orig), np.max(x_orig), num=10*x_orig.size-9)
else:
_x = np.linspace(np.min(x_orig), np.max(x_orig), num=10*x_orig.size-9)
else:
@ -62,15 +63,6 @@ class FitResultCreator:
parameters = OrderedDict([(k, v) for k, v in zip(pnames, p)])
p_final = [p.value for p in parameters.values()]
part_functions = []
if model.is_multi:
for sub_name, sub_y in zip(model.sub_name(), model.sub(p_final, _x, **fun_kwargs)):
if np.iscomplexobj(sub_y):
part_functions.append(Signal(_x, sub_y, name=sub_name))
else:
part_functions.append(Points(_x, sub_y, name=sub_name))
_y = model.func(p_final, _x, **fun_kwargs)
resid = model.func(p_final, x_orig, **fun_kwargs) - y_orig
@ -97,13 +89,10 @@ class FitResultCreator:
correlation = corr
partial_correlation = pcorr
return (
FitResult(_x, _y, x_orig, y_orig, parameters, fun_kwargs, resid,
nobs, nvar, model.name, stats,
idx=idx, corr=correlation, pcorr=partial_correlation,
islog=islog),
part_functions,
)
return FitResult(_x, _y, x_orig, y_orig, parameters, fun_kwargs, resid,
nobs, nvar, model.name, stats,
idx=idx, corr=correlation, pcorr=partial_correlation,
islog=islog, func=model)
@staticmethod
def calc_statistics(y, residual, nobs=None, nvar=None):
@ -141,8 +130,11 @@ class FitResultCreator:
class FitResult(Points):
def __init__(self, x, y, x_data, y_data, params, fun_kwargs, resid, nobs, nvar, name, stats,
idx=None, corr=None, pcorr=None, islog=False,
def __init__(self, x: np.ndarray, y: np.ndarray,
x_data: np.ndarray, y_data: np.ndarray,
params: dict, fun_kwargs: dict,
resid: np.ndarray, nobs: int, nvar: int, name: str, stats: dict,
idx=None, corr=None, pcorr=None, islog=False, func=None,
**kwargs):
self.parameter, name = self._prepare_names(params, name)
@ -162,6 +154,7 @@ class FitResult(Points):
self.x_data = x_data
self.y_data = y_data
self._model_name = name
self._func = func
@staticmethod
def _prepare_names(parameter: dict, modelname: str):
@ -200,6 +193,13 @@ class FitResult(Points):
except AttributeError:
return 'FitObject'
@property
def func(self):
if isinstance(self._func, MultiModel):
return self._func.func
else:
return self._func
@property
def p_final(self):
return [pp.value for pp in self.parameter.values()]
@ -215,6 +215,7 @@ class FitResult(Points):
print(' #var :', self.nvar)
print('\nParameter')
print(self._parameter_string())
if statistics:
print('Statistics')
for k, v in self.statistics.items():
@ -342,3 +343,24 @@ class FitResult(Points):
data = FitResult(**state)
return data
def with_new_x(self, x_values):
if self.func is None:
raise ValueError('no fit function available to calcualate new y values')
new_fit = self.copy()
y_values = self.func.func(self.p_final, x_values, **self.fun_kwargs)
new_fit.set_data(x_values, y_values)
return new_fit
def sub(self, x_values):
part_functions = []
for sub_name, sub_y in zip(self.func.sub_name(), self.func.sub(self.p_final, x_values, **self.fun_kwargs)):
if np.iscomplexobj(sub_y):
part_functions.append(Signal(x_values, sub_y, name=sub_name))
else:
part_functions.append(Points(x_values, sub_y, name=sub_name))
return part_functions

View File

@ -1,5 +1,6 @@
import pathlib
import re
from io import BytesIO
from itertools import islice
import numpy as np
@ -99,7 +100,10 @@ class AsciiReader:
y = list(range(1, max(self.width)))
cols = x + y + yerr
raw_data = np.genfromtxt(self.fname, usecols=cols, missing_values='--')
with self.fname.open('rb') as fh:
tmp_ = re.sub(b'[;,]', b' ', fh.read())
raw_data = np.genfromtxt(BytesIO(tmp_), usecols=cols, missing_values='--')
del tmp_
if raw_data.ndim == 1:
# only one row or column
if len(self.data) == 1:

View File

@ -1,5 +1,6 @@
from __future__ import annotations
import codecs
import pathlib
import re
import warnings
@ -104,9 +105,8 @@ class GraceEditor:
# we start always with the header
current_pos = 'header'
with self.file.open('r') as f:
with self.file.open('r', errors='replace') as f:
for line_nr, line in enumerate(f):
# lots of states to check
# agr file order: header, drawing object, region, graph, set
if current_pos == 'header':

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>817</width>
<height>584</height>
<width>864</width>
<height>649</height>
</rect>
</property>
<property name="windowTitle">
@ -98,7 +98,37 @@
<property name="spacing">
<number>3</number>
</property>
<item row="1" column="1">
<item row="1" column="0">
<widget class="QCheckBox" name="extrapolate_box">
<property name="toolTip">
<string>Extrapolates only main function</string>
</property>
<property name="text">
<string>Extrapolate curves</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QCheckBox" name="parameter_checkbox">
<property name="text">
<string>Plot parameter</string>
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QComboBox" name="graph_comboBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QCheckBox" name="graph_checkBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
@ -107,46 +137,88 @@
</sizepolicy>
</property>
<property name="text">
<string>New graph</string>
<string>New graph for parameter</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="minx_line">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Leave empty to start at lowest point</string>
</property>
<property name="placeholderText">
<string>min x</string>
</property>
</widget>
</item>
<item row="0" column="4" rowspan="2">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="graph_comboBox">
<widget class="QLineEdit" name="maxx_line">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="curve_checkbox">
<property name="text">
<string>Plot fit curve</string>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="checked">
<bool>true</bool>
<property name="toolTip">
<string>Leave empty to start at highest point</string>
</property>
<property name="placeholderText">
<string>max x</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="partial_checkBox">
<property name="text">
<string>Plot partial functions</string>
<item row="1" column="3">
<widget class="QLineEdit" name="numx_line">
<property name="enabled">
<bool>false</bool>
</property>
<property name="placeholderText">
<string># pts</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="parameter_checkbox">
<property name="text">
<string>Plot parameter</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<item row="0" column="0" colspan="4">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="curve_checkbox">
<property name="text">
<string>Plot fit curve</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="partial_checkBox">
<property name="text">
<string>Plot partial functions</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
@ -180,7 +252,7 @@
</widget>
</item>
<item row="0" column="1" rowspan="3">
<widget class="QToolBox" name="stack">
<widget class="QTabWidget" name="stack">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
@ -190,19 +262,8 @@
<property name="currentIndex">
<number>0</number>
</property>
<property name="tabSpacing">
<number>0</number>
</property>
<widget class="QWidget" name="page">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>399</width>
<height>346</height>
</rect>
</property>
<attribute name="label">
<widget class="QWidget" name="stackPage1" native="true">
<attribute name="title">
<string>Plot</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
@ -246,16 +307,8 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>399</width>
<height>346</height>
</rect>
</property>
<attribute name="label">
<widget class="QWidget" name="stackPage2" native="true">
<attribute name="title">
<string>Statistics</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_2">
@ -296,16 +349,8 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="page_3">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>399</width>
<height>346</height>
</rect>
</property>
<attribute name="label">
<widget class="QWidget" name="stackPage3" native="true">
<attribute name="title">
<string>Correlations</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">

View File

@ -4,33 +4,33 @@ if [ -z ${GO_PIPELINE_LABEL} ]; then
else
APPIMAGE=NMReval-${GO_PIPELINE_LABEL}-x86_64.AppImage
ZSYNC=NMReval-${GO_PIPELINE_LABEL}-x86_64.AppImage.zsync
GITEA_OWNER=IPKM-Public
GITEA_OWNER=IPKM
#
# AppImage
#
# versioned
curl --user ${gitea_user}:${gitea_token} \
curl -sS --user ${gitea_user}:${gitea_token} \
--upload-file $APPIMAGE \
https://gitea.pkm.physik.tu-darmstadt.de/api/packages/${GITEA_OWNER}/generic/NMReval/${GO_PIPELINE_LABEL}/$APPIMAGE
# latest
curl --user ${gitea_user}:${gitea_token} --delete \
curl -sS --user ${gitea_user}:${gitea_token} -X DELETE \
https://gitea.pkm.physik.tu-darmstadt.de/api/packages/${GITEA_OWNER}/generic/NMReval/latest/NMReval-latest-x86_64.Appimage
curl --user ${gitea_user}:${gitea_token} \
curl -sS --user ${gitea_user}:${gitea_token} \
--upload-file $APPIMAGE \
https://gitea.pkm.physik.tu-darmstadt.de/api/packages/${GITEA_OWNER}/generic/NMReval/latest/NMReval-latest-x86_64.Appimage
#
# zsync files
#
# versioned
curl --user ${gitea_user}:${gitea_token} \
curl -sS --user ${gitea_user}:${gitea_token} \
--upload-file $ZSYNC \
https://gitea.pkm.physik.tu-darmstadt.de/api/packages/${GITEA_OWNER}/generic/NMReval/${GO_PIPELINE_LABEL}/$ZSYNC
# latest
curl --user ${gitea_user}:${gitea_token} --delete \
curl -sS --user ${gitea_user}:${gitea_token} -X DELETE \
https://gitea.pkm.physik.tu-darmstadt.de/api/packages/${GITEA_OWNER}/generic/NMReval/latest/NMReval-latest-x86_64.Appimage.zsync
curl --user ${gitea_user}:${gitea_token} \
curl -sS --user ${gitea_user}:${gitea_token} \
--upload-file $ZSYNC \
https://gitea.pkm.physik.tu-darmstadt.de/api/packages/${GITEA_OWNER}/generic/NMReval/latest/NMReval-latest-x86_64.Appimage.zsync
fi