forked from IPKM/nmreval
Compare commits
123 Commits
Author | SHA1 | Date | |
---|---|---|---|
90084e3481 | |||
91b2594b90 | |||
7145f9e3cd | |||
4108deb69a | |||
b2a3881fa8 | |||
1ab32af333 | |||
e1b76e837d | |||
5823ddd18c | |||
a2a95e796a | |||
8f92d8d822 | |||
6ecc789cd5 | |||
|
3ee7dca457 | ||
79d0ab1628 | |||
1162458290 | |||
c8aad904a8 | |||
b25db92cf1 | |||
403273e0d7 | |||
299bb043ea | |||
2f9cb761cf | |||
24f77f753c | |||
04d384363a | |||
ffba4900a1 | |||
80d9c7098c | |||
8d3ab75c97 | |||
24640d374e | |||
881eff2770 | |||
40746bfa7c | |||
567148b7e6 | |||
39b0fe75cb | |||
7161a17348 | |||
813e18a744 | |||
3626cfc7ea | |||
575cb5e8f6 | |||
465fb0c09a | |||
06491ff413 | |||
|
256bc20846 | ||
38a44047de | |||
d83e112515 | |||
73bdc71a83 | |||
58e86f4abc | |||
5ad6456b16 | |||
|
a1ab8ad889 | ||
57afee372f | |||
24bba43b40 | |||
694d47267d | |||
2cf94af2c4 | |||
92a3933ed4 | |||
9815c0df40 | |||
789801228a | |||
ce9bd5d2fd | |||
5b74ee1f29 | |||
036d798813 | |||
af0e0fc76f | |||
a0c07231c3 | |||
eda89b26fb | |||
c2dc4cc6b8 | |||
f7a17f22cf | |||
|
cd97dda2d4 | ||
b50200592d | |||
bfc25e33f9 | |||
772c51669d | |||
35ae571de0 | |||
bcc828efdc | |||
4df0ad6d20 | |||
adb71257ff | |||
c0dabbe9fe | |||
500e473212 | |||
3928e02b44 | |||
0c448e8ee9 | |||
6fd44a14fa | |||
9323cb8883 | |||
025b14a288 | |||
a7fed328ae | |||
a09a6bd988 | |||
6ee8d27d4a | |||
a789612eae | |||
c7855a74f4 | |||
d099253812 | |||
7c586c4bf0 | |||
0a9d596a91 | |||
49a1b0d4fa | |||
bd9288d20e | |||
223ddd4cda | |||
53349d7764 | |||
4afa7a37ca | |||
32ca840c78 | |||
a3f57fbf73 | |||
c157ebb0f9 | |||
962802ebe4 | |||
340bba747a | |||
331f700933 | |||
2a1852b4ca | |||
98c9354883 | |||
94fc92fb56 | |||
7e3541806b | |||
bd9051be00 | |||
d5293cf534 | |||
d4812a25ea | |||
a37704acc4 | |||
787d2f4c0f | |||
|
a9d284eabe | ||
|
20592e05c6 | ||
|
728eb34ca7 | ||
|
843866be45 | ||
|
aa0d14a322 | ||
|
12726e6f56 | ||
|
d146f4fe7e | ||
|
edf69b6424 | ||
|
e662dcf03c | ||
|
bb5c6a5491 | ||
|
386bc5a371 | ||
|
0c7ca0b9ba | ||
7c71061877 | |||
|
8a6c909c3e | ||
|
340d5d1038 | ||
|
c04052294c | ||
|
e063abc712 | ||
|
412708cecd | ||
|
c7a21c72f2 | ||
|
929bb80f2f | ||
|
dfe9eab817 | ||
|
d18b3ee671 | ||
|
64b270d7c1 |
51
.gitea/ISSUE_TEMPLATE/BUG_TEMPLATE.yml
Normal file
51
.gitea/ISSUE_TEMPLATE/BUG_TEMPLATE.yml
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
name: 🐞 Bug Report
|
||||||
|
description: File a bug/issue
|
||||||
|
title: "[BUG] <title>"
|
||||||
|
labels: ["Kind/Bug"]
|
||||||
|
assignees:
|
||||||
|
- dominik
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Current behavior
|
||||||
|
description: A concise description of what you're experiencing.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Version
|
||||||
|
description: For which version have you observed this behavior?
|
||||||
|
placeholder: You find the program version in "Help/About"
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Expected behavior
|
||||||
|
description: A concise description of what you expected to happen.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
description: If possible, describe steps to reproduce the behavior.
|
||||||
|
placeholder: |
|
||||||
|
1. Pressed button '...'
|
||||||
|
2. See error...
|
||||||
|
3. Infinite sadness 😞
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Log messages
|
||||||
|
description: |
|
||||||
|
Please copy and paste any relevant log output.
|
||||||
|
render: shell
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Anything else?
|
||||||
|
description: |
|
||||||
|
Everything else that could provide more context about the issue, e.g. screenshots.
|
||||||
|
validations:
|
||||||
|
required: false
|
26
.gitea/ISSUE_TEMPLATE/FEATURE_TEMPLATE.yml
Normal file
26
.gitea/ISSUE_TEMPLATE/FEATURE_TEMPLATE.yml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
name: 🙂 Feature Request
|
||||||
|
about: Request a new feature or feature improvement
|
||||||
|
title: "[Feature]: <title>"
|
||||||
|
labels: ["Kind/Feature", "Kind/Enhancement"]
|
||||||
|
assignees:
|
||||||
|
- dominik
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Proposed Behavior
|
||||||
|
description: A concise description of what you want to happen.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Possible benefits
|
||||||
|
description: A concise description of why this is an benefit for users.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Anything else?
|
||||||
|
description: |
|
||||||
|
Everything else that could provide more context about the issue, e.g. screenshots.
|
||||||
|
validations:
|
||||||
|
required: false
|
5
.gitea/ISSUE_TEMPLATE/config.yaml
Normal file
5
.gitea/ISSUE_TEMPLATE/config.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Mystery
|
||||||
|
url: https://c.xkcd.com/random/comic/
|
||||||
|
about: What is behind door number 3?
|
38
.gitea/workflows/build-appimage.yaml
Normal file
38
.gitea/workflows/build-appimage.yaml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
name: Build AppImage
|
||||||
|
run-name: ${{ gitea.actor }} is building THE AppImage 🚀 # a lot of excitement for this build
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Explore-Gitea-Actions:
|
||||||
|
runs-on: bookworm
|
||||||
|
steps:
|
||||||
|
- name: Check out repository code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- run: |
|
||||||
|
apt-get -y update
|
||||||
|
apt-get -y install python3-yaml python3-requests
|
||||||
|
- name: Declare some variables
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
echo "SHA_SHORT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
|
||||||
|
echo "YEAR=$(date +%Y)" >> $GITHUB_ENV
|
||||||
|
- name: Build AppImage
|
||||||
|
run: |
|
||||||
|
echo $GO_PIPELINE_LABEL
|
||||||
|
eval $(gpg-agent --daemon --allow-preset-passphrase --default-cache-ttl 1 --max-cache-ttl 7200)
|
||||||
|
/usr/lib/gnupg/gpg-preset-passphrase --preset --passphrase ${GPG_PASSPHRASE} ${GPG_KEYGRIP}
|
||||||
|
./tools/update_version.py
|
||||||
|
./tools/build.sh
|
||||||
|
env:
|
||||||
|
GPG_KEYGRIP: ${{ vars.GPG_KEYGRIP }}
|
||||||
|
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
|
GO_PIPELINE_LABEL: ${{ env.YEAR }}.${{ gitea.run_number }}_${{ env.SHA_SHORT }}
|
||||||
|
- name: Upload AppImage
|
||||||
|
run: ./tools/upload_gitea.sh
|
||||||
|
env:
|
||||||
|
GO_PIPELINE_LABEL: ${{ env.YEAR }}.${{ gitea.run_number }}_${{ env.SHA_SHORT }}
|
||||||
|
UPLOAD_TOKEN: ${{ secrets.UPLOAD_TOKEN }}
|
||||||
|
UPLOAD_USER: ${{ vars.UPLOAD_USER }}
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import os
|
||||||
sys.path.append(str(pathlib.Path(__file__).absolute().parent.parent / 'src'))
|
sys.path.append(str(pathlib.Path(__file__).absolute().parent.parent / 'src'))
|
||||||
|
|
||||||
from nmreval.configs import check_for_config
|
from nmreval.configs import check_for_config
|
||||||
@ -16,12 +17,45 @@ from nmreval.lib.logger import handle_exception
|
|||||||
sys.excepthook = handle_exception
|
sys.excepthook = handle_exception
|
||||||
|
|
||||||
from gui_qt import App
|
from gui_qt import App
|
||||||
|
from gui_qt.Qt import QtCore
|
||||||
|
|
||||||
app = App(['Team Rocket FTW!'])
|
app = App(['NMReval'])
|
||||||
|
|
||||||
from gui_qt.main.mainwindow import NMRMainWindow
|
from gui_qt.main.mainwindow import NMRMainWindow
|
||||||
|
from gui_qt.lib.backup import BackupManager
|
||||||
|
|
||||||
|
|
||||||
|
def do_autosave():
|
||||||
|
# autosave and update timestamp in db
|
||||||
|
success = mplQt.autosave()
|
||||||
|
if success:
|
||||||
|
backuping.update_last_save()
|
||||||
|
|
||||||
|
# autosave stuff: keep track of instance and their backup files
|
||||||
|
backuping = BackupManager()
|
||||||
|
|
||||||
|
# look for autosaves in DB without running programs
|
||||||
|
files = backuping.search_unsaved()
|
||||||
|
|
||||||
|
# tell everyone what autosave files belongs to this process
|
||||||
|
pid = os.getpid()
|
||||||
|
bck_name = backuping.create_entry(pid)
|
||||||
|
mplQt = NMRMainWindow(bck_file=bck_name)
|
||||||
|
|
||||||
|
# one manual autosave to create the file
|
||||||
|
do_autosave()
|
||||||
|
|
||||||
|
# load all selected autosaves to program
|
||||||
|
for f in files:
|
||||||
|
mplQt.management.load_files(f)
|
||||||
|
f.unlink()
|
||||||
|
|
||||||
|
timer = QtCore.QTimer()
|
||||||
|
timer.timeout.connect(do_autosave)
|
||||||
|
timer.start(3 * 60 * 1000)
|
||||||
|
|
||||||
|
app.aboutToQuit.connect(backuping.close)
|
||||||
|
|
||||||
mplQt = NMRMainWindow()
|
|
||||||
mplQt.show()
|
mplQt.show()
|
||||||
|
|
||||||
sys.exit(app.exec())
|
sys.exit(app.exec())
|
||||||
|
@ -360,7 +360,7 @@ class Ui_ascii_reader(object):
|
|||||||
self.x_label.setText(_translate("ascii_reader", "x"))
|
self.x_label.setText(_translate("ascii_reader", "x"))
|
||||||
self.dsdfsf.setText(_translate("ascii_reader", "Numerical value"))
|
self.dsdfsf.setText(_translate("ascii_reader", "Numerical value"))
|
||||||
self.label_9.setText(_translate("ascii_reader", "Match index"))
|
self.label_9.setText(_translate("ascii_reader", "Match index"))
|
||||||
self.regex_input.setToolTip(_translate("ascii_reader", "<html><head/><body><p>Token:<br/>[abc]: Matches any of a, b, or c<br/>[a-z]: Matches any digit in the range a-z<br/>\\d: Matches any digit in the range 0-9 (equal to [0-9}</p><p>Quantifiers:<br/>a*: 0 or more of a<br/>a*: 1 or more of a<br/>a?: 0 or 1 of a</p></body></html>"))
|
self.regex_input.setToolTip(_translate("ascii_reader", "<html><head/><body><p>Token:<br/>[abc]: Matches any of a, b, or c<br/>[a-z]: Matches any digit in the range a-z<br/>\\d: Matches any digit in the range 0-9 (equal to [0-9}</p><p>Quantifiers:<br/>a*: 0 or more of a<br/>a+: 1 or more of a<br/>a?: 0 or 1 of a</p></body></html>"))
|
||||||
self.re_button.setText(_translate("ascii_reader", "Regex"))
|
self.re_button.setText(_translate("ascii_reader", "Regex"))
|
||||||
self.custom_button.setText(_translate("ascii_reader", "Custom value"))
|
self.custom_button.setText(_translate("ascii_reader", "Custom value"))
|
||||||
self.label_8.setText(_translate("ascii_reader", "Filename"))
|
self.label_8.setText(_translate("ascii_reader", "Filename"))
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'src/resources/_ui/basewindow.ui'
|
# Form implementation generated from reading ui file './nmreval/src/resources/_ui/basewindow.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.15.9
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
# 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.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
@ -87,6 +87,8 @@ class Ui_BaseWindow(object):
|
|||||||
self.menuSave.setObjectName("menuSave")
|
self.menuSave.setObjectName("menuSave")
|
||||||
self.menuData = QtWidgets.QMenu(self.menubar)
|
self.menuData = QtWidgets.QMenu(self.menubar)
|
||||||
self.menuData.setObjectName("menuData")
|
self.menuData.setObjectName("menuData")
|
||||||
|
self.menuCut_to_visible_range = QtWidgets.QMenu(self.menuData)
|
||||||
|
self.menuCut_to_visible_range.setObjectName("menuCut_to_visible_range")
|
||||||
self.menuHelp = QtWidgets.QMenu(self.menubar)
|
self.menuHelp = QtWidgets.QMenu(self.menubar)
|
||||||
self.menuHelp.setObjectName("menuHelp")
|
self.menuHelp.setObjectName("menuHelp")
|
||||||
self.menuExtra = QtWidgets.QMenu(self.menubar)
|
self.menuExtra = QtWidgets.QMenu(self.menubar)
|
||||||
@ -153,15 +155,6 @@ class Ui_BaseWindow(object):
|
|||||||
self.toolBar_nmr.setIconSize(QtCore.QSize(24, 24))
|
self.toolBar_nmr.setIconSize(QtCore.QSize(24, 24))
|
||||||
self.toolBar_nmr.setObjectName("toolBar_nmr")
|
self.toolBar_nmr.setObjectName("toolBar_nmr")
|
||||||
BaseWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar_nmr)
|
BaseWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar_nmr)
|
||||||
self.toolBar_fit = QtWidgets.QToolBar(BaseWindow)
|
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
|
||||||
sizePolicy.setHorizontalStretch(0)
|
|
||||||
sizePolicy.setVerticalStretch(0)
|
|
||||||
sizePolicy.setHeightForWidth(self.toolBar_fit.sizePolicy().hasHeightForWidth())
|
|
||||||
self.toolBar_fit.setSizePolicy(sizePolicy)
|
|
||||||
self.toolBar_fit.setIconSize(QtCore.QSize(24, 24))
|
|
||||||
self.toolBar_fit.setObjectName("toolBar_fit")
|
|
||||||
BaseWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar_fit)
|
|
||||||
self.toolBar_spectrum = QtWidgets.QToolBar(BaseWindow)
|
self.toolBar_spectrum = QtWidgets.QToolBar(BaseWindow)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
@ -313,8 +306,6 @@ class Ui_BaseWindow(object):
|
|||||||
self.actionDerivation.setObjectName("actionDerivation")
|
self.actionDerivation.setObjectName("actionDerivation")
|
||||||
self.actionIntegration = QtWidgets.QAction(BaseWindow)
|
self.actionIntegration = QtWidgets.QAction(BaseWindow)
|
||||||
self.actionIntegration.setObjectName("actionIntegration")
|
self.actionIntegration.setObjectName("actionIntegration")
|
||||||
self.action_cut = QtWidgets.QAction(BaseWindow)
|
|
||||||
self.action_cut.setObjectName("action_cut")
|
|
||||||
self.actionMove_between_plots = QtWidgets.QAction(BaseWindow)
|
self.actionMove_between_plots = QtWidgets.QAction(BaseWindow)
|
||||||
self.actionMove_between_plots.setObjectName("actionMove_between_plots")
|
self.actionMove_between_plots.setObjectName("actionMove_between_plots")
|
||||||
self.actionBaseline = QtWidgets.QAction(BaseWindow)
|
self.actionBaseline = QtWidgets.QAction(BaseWindow)
|
||||||
@ -374,6 +365,15 @@ class Ui_BaseWindow(object):
|
|||||||
self.actionBinning.setObjectName("actionBinning")
|
self.actionBinning.setObjectName("actionBinning")
|
||||||
self.actionTNMH = QtWidgets.QAction(BaseWindow)
|
self.actionTNMH = QtWidgets.QAction(BaseWindow)
|
||||||
self.actionTNMH.setObjectName("actionTNMH")
|
self.actionTNMH.setObjectName("actionTNMH")
|
||||||
|
self.actionExclude_region = QtWidgets.QAction(BaseWindow)
|
||||||
|
self.actionExclude_region.setCheckable(True)
|
||||||
|
self.actionExclude_region.setObjectName("actionExclude_region")
|
||||||
|
self.action_cut_xaxis = QtWidgets.QAction(BaseWindow)
|
||||||
|
self.action_cut_xaxis.setObjectName("action_cut_xaxis")
|
||||||
|
self.action_cut_yaxis = QtWidgets.QAction(BaseWindow)
|
||||||
|
self.action_cut_yaxis.setObjectName("action_cut_yaxis")
|
||||||
|
self.actionUse_script = QtWidgets.QAction(BaseWindow)
|
||||||
|
self.actionUse_script.setObjectName("actionUse_script")
|
||||||
self.menuSave.addAction(self.actionSave)
|
self.menuSave.addAction(self.actionSave)
|
||||||
self.menuSave.addAction(self.actionExportGraphic)
|
self.menuSave.addAction(self.actionExportGraphic)
|
||||||
self.menuSave.addAction(self.action_save_fit_parameter)
|
self.menuSave.addAction(self.action_save_fit_parameter)
|
||||||
@ -386,6 +386,9 @@ class Ui_BaseWindow(object):
|
|||||||
self.menuFile.addSeparator()
|
self.menuFile.addSeparator()
|
||||||
self.menuFile.addAction(self.action_close)
|
self.menuFile.addAction(self.action_close)
|
||||||
self.menuFile.addSeparator()
|
self.menuFile.addSeparator()
|
||||||
|
self.menuCut_to_visible_range.addSeparator()
|
||||||
|
self.menuCut_to_visible_range.addAction(self.action_cut_xaxis)
|
||||||
|
self.menuCut_to_visible_range.addAction(self.action_cut_yaxis)
|
||||||
self.menuData.addAction(self.action_new_set)
|
self.menuData.addAction(self.action_new_set)
|
||||||
self.menuData.addAction(self.action_delete_sets)
|
self.menuData.addAction(self.action_delete_sets)
|
||||||
self.menuData.addAction(self.actionMove_between_plots)
|
self.menuData.addAction(self.actionMove_between_plots)
|
||||||
@ -395,9 +398,10 @@ class Ui_BaseWindow(object):
|
|||||||
self.menuData.addAction(self.action_sort_pts)
|
self.menuData.addAction(self.action_sort_pts)
|
||||||
self.menuData.addAction(self.actionSkip_points)
|
self.menuData.addAction(self.actionSkip_points)
|
||||||
self.menuData.addSeparator()
|
self.menuData.addSeparator()
|
||||||
self.menuData.addAction(self.action_cut)
|
self.menuData.addAction(self.menuCut_to_visible_range.menuAction())
|
||||||
self.menuData.addSeparator()
|
self.menuData.addSeparator()
|
||||||
self.menuData.addAction(self.actionChange_datatypes)
|
self.menuData.addAction(self.actionChange_datatypes)
|
||||||
|
self.menuData.addAction(self.actionUse_script)
|
||||||
self.menuHelp.addAction(self.actionShow_error_log)
|
self.menuHelp.addAction(self.actionShow_error_log)
|
||||||
self.menuHelp.addAction(self.actionUpdate)
|
self.menuHelp.addAction(self.actionUpdate)
|
||||||
self.menuHelp.addAction(self.actionBugs)
|
self.menuHelp.addAction(self.actionBugs)
|
||||||
@ -428,6 +432,7 @@ class Ui_BaseWindow(object):
|
|||||||
self.menuLimits.addAction(self.action_no_range)
|
self.menuLimits.addAction(self.action_no_range)
|
||||||
self.menuLimits.addAction(self.action_x_range)
|
self.menuLimits.addAction(self.action_x_range)
|
||||||
self.menuLimits.addAction(self.action_custom_range)
|
self.menuLimits.addAction(self.action_custom_range)
|
||||||
|
self.menuLimits.addAction(self.actionExclude_region)
|
||||||
self.menuFit.addAction(self.action_FitWidget)
|
self.menuFit.addAction(self.action_FitWidget)
|
||||||
self.menuFit.addSeparator()
|
self.menuFit.addSeparator()
|
||||||
self.menuFit.addAction(self.action_create_fit_function)
|
self.menuFit.addAction(self.action_create_fit_function)
|
||||||
@ -496,7 +501,6 @@ class Ui_BaseWindow(object):
|
|||||||
self.toolbar_edit.addAction(self.actionShift)
|
self.toolbar_edit.addAction(self.actionShift)
|
||||||
self.toolBar_nmr.addAction(self.t1action)
|
self.toolBar_nmr.addAction(self.t1action)
|
||||||
self.toolBar_nmr.addAction(self.actionCalculateT1)
|
self.toolBar_nmr.addAction(self.actionCalculateT1)
|
||||||
self.toolBar_fit.addAction(self.action_FitWidget)
|
|
||||||
self.toolBar_spectrum.addAction(self.action_edit)
|
self.toolBar_spectrum.addAction(self.action_edit)
|
||||||
self.toolBar_spectrum.addAction(self.actionPick_position)
|
self.toolBar_spectrum.addAction(self.actionPick_position)
|
||||||
self.toolBar_data.addAction(self.actionConcatenate_sets)
|
self.toolBar_data.addAction(self.actionConcatenate_sets)
|
||||||
@ -521,6 +525,7 @@ class Ui_BaseWindow(object):
|
|||||||
self.menuFile.setTitle(_translate("BaseWindow", "&File"))
|
self.menuFile.setTitle(_translate("BaseWindow", "&File"))
|
||||||
self.menuSave.setTitle(_translate("BaseWindow", "&Save..."))
|
self.menuSave.setTitle(_translate("BaseWindow", "&Save..."))
|
||||||
self.menuData.setTitle(_translate("BaseWindow", "&Data"))
|
self.menuData.setTitle(_translate("BaseWindow", "&Data"))
|
||||||
|
self.menuCut_to_visible_range.setTitle(_translate("BaseWindow", "Cut to visible range"))
|
||||||
self.menuHelp.setTitle(_translate("BaseWindow", "&Help"))
|
self.menuHelp.setTitle(_translate("BaseWindow", "&Help"))
|
||||||
self.menuExtra.setTitle(_translate("BaseWindow", "Math"))
|
self.menuExtra.setTitle(_translate("BaseWindow", "Math"))
|
||||||
self.menuNormalize.setTitle(_translate("BaseWindow", "&Normalize"))
|
self.menuNormalize.setTitle(_translate("BaseWindow", "&Normalize"))
|
||||||
@ -537,7 +542,6 @@ class Ui_BaseWindow(object):
|
|||||||
self.toolBar.setWindowTitle(_translate("BaseWindow", "Main"))
|
self.toolBar.setWindowTitle(_translate("BaseWindow", "Main"))
|
||||||
self.toolbar_edit.setWindowTitle(_translate("BaseWindow", "Math"))
|
self.toolbar_edit.setWindowTitle(_translate("BaseWindow", "Math"))
|
||||||
self.toolBar_nmr.setWindowTitle(_translate("BaseWindow", "NMR"))
|
self.toolBar_nmr.setWindowTitle(_translate("BaseWindow", "NMR"))
|
||||||
self.toolBar_fit.setWindowTitle(_translate("BaseWindow", "Fit"))
|
|
||||||
self.toolBar_spectrum.setWindowTitle(_translate("BaseWindow", "Spectrum"))
|
self.toolBar_spectrum.setWindowTitle(_translate("BaseWindow", "Spectrum"))
|
||||||
self.toolBar_data.setWindowTitle(_translate("BaseWindow", "Data"))
|
self.toolBar_data.setWindowTitle(_translate("BaseWindow", "Data"))
|
||||||
self.action_close.setText(_translate("BaseWindow", "&Quit"))
|
self.action_close.setText(_translate("BaseWindow", "&Quit"))
|
||||||
@ -615,7 +619,6 @@ class Ui_BaseWindow(object):
|
|||||||
self.actionIntegrate.setText(_translate("BaseWindow", "Integrate"))
|
self.actionIntegrate.setText(_translate("BaseWindow", "Integrate"))
|
||||||
self.actionDerivation.setText(_translate("BaseWindow", "Differentiation..."))
|
self.actionDerivation.setText(_translate("BaseWindow", "Differentiation..."))
|
||||||
self.actionIntegration.setText(_translate("BaseWindow", "Integration..."))
|
self.actionIntegration.setText(_translate("BaseWindow", "Integration..."))
|
||||||
self.action_cut.setText(_translate("BaseWindow", "Cut to visible range"))
|
|
||||||
self.actionMove_between_plots.setText(_translate("BaseWindow", "Move sets..."))
|
self.actionMove_between_plots.setText(_translate("BaseWindow", "Move sets..."))
|
||||||
self.actionBaseline.setText(_translate("BaseWindow", "Baseline..."))
|
self.actionBaseline.setText(_translate("BaseWindow", "Baseline..."))
|
||||||
self.actionCalculateT1.setText(_translate("BaseWindow", "Calculate relaxation..."))
|
self.actionCalculateT1.setText(_translate("BaseWindow", "Calculate relaxation..."))
|
||||||
@ -642,6 +645,12 @@ class Ui_BaseWindow(object):
|
|||||||
self.actionTNMH_model.setText(_translate("BaseWindow", "Tg , Hodge, TNMH,,,"))
|
self.actionTNMH_model.setText(_translate("BaseWindow", "Tg , Hodge, TNMH,,,"))
|
||||||
self.actionBinning.setText(_translate("BaseWindow", "Binning..."))
|
self.actionBinning.setText(_translate("BaseWindow", "Binning..."))
|
||||||
self.actionTNMH.setText(_translate("BaseWindow", "TNMH..."))
|
self.actionTNMH.setText(_translate("BaseWindow", "TNMH..."))
|
||||||
|
self.actionExclude_region.setText(_translate("BaseWindow", "Exclude region"))
|
||||||
|
self.action_cut_xaxis.setText(_translate("BaseWindow", "x axis"))
|
||||||
|
self.action_cut_xaxis.setToolTip(_translate("BaseWindow", "Remove data points outside visible x range."))
|
||||||
|
self.action_cut_yaxis.setText(_translate("BaseWindow", "y axis"))
|
||||||
|
self.action_cut_yaxis.setToolTip(_translate("BaseWindow", "Remove data points outside visible y range. Uses real part of points."))
|
||||||
|
self.actionUse_script.setText(_translate("BaseWindow", "Use script..."))
|
||||||
from ..data.datawidget.datawidget import DataWidget
|
from ..data.datawidget.datawidget import DataWidget
|
||||||
from ..data.integral_widget import IntegralWidget
|
from ..data.integral_widget import IntegralWidget
|
||||||
from ..data.point_select import PointSelectWidget
|
from ..data.point_select import PointSelectWidget
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'resources/_ui/datawidget.ui'
|
# Form implementation generated from reading ui file './nmreval/src/resources/_ui/datawidget.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.12.3
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# 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
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
@ -49,6 +50,12 @@ class Ui_DataWidget(object):
|
|||||||
self.horizontalLayout.addWidget(self.func_toolButton)
|
self.horizontalLayout.addWidget(self.func_toolButton)
|
||||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
self.horizontalLayout.addItem(spacerItem)
|
self.horizontalLayout.addItem(spacerItem)
|
||||||
|
self.pokemon_toolbutton = QtWidgets.QToolButton(self.frame)
|
||||||
|
self.pokemon_toolbutton.setText("")
|
||||||
|
self.pokemon_toolbutton.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
|
||||||
|
self.pokemon_toolbutton.setAutoRaise(True)
|
||||||
|
self.pokemon_toolbutton.setObjectName("pokemon_toolbutton")
|
||||||
|
self.horizontalLayout.addWidget(self.pokemon_toolbutton)
|
||||||
self.verticalLayout_2.addWidget(self.frame)
|
self.verticalLayout_2.addWidget(self.frame)
|
||||||
|
|
||||||
self.retranslateUi(DataWidget)
|
self.retranslateUi(DataWidget)
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'resources/_ui/fcreader.ui'
|
# Form implementation generated from reading ui file 'src/resources/_ui/fcreader.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.12.3
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# 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
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
@ -47,6 +48,7 @@ class Ui_FCEval_dialog(object):
|
|||||||
self.verticalLayout.addWidget(self.input_box)
|
self.verticalLayout.addWidget(self.input_box)
|
||||||
self.region_box = QtWidgets.QGroupBox(FCEval_dialog)
|
self.region_box = QtWidgets.QGroupBox(FCEval_dialog)
|
||||||
self.region_box.setCheckable(True)
|
self.region_box.setCheckable(True)
|
||||||
|
self.region_box.setChecked(False)
|
||||||
self.region_box.setObjectName("region_box")
|
self.region_box.setObjectName("region_box")
|
||||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.region_box)
|
self.horizontalLayout = QtWidgets.QHBoxLayout(self.region_box)
|
||||||
self.horizontalLayout.setContentsMargins(3, 3, 3, 3)
|
self.horizontalLayout.setContentsMargins(3, 3, 3, 3)
|
||||||
@ -139,6 +141,7 @@ class Ui_FCEval_dialog(object):
|
|||||||
self.line.setObjectName("line")
|
self.line.setObjectName("line")
|
||||||
self.gridLayout.addWidget(self.line, 2, 0, 1, 2)
|
self.gridLayout.addWidget(self.line, 2, 0, 1, 2)
|
||||||
self.graph_comboBox = QtWidgets.QComboBox(self.out_box)
|
self.graph_comboBox = QtWidgets.QComboBox(self.out_box)
|
||||||
|
self.graph_comboBox.setEnabled(False)
|
||||||
self.graph_comboBox.setObjectName("graph_comboBox")
|
self.graph_comboBox.setObjectName("graph_comboBox")
|
||||||
self.gridLayout.addWidget(self.graph_comboBox, 3, 1, 1, 1)
|
self.gridLayout.addWidget(self.graph_comboBox, 3, 1, 1, 1)
|
||||||
self.graph_checkbox = QtWidgets.QCheckBox(self.out_box)
|
self.graph_checkbox = QtWidgets.QCheckBox(self.out_box)
|
||||||
@ -167,8 +170,8 @@ class Ui_FCEval_dialog(object):
|
|||||||
self.label_6.setBuddy(self.m0_cb)
|
self.label_6.setBuddy(self.m0_cb)
|
||||||
|
|
||||||
self.retranslateUi(FCEval_dialog)
|
self.retranslateUi(FCEval_dialog)
|
||||||
self.buttonBox.accepted.connect(FCEval_dialog.accept)
|
self.buttonBox.accepted.connect(FCEval_dialog.accept) # type: ignore
|
||||||
self.buttonBox.rejected.connect(FCEval_dialog.reject)
|
self.buttonBox.rejected.connect(FCEval_dialog.reject) # type: ignore
|
||||||
QtCore.QMetaObject.connectSlotsByName(FCEval_dialog)
|
QtCore.QMetaObject.connectSlotsByName(FCEval_dialog)
|
||||||
|
|
||||||
def retranslateUi(self, FCEval_dialog):
|
def retranslateUi(self, FCEval_dialog):
|
||||||
@ -178,7 +181,7 @@ class Ui_FCEval_dialog(object):
|
|||||||
self.file_pushbutton.setText(_translate("FCEval_dialog", "Add HDF files..."))
|
self.file_pushbutton.setText(_translate("FCEval_dialog", "Add HDF files..."))
|
||||||
self.dir_pushbutton.setText(_translate("FCEval_dialog", "Add directory..."))
|
self.dir_pushbutton.setText(_translate("FCEval_dialog", "Add directory..."))
|
||||||
self.overwrite_cb.setText(_translate("FCEval_dialog", "Overwrite prev. data"))
|
self.overwrite_cb.setText(_translate("FCEval_dialog", "Overwrite prev. data"))
|
||||||
self.region_box.setTitle(_translate("FCEval_dialog", "Evaluate region (empty values default to start/end)"))
|
self.region_box.setTitle(_translate("FCEval_dialog", "Evaluate region (empty values default to values of the script)"))
|
||||||
self.start_lineedit.setPlaceholderText(_translate("FCEval_dialog", "start pos in µs"))
|
self.start_lineedit.setPlaceholderText(_translate("FCEval_dialog", "start pos in µs"))
|
||||||
self.stop_lineedit.setPlaceholderText(_translate("FCEval_dialog", "end pos in µs"))
|
self.stop_lineedit.setPlaceholderText(_translate("FCEval_dialog", "end pos in µs"))
|
||||||
self.fit_box.setTitle(_translate("FCEval_dialog", "Fit equation"))
|
self.fit_box.setTitle(_translate("FCEval_dialog", "Fit equation"))
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'resources/_ui/fitcreationdialog.ui'
|
# Form implementation generated from reading ui file 'resources/_ui/fitcreationdialog.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.15.4
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
# 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.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
@ -51,9 +51,8 @@ class Ui_Dialog(object):
|
|||||||
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.namespace_box)
|
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.namespace_box)
|
||||||
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
||||||
self.tabWidget.addTab(self.namespace_box, "")
|
self.tabWidget.addTab(self.namespace_box, "")
|
||||||
self.plainTextEdit = CodeEditor(self.splitter)
|
self.editor = EditorWidget(self.splitter)
|
||||||
self.plainTextEdit.setEnabled(True)
|
self.editor.setObjectName("editor")
|
||||||
self.plainTextEdit.setObjectName("plainTextEdit")
|
|
||||||
self.verticalLayout.addWidget(self.splitter)
|
self.verticalLayout.addWidget(self.splitter)
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
||||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||||
@ -63,8 +62,8 @@ class Ui_Dialog(object):
|
|||||||
|
|
||||||
self.retranslateUi(Dialog)
|
self.retranslateUi(Dialog)
|
||||||
self.tabWidget.setCurrentIndex(0)
|
self.tabWidget.setCurrentIndex(0)
|
||||||
self.buttonBox.accepted.connect(Dialog.accept)
|
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
|
||||||
self.buttonBox.rejected.connect(Dialog.reject)
|
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
|
||||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||||
|
|
||||||
def retranslateUi(self, Dialog):
|
def retranslateUi(self, Dialog):
|
||||||
@ -74,4 +73,4 @@ class Ui_Dialog(object):
|
|||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.args_box), _translate("Dialog", "Variables"))
|
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.kwargs_box), _translate("Dialog", "Multiple choice"))
|
||||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.namespace_box), _translate("Dialog", "Available Functions"))
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.namespace_box), _translate("Dialog", "Available Functions"))
|
||||||
from ..lib.codeeditor import CodeEditor
|
from ..lib.codeeditor import EditorWidget
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'src/resources/_ui/fitmodelwidget.ui'
|
# Form implementation generated from reading ui file 'src/resources/_ui/fitmodelwidget.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.15.9
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
# 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.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
@ -42,6 +42,7 @@ class Ui_FitParameter(object):
|
|||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.parameter_line.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.parameter_line.sizePolicy().hasHeightForWidth())
|
||||||
self.parameter_line.setSizePolicy(sizePolicy)
|
self.parameter_line.setSizePolicy(sizePolicy)
|
||||||
|
self.parameter_line.setMaximumSize(QtCore.QSize(160, 16777215))
|
||||||
self.parameter_line.setText("")
|
self.parameter_line.setText("")
|
||||||
self.parameter_line.setObjectName("parameter_line")
|
self.parameter_line.setObjectName("parameter_line")
|
||||||
self.horizontalLayout_2.addWidget(self.parameter_line)
|
self.horizontalLayout_2.addWidget(self.parameter_line)
|
||||||
@ -51,6 +52,9 @@ class Ui_FitParameter(object):
|
|||||||
self.global_checkbox = QtWidgets.QCheckBox(FitParameter)
|
self.global_checkbox = QtWidgets.QCheckBox(FitParameter)
|
||||||
self.global_checkbox.setObjectName("global_checkbox")
|
self.global_checkbox.setObjectName("global_checkbox")
|
||||||
self.horizontalLayout_2.addWidget(self.global_checkbox)
|
self.horizontalLayout_2.addWidget(self.global_checkbox)
|
||||||
|
self.reset_button = QtWidgets.QPushButton(FitParameter)
|
||||||
|
self.reset_button.setObjectName("reset_button")
|
||||||
|
self.horizontalLayout_2.addWidget(self.reset_button)
|
||||||
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
||||||
self.frame = QtWidgets.QFrame(FitParameter)
|
self.frame = QtWidgets.QFrame(FitParameter)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
|
||||||
@ -82,6 +86,7 @@ class Ui_FitParameter(object):
|
|||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.lineEdit.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.lineEdit.sizePolicy().hasHeightForWidth())
|
||||||
self.lineEdit.setSizePolicy(sizePolicy)
|
self.lineEdit.setSizePolicy(sizePolicy)
|
||||||
|
self.lineEdit.setMaximumSize(QtCore.QSize(100, 16777215))
|
||||||
self.lineEdit.setText("")
|
self.lineEdit.setText("")
|
||||||
self.lineEdit.setFrame(True)
|
self.lineEdit.setFrame(True)
|
||||||
self.lineEdit.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
|
self.lineEdit.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
|
||||||
@ -100,6 +105,7 @@ class Ui_FitParameter(object):
|
|||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy.setHeightForWidth(self.lineEdit_2.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.lineEdit_2.sizePolicy().hasHeightForWidth())
|
||||||
self.lineEdit_2.setSizePolicy(sizePolicy)
|
self.lineEdit_2.setSizePolicy(sizePolicy)
|
||||||
|
self.lineEdit_2.setMaximumSize(QtCore.QSize(100, 16777215))
|
||||||
self.lineEdit_2.setText("")
|
self.lineEdit_2.setText("")
|
||||||
self.lineEdit_2.setFrame(True)
|
self.lineEdit_2.setFrame(True)
|
||||||
self.lineEdit_2.setObjectName("lineEdit_2")
|
self.lineEdit_2.setObjectName("lineEdit_2")
|
||||||
@ -122,6 +128,7 @@ class Ui_FitParameter(object):
|
|||||||
self.parameter_line.setPlaceholderText(_translate("FitParameter", "0"))
|
self.parameter_line.setPlaceholderText(_translate("FitParameter", "0"))
|
||||||
self.fixed_check.setText(_translate("FitParameter", "Fix"))
|
self.fixed_check.setText(_translate("FitParameter", "Fix"))
|
||||||
self.global_checkbox.setText(_translate("FitParameter", "Global"))
|
self.global_checkbox.setText(_translate("FitParameter", "Global"))
|
||||||
|
self.reset_button.setText(_translate("FitParameter", "Use global"))
|
||||||
self.lineEdit.setToolTip(_translate("FitParameter", "<html><head/><body><p>Lower bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html>"))
|
self.lineEdit.setToolTip(_translate("FitParameter", "<html><head/><body><p>Lower bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html>"))
|
||||||
self.label_3.setText(_translate("FitParameter", "Textlabel"))
|
self.label_3.setText(_translate("FitParameter", "Textlabel"))
|
||||||
self.lineEdit_2.setToolTip(_translate("FitParameter", "<html><head/><body><p>Upper bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html>"))
|
self.lineEdit_2.setToolTip(_translate("FitParameter", "<html><head/><body><p>Upper bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html>"))
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'src/resources/_ui/fitresult.ui'
|
# Form implementation generated from reading ui file 'src/resources/_ui/fitresult.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.15.9
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
# 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.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
@ -27,20 +27,48 @@ class Ui_Dialog(object):
|
|||||||
self.stackPage1 = QtWidgets.QWidget()
|
self.stackPage1 = QtWidgets.QWidget()
|
||||||
self.stackPage1.setObjectName("stackPage1")
|
self.stackPage1.setObjectName("stackPage1")
|
||||||
self.gridLayout_3 = QtWidgets.QGridLayout(self.stackPage1)
|
self.gridLayout_3 = QtWidgets.QGridLayout(self.stackPage1)
|
||||||
self.gridLayout_3.setContentsMargins(3, 3, 3, 3)
|
self.gridLayout_3.setContentsMargins(6, 3, 6, 3)
|
||||||
self.gridLayout_3.setSpacing(3)
|
self.gridLayout_3.setSpacing(3)
|
||||||
self.gridLayout_3.setObjectName("gridLayout_3")
|
self.gridLayout_3.setObjectName("gridLayout_3")
|
||||||
self.logy_box = QtWidgets.QCheckBox(self.stackPage1)
|
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
self.logy_box.setLayoutDirection(QtCore.Qt.RightToLeft)
|
self.gridLayout_3.addItem(spacerItem, 2, 3, 1, 1)
|
||||||
self.logy_box.setObjectName("logy_box")
|
self.autoscale_box = QtWidgets.QToolButton(self.stackPage1)
|
||||||
self.gridLayout_3.addWidget(self.logy_box, 2, 1, 1, 1)
|
self.autoscale_box.setObjectName("autoscale_box")
|
||||||
self.logx_box = QtWidgets.QCheckBox(self.stackPage1)
|
self.gridLayout_3.addWidget(self.autoscale_box, 2, 4, 1, 1)
|
||||||
self.logx_box.setLayoutDirection(QtCore.Qt.RightToLeft)
|
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
|
self.gridLayout_3.addItem(spacerItem1, 2, 1, 1, 1)
|
||||||
|
self.verticalGroupBox_2 = QtWidgets.QGroupBox(self.stackPage1)
|
||||||
|
self.verticalGroupBox_2.setObjectName("verticalGroupBox_2")
|
||||||
|
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.verticalGroupBox_2)
|
||||||
|
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||||
|
self.logx_box = QtWidgets.QCheckBox(self.verticalGroupBox_2)
|
||||||
|
self.logx_box.setLayoutDirection(QtCore.Qt.LeftToRight)
|
||||||
self.logx_box.setObjectName("logx_box")
|
self.logx_box.setObjectName("logx_box")
|
||||||
self.gridLayout_3.addWidget(self.logx_box, 2, 0, 1, 1)
|
self.verticalLayout_4.addWidget(self.logx_box)
|
||||||
|
self.logy_box = QtWidgets.QCheckBox(self.verticalGroupBox_2)
|
||||||
|
self.logy_box.setLayoutDirection(QtCore.Qt.LeftToRight)
|
||||||
|
self.logy_box.setObjectName("logy_box")
|
||||||
|
self.verticalLayout_4.addWidget(self.logy_box)
|
||||||
|
self.gridLayout_3.addWidget(self.verticalGroupBox_2, 2, 2, 1, 1)
|
||||||
|
self.verticalGroupBox = QtWidgets.QGroupBox(self.stackPage1)
|
||||||
|
self.verticalGroupBox.setObjectName("verticalGroupBox")
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalGroupBox)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.rel_dev_button = QtWidgets.QRadioButton(self.verticalGroupBox)
|
||||||
|
self.rel_dev_button.setObjectName("rel_dev_button")
|
||||||
|
self.buttonGroup = QtWidgets.QButtonGroup(Dialog)
|
||||||
|
self.buttonGroup.setObjectName("buttonGroup")
|
||||||
|
self.buttonGroup.addButton(self.rel_dev_button)
|
||||||
|
self.verticalLayout.addWidget(self.rel_dev_button)
|
||||||
|
self.abs_dev_button = QtWidgets.QRadioButton(self.verticalGroupBox)
|
||||||
|
self.abs_dev_button.setChecked(True)
|
||||||
|
self.abs_dev_button.setObjectName("abs_dev_button")
|
||||||
|
self.buttonGroup.addButton(self.abs_dev_button)
|
||||||
|
self.verticalLayout.addWidget(self.abs_dev_button)
|
||||||
|
self.gridLayout_3.addWidget(self.verticalGroupBox, 2, 0, 1, 1)
|
||||||
self.graphicsView = GraphicsLayoutWidget(self.stackPage1)
|
self.graphicsView = GraphicsLayoutWidget(self.stackPage1)
|
||||||
self.graphicsView.setObjectName("graphicsView")
|
self.graphicsView.setObjectName("graphicsView")
|
||||||
self.gridLayout_3.addWidget(self.graphicsView, 0, 0, 1, 2)
|
self.gridLayout_3.addWidget(self.graphicsView, 0, 0, 1, 5)
|
||||||
self.stack.addTab(self.stackPage1, "")
|
self.stack.addTab(self.stackPage1, "")
|
||||||
self.stackPage2 = QtWidgets.QWidget()
|
self.stackPage2 = QtWidgets.QWidget()
|
||||||
self.stackPage2.setObjectName("stackPage2")
|
self.stackPage2.setObjectName("stackPage2")
|
||||||
@ -84,10 +112,6 @@ class Ui_Dialog(object):
|
|||||||
self.verticalLayout_3.addWidget(self.corr_tableWidget)
|
self.verticalLayout_3.addWidget(self.corr_tableWidget)
|
||||||
self.stack.addTab(self.stackPage3, "")
|
self.stack.addTab(self.stackPage3, "")
|
||||||
self.gridLayout.addWidget(self.stack, 0, 1, 5, 1)
|
self.gridLayout.addWidget(self.stack, 0, 1, 5, 1)
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
|
||||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Retry)
|
|
||||||
self.buttonBox.setObjectName("buttonBox")
|
|
||||||
self.gridLayout.addWidget(self.buttonBox, 8, 0, 1, 2)
|
|
||||||
self.param_tableWidget = QtWidgets.QTableWidget(Dialog)
|
self.param_tableWidget = QtWidgets.QTableWidget(Dialog)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
@ -113,74 +137,6 @@ class Ui_Dialog(object):
|
|||||||
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||||
self.line.setObjectName("line")
|
self.line.setObjectName("line")
|
||||||
self.gridLayout.addWidget(self.line, 5, 0, 1, 2)
|
self.gridLayout.addWidget(self.line, 5, 0, 1, 2)
|
||||||
self.groupBox = QtWidgets.QGroupBox(Dialog)
|
|
||||||
self.groupBox.setObjectName("groupBox")
|
|
||||||
self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox)
|
|
||||||
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)
|
|
||||||
sizePolicy.setVerticalStretch(0)
|
|
||||||
sizePolicy.setHeightForWidth(self.graph_checkBox.sizePolicy().hasHeightForWidth())
|
|
||||||
self.graph_checkBox.setSizePolicy(sizePolicy)
|
|
||||||
self.graph_checkBox.setChecked(True)
|
|
||||||
self.graph_checkBox.setObjectName("graph_checkBox")
|
|
||||||
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.horizontalLayout.addWidget(self.curve_checkbox)
|
|
||||||
self.partial_checkBox = QtWidgets.QCheckBox(self.groupBox)
|
|
||||||
self.partial_checkBox.setObjectName("partial_checkBox")
|
|
||||||
self.horizontalLayout.addWidget(self.partial_checkBox)
|
|
||||||
self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 4)
|
|
||||||
self.gridLayout.addWidget(self.groupBox, 7, 0, 1, 2)
|
|
||||||
self.sets_comboBox = ElideComboBox(Dialog)
|
self.sets_comboBox = ElideComboBox(Dialog)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
@ -195,6 +151,102 @@ class Ui_Dialog(object):
|
|||||||
self.reject_fit_checkBox = QtWidgets.QCheckBox(Dialog)
|
self.reject_fit_checkBox = QtWidgets.QCheckBox(Dialog)
|
||||||
self.reject_fit_checkBox.setObjectName("reject_fit_checkBox")
|
self.reject_fit_checkBox.setObjectName("reject_fit_checkBox")
|
||||||
self.gridLayout.addWidget(self.reject_fit_checkBox, 2, 0, 1, 1)
|
self.gridLayout.addWidget(self.reject_fit_checkBox, 2, 0, 1, 1)
|
||||||
|
self.groupBox = QtWidgets.QGroupBox(Dialog)
|
||||||
|
self.groupBox.setObjectName("groupBox")
|
||||||
|
self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox)
|
||||||
|
self.gridLayout_2.setContentsMargins(3, 3, 3, 3)
|
||||||
|
self.gridLayout_2.setSpacing(3)
|
||||||
|
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||||
|
self.graph_comboBox = QtWidgets.QComboBox(self.groupBox)
|
||||||
|
self.graph_comboBox.setEnabled(False)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, 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, 7, 1, 1)
|
||||||
|
self.minx_line = QtWidgets.QLineEdit(self.groupBox)
|
||||||
|
self.minx_line.setEnabled(False)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, 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.extrapolate_box = QtWidgets.QCheckBox(self.groupBox)
|
||||||
|
self.extrapolate_box.setObjectName("extrapolate_box")
|
||||||
|
self.gridLayout_2.addWidget(self.extrapolate_box, 1, 0, 1, 1)
|
||||||
|
self.numx_line = QtWidgets.QLineEdit(self.groupBox)
|
||||||
|
self.numx_line.setEnabled(False)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.numx_line.sizePolicy().hasHeightForWidth())
|
||||||
|
self.numx_line.setSizePolicy(sizePolicy)
|
||||||
|
self.numx_line.setObjectName("numx_line")
|
||||||
|
self.gridLayout_2.addWidget(self.numx_line, 1, 3, 1, 1)
|
||||||
|
self.graph_checkBox = QtWidgets.QCheckBox(self.groupBox)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.graph_checkBox.sizePolicy().hasHeightForWidth())
|
||||||
|
self.graph_checkBox.setSizePolicy(sizePolicy)
|
||||||
|
self.graph_checkBox.setChecked(True)
|
||||||
|
self.graph_checkBox.setObjectName("graph_checkBox")
|
||||||
|
self.gridLayout_2.addWidget(self.graph_checkBox, 1, 6, 1, 1)
|
||||||
|
self.maxx_line = QtWidgets.QLineEdit(self.groupBox)
|
||||||
|
self.maxx_line.setEnabled(False)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, 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.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, 5, 2, 1)
|
||||||
|
self.newx_log_checkbox = QtWidgets.QCheckBox(self.groupBox)
|
||||||
|
self.newx_log_checkbox.setEnabled(False)
|
||||||
|
self.newx_log_checkbox.setObjectName("newx_log_checkbox")
|
||||||
|
self.gridLayout_2.addWidget(self.newx_log_checkbox, 1, 4, 1, 1)
|
||||||
|
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
|
self.curve_checkbox = QtWidgets.QCheckBox(self.groupBox)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.curve_checkbox.sizePolicy().hasHeightForWidth())
|
||||||
|
self.curve_checkbox.setSizePolicy(sizePolicy)
|
||||||
|
self.curve_checkbox.setChecked(True)
|
||||||
|
self.curve_checkbox.setObjectName("curve_checkbox")
|
||||||
|
self.horizontalLayout.addWidget(self.curve_checkbox)
|
||||||
|
self.partial_checkBox = QtWidgets.QCheckBox(self.groupBox)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.partial_checkBox.sizePolicy().hasHeightForWidth())
|
||||||
|
self.partial_checkBox.setSizePolicy(sizePolicy)
|
||||||
|
self.partial_checkBox.setObjectName("partial_checkBox")
|
||||||
|
self.horizontalLayout.addWidget(self.partial_checkBox)
|
||||||
|
self.gridLayout_2.addLayout(self.horizontalLayout, 0, 0, 1, 5)
|
||||||
|
self.parameter_checkbox = QtWidgets.QCheckBox(self.groupBox)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.parameter_checkbox.sizePolicy().hasHeightForWidth())
|
||||||
|
self.parameter_checkbox.setSizePolicy(sizePolicy)
|
||||||
|
self.parameter_checkbox.setObjectName("parameter_checkbox")
|
||||||
|
self.gridLayout_2.addWidget(self.parameter_checkbox, 0, 6, 1, 2)
|
||||||
|
self.gridLayout.addWidget(self.groupBox, 7, 0, 1, 2)
|
||||||
|
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
||||||
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Retry)
|
||||||
|
self.buttonBox.setObjectName("buttonBox")
|
||||||
|
self.gridLayout.addWidget(self.buttonBox, 8, 0, 1, 2)
|
||||||
|
|
||||||
self.retranslateUi(Dialog)
|
self.retranslateUi(Dialog)
|
||||||
self.stack.setCurrentIndex(0)
|
self.stack.setCurrentIndex(0)
|
||||||
@ -203,8 +255,14 @@ class Ui_Dialog(object):
|
|||||||
def retranslateUi(self, Dialog):
|
def retranslateUi(self, Dialog):
|
||||||
_translate = QtCore.QCoreApplication.translate
|
_translate = QtCore.QCoreApplication.translate
|
||||||
Dialog.setWindowTitle(_translate("Dialog", "Fit results"))
|
Dialog.setWindowTitle(_translate("Dialog", "Fit results"))
|
||||||
self.logy_box.setText(_translate("Dialog", "logarithmic y axis"))
|
self.autoscale_box.setToolTip(_translate("Dialog", "Auto-scale graph for all sets"))
|
||||||
self.logx_box.setText(_translate("Dialog", "logarithmic x axis"))
|
self.autoscale_box.setText(_translate("Dialog", "Autoscale all sets"))
|
||||||
|
self.verticalGroupBox_2.setTitle(_translate("Dialog", "Logarithmic axes"))
|
||||||
|
self.logx_box.setText(_translate("Dialog", "x axis"))
|
||||||
|
self.logy_box.setText(_translate("Dialog", "y axis"))
|
||||||
|
self.verticalGroupBox.setTitle(_translate("Dialog", "Residuals"))
|
||||||
|
self.rel_dev_button.setText(_translate("Dialog", "relative deviation"))
|
||||||
|
self.abs_dev_button.setText(_translate("Dialog", "absolute deviation"))
|
||||||
self.stack.setTabText(self.stack.indexOf(self.stackPage1), _translate("Dialog", "Plot"))
|
self.stack.setTabText(self.stack.indexOf(self.stackPage1), _translate("Dialog", "Plot"))
|
||||||
self.stack.setTabText(self.stack.indexOf(self.stackPage2), _translate("Dialog", "Statistics"))
|
self.stack.setTabText(self.stack.indexOf(self.stackPage2), _translate("Dialog", "Statistics"))
|
||||||
item = self.corr_tableWidget.horizontalHeaderItem(0)
|
item = self.corr_tableWidget.horizontalHeaderItem(0)
|
||||||
@ -217,18 +275,19 @@ class Ui_Dialog(object):
|
|||||||
item.setText(_translate("Dialog", "Partial Corr."))
|
item.setText(_translate("Dialog", "Partial Corr."))
|
||||||
self.stack.setTabText(self.stack.indexOf(self.stackPage3), _translate("Dialog", "Correlations"))
|
self.stack.setTabText(self.stack.indexOf(self.stackPage3), _translate("Dialog", "Correlations"))
|
||||||
self.del_prev_checkBox.setText(_translate("Dialog", "Delete previous fits of this set"))
|
self.del_prev_checkBox.setText(_translate("Dialog", "Delete previous fits of this set"))
|
||||||
|
self.reject_fit_checkBox.setText(_translate("Dialog", "Reject this fit"))
|
||||||
self.groupBox.setTitle(_translate("Dialog", "Output"))
|
self.groupBox.setTitle(_translate("Dialog", "Output"))
|
||||||
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.setToolTip(_translate("Dialog", "Leave empty to start at lowest point"))
|
||||||
self.minx_line.setPlaceholderText(_translate("Dialog", "min x"))
|
self.minx_line.setPlaceholderText(_translate("Dialog", "min x"))
|
||||||
|
self.extrapolate_box.setToolTip(_translate("Dialog", "Extrapolates only main function"))
|
||||||
|
self.extrapolate_box.setText(_translate("Dialog", "Extrapolate curves"))
|
||||||
|
self.numx_line.setPlaceholderText(_translate("Dialog", "# pts"))
|
||||||
|
self.graph_checkBox.setText(_translate("Dialog", "New graph for parameter"))
|
||||||
self.maxx_line.setToolTip(_translate("Dialog", "Leave empty to start at highest point"))
|
self.maxx_line.setToolTip(_translate("Dialog", "Leave empty to start at highest point"))
|
||||||
self.maxx_line.setPlaceholderText(_translate("Dialog", "max x"))
|
self.maxx_line.setPlaceholderText(_translate("Dialog", "max x"))
|
||||||
self.numx_line.setPlaceholderText(_translate("Dialog", "# pts"))
|
self.newx_log_checkbox.setText(_translate("Dialog", "log-spaced?"))
|
||||||
self.curve_checkbox.setText(_translate("Dialog", "Plot fit curve"))
|
self.curve_checkbox.setText(_translate("Dialog", "Plot fit curve"))
|
||||||
self.partial_checkBox.setText(_translate("Dialog", "Plot partial functions"))
|
self.partial_checkBox.setText(_translate("Dialog", "Plot partial functions"))
|
||||||
self.reject_fit_checkBox.setText(_translate("Dialog", "Reject this fit"))
|
self.parameter_checkbox.setText(_translate("Dialog", "Plot parameter"))
|
||||||
from ..lib.forms import ElideComboBox
|
from ..lib.forms import ElideComboBox
|
||||||
from pyqtgraph import GraphicsLayoutWidget
|
from pyqtgraph import GraphicsLayoutWidget
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'src/resources/_ui/graph.ui'
|
# Form implementation generated from reading ui file 'resources/_ui/graph.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.15.9
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
# 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.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
@ -271,8 +271,11 @@ class Ui_GraphWindow(object):
|
|||||||
self.label_4.setText(_translate("GraphWindow", "---"))
|
self.label_4.setText(_translate("GraphWindow", "---"))
|
||||||
self.apply_button.setText(_translate("GraphWindow", "Apply"))
|
self.apply_button.setText(_translate("GraphWindow", "Apply"))
|
||||||
self.label_5.setText(_translate("GraphWindow", "Title"))
|
self.label_5.setText(_translate("GraphWindow", "Title"))
|
||||||
|
self.title_lineedit.setToolTip(_translate("GraphWindow", "<html><head/><body><p>Uses simple latex syntax, does not support italic/math environment. Sub-/superscripts need curly brackets.<br/></p><p>Example: \\alpha^{123}</p></body></html>"))
|
||||||
self.label_6.setText(_translate("GraphWindow", "X Axis"))
|
self.label_6.setText(_translate("GraphWindow", "X Axis"))
|
||||||
|
self.xaxis_linedit.setToolTip(_translate("GraphWindow", "<html><head/><body><p>Uses simple latex syntax, does not support italic/math environment. Sub-/superscripts need curly brackets.<br/></p><p>Example: \\alpha^{123}</p></body></html>"))
|
||||||
self.label_7.setText(_translate("GraphWindow", "Y Axis"))
|
self.label_7.setText(_translate("GraphWindow", "Y Axis"))
|
||||||
|
self.yaxis_linedit.setToolTip(_translate("GraphWindow", "<html><head/><body><p>Uses simple latex syntax, does not support italic/math environment. Sub-/superscripts need curly brackets.<br/></p><p>Example: \\alpha^{123}</p></body></html>"))
|
||||||
self.checkBox.setText(_translate("GraphWindow", "Show legend"))
|
self.checkBox.setText(_translate("GraphWindow", "Show legend"))
|
||||||
from ..lib.graph_items import NMRPlotWidget
|
from ..lib.graph_items import NMRPlotWidget
|
||||||
from ..lib.listwidget import QListWidgetSelect
|
from ..lib.listwidget import QListWidgetSelect
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'src/resources/_ui/interpol_dialog.ui'
|
# Form implementation generated from reading ui file './nmreval/src/resources/_ui/interpol_dialog.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.15.9
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
# 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.
|
# run again. Do not edit this file unless you know what you are doing.
|
||||||
@ -55,7 +55,7 @@ class Ui_Dialog(object):
|
|||||||
self.gridLayout.addWidget(self.interp_comboBox, 4, 1, 1, 1)
|
self.gridLayout.addWidget(self.interp_comboBox, 4, 1, 1, 1)
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
||||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Apply|QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||||
self.buttonBox.setObjectName("buttonBox")
|
self.buttonBox.setObjectName("buttonBox")
|
||||||
self.gridLayout.addWidget(self.buttonBox, 12, 0, 1, 2)
|
self.gridLayout.addWidget(self.buttonBox, 12, 0, 1, 2)
|
||||||
self.line = QtWidgets.QFrame(Dialog)
|
self.line = QtWidgets.QFrame(Dialog)
|
||||||
@ -132,8 +132,6 @@ class Ui_Dialog(object):
|
|||||||
self.label_8.setBuddy(self.dest_combobox)
|
self.label_8.setBuddy(self.dest_combobox)
|
||||||
|
|
||||||
self.retranslateUi(Dialog)
|
self.retranslateUi(Dialog)
|
||||||
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
|
|
||||||
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
|
|
||||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||||
Dialog.setTabOrder(self.listWidget, self.ylog_checkBox)
|
Dialog.setTabOrder(self.listWidget, self.ylog_checkBox)
|
||||||
Dialog.setTabOrder(self.ylog_checkBox, self.interp_comboBox)
|
Dialog.setTabOrder(self.ylog_checkBox, self.interp_comboBox)
|
||||||
|
260
src/gui_qt/_py/pokeentry.py
Normal file
260
src/gui_qt/_py/pokeentry.py
Normal file
@ -0,0 +1,260 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file './nmreval/src/resources/_ui/pokeentry.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
|
#
|
||||||
|
# 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_Form(object):
|
||||||
|
def setupUi(self, Form):
|
||||||
|
Form.setObjectName("Form")
|
||||||
|
Form.resize(640, 642)
|
||||||
|
self.verticalLayout_4 = QtWidgets.QVBoxLayout(Form)
|
||||||
|
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||||
|
self.artwork_label = QtWidgets.QLabel(Form)
|
||||||
|
self.artwork_label.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
|
||||||
|
self.artwork_label.setObjectName("artwork_label")
|
||||||
|
self.verticalLayout_4.addWidget(self.artwork_label)
|
||||||
|
self.formLayout = QtWidgets.QFormLayout()
|
||||||
|
self.formLayout.setContentsMargins(3, 3, 3, 3)
|
||||||
|
self.formLayout.setVerticalSpacing(12)
|
||||||
|
self.formLayout.setObjectName("formLayout")
|
||||||
|
self.label = QtWidgets.QLabel(Form)
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label)
|
||||||
|
self.nationaldex_label = QtWidgets.QLabel(Form)
|
||||||
|
self.nationaldex_label.setObjectName("nationaldex_label")
|
||||||
|
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.nationaldex_label)
|
||||||
|
self.label_1 = QtWidgets.QLabel(Form)
|
||||||
|
self.label_1.setObjectName("label_1")
|
||||||
|
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_1)
|
||||||
|
self.species_label = QtWidgets.QLabel(Form)
|
||||||
|
self.species_label.setObjectName("species_label")
|
||||||
|
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.species_label)
|
||||||
|
self.label_4 = QtWidgets.QLabel(Form)
|
||||||
|
self.label_4.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
|
||||||
|
self.label_4.setObjectName("label_4")
|
||||||
|
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_4)
|
||||||
|
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
|
||||||
|
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||||
|
self.type1_label = QtWidgets.QLabel(Form)
|
||||||
|
self.type1_label.setObjectName("type1_label")
|
||||||
|
self.verticalLayout_2.addWidget(self.type1_label)
|
||||||
|
self.type2_label = QtWidgets.QLabel(Form)
|
||||||
|
self.type2_label.setObjectName("type2_label")
|
||||||
|
self.verticalLayout_2.addWidget(self.type2_label)
|
||||||
|
self.formLayout.setLayout(2, QtWidgets.QFormLayout.FieldRole, self.verticalLayout_2)
|
||||||
|
self.label_5 = QtWidgets.QLabel(Form)
|
||||||
|
self.label_5.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
|
||||||
|
self.label_5.setObjectName("label_5")
|
||||||
|
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_5)
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout()
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.ability1_label = QtWidgets.QLabel(Form)
|
||||||
|
self.ability1_label.setObjectName("ability1_label")
|
||||||
|
self.verticalLayout.addWidget(self.ability1_label)
|
||||||
|
self.ability2_label = QtWidgets.QLabel(Form)
|
||||||
|
self.ability2_label.setObjectName("ability2_label")
|
||||||
|
self.verticalLayout.addWidget(self.ability2_label)
|
||||||
|
self.ability3_label = QtWidgets.QLabel(Form)
|
||||||
|
self.ability3_label.setObjectName("ability3_label")
|
||||||
|
self.verticalLayout.addWidget(self.ability3_label)
|
||||||
|
self.formLayout.setLayout(3, QtWidgets.QFormLayout.FieldRole, self.verticalLayout)
|
||||||
|
self.label_2 = QtWidgets.QLabel(Form)
|
||||||
|
self.label_2.setObjectName("label_2")
|
||||||
|
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_2)
|
||||||
|
self.height_label = QtWidgets.QLabel(Form)
|
||||||
|
self.height_label.setObjectName("height_label")
|
||||||
|
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.height_label)
|
||||||
|
self.label_3 = QtWidgets.QLabel(Form)
|
||||||
|
self.label_3.setObjectName("label_3")
|
||||||
|
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.label_3)
|
||||||
|
self.weight_label = QtWidgets.QLabel(Form)
|
||||||
|
self.weight_label.setObjectName("weight_label")
|
||||||
|
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.weight_label)
|
||||||
|
self.gender_label = QtWidgets.QLabel(Form)
|
||||||
|
self.gender_label.setObjectName("gender_label")
|
||||||
|
self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.gender_label)
|
||||||
|
self.verticalLayout_4.addLayout(self.formLayout)
|
||||||
|
self.groupBox = QtWidgets.QGroupBox(Form)
|
||||||
|
self.groupBox.setFlat(True)
|
||||||
|
self.groupBox.setObjectName("groupBox")
|
||||||
|
self.gridLayout_4 = QtWidgets.QGridLayout(self.groupBox)
|
||||||
|
self.gridLayout_4.setContentsMargins(3, 3, 3, 3)
|
||||||
|
self.gridLayout_4.setObjectName("gridLayout_4")
|
||||||
|
self.spec_attack_bar = QtWidgets.QProgressBar(self.groupBox)
|
||||||
|
self.spec_attack_bar.setStyleSheet("QProgressBar{\n"
|
||||||
|
" border: none;\n"
|
||||||
|
" background-color: transparent;\n"
|
||||||
|
" text-align: center;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"QProgressBar::chunk {\n"
|
||||||
|
" background-color: #009cda;\n"
|
||||||
|
" border-radius: 3px;\n"
|
||||||
|
"}")
|
||||||
|
self.spec_attack_bar.setMaximum(194)
|
||||||
|
self.spec_attack_bar.setProperty("value", 24)
|
||||||
|
self.spec_attack_bar.setObjectName("spec_attack_bar")
|
||||||
|
self.gridLayout_4.addWidget(self.spec_attack_bar, 0, 3, 1, 1)
|
||||||
|
self.label_8 = QtWidgets.QLabel(self.groupBox)
|
||||||
|
self.label_8.setObjectName("label_8")
|
||||||
|
self.gridLayout_4.addWidget(self.label_8, 0, 2, 1, 1)
|
||||||
|
self.spec_defense_bar = QtWidgets.QProgressBar(self.groupBox)
|
||||||
|
self.spec_defense_bar.setStyleSheet("QProgressBar{\n"
|
||||||
|
" border: none;\n"
|
||||||
|
" background-color: transparent;\n"
|
||||||
|
" text-align: center;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"QProgressBar::chunk {\n"
|
||||||
|
" background-color: #009cda;\n"
|
||||||
|
" border-radius: 3px;\n"
|
||||||
|
"}")
|
||||||
|
self.spec_defense_bar.setMaximum(250)
|
||||||
|
self.spec_defense_bar.setProperty("value", 24)
|
||||||
|
self.spec_defense_bar.setObjectName("spec_defense_bar")
|
||||||
|
self.gridLayout_4.addWidget(self.spec_defense_bar, 1, 3, 1, 1)
|
||||||
|
self.label_6 = QtWidgets.QLabel(self.groupBox)
|
||||||
|
self.label_6.setFrameShadow(QtWidgets.QFrame.Plain)
|
||||||
|
self.label_6.setObjectName("label_6")
|
||||||
|
self.gridLayout_4.addWidget(self.label_6, 0, 0, 1, 1)
|
||||||
|
self.hp_bar = QtWidgets.QProgressBar(self.groupBox)
|
||||||
|
self.hp_bar.setStyleSheet("QProgressBar{\n"
|
||||||
|
" border: none;\n"
|
||||||
|
" background-color: transparent;\n"
|
||||||
|
" text-align: center;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"QProgressBar::chunk {\n"
|
||||||
|
" background-color: #009cda;\n"
|
||||||
|
" border-radius: 3px;\n"
|
||||||
|
"}")
|
||||||
|
self.hp_bar.setMaximum(255)
|
||||||
|
self.hp_bar.setProperty("value", 24)
|
||||||
|
self.hp_bar.setObjectName("hp_bar")
|
||||||
|
self.gridLayout_4.addWidget(self.hp_bar, 0, 1, 1, 1)
|
||||||
|
self.speed_bar = QtWidgets.QProgressBar(self.groupBox)
|
||||||
|
self.speed_bar.setStyleSheet("QProgressBar{\n"
|
||||||
|
" border: none;\n"
|
||||||
|
" background-color: transparent;\n"
|
||||||
|
" text-align: center;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"QProgressBar::chunk {\n"
|
||||||
|
" background-color: #009cda;\n"
|
||||||
|
" border-radius: 3px;\n"
|
||||||
|
"}")
|
||||||
|
self.speed_bar.setMaximum(200)
|
||||||
|
self.speed_bar.setProperty("value", 24)
|
||||||
|
self.speed_bar.setObjectName("speed_bar")
|
||||||
|
self.gridLayout_4.addWidget(self.speed_bar, 2, 3, 1, 1)
|
||||||
|
self.label_11 = QtWidgets.QLabel(self.groupBox)
|
||||||
|
self.label_11.setObjectName("label_11")
|
||||||
|
self.gridLayout_4.addWidget(self.label_11, 2, 2, 1, 1)
|
||||||
|
self.label_10 = QtWidgets.QLabel(self.groupBox)
|
||||||
|
self.label_10.setObjectName("label_10")
|
||||||
|
self.gridLayout_4.addWidget(self.label_10, 1, 2, 1, 1)
|
||||||
|
self.defense_bar = QtWidgets.QProgressBar(self.groupBox)
|
||||||
|
self.defense_bar.setStyleSheet("QProgressBar{\n"
|
||||||
|
" border: none;\n"
|
||||||
|
" background-color: transparent;\n"
|
||||||
|
" text-align: center;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"QProgressBar::chunk {\n"
|
||||||
|
" background-color: #009cda;\n"
|
||||||
|
" border-radius: 3px;\n"
|
||||||
|
"}")
|
||||||
|
self.defense_bar.setMaximum(250)
|
||||||
|
self.defense_bar.setProperty("value", 24)
|
||||||
|
self.defense_bar.setObjectName("defense_bar")
|
||||||
|
self.gridLayout_4.addWidget(self.defense_bar, 2, 1, 1, 1)
|
||||||
|
self.attack_bar = QtWidgets.QProgressBar(self.groupBox)
|
||||||
|
self.attack_bar.setStyleSheet("QProgressBar{\n"
|
||||||
|
" border: none;\n"
|
||||||
|
" background-color: transparent;\n"
|
||||||
|
" text-align: center;\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"QProgressBar::chunk {\n"
|
||||||
|
" background-color: #009cda;\n"
|
||||||
|
" border-radius: 3px;\n"
|
||||||
|
"}")
|
||||||
|
self.attack_bar.setMaximum(190)
|
||||||
|
self.attack_bar.setProperty("value", 24)
|
||||||
|
self.attack_bar.setObjectName("attack_bar")
|
||||||
|
self.gridLayout_4.addWidget(self.attack_bar, 1, 1, 1, 1)
|
||||||
|
self.label_7 = QtWidgets.QLabel(self.groupBox)
|
||||||
|
self.label_7.setObjectName("label_7")
|
||||||
|
self.gridLayout_4.addWidget(self.label_7, 1, 0, 1, 1)
|
||||||
|
self.label_9 = QtWidgets.QLabel(self.groupBox)
|
||||||
|
self.label_9.setObjectName("label_9")
|
||||||
|
self.gridLayout_4.addWidget(self.label_9, 2, 0, 1, 1)
|
||||||
|
self.verticalLayout_4.addWidget(self.groupBox)
|
||||||
|
self.groupBox_2 = QtWidgets.QGroupBox(Form)
|
||||||
|
self.groupBox_2.setFlat(True)
|
||||||
|
self.groupBox_2.setCheckable(False)
|
||||||
|
self.groupBox_2.setObjectName("groupBox_2")
|
||||||
|
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.groupBox_2)
|
||||||
|
self.verticalLayout_3.setContentsMargins(3, 3, 3, 3)
|
||||||
|
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||||
|
self.tableWidget = QtWidgets.QTableWidget(self.groupBox_2)
|
||||||
|
self.tableWidget.setStyleSheet("background-color: transparent;")
|
||||||
|
self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||||
|
self.tableWidget.setShowGrid(False)
|
||||||
|
self.tableWidget.setGridStyle(QtCore.Qt.NoPen)
|
||||||
|
self.tableWidget.setWordWrap(False)
|
||||||
|
self.tableWidget.setObjectName("tableWidget")
|
||||||
|
self.tableWidget.setColumnCount(0)
|
||||||
|
self.tableWidget.setRowCount(0)
|
||||||
|
self.tableWidget.horizontalHeader().setVisible(False)
|
||||||
|
self.tableWidget.verticalHeader().setVisible(False)
|
||||||
|
self.verticalLayout_3.addWidget(self.tableWidget)
|
||||||
|
self.verticalLayout_4.addWidget(self.groupBox_2)
|
||||||
|
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
|
self.verticalLayout_4.addItem(spacerItem)
|
||||||
|
|
||||||
|
self.retranslateUi(Form)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(Form)
|
||||||
|
|
||||||
|
def retranslateUi(self, Form):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
Form.setWindowTitle(_translate("Form", "Form"))
|
||||||
|
self.artwork_label.setText(_translate("Form", "TextLabel"))
|
||||||
|
self.label.setText(_translate("Form", "National No."))
|
||||||
|
self.nationaldex_label.setText(_translate("Form", "TextLabel"))
|
||||||
|
self.label_1.setText(_translate("Form", "Species"))
|
||||||
|
self.species_label.setText(_translate("Form", "TextLabel"))
|
||||||
|
self.label_4.setText(_translate("Form", "Type"))
|
||||||
|
self.type1_label.setText(_translate("Form", "TextLabel"))
|
||||||
|
self.type2_label.setText(_translate("Form", "TextLabel"))
|
||||||
|
self.label_5.setText(_translate("Form", "Abilities"))
|
||||||
|
self.ability1_label.setText(_translate("Form", "TextLabel"))
|
||||||
|
self.ability2_label.setText(_translate("Form", "TextLabel"))
|
||||||
|
self.ability3_label.setText(_translate("Form", "TextLabel"))
|
||||||
|
self.label_2.setText(_translate("Form", "Height"))
|
||||||
|
self.height_label.setText(_translate("Form", "0.0 m"))
|
||||||
|
self.label_3.setText(_translate("Form", "Weight"))
|
||||||
|
self.weight_label.setText(_translate("Form", "0.0 kg"))
|
||||||
|
self.gender_label.setText(_translate("Form", "TextLabel"))
|
||||||
|
self.groupBox.setTitle(_translate("Form", "Stats"))
|
||||||
|
self.spec_attack_bar.setFormat(_translate("Form", "%v"))
|
||||||
|
self.label_8.setText(_translate("Form", "Special Attack"))
|
||||||
|
self.spec_defense_bar.setFormat(_translate("Form", "%v"))
|
||||||
|
self.label_6.setText(_translate("Form", "HP"))
|
||||||
|
self.hp_bar.setFormat(_translate("Form", "%v"))
|
||||||
|
self.speed_bar.setFormat(_translate("Form", "%v"))
|
||||||
|
self.label_11.setText(_translate("Form", "Speed"))
|
||||||
|
self.label_10.setText(_translate("Form", "Special Defense"))
|
||||||
|
self.defense_bar.setFormat(_translate("Form", "%v"))
|
||||||
|
self.attack_bar.setFormat(_translate("Form", "%v"))
|
||||||
|
self.label_7.setText(_translate("Form", "Attack"))
|
||||||
|
self.label_9.setText(_translate("Form", "Defense"))
|
||||||
|
self.groupBox_2.setTitle(_translate("Form", "Evolution chain"))
|
@ -1,118 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'resources/_ui/pokemon.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(400, 359)
|
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, 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.tabWidget = QtWidgets.QTabWidget(Dialog)
|
|
||||||
self.tabWidget.setObjectName("tabWidget")
|
|
||||||
self.verticalLayout.addWidget(self.tabWidget)
|
|
||||||
self.formLayout = QtWidgets.QFormLayout()
|
|
||||||
self.formLayout.setObjectName("formLayout")
|
|
||||||
self.label = QtWidgets.QLabel(Dialog)
|
|
||||||
self.label.setObjectName("label")
|
|
||||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.label)
|
|
||||||
self.pokedex_nr = QtWidgets.QLabel(Dialog)
|
|
||||||
self.pokedex_nr.setObjectName("pokedex_nr")
|
|
||||||
self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.pokedex_nr)
|
|
||||||
self.label_2 = QtWidgets.QLabel(Dialog)
|
|
||||||
self.label_2.setObjectName("label_2")
|
|
||||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.label_2)
|
|
||||||
self.name = QtWidgets.QComboBox(Dialog)
|
|
||||||
self.name.setObjectName("name")
|
|
||||||
self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.name)
|
|
||||||
self.label_3 = QtWidgets.QLabel(Dialog)
|
|
||||||
self.label_3.setObjectName("label_3")
|
|
||||||
self.formLayout.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.label_3)
|
|
||||||
self.category = QtWidgets.QLabel(Dialog)
|
|
||||||
self.category.setObjectName("category")
|
|
||||||
self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.category)
|
|
||||||
self.label_4 = QtWidgets.QLabel(Dialog)
|
|
||||||
self.label_4.setObjectName("label_4")
|
|
||||||
self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.label_4)
|
|
||||||
self.poketype = QtWidgets.QLabel(Dialog)
|
|
||||||
self.poketype.setObjectName("poketype")
|
|
||||||
self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.poketype)
|
|
||||||
self.label_5 = QtWidgets.QLabel(Dialog)
|
|
||||||
self.label_5.setObjectName("label_5")
|
|
||||||
self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.label_5)
|
|
||||||
self.height = QtWidgets.QLabel(Dialog)
|
|
||||||
self.height.setObjectName("height")
|
|
||||||
self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.height)
|
|
||||||
self.label_6 = QtWidgets.QLabel(Dialog)
|
|
||||||
self.label_6.setObjectName("label_6")
|
|
||||||
self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.label_6)
|
|
||||||
self.weight = QtWidgets.QLabel(Dialog)
|
|
||||||
self.weight.setObjectName("weight")
|
|
||||||
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.weight)
|
|
||||||
self.label_7 = QtWidgets.QLabel(Dialog)
|
|
||||||
self.label_7.setObjectName("label_7")
|
|
||||||
self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.label_7)
|
|
||||||
self.color = QtWidgets.QLabel(Dialog)
|
|
||||||
self.color.setObjectName("color")
|
|
||||||
self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.color)
|
|
||||||
self.label_8 = QtWidgets.QLabel(Dialog)
|
|
||||||
self.label_8.setObjectName("label_8")
|
|
||||||
self.formLayout.setWidget(7, QtWidgets.QFormLayout.LabelRole, self.label_8)
|
|
||||||
self.info = QtWidgets.QLabel(Dialog)
|
|
||||||
self.info.setObjectName("info")
|
|
||||||
self.formLayout.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.info)
|
|
||||||
self.verticalLayout.addLayout(self.formLayout)
|
|
||||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
|
||||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
|
||||||
self.prev_button = QtWidgets.QToolButton(Dialog)
|
|
||||||
self.prev_button.setObjectName("prev_button")
|
|
||||||
self.horizontalLayout_2.addWidget(self.prev_button)
|
|
||||||
self.next_button = QtWidgets.QToolButton(Dialog)
|
|
||||||
self.next_button.setObjectName("next_button")
|
|
||||||
self.horizontalLayout_2.addWidget(self.next_button)
|
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
|
||||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Close|QtWidgets.QDialogButtonBox.Retry)
|
|
||||||
self.buttonBox.setCenterButtons(False)
|
|
||||||
self.buttonBox.setObjectName("buttonBox")
|
|
||||||
self.horizontalLayout_2.addWidget(self.buttonBox)
|
|
||||||
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
|
||||||
self.label_2.setBuddy(self.name)
|
|
||||||
|
|
||||||
self.retranslateUi(Dialog)
|
|
||||||
self.tabWidget.setCurrentIndex(-1)
|
|
||||||
self.buttonBox.rejected.connect(Dialog.reject)
|
|
||||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
|
||||||
|
|
||||||
def retranslateUi(self, Dialog):
|
|
||||||
_translate = QtCore.QCoreApplication.translate
|
|
||||||
Dialog.setWindowTitle(_translate("Dialog", "Random Pokémon"))
|
|
||||||
self.label.setText(_translate("Dialog", "National-Dex"))
|
|
||||||
self.pokedex_nr.setText(_translate("Dialog", "TextLabel"))
|
|
||||||
self.label_2.setText(_translate("Dialog", "Name"))
|
|
||||||
self.label_3.setText(_translate("Dialog", "Kategorie"))
|
|
||||||
self.category.setText(_translate("Dialog", "TextLabel"))
|
|
||||||
self.label_4.setText(_translate("Dialog", "Typ"))
|
|
||||||
self.poketype.setText(_translate("Dialog", "TextLabel"))
|
|
||||||
self.label_5.setText(_translate("Dialog", "Größe"))
|
|
||||||
self.height.setText(_translate("Dialog", "TextLabel"))
|
|
||||||
self.label_6.setText(_translate("Dialog", "Gewicht"))
|
|
||||||
self.weight.setText(_translate("Dialog", "TextLabel"))
|
|
||||||
self.label_7.setText(_translate("Dialog", "Farbe"))
|
|
||||||
self.color.setText(_translate("Dialog", "TextLabel"))
|
|
||||||
self.label_8.setText(_translate("Dialog", "Mehr..."))
|
|
||||||
self.info.setText(_translate("Dialog", "TextLabel"))
|
|
||||||
self.prev_button.setText(_translate("Dialog", "Prev."))
|
|
||||||
self.next_button.setText(_translate("Dialog", "Next"))
|
|
131
src/gui_qt/_py/pokewindow.py
Normal file
131
src/gui_qt/_py/pokewindow.py
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file './nmreval/src/resources/_ui/pokewindow.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
|
#
|
||||||
|
# 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(1687, 991)
|
||||||
|
self.gridLayout = QtWidgets.QGridLayout(Dialog)
|
||||||
|
self.gridLayout.setObjectName("gridLayout")
|
||||||
|
self.pushButton = QtWidgets.QPushButton(Dialog)
|
||||||
|
self.pushButton.setObjectName("pushButton")
|
||||||
|
self.gridLayout.addWidget(self.pushButton, 0, 2, 1, 1)
|
||||||
|
self.comboBox_2 = QtWidgets.QComboBox(Dialog)
|
||||||
|
self.comboBox_2.setObjectName("comboBox_2")
|
||||||
|
self.gridLayout.addWidget(self.comboBox_2, 0, 0, 1, 1)
|
||||||
|
self.comboBox = QtWidgets.QComboBox(Dialog)
|
||||||
|
self.comboBox.setObjectName("comboBox")
|
||||||
|
self.gridLayout.addWidget(self.comboBox, 0, 1, 1, 1)
|
||||||
|
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||||
|
self.gridLayout.addItem(spacerItem, 0, 4, 1, 1)
|
||||||
|
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.buttonBox.sizePolicy().hasHeightForWidth())
|
||||||
|
self.buttonBox.setSizePolicy(sizePolicy)
|
||||||
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Close)
|
||||||
|
self.buttonBox.setObjectName("buttonBox")
|
||||||
|
self.gridLayout.addWidget(self.buttonBox, 0, 3, 1, 1)
|
||||||
|
self.splitter = QtWidgets.QSplitter(Dialog)
|
||||||
|
self.splitter.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.splitter.setObjectName("splitter")
|
||||||
|
self.tableWidget_2 = QtWidgets.QTableWidget(self.splitter)
|
||||||
|
self.tableWidget_2.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||||
|
self.tableWidget_2.setAlternatingRowColors(True)
|
||||||
|
self.tableWidget_2.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
|
||||||
|
self.tableWidget_2.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||||
|
self.tableWidget_2.setShowGrid(False)
|
||||||
|
self.tableWidget_2.setGridStyle(QtCore.Qt.NoPen)
|
||||||
|
self.tableWidget_2.setObjectName("tableWidget_2")
|
||||||
|
self.tableWidget_2.setColumnCount(13)
|
||||||
|
self.tableWidget_2.setRowCount(0)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(0, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(1, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(2, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(3, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(4, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(5, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(6, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(7, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(8, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(9, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(10, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(11, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
self.tableWidget_2.setHorizontalHeaderItem(12, item)
|
||||||
|
self.tableWidget_2.horizontalHeader().setDefaultSectionSize(80)
|
||||||
|
self.tableWidget_2.horizontalHeader().setStretchLastSection(False)
|
||||||
|
self.tableWidget_2.verticalHeader().setVisible(False)
|
||||||
|
self.tabWidget = QtWidgets.QTabWidget(self.splitter)
|
||||||
|
self.tabWidget.setMinimumSize(QtCore.QSize(418, 0))
|
||||||
|
self.tabWidget.setObjectName("tabWidget")
|
||||||
|
self.gridLayout.addWidget(self.splitter, 1, 0, 1, 5)
|
||||||
|
|
||||||
|
self.retranslateUi(Dialog)
|
||||||
|
self.tabWidget.setCurrentIndex(-1)
|
||||||
|
self.buttonBox.rejected.connect(Dialog.close) # type: ignore
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||||
|
|
||||||
|
def retranslateUi(self, Dialog):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
Dialog.setWindowTitle(_translate("Dialog", "Gotta catch \'em all!"))
|
||||||
|
self.pushButton.setText(_translate("Dialog", "Random"))
|
||||||
|
self.tableWidget_2.setSortingEnabled(True)
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(0)
|
||||||
|
item.setText(_translate("Dialog", "#"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(1)
|
||||||
|
item.setText(_translate("Dialog", "Pokemon"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(2)
|
||||||
|
item.setText(_translate("Dialog", "Type"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(3)
|
||||||
|
item.setText(_translate("Dialog", "Total"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(4)
|
||||||
|
item.setText(_translate("Dialog", "HP"))
|
||||||
|
item.setToolTip(_translate("Dialog", "Hit Points; Kraftpunkte"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(5)
|
||||||
|
item.setText(_translate("Dialog", "Attack"))
|
||||||
|
item.setToolTip(_translate("Dialog", "Attacke"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(6)
|
||||||
|
item.setText(_translate("Dialog", "Defense"))
|
||||||
|
item.setToolTip(_translate("Dialog", "Verteidigung"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(7)
|
||||||
|
item.setText(_translate("Dialog", "Sp. Attack"))
|
||||||
|
item.setToolTip(_translate("Dialog", "Special Attack; Spezial-Attacke"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(8)
|
||||||
|
item.setText(_translate("Dialog", "Sp. Defense"))
|
||||||
|
item.setToolTip(_translate("Dialog", "Special Defense; Spezial-Verteidigung"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(9)
|
||||||
|
item.setText(_translate("Dialog", "Speed"))
|
||||||
|
item.setToolTip(_translate("Dialog", "Initiative"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(10)
|
||||||
|
item.setText(_translate("Dialog", "Height"))
|
||||||
|
item.setToolTip(_translate("Dialog", "Größe"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(11)
|
||||||
|
item.setText(_translate("Dialog", "Weight"))
|
||||||
|
item.setToolTip(_translate("Dialog", "Gewicht"))
|
||||||
|
item = self.tableWidget_2.horizontalHeaderItem(12)
|
||||||
|
item.setText(_translate("Dialog", "BMI"))
|
||||||
|
item.setToolTip(_translate("Dialog", "Body-Mass-Index"))
|
@ -1,10 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'resources/_ui/ptstab.ui'
|
# Form implementation generated from reading ui file 'nmreval/src/resources/_ui/ptstab.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.12.3
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# 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
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
@ -13,29 +14,50 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
|||||||
class Ui_Form(object):
|
class Ui_Form(object):
|
||||||
def setupUi(self, Form):
|
def setupUi(self, Form):
|
||||||
Form.setObjectName("Form")
|
Form.setObjectName("Form")
|
||||||
Form.resize(316, 747)
|
Form.resize(417, 746)
|
||||||
self.verticalLayout = QtWidgets.QVBoxLayout(Form)
|
self.gridLayout = QtWidgets.QGridLayout(Form)
|
||||||
self.verticalLayout.setContentsMargins(3, 3, 3, 3)
|
self.gridLayout.setObjectName("gridLayout")
|
||||||
self.verticalLayout.setObjectName("verticalLayout")
|
self.label_2 = QtWidgets.QLabel(Form)
|
||||||
|
self.label_2.setObjectName("label_2")
|
||||||
|
self.gridLayout.addWidget(self.label_2, 0, 0, 1, 2)
|
||||||
self.peaktable = QtWidgets.QListWidget(Form)
|
self.peaktable = QtWidgets.QListWidget(Form)
|
||||||
self.peaktable.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked|QtWidgets.QAbstractItemView.EditKeyPressed)
|
self.peaktable.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked|QtWidgets.QAbstractItemView.EditKeyPressed)
|
||||||
self.peaktable.setObjectName("peaktable")
|
self.peaktable.setObjectName("peaktable")
|
||||||
self.verticalLayout.addWidget(self.peaktable)
|
self.gridLayout.addWidget(self.peaktable, 1, 0, 1, 2)
|
||||||
self.groupBox = QtWidgets.QGroupBox(Form)
|
self.special_checkbox = QtWidgets.QCheckBox(Form)
|
||||||
self.groupBox.setObjectName("groupBox")
|
self.special_checkbox.setObjectName("special_checkbox")
|
||||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox)
|
self.gridLayout.addWidget(self.special_checkbox, 3, 0, 1, 1)
|
||||||
self.horizontalLayout.setContentsMargins(3, 3, 3, 3)
|
self.special_comboBox = QtWidgets.QComboBox(Form)
|
||||||
self.horizontalLayout.setSpacing(3)
|
self.special_comboBox.setEnabled(False)
|
||||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
self.special_comboBox.setObjectName("special_comboBox")
|
||||||
self.left_pt = QtWidgets.QSpinBox(self.groupBox)
|
self.special_comboBox.addItem("")
|
||||||
self.left_pt.setMaximum(999)
|
self.special_comboBox.addItem("")
|
||||||
self.left_pt.setObjectName("left_pt")
|
self.special_comboBox.addItem("")
|
||||||
self.horizontalLayout.addWidget(self.left_pt)
|
self.special_comboBox.addItem("")
|
||||||
self.right_pt = QtWidgets.QSpinBox(self.groupBox)
|
self.gridLayout.addWidget(self.special_comboBox, 3, 1, 1, 1)
|
||||||
self.right_pt.setMaximum(999)
|
spacerItem = QtWidgets.QSpacerItem(20, 30, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
|
||||||
self.right_pt.setObjectName("right_pt")
|
self.gridLayout.addItem(spacerItem, 4, 0, 1, 1)
|
||||||
self.horizontalLayout.addWidget(self.right_pt)
|
self.label_3 = QtWidgets.QLabel(Form)
|
||||||
self.average_combobox = QtWidgets.QComboBox(self.groupBox)
|
self.label_3.setObjectName("label_3")
|
||||||
|
self.gridLayout.addWidget(self.label_3, 5, 0, 1, 1)
|
||||||
|
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||||
|
self.left_limit = QtWidgets.QLineEdit(Form)
|
||||||
|
self.left_limit.setObjectName("left_limit")
|
||||||
|
self.horizontalLayout_2.addWidget(self.left_limit)
|
||||||
|
self.right_limit = QtWidgets.QLineEdit(Form)
|
||||||
|
self.right_limit.setObjectName("right_limit")
|
||||||
|
self.horizontalLayout_2.addWidget(self.right_limit)
|
||||||
|
self.limit_combobox = QtWidgets.QComboBox(Form)
|
||||||
|
self.limit_combobox.setObjectName("limit_combobox")
|
||||||
|
self.limit_combobox.addItem("")
|
||||||
|
self.limit_combobox.addItem("")
|
||||||
|
self.horizontalLayout_2.addWidget(self.limit_combobox)
|
||||||
|
self.gridLayout.addLayout(self.horizontalLayout_2, 5, 1, 1, 1)
|
||||||
|
self.label_5 = QtWidgets.QLabel(Form)
|
||||||
|
self.label_5.setObjectName("label_5")
|
||||||
|
self.gridLayout.addWidget(self.label_5, 6, 0, 1, 1)
|
||||||
|
self.average_combobox = QtWidgets.QComboBox(Form)
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
|
||||||
sizePolicy.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
@ -45,89 +67,94 @@ class Ui_Form(object):
|
|||||||
self.average_combobox.addItem("")
|
self.average_combobox.addItem("")
|
||||||
self.average_combobox.addItem("")
|
self.average_combobox.addItem("")
|
||||||
self.average_combobox.addItem("")
|
self.average_combobox.addItem("")
|
||||||
self.horizontalLayout.addWidget(self.average_combobox)
|
self.average_combobox.addItem("")
|
||||||
self.verticalLayout.addWidget(self.groupBox)
|
self.gridLayout.addWidget(self.average_combobox, 6, 1, 1, 1)
|
||||||
self.groupBox_2 = QtWidgets.QGroupBox(Form)
|
self.label_4 = QtWidgets.QLabel(Form)
|
||||||
self.groupBox_2.setCheckable(True)
|
self.label_4.setObjectName("label_4")
|
||||||
self.groupBox_2.setChecked(False)
|
self.gridLayout.addWidget(self.label_4, 7, 0, 1, 1)
|
||||||
self.groupBox_2.setObjectName("groupBox_2")
|
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||||
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.groupBox_2)
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
self.horizontalLayout_5.setContentsMargins(3, 3, 3, 3)
|
self.xbutton = QtWidgets.QCheckBox(Form)
|
||||||
self.horizontalLayout_5.setSpacing(2)
|
|
||||||
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
|
|
||||||
self.special_comboBox = QtWidgets.QComboBox(self.groupBox_2)
|
|
||||||
self.special_comboBox.setObjectName("special_comboBox")
|
|
||||||
self.special_comboBox.addItem("")
|
|
||||||
self.special_comboBox.addItem("")
|
|
||||||
self.special_comboBox.addItem("")
|
|
||||||
self.special_comboBox.addItem("")
|
|
||||||
self.horizontalLayout_5.addWidget(self.special_comboBox)
|
|
||||||
self.verticalLayout.addWidget(self.groupBox_2)
|
|
||||||
self.groupBox_3 = QtWidgets.QGroupBox(Form)
|
|
||||||
self.groupBox_3.setObjectName("groupBox_3")
|
|
||||||
self.gridLayout = QtWidgets.QGridLayout(self.groupBox_3)
|
|
||||||
self.gridLayout.setContentsMargins(3, 3, 3, 3)
|
|
||||||
self.gridLayout.setSpacing(3)
|
|
||||||
self.gridLayout.setObjectName("gridLayout")
|
|
||||||
self.xbutton = QtWidgets.QCheckBox(self.groupBox_3)
|
|
||||||
self.xbutton.setObjectName("xbutton")
|
self.xbutton.setObjectName("xbutton")
|
||||||
self.gridLayout.addWidget(self.xbutton, 0, 0, 1, 1)
|
self.horizontalLayout.addWidget(self.xbutton)
|
||||||
self.ybutton = QtWidgets.QCheckBox(self.groupBox_3)
|
self.ybutton = QtWidgets.QCheckBox(Form)
|
||||||
self.ybutton.setChecked(True)
|
self.ybutton.setChecked(True)
|
||||||
self.ybutton.setObjectName("ybutton")
|
self.ybutton.setObjectName("ybutton")
|
||||||
self.gridLayout.addWidget(self.ybutton, 0, 1, 1, 1)
|
self.horizontalLayout.addWidget(self.ybutton)
|
||||||
self.graph_checkbox = QtWidgets.QCheckBox(self.groupBox_3)
|
self.gridLayout.addLayout(self.horizontalLayout, 7, 1, 1, 1)
|
||||||
|
self.label = QtWidgets.QLabel(Form)
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.gridLayout.addWidget(self.label, 8, 0, 1, 1)
|
||||||
|
self.group_box = QtWidgets.QComboBox(Form)
|
||||||
|
self.group_box.setObjectName("group_box")
|
||||||
|
self.group_box.addItem("")
|
||||||
|
self.group_box.addItem("")
|
||||||
|
self.gridLayout.addWidget(self.group_box, 8, 1, 1, 1)
|
||||||
|
spacerItem1 = QtWidgets.QSpacerItem(20, 20, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
|
||||||
|
self.gridLayout.addItem(spacerItem1, 9, 0, 1, 1)
|
||||||
|
self.graph_checkbox = QtWidgets.QCheckBox(Form)
|
||||||
self.graph_checkbox.setChecked(True)
|
self.graph_checkbox.setChecked(True)
|
||||||
self.graph_checkbox.setObjectName("graph_checkbox")
|
self.graph_checkbox.setObjectName("graph_checkbox")
|
||||||
self.gridLayout.addWidget(self.graph_checkbox, 1, 0, 1, 1)
|
self.gridLayout.addWidget(self.graph_checkbox, 10, 0, 1, 1)
|
||||||
self.graph_combobox = QtWidgets.QComboBox(self.groupBox_3)
|
self.graph_combobox = QtWidgets.QComboBox(Form)
|
||||||
self.graph_combobox.setEnabled(False)
|
self.graph_combobox.setEnabled(False)
|
||||||
self.graph_combobox.setObjectName("graph_combobox")
|
self.graph_combobox.setObjectName("graph_combobox")
|
||||||
self.gridLayout.addWidget(self.graph_combobox, 1, 1, 1, 1)
|
self.gridLayout.addWidget(self.graph_combobox, 10, 1, 1, 1)
|
||||||
self.verticalLayout.addWidget(self.groupBox_3)
|
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
self.gridLayout.addItem(spacerItem2, 12, 0, 1, 1)
|
||||||
self.horizontalLayout_2.setContentsMargins(-1, 0, -1, -1)
|
|
||||||
self.horizontalLayout_2.setSpacing(2)
|
|
||||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
|
||||||
self.okButton = QtWidgets.QPushButton(Form)
|
self.okButton = QtWidgets.QPushButton(Form)
|
||||||
icon = QtGui.QIcon.fromTheme("dialog-ok")
|
icon = QtGui.QIcon.fromTheme("dialog-ok")
|
||||||
self.okButton.setIcon(icon)
|
self.okButton.setIcon(icon)
|
||||||
self.okButton.setObjectName("okButton")
|
self.okButton.setObjectName("okButton")
|
||||||
self.horizontalLayout_2.addWidget(self.okButton)
|
self.gridLayout.addWidget(self.okButton, 11, 0, 1, 2)
|
||||||
self.deleteButton = QtWidgets.QPushButton(Form)
|
self.deleteButton = QtWidgets.QPushButton(Form)
|
||||||
icon = QtGui.QIcon.fromTheme("dialog-cancel")
|
icon = QtGui.QIcon.fromTheme("dialog-cancel")
|
||||||
self.deleteButton.setIcon(icon)
|
self.deleteButton.setIcon(icon)
|
||||||
self.deleteButton.setObjectName("deleteButton")
|
self.deleteButton.setObjectName("deleteButton")
|
||||||
self.horizontalLayout_2.addWidget(self.deleteButton)
|
self.gridLayout.addWidget(self.deleteButton, 2, 0, 1, 2)
|
||||||
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
self.label_2.setBuddy(self.peaktable)
|
||||||
|
self.label_5.setBuddy(self.average_combobox)
|
||||||
|
self.label_4.setBuddy(self.xbutton)
|
||||||
|
self.label.setBuddy(self.group_box)
|
||||||
|
|
||||||
self.retranslateUi(Form)
|
self.retranslateUi(Form)
|
||||||
QtCore.QMetaObject.connectSlotsByName(Form)
|
QtCore.QMetaObject.connectSlotsByName(Form)
|
||||||
|
Form.setTabOrder(self.peaktable, self.limit_combobox)
|
||||||
|
Form.setTabOrder(self.limit_combobox, self.average_combobox)
|
||||||
|
Form.setTabOrder(self.average_combobox, self.xbutton)
|
||||||
|
Form.setTabOrder(self.xbutton, self.ybutton)
|
||||||
|
Form.setTabOrder(self.ybutton, self.group_box)
|
||||||
|
Form.setTabOrder(self.group_box, self.graph_checkbox)
|
||||||
|
Form.setTabOrder(self.graph_checkbox, self.graph_combobox)
|
||||||
|
|
||||||
def retranslateUi(self, Form):
|
def retranslateUi(self, Form):
|
||||||
_translate = QtCore.QCoreApplication.translate
|
_translate = QtCore.QCoreApplication.translate
|
||||||
Form.setWindowTitle(_translate("Form", "Form"))
|
Form.setWindowTitle(_translate("Form", "Form"))
|
||||||
|
self.label_2.setText(_translate("Form", "Selected points and regions"))
|
||||||
self.peaktable.setToolTip(_translate("Form", "Edit by entering new value: \n"
|
self.peaktable.setToolTip(_translate("Form", "Edit by entering new value: \n"
|
||||||
"Single number for points (e.g. 1e-6); \n"
|
"Single number for points (e.g. 1e-6); \n"
|
||||||
"two numbers separated by space for regions (e.g. 1e-6 5e-6). \n"
|
"two numbers separated by space for regions (e.g. 1e-6 5e-6). \n"
|
||||||
"Changing between regions and points is NOT possible"))
|
"Changing between regions and points is NOT possible"))
|
||||||
self.groupBox.setTitle(_translate("Form", "Average"))
|
self.special_checkbox.setText(_translate("Form", "Use special value"))
|
||||||
self.left_pt.setSuffix(_translate("Form", " pts"))
|
|
||||||
self.left_pt.setPrefix(_translate("Form", "- "))
|
|
||||||
self.right_pt.setSuffix(_translate("Form", " pts"))
|
|
||||||
self.right_pt.setPrefix(_translate("Form", "+ "))
|
|
||||||
self.average_combobox.setItemText(0, _translate("Form", "Mean"))
|
|
||||||
self.average_combobox.setItemText(1, _translate("Form", "Sum"))
|
|
||||||
self.average_combobox.setItemText(2, _translate("Form", "Integral"))
|
|
||||||
self.groupBox_2.setTitle(_translate("Form", "Special value"))
|
|
||||||
self.special_comboBox.setToolTip(_translate("Form", "Automatic selection of respective points"))
|
self.special_comboBox.setToolTip(_translate("Form", "Automatic selection of respective points"))
|
||||||
self.special_comboBox.setItemText(0, _translate("Form", "max(y)"))
|
self.special_comboBox.setItemText(0, _translate("Form", "max(y)"))
|
||||||
self.special_comboBox.setItemText(1, _translate("Form", "max(abs(y))"))
|
self.special_comboBox.setItemText(1, _translate("Form", "max(abs(y))"))
|
||||||
self.special_comboBox.setItemText(2, _translate("Form", "min(y)"))
|
self.special_comboBox.setItemText(2, _translate("Form", "min(y)"))
|
||||||
self.special_comboBox.setItemText(3, _translate("Form", "min(abs(y))"))
|
self.special_comboBox.setItemText(3, _translate("Form", "min(abs(y))"))
|
||||||
self.groupBox_3.setTitle(_translate("Form", "Result"))
|
self.label_3.setText(_translate("Form", "Region around points"))
|
||||||
|
self.limit_combobox.setItemText(0, _translate("Form", "points"))
|
||||||
|
self.limit_combobox.setItemText(1, _translate("Form", "range"))
|
||||||
|
self.label_5.setText(_translate("Form", "Aggregation"))
|
||||||
|
self.average_combobox.setItemText(0, _translate("Form", "Mean"))
|
||||||
|
self.average_combobox.setItemText(1, _translate("Form", "Sum"))
|
||||||
|
self.average_combobox.setItemText(2, _translate("Form", "Integral"))
|
||||||
|
self.average_combobox.setItemText(3, _translate("Form", "Std. deviation"))
|
||||||
|
self.label_4.setText(_translate("Form", "New set based on"))
|
||||||
self.xbutton.setText(_translate("Form", "x"))
|
self.xbutton.setText(_translate("Form", "x"))
|
||||||
self.ybutton.setText(_translate("Form", "y"))
|
self.ybutton.setText(_translate("Form", "y"))
|
||||||
|
self.label.setText(_translate("Form", "Group by"))
|
||||||
|
self.group_box.setItemText(0, _translate("Form", "\"Group\" value"))
|
||||||
|
self.group_box.setItemText(1, _translate("Form", "x value"))
|
||||||
self.graph_checkbox.setText(_translate("Form", "New graph?"))
|
self.graph_checkbox.setText(_translate("Form", "New graph?"))
|
||||||
self.okButton.setText(_translate("Form", "Apply"))
|
self.okButton.setText(_translate("Form", "Apply"))
|
||||||
self.deleteButton.setText(_translate("Form", "Delete selected"))
|
self.deleteButton.setText(_translate("Form", "Delete selection"))
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'resources/_ui/smoothdialog.ui'
|
# Form implementation generated from reading ui file 'src/resources/_ui/smoothdialog.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.12.3
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# 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
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
@ -17,9 +18,37 @@ class Ui_SmoothDialog(object):
|
|||||||
self.gridLayout = QtWidgets.QGridLayout(SmoothDialog)
|
self.gridLayout = QtWidgets.QGridLayout(SmoothDialog)
|
||||||
self.gridLayout.setSpacing(3)
|
self.gridLayout.setSpacing(3)
|
||||||
self.gridLayout.setObjectName("gridLayout")
|
self.gridLayout.setObjectName("gridLayout")
|
||||||
|
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||||
|
self.gridLayout.addItem(spacerItem, 7, 0, 1, 1)
|
||||||
self.frac_label = QtWidgets.QLabel(SmoothDialog)
|
self.frac_label = QtWidgets.QLabel(SmoothDialog)
|
||||||
self.frac_label.setObjectName("frac_label")
|
self.frac_label.setObjectName("frac_label")
|
||||||
self.gridLayout.addWidget(self.frac_label, 1, 0, 1, 1)
|
self.gridLayout.addWidget(self.frac_label, 2, 0, 1, 1)
|
||||||
|
self.line = QtWidgets.QFrame(SmoothDialog)
|
||||||
|
self.line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||||
|
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||||
|
self.line.setObjectName("line")
|
||||||
|
self.gridLayout.addWidget(self.line, 5, 0, 1, 2)
|
||||||
|
self.widget = QtWidgets.QWidget(SmoothDialog)
|
||||||
|
self.widget.setObjectName("widget")
|
||||||
|
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget)
|
||||||
|
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.horizontalLayout_2.setSpacing(3)
|
||||||
|
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||||
|
self.label = QtWidgets.QLabel(self.widget)
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.horizontalLayout_2.addWidget(self.label)
|
||||||
|
self.polynom_spinBox = QtWidgets.QSpinBox(self.widget)
|
||||||
|
self.polynom_spinBox.setMinimum(1)
|
||||||
|
self.polynom_spinBox.setMaximum(3)
|
||||||
|
self.polynom_spinBox.setObjectName("polynom_spinBox")
|
||||||
|
self.horizontalLayout_2.addWidget(self.polynom_spinBox)
|
||||||
|
self.gridLayout.addWidget(self.widget, 3, 0, 1, 2)
|
||||||
|
self.y_checkBox = QtWidgets.QCheckBox(SmoothDialog)
|
||||||
|
self.y_checkBox.setObjectName("y_checkBox")
|
||||||
|
self.gridLayout.addWidget(self.y_checkBox, 6, 1, 1, 1)
|
||||||
|
self.x_checkBox = QtWidgets.QCheckBox(SmoothDialog)
|
||||||
|
self.x_checkBox.setObjectName("x_checkBox")
|
||||||
|
self.gridLayout.addWidget(self.x_checkBox, 6, 0, 1, 1)
|
||||||
self.widget_2 = QtWidgets.QWidget(SmoothDialog)
|
self.widget_2 = QtWidgets.QWidget(SmoothDialog)
|
||||||
self.widget_2.setObjectName("widget_2")
|
self.widget_2.setObjectName("widget_2")
|
||||||
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget_2)
|
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget_2)
|
||||||
@ -35,37 +64,17 @@ class Ui_SmoothDialog(object):
|
|||||||
self.iter_spinBox.setProperty("value", 1)
|
self.iter_spinBox.setProperty("value", 1)
|
||||||
self.iter_spinBox.setObjectName("iter_spinBox")
|
self.iter_spinBox.setObjectName("iter_spinBox")
|
||||||
self.horizontalLayout_3.addWidget(self.iter_spinBox)
|
self.horizontalLayout_3.addWidget(self.iter_spinBox)
|
||||||
self.gridLayout.addWidget(self.widget_2, 3, 0, 1, 2)
|
self.gridLayout.addWidget(self.widget_2, 4, 0, 1, 2)
|
||||||
self.line = QtWidgets.QFrame(SmoothDialog)
|
|
||||||
self.line.setFrameShape(QtWidgets.QFrame.HLine)
|
|
||||||
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
|
||||||
self.line.setObjectName("line")
|
|
||||||
self.gridLayout.addWidget(self.line, 4, 0, 1, 2)
|
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox(SmoothDialog)
|
|
||||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
|
||||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Apply|QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
|
||||||
self.buttonBox.setObjectName("buttonBox")
|
|
||||||
self.gridLayout.addWidget(self.buttonBox, 7, 0, 1, 2)
|
|
||||||
self.widget = QtWidgets.QWidget(SmoothDialog)
|
|
||||||
self.widget.setObjectName("widget")
|
|
||||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget)
|
|
||||||
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
|
|
||||||
self.horizontalLayout_2.setSpacing(3)
|
|
||||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
|
||||||
self.label = QtWidgets.QLabel(self.widget)
|
|
||||||
self.label.setObjectName("label")
|
|
||||||
self.horizontalLayout_2.addWidget(self.label)
|
|
||||||
self.polynom_spinBox = QtWidgets.QSpinBox(self.widget)
|
|
||||||
self.polynom_spinBox.setMinimum(1)
|
|
||||||
self.polynom_spinBox.setMaximum(3)
|
|
||||||
self.polynom_spinBox.setObjectName("polynom_spinBox")
|
|
||||||
self.horizontalLayout_2.addWidget(self.polynom_spinBox)
|
|
||||||
self.gridLayout.addWidget(self.widget, 2, 0, 1, 2)
|
|
||||||
self.frac_spinBox = QtWidgets.QSpinBox(SmoothDialog)
|
self.frac_spinBox = QtWidgets.QSpinBox(SmoothDialog)
|
||||||
self.frac_spinBox.setMinimum(1)
|
self.frac_spinBox.setMinimum(1)
|
||||||
self.frac_spinBox.setMaximum(999)
|
self.frac_spinBox.setMaximum(999)
|
||||||
self.frac_spinBox.setObjectName("frac_spinBox")
|
self.frac_spinBox.setObjectName("frac_spinBox")
|
||||||
self.gridLayout.addWidget(self.frac_spinBox, 1, 1, 1, 1)
|
self.gridLayout.addWidget(self.frac_spinBox, 2, 1, 1, 1)
|
||||||
|
self.buttonBox = QtWidgets.QDialogButtonBox(SmoothDialog)
|
||||||
|
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Apply|QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||||
|
self.buttonBox.setObjectName("buttonBox")
|
||||||
|
self.gridLayout.addWidget(self.buttonBox, 8, 0, 1, 2)
|
||||||
self.comboBox = QtWidgets.QComboBox(SmoothDialog)
|
self.comboBox = QtWidgets.QComboBox(SmoothDialog)
|
||||||
self.comboBox.setObjectName("comboBox")
|
self.comboBox.setObjectName("comboBox")
|
||||||
self.comboBox.addItem("")
|
self.comboBox.addItem("")
|
||||||
@ -77,22 +86,17 @@ class Ui_SmoothDialog(object):
|
|||||||
self.comboBox.addItem("")
|
self.comboBox.addItem("")
|
||||||
self.comboBox.addItem("")
|
self.comboBox.addItem("")
|
||||||
self.comboBox.addItem("")
|
self.comboBox.addItem("")
|
||||||
self.gridLayout.addWidget(self.comboBox, 0, 0, 1, 2)
|
self.gridLayout.addWidget(self.comboBox, 1, 0, 1, 2)
|
||||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
self.label_2 = QtWidgets.QLabel(SmoothDialog)
|
||||||
self.gridLayout.addItem(spacerItem, 6, 0, 1, 1)
|
self.label_2.setObjectName("label_2")
|
||||||
self.y_checkBox = QtWidgets.QCheckBox(SmoothDialog)
|
self.gridLayout.addWidget(self.label_2, 0, 0, 1, 2)
|
||||||
self.y_checkBox.setObjectName("y_checkBox")
|
|
||||||
self.gridLayout.addWidget(self.y_checkBox, 5, 1, 1, 1)
|
|
||||||
self.x_checkBox = QtWidgets.QCheckBox(SmoothDialog)
|
|
||||||
self.x_checkBox.setObjectName("x_checkBox")
|
|
||||||
self.gridLayout.addWidget(self.x_checkBox, 5, 0, 1, 1)
|
|
||||||
self.frac_label.setBuddy(self.frac_spinBox)
|
self.frac_label.setBuddy(self.frac_spinBox)
|
||||||
self.label_3.setBuddy(self.iter_spinBox)
|
|
||||||
self.label.setBuddy(self.polynom_spinBox)
|
self.label.setBuddy(self.polynom_spinBox)
|
||||||
|
self.label_3.setBuddy(self.iter_spinBox)
|
||||||
|
|
||||||
self.retranslateUi(SmoothDialog)
|
self.retranslateUi(SmoothDialog)
|
||||||
self.buttonBox.accepted.connect(SmoothDialog.accept)
|
self.buttonBox.accepted.connect(SmoothDialog.accept) # type: ignore
|
||||||
self.buttonBox.rejected.connect(SmoothDialog.reject)
|
self.buttonBox.rejected.connect(SmoothDialog.reject) # type: ignore
|
||||||
QtCore.QMetaObject.connectSlotsByName(SmoothDialog)
|
QtCore.QMetaObject.connectSlotsByName(SmoothDialog)
|
||||||
SmoothDialog.setTabOrder(self.comboBox, self.frac_spinBox)
|
SmoothDialog.setTabOrder(self.comboBox, self.frac_spinBox)
|
||||||
SmoothDialog.setTabOrder(self.frac_spinBox, self.polynom_spinBox)
|
SmoothDialog.setTabOrder(self.frac_spinBox, self.polynom_spinBox)
|
||||||
@ -104,9 +108,11 @@ class Ui_SmoothDialog(object):
|
|||||||
_translate = QtCore.QCoreApplication.translate
|
_translate = QtCore.QCoreApplication.translate
|
||||||
SmoothDialog.setWindowTitle(_translate("SmoothDialog", "1D smoothing filter"))
|
SmoothDialog.setWindowTitle(_translate("SmoothDialog", "1D smoothing filter"))
|
||||||
self.frac_label.setText(_translate("SmoothDialog", "Window length"))
|
self.frac_label.setText(_translate("SmoothDialog", "Window length"))
|
||||||
self.label_3.setText(_translate("SmoothDialog", "Iterations"))
|
|
||||||
self.label.setText(_translate("SmoothDialog", "Polynomial degree"))
|
self.label.setText(_translate("SmoothDialog", "Polynomial degree"))
|
||||||
self.polynom_spinBox.setToolTip(_translate("SmoothDialog", "Deg"))
|
self.polynom_spinBox.setToolTip(_translate("SmoothDialog", "Deg"))
|
||||||
|
self.y_checkBox.setText(_translate("SmoothDialog", "y log-spaced?"))
|
||||||
|
self.x_checkBox.setText(_translate("SmoothDialog", "x log-spaced?"))
|
||||||
|
self.label_3.setText(_translate("SmoothDialog", "Iterations"))
|
||||||
self.frac_spinBox.setToolTip(_translate("SmoothDialog", "<html><head/><body><p>Number of data points used as smoothing window.</p></body></html>"))
|
self.frac_spinBox.setToolTip(_translate("SmoothDialog", "<html><head/><body><p>Number of data points used as smoothing window.</p></body></html>"))
|
||||||
self.comboBox.setItemText(0, _translate("SmoothDialog", "Moving mean"))
|
self.comboBox.setItemText(0, _translate("SmoothDialog", "Moving mean"))
|
||||||
self.comboBox.setItemText(1, _translate("SmoothDialog", "Savitzky-Golay"))
|
self.comboBox.setItemText(1, _translate("SmoothDialog", "Savitzky-Golay"))
|
||||||
@ -117,5 +123,4 @@ class Ui_SmoothDialog(object):
|
|||||||
self.comboBox.setItemText(6, _translate("SmoothDialog", "Moving maximum"))
|
self.comboBox.setItemText(6, _translate("SmoothDialog", "Moving maximum"))
|
||||||
self.comboBox.setItemText(7, _translate("SmoothDialog", "Moving minimum"))
|
self.comboBox.setItemText(7, _translate("SmoothDialog", "Moving minimum"))
|
||||||
self.comboBox.setItemText(8, _translate("SmoothDialog", "Moving sum"))
|
self.comboBox.setItemText(8, _translate("SmoothDialog", "Moving sum"))
|
||||||
self.y_checkBox.setText(_translate("SmoothDialog", "y log-spaced?"))
|
self.label_2.setText(_translate("SmoothDialog", "<html><head/><body><p><span style=\" font-weight:600;\">Note:</span> Sets must be sorted for correct results</p></body></html>"))
|
||||||
self.x_checkBox.setText(_translate("SmoothDialog", "x log-spaced?"))
|
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
|
|
||||||
# Form implementation generated from reading ui file 'resources/_ui/usermodeleditor.ui'
|
# Form implementation generated from reading ui file 'resources/_ui/usermodeleditor.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.12.3
|
# Created by: PyQt5 UI code generator 5.15.10
|
||||||
#
|
#
|
||||||
# WARNING! All changes made in this file will be lost!
|
# 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
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
@ -20,15 +21,12 @@ class Ui_MainWindow(object):
|
|||||||
self.verticalLayout.setContentsMargins(3, 3, 3, 3)
|
self.verticalLayout.setContentsMargins(3, 3, 3, 3)
|
||||||
self.verticalLayout.setSpacing(3)
|
self.verticalLayout.setSpacing(3)
|
||||||
self.verticalLayout.setObjectName("verticalLayout")
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
self.edit_field = CodeEditor(self.centralwidget)
|
self.widget = EditorWidget(self.centralwidget)
|
||||||
font = QtGui.QFont()
|
self.widget.setObjectName("widget")
|
||||||
font.setPointSize(10)
|
self.verticalLayout.addWidget(self.widget)
|
||||||
self.edit_field.setFont(font)
|
|
||||||
self.edit_field.setObjectName("edit_field")
|
|
||||||
self.verticalLayout.addWidget(self.edit_field)
|
|
||||||
MainWindow.setCentralWidget(self.centralwidget)
|
MainWindow.setCentralWidget(self.centralwidget)
|
||||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 30))
|
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 20))
|
||||||
self.menubar.setObjectName("menubar")
|
self.menubar.setObjectName("menubar")
|
||||||
self.menuFile = QtWidgets.QMenu(self.menubar)
|
self.menuFile = QtWidgets.QMenu(self.menubar)
|
||||||
self.menuFile.setObjectName("menuFile")
|
self.menuFile.setObjectName("menuFile")
|
||||||
@ -61,4 +59,4 @@ class Ui_MainWindow(object):
|
|||||||
self.actionSave.setText(_translate("MainWindow", "Save"))
|
self.actionSave.setText(_translate("MainWindow", "Save"))
|
||||||
self.actionSave_as.setText(_translate("MainWindow", "Save as..."))
|
self.actionSave_as.setText(_translate("MainWindow", "Save as..."))
|
||||||
self.actionClose.setText(_translate("MainWindow", "Close"))
|
self.actionClose.setText(_translate("MainWindow", "Close"))
|
||||||
from ..lib.codeeditor import CodeEditor
|
from ..lib.codeeditor import EditorWidget
|
||||||
|
@ -300,10 +300,12 @@ class ExperimentContainer(QtCore.QObject):
|
|||||||
self._relations.pop(relation_type)
|
self._relations.pop(relation_type)
|
||||||
|
|
||||||
def _update_actions(self):
|
def _update_actions(self):
|
||||||
self.actions.update({'sort': self._data.sort,
|
self.actions.update({
|
||||||
|
'sort': self._data.sort,
|
||||||
'cut': self._data.cut,
|
'cut': self._data.cut,
|
||||||
'norm': self._data.normalize,
|
'norm': self._data.normalize,
|
||||||
'center': self.center})
|
'center': self.center,
|
||||||
|
})
|
||||||
|
|
||||||
@plot_update
|
@plot_update
|
||||||
def update(self, opts: dict):
|
def update(self, opts: dict):
|
||||||
@ -311,9 +313,11 @@ class ExperimentContainer(QtCore.QObject):
|
|||||||
|
|
||||||
def get_properties(self) -> dict:
|
def get_properties(self) -> dict:
|
||||||
props = OrderedDict()
|
props = OrderedDict()
|
||||||
props['General'] = OrderedDict([('Name', self.name),
|
props['General'] = OrderedDict([
|
||||||
|
('Name', self.name),
|
||||||
('Value', str(self.value)),
|
('Value', str(self.value)),
|
||||||
('Group', str(self.group))])
|
('Group', str(self.group)),
|
||||||
|
])
|
||||||
props['Symbol'] = OrderedDict()
|
props['Symbol'] = OrderedDict()
|
||||||
props['Line'] = OrderedDict()
|
props['Line'] = OrderedDict()
|
||||||
|
|
||||||
@ -480,10 +484,12 @@ class ExperimentContainer(QtCore.QObject):
|
|||||||
else:
|
else:
|
||||||
prefix = f'g[{i}].s[{j}].'
|
prefix = f'g[{i}].s[{j}].'
|
||||||
|
|
||||||
namespace = {prefix + 'x': (self.x, 'x values'),
|
namespace = {
|
||||||
|
prefix + 'x': (self.x, 'x values'),
|
||||||
prefix + 'y': [self.y, 'y values'],
|
prefix + 'y': [self.y, 'y values'],
|
||||||
prefix + 'y_err': (self.y_err, 'y error values'),
|
prefix + 'y_err': (self.y_err, 'y error values'),
|
||||||
prefix + 'value': (self.value, str(self.value))}
|
prefix + 'value': (self.value, str(self.value)),
|
||||||
|
}
|
||||||
|
|
||||||
if len(self._fits) == 1:
|
if len(self._fits) == 1:
|
||||||
namespace.update({
|
namespace.update({
|
||||||
|
@ -17,7 +17,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
moveItem = QtCore.pyqtSignal(list, str, str, int) # items, from, to, new row
|
moveItem = QtCore.pyqtSignal(list, str, str, int) # items, from, to, new row
|
||||||
copyItem = QtCore.pyqtSignal(list, str)
|
copyItem = QtCore.pyqtSignal(list, str)
|
||||||
saveFits = QtCore.pyqtSignal(list)
|
saveFits = QtCore.pyqtSignal(list)
|
||||||
extendFits = QtCore.pyqtSignal(list)
|
extendFits = QtCore.pyqtSignal(list, bool)
|
||||||
|
|
||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
@ -49,11 +49,16 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
def add_graph(self, idd: str, name: str):
|
def add_graph(self, idd: str, name: str):
|
||||||
item = QtWidgets.QTreeWidgetItem()
|
item = QtWidgets.QTreeWidgetItem()
|
||||||
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDropEnabled | QtCore.Qt.ItemIsEditable |
|
item.setFlags(
|
||||||
QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable)
|
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsDropEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsEditable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||||
|
)
|
||||||
item.setText(0, name)
|
item.setText(0, name)
|
||||||
item.setData(0, QtCore.Qt.UserRole, idd)
|
item.setData(0, QtCore.Qt.ItemDataRole.UserRole, idd)
|
||||||
item.setCheckState(0, QtCore.Qt.Checked)
|
item.setCheckState(0, QtCore.Qt.CheckState.Checked)
|
||||||
|
|
||||||
self.addTopLevelItem(item)
|
self.addTopLevelItem(item)
|
||||||
self._checked_graphs.add(idd)
|
self._checked_graphs.add(idd)
|
||||||
@ -67,14 +72,19 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
for row in range(self.invisibleRootItem().childCount()):
|
for row in range(self.invisibleRootItem().childCount()):
|
||||||
graph = self.invisibleRootItem().child(row)
|
graph = self.invisibleRootItem().child(row)
|
||||||
if graph.data(0, QtCore.Qt.UserRole) == gid:
|
if graph.data(0, QtCore.Qt.ItemDataRole.UserRole) == gid:
|
||||||
for (idd, name, value) in items:
|
for (idd, name, value) in items:
|
||||||
item = QtWidgets.QTreeWidgetItem([name])
|
item = QtWidgets.QTreeWidgetItem([name])
|
||||||
item.setToolTip(0, f'Value: {value}')
|
item.setToolTip(0, f'Value: {value}')
|
||||||
item.setData(0, QtCore.Qt.UserRole, idd)
|
item.setData(0, QtCore.Qt.ItemDataRole.UserRole, idd)
|
||||||
item.setCheckState(0, QtCore.Qt.Checked)
|
item.setCheckState(0, QtCore.Qt.CheckState.Checked)
|
||||||
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsEditable |
|
item.setFlags(
|
||||||
QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable)
|
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsDragEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsEditable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||||
|
)
|
||||||
graph.addChild(item)
|
graph.addChild(item)
|
||||||
self._checked_sets.add(idd)
|
self._checked_sets.add(idd)
|
||||||
|
|
||||||
@ -85,8 +95,8 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem)
|
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem)
|
||||||
def data_change(self, item: QtWidgets.QTreeWidgetItem, emit: bool = True) -> tuple[set, set]:
|
def data_change(self, item: QtWidgets.QTreeWidgetItem, emit: bool = True) -> tuple[set, set]:
|
||||||
idd = item.data(0, QtCore.Qt.UserRole)
|
idd = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
is_selected = item.checkState(0) == QtCore.Qt.Checked
|
is_selected = item.checkState(0) == QtCore.Qt.CheckState.Checked
|
||||||
to_be_hidden = set()
|
to_be_hidden = set()
|
||||||
to_be_shown = set()
|
to_be_shown = set()
|
||||||
|
|
||||||
@ -104,9 +114,9 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
self.blockSignals(True)
|
self.blockSignals(True)
|
||||||
for i in range(item.childCount()):
|
for i in range(item.childCount()):
|
||||||
child = item.child(i)
|
child = item.child(i)
|
||||||
child.setCheckState(0, QtCore.Qt.Checked)
|
child.setCheckState(0, QtCore.Qt.CheckState.Checked)
|
||||||
to_be_shown.add(child.data(0, QtCore.Qt.UserRole))
|
to_be_shown.add(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
self._checked_sets.add(child.data(0, QtCore.Qt.UserRole))
|
self._checked_sets.add(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
|
|
||||||
# check state change to unchecked
|
# check state change to unchecked
|
||||||
@ -115,10 +125,10 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
self.blockSignals(True)
|
self.blockSignals(True)
|
||||||
for i in range(item.childCount()):
|
for i in range(item.childCount()):
|
||||||
child = item.child(i)
|
child = item.child(i)
|
||||||
child.setCheckState(0, QtCore.Qt.Unchecked)
|
child.setCheckState(0, QtCore.Qt.CheckState.Unchecked)
|
||||||
to_be_hidden.add(child.data(0, QtCore.Qt.UserRole))
|
to_be_hidden.add(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
try:
|
try:
|
||||||
self._checked_sets.remove(child.data(0, QtCore.Qt.UserRole))
|
self._checked_sets.remove(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
@ -153,7 +163,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem)
|
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem)
|
||||||
def new_selection(self, item: QtWidgets.QTreeWidgetItem):
|
def new_selection(self, item: QtWidgets.QTreeWidgetItem):
|
||||||
if item.parent() is None:
|
if item.parent() is None:
|
||||||
self.management.select_window(item.data(0, QtCore.Qt.UserRole))
|
self.management.select_window(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
def dropEvent(self, evt: QtGui.QDropEvent):
|
def dropEvent(self, evt: QtGui.QDropEvent):
|
||||||
dropped_index = self.indexAt(evt.pos())
|
dropped_index = self.indexAt(evt.pos())
|
||||||
@ -179,7 +189,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
from_parent.removeChild(it)
|
from_parent.removeChild(it)
|
||||||
tobemoved.append(it)
|
tobemoved.append(it)
|
||||||
take_from.append(from_parent.data(0, QtCore.Qt.UserRole))
|
take_from.append(from_parent.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
pos = QtCore.QModelIndex(persistent_drop)
|
pos = QtCore.QModelIndex(persistent_drop)
|
||||||
if self.dropIndicatorPosition() == QtWidgets.QAbstractItemView.BelowItem:
|
if self.dropIndicatorPosition() == QtWidgets.QAbstractItemView.BelowItem:
|
||||||
@ -191,8 +201,8 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
else:
|
else:
|
||||||
to_parent.insertChildren(row, tobemoved)
|
to_parent.insertChildren(row, tobemoved)
|
||||||
|
|
||||||
self.management.move_sets([it.data(0, QtCore.Qt.UserRole) for it in tobemoved],
|
self.management.move_sets([it.data(0, QtCore.Qt.ItemDataRole.UserRole) for it in tobemoved],
|
||||||
to_parent.data(0, QtCore.Qt.UserRole), take_from,
|
to_parent.data(0, QtCore.Qt.ItemDataRole.UserRole), take_from,
|
||||||
pos=-1 if append else row)
|
pos=-1 if append else row)
|
||||||
|
|
||||||
self.update_indexes()
|
self.update_indexes()
|
||||||
@ -207,7 +217,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
if item is not None:
|
if item is not None:
|
||||||
data = item.data(0, QtCore.Qt.UserRole)
|
data = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if data == gid_out:
|
if data == gid_out:
|
||||||
from_parent = item
|
from_parent = item
|
||||||
|
|
||||||
@ -231,7 +241,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
|
|
||||||
def sort(self, graph_item: QtWidgets.QTreeWidgetItem, mode: str = 'value'):
|
def sort(self, graph_item: QtWidgets.QTreeWidgetItem, mode: str = 'value'):
|
||||||
graph_id = graph_item.data(0, QtCore.Qt.UserRole)
|
graph_id = graph_item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
sets = self.management.get_attributes(graph_id, mode)
|
sets = self.management.get_attributes(graph_id, mode)
|
||||||
sets = [el[0] for el in sorted(sets.items(), key=lambda x: x[1])]
|
sets = [el[0] for el in sorted(sets.items(), key=lambda x: x[1])]
|
||||||
|
|
||||||
@ -243,7 +253,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
|
|
||||||
for s in sets:
|
for s in sets:
|
||||||
for c in children:
|
for c in children:
|
||||||
if c.data(0, QtCore.Qt.UserRole) == s:
|
if c.data(0, QtCore.Qt.ItemDataRole.UserRole) == s:
|
||||||
graph_item.addChild(c)
|
graph_item.addChild(c)
|
||||||
|
|
||||||
self.update_indexes()
|
self.update_indexes()
|
||||||
@ -276,7 +286,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
if item is not None:
|
if item is not None:
|
||||||
data = item.data(0, QtCore.Qt.UserRole)
|
data = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if data == sid:
|
if data == sid:
|
||||||
if name != item.text(0):
|
if name != item.text(0):
|
||||||
item.setText(0, name)
|
item.setText(0, name)
|
||||||
@ -285,7 +295,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
iterator += 1
|
iterator += 1
|
||||||
|
|
||||||
def keyPressEvent(self, evt: QtGui.QKeyEvent):
|
def keyPressEvent(self, evt: QtGui.QKeyEvent):
|
||||||
if evt.key() == QtCore.Qt.Key_Delete:
|
if evt.key() == QtCore.Qt.Key.Key_Delete:
|
||||||
rm_sets = []
|
rm_sets = []
|
||||||
rm_graphs = []
|
rm_graphs = []
|
||||||
for idx in self.selectedIndexes():
|
for idx in self.selectedIndexes():
|
||||||
@ -296,20 +306,20 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
if item.parent() is None:
|
if item.parent() is None:
|
||||||
for c_i in range(item.childCount()):
|
for c_i in range(item.childCount()):
|
||||||
# add sets inside graph to removal
|
# add sets inside graph to removal
|
||||||
child_data = item.child(c_i).data(0, QtCore.Qt.UserRole)
|
child_data = item.child(c_i).data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if child_data not in rm_sets:
|
if child_data not in rm_sets:
|
||||||
rm_sets.append(child_data)
|
rm_sets.append(child_data)
|
||||||
rm_graphs.append(item.data(0, QtCore.Qt.UserRole))
|
rm_graphs.append(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
item_data = item.data(0, QtCore.Qt.UserRole)
|
item_data = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if item_data not in rm_sets:
|
if item_data not in rm_sets:
|
||||||
rm_sets.append(item_data)
|
rm_sets.append(item_data)
|
||||||
|
|
||||||
# self.deleteItem.emit(rm_sets+rm_graphs)
|
# self.deleteItem.emit(rm_sets+rm_graphs)
|
||||||
self.management.delete_sets(rm_sets+rm_graphs)
|
self.management.delete_sets(rm_sets+rm_graphs)
|
||||||
|
|
||||||
elif evt.key() == QtCore.Qt.Key_Space:
|
elif evt.key() == QtCore.Qt.Key.Key_Space:
|
||||||
sets = []
|
sets = []
|
||||||
from_parent = []
|
from_parent = []
|
||||||
|
|
||||||
@ -329,7 +339,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
for it in sets:
|
for it in sets:
|
||||||
if it in from_parent:
|
if it in from_parent:
|
||||||
continue
|
continue
|
||||||
it.setCheckState(0, QtCore.Qt.Unchecked if it.checkState(0) == QtCore.Qt.Checked else QtCore.Qt.Checked)
|
it.setCheckState(0, QtCore.Qt.CheckState.Unchecked if it.checkState(0) == QtCore.Qt.CheckState.Checked else QtCore.Qt.CheckState.Checked)
|
||||||
s1, s2 = self.data_change(it, emit=False)
|
s1, s2 = self.data_change(it, emit=False)
|
||||||
to_be_hidden |= s2
|
to_be_hidden |= s2
|
||||||
to_be_shown |= s1
|
to_be_shown |= s1
|
||||||
@ -353,7 +363,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
# find all items that have to be removed
|
# find all items that have to be removed
|
||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
_id = item.data(0, QtCore.Qt.UserRole)
|
_id = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if _id in ids:
|
if _id in ids:
|
||||||
try:
|
try:
|
||||||
item_parent = item.parent()
|
item_parent = item.parent()
|
||||||
@ -410,6 +420,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
self.ctx_sets(evt, menu)
|
self.ctx_sets(evt, menu)
|
||||||
|
|
||||||
def ctx_graphs(self, evt, menu):
|
def ctx_graphs(self, evt, menu):
|
||||||
|
copy_action = menu.addAction('Replicate graph!')
|
||||||
del_action = menu.addAction('Exterminate graph!')
|
del_action = menu.addAction('Exterminate graph!')
|
||||||
|
|
||||||
sort_menu = menu.addMenu('Sort sets')
|
sort_menu = menu.addMenu('Sort sets')
|
||||||
@ -430,12 +441,16 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
if i.column() == 0:
|
if i.column() == 0:
|
||||||
continue
|
continue
|
||||||
items.append(self.itemFromIndex(i))
|
items.append(self.itemFromIndex(i))
|
||||||
graphs.append(self.itemFromIndex(i).data(0, QtCore.Qt.UserRole))
|
graphs.append(self.itemFromIndex(i).data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
if action == del_action:
|
if action == del_action:
|
||||||
for gid in graphs:
|
for gid in graphs:
|
||||||
self.management.delete_graph(gid)
|
self.management.delete_graph(gid)
|
||||||
|
|
||||||
|
elif action == copy_action:
|
||||||
|
for gid in graphs:
|
||||||
|
self.management.copy_graph(gid)
|
||||||
|
|
||||||
elif action.parent() == col_menu:
|
elif action.parent() == col_menu:
|
||||||
for gid in graphs:
|
for gid in graphs:
|
||||||
self.management.set_cycle(self.management.graphs[gid].sets, action.text())
|
self.management.set_cycle(self.management.graphs[gid].sets, action.text())
|
||||||
@ -450,7 +465,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
del_action = menu.addAction('Exterminate sets')
|
del_action = menu.addAction('Exterminate sets')
|
||||||
cp_action = menu.addAction('Replicate sets')
|
cp_action = menu.addAction('Replicate sets')
|
||||||
cat_action = menu.addAction('Join us!')
|
cat_action = menu.addAction('Join us!')
|
||||||
plt_action = save_action = extend_action = None
|
plt_action = save_action = extend_action = subfit_action = None
|
||||||
menu.addSeparator()
|
menu.addSeparator()
|
||||||
col_menu = menu.addMenu('Color cycle')
|
col_menu = menu.addMenu('Color cycle')
|
||||||
for c in available_cycles.keys():
|
for c in available_cycles.keys():
|
||||||
@ -468,12 +483,12 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
else:
|
else:
|
||||||
graph_id = parent.data(0, QtCore.Qt.UserRole)
|
graph_id = parent.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if graph_id not in idx:
|
if graph_id not in idx:
|
||||||
idx[graph_id] = []
|
idx[graph_id] = []
|
||||||
# collect sets in their graph
|
# collect sets in their graph
|
||||||
idx[graph_id].append(item.data(0, QtCore.Qt.UserRole))
|
idx[graph_id].append(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
data = self.management[item.data(0, QtCore.Qt.UserRole)]
|
data = self.management[item.data(0, QtCore.Qt.ItemDataRole.UserRole)]
|
||||||
if data.mode == 'fit':
|
if data.mode == 'fit':
|
||||||
has_fits = True
|
has_fits = True
|
||||||
|
|
||||||
@ -482,6 +497,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
plt_action = menu.addAction('Plot fit parameter')
|
plt_action = menu.addAction('Plot fit parameter')
|
||||||
save_action = menu.addAction('Save fit parameter')
|
save_action = menu.addAction('Save fit parameter')
|
||||||
extend_action = menu.addAction('Extrapolate fit')
|
extend_action = menu.addAction('Extrapolate fit')
|
||||||
|
subfit_action = menu.addAction('Plot partial functions')
|
||||||
|
|
||||||
action = menu.exec(evt.globalPos())
|
action = menu.exec(evt.globalPos())
|
||||||
|
|
||||||
@ -489,6 +505,9 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
for gid, sets in idx.items():
|
for gid, sets in idx.items():
|
||||||
s.extend(sets)
|
s.extend(sets)
|
||||||
|
|
||||||
|
if action is None:
|
||||||
|
return
|
||||||
|
|
||||||
if action == del_action:
|
if action == del_action:
|
||||||
self.management.delete_sets(s)
|
self.management.delete_sets(s)
|
||||||
|
|
||||||
@ -506,7 +525,10 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
self.saveFits.emit(s)
|
self.saveFits.emit(s)
|
||||||
|
|
||||||
elif action == extend_action:
|
elif action == extend_action:
|
||||||
self.extendFits.emit(s)
|
self.extendFits.emit(s, False)
|
||||||
|
|
||||||
|
elif action == subfit_action:
|
||||||
|
self.extendFits.emit(s, True)
|
||||||
|
|
||||||
elif action.parent() == col_menu:
|
elif action.parent() == col_menu:
|
||||||
self.management.set_cycle(s, action.text())
|
self.management.set_cycle(s, action.text())
|
||||||
@ -518,7 +540,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
if item is not None:
|
if item is not None:
|
||||||
if item.data(0, QtCore.Qt.UserRole) == gid:
|
if item.data(0, QtCore.Qt.ItemDataRole.UserRole) == gid:
|
||||||
item.setBackground(0, QtGui.QBrush(QtGui.QColor('gray')))
|
item.setBackground(0, QtGui.QBrush(QtGui.QColor('gray')))
|
||||||
else:
|
else:
|
||||||
item.setBackground(0, QtGui.QBrush())
|
item.setBackground(0, QtGui.QBrush())
|
||||||
@ -527,11 +549,14 @@ class DataTree(QtWidgets.QTreeWidget):
|
|||||||
def uncheck_sets(self, sets: list[str]):
|
def uncheck_sets(self, sets: list[str]):
|
||||||
self.blockSignals(True)
|
self.blockSignals(True)
|
||||||
iterator = QtWidgets.QTreeWidgetItemIterator(self)
|
iterator = QtWidgets.QTreeWidgetItemIterator(self)
|
||||||
|
self._checked_sets = set()
|
||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
if item is not None:
|
if item is not None:
|
||||||
if item.data(0, QtCore.Qt.UserRole) in sets:
|
if item.data(0, QtCore.Qt.ItemDataRole.UserRole) in sets:
|
||||||
item.setCheckState(0, QtCore.Qt.Unchecked)
|
item.setCheckState(0, QtCore.Qt.CheckState.Unchecked)
|
||||||
|
else:
|
||||||
|
self._checked_sets.add(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
iterator += 1
|
iterator += 1
|
||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
|
|
||||||
@ -559,6 +584,8 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
|||||||
self.propwidget.expansionChanged.connect(self.show_property)
|
self.propwidget.expansionChanged.connect(self.show_property)
|
||||||
self.proptable.propertyChanged.connect(self.change_property)
|
self.proptable.propertyChanged.connect(self.change_property)
|
||||||
|
|
||||||
|
self.pokemon_toolbutton.clicked.connect(self.catchthemall)
|
||||||
|
|
||||||
make_action_icons(self)
|
make_action_icons(self)
|
||||||
|
|
||||||
def add_graph(self, idd: str, name: str):
|
def add_graph(self, idd: str, name: str):
|
||||||
@ -586,7 +613,7 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
|||||||
sid = []
|
sid = []
|
||||||
for i in self.tree.selectedIndexes():
|
for i in self.tree.selectedIndexes():
|
||||||
if i.column() == 0:
|
if i.column() == 0:
|
||||||
sid.append(i.data(role=QtCore.Qt.UserRole))
|
sid.append(i.data(role=QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
self.startShowProperty.emit(sid)
|
self.startShowProperty.emit(sid)
|
||||||
|
|
||||||
@ -595,15 +622,23 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
|||||||
self.proptable.populate(props)
|
self.proptable.populate(props)
|
||||||
|
|
||||||
def change_property(self, key1, key2, value):
|
def change_property(self, key1, key2, value):
|
||||||
ids = [item.data(0, QtCore.Qt.UserRole) for item in self.tree.selectedItems()]
|
|
||||||
if key2 == 'Value':
|
if key2 == 'Value':
|
||||||
try:
|
try:
|
||||||
value = float(value)
|
value = float(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
QtWidgets.QMessageBox.warning(self, 'Invalid entry',
|
QtWidgets.QMessageBox.warning(
|
||||||
'Value %r is not a valid number for `value`.' % value)
|
self,
|
||||||
|
'Invalid entry',
|
||||||
|
f'Value {value!r} is not a valid number for `value`.')
|
||||||
return
|
return
|
||||||
|
|
||||||
|
ids = []
|
||||||
|
for item in self.tree.selectedItems():
|
||||||
|
ids.append(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
item.setToolTip(0, str(value))
|
||||||
|
else:
|
||||||
|
ids = [item.data(0, QtCore.Qt.ItemDataRole.UserRole) for item in self.tree.selectedItems()]
|
||||||
|
|
||||||
self.propertyChanged.emit(ids, key1, key2, value)
|
self.propertyChanged.emit(ids, key1, key2, value)
|
||||||
|
|
||||||
def uncheck_sets(self, sets: list[str]):
|
def uncheck_sets(self, sets: list[str]):
|
||||||
@ -612,6 +647,12 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
|||||||
def set_name(self, sid, value):
|
def set_name(self, sid, value):
|
||||||
self.tree.set_name(sid, value)
|
self.tree.set_name(sid, value)
|
||||||
|
|
||||||
|
def catchthemall(self):
|
||||||
|
from gui_qt.lib.pokemon import QPoke
|
||||||
|
|
||||||
|
dialog = QPoke( parent=self)
|
||||||
|
dialog.exec()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def management(self):
|
def management(self):
|
||||||
return self.tree.management
|
return self.tree.management
|
||||||
|
@ -41,7 +41,7 @@ class PropWidget(QtWidgets.QWidget):
|
|||||||
idx = table.indexFromItem(item)
|
idx = table.indexFromItem(item)
|
||||||
self.propertyChanged.emit(self.tab.tabText(tab_idx),
|
self.propertyChanged.emit(self.tab.tabText(tab_idx),
|
||||||
table.item(idx.row(), idx.column()-1).text(),
|
table.item(idx.row(), idx.column()-1).text(),
|
||||||
item.data(QtCore.Qt.DisplayRole))
|
item.data(QtCore.Qt.ItemDataRole.DisplayRole))
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int)
|
@QtCore.pyqtSlot(int)
|
||||||
def tab_change(self, idx: int):
|
def tab_change(self, idx: int):
|
||||||
@ -66,10 +66,10 @@ class PropTable(QtWidgets.QTableWidget):
|
|||||||
self.blockSignals(True)
|
self.blockSignals(True)
|
||||||
for k, v in prop.items():
|
for k, v in prop.items():
|
||||||
value_item = QtWidgets.QTableWidgetItem('')
|
value_item = QtWidgets.QTableWidgetItem('')
|
||||||
value_item.setData(QtCore.Qt.DisplayRole, v)
|
value_item.setData(QtCore.Qt.ItemDataRole.DisplayRole, v)
|
||||||
|
|
||||||
key_item = QtWidgets.QTableWidgetItem(k)
|
key_item = QtWidgets.QTableWidgetItem(k)
|
||||||
key_item.setFlags(QtCore.Qt.NoItemFlags)
|
key_item.setFlags(QtCore.Qt.ItemFlag.NoItemFlags)
|
||||||
key_item.setForeground(QtGui.QBrush(QtGui.QColor(0, 0, 0)))
|
key_item.setForeground(QtGui.QBrush(QtGui.QColor(0, 0, 0)))
|
||||||
|
|
||||||
self.setRowCount(self.rowCount()+1)
|
self.setRowCount(self.rowCount()+1)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from ..Qt import QtCore, QtWidgets
|
from ..Qt import QtCore, QtWidgets, QtGui
|
||||||
from .._py.ptstab import Ui_Form
|
from .._py.ptstab import Ui_Form
|
||||||
from ..lib.pg_objects import LogInfiniteLine, RegionItem
|
from ..lib.pg_objects import LogInfiniteLine, RegionItem
|
||||||
|
|
||||||
@ -27,15 +27,23 @@ class PointSelectWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
self._last_item = None
|
self._last_item = None
|
||||||
self.connected_figure = ''
|
self.connected_figure = ''
|
||||||
|
|
||||||
|
self._avg_modes = ['mean', 'sum', 'integral', 'std']
|
||||||
|
self._special_values = ['max', 'absmax', 'min', 'absmin']
|
||||||
|
self._group_modes = ['group', 'x']
|
||||||
|
|
||||||
self.okButton.clicked.connect(self.apply)
|
self.okButton.clicked.connect(self.apply)
|
||||||
self.deleteButton.clicked.connect(self.remove_points)
|
self.deleteButton.clicked.connect(self.remove_points)
|
||||||
|
|
||||||
self.peaktable.itemChanged.connect(self.editing_finished)
|
self.peaktable.itemChanged.connect(self.editing_finished)
|
||||||
self.peaktable.itemDoubleClicked.connect(self.editing_started)
|
self.peaktable.itemDoubleClicked.connect(self.editing_started)
|
||||||
|
|
||||||
|
self.left_limit.setValidator(QtGui.QDoubleValidator())
|
||||||
|
self.right_limit.setValidator(QtGui.QDoubleValidator())
|
||||||
|
|
||||||
def keyPressEvent(self, e):
|
def keyPressEvent(self, e):
|
||||||
if e.key() == QtCore.Qt.Key_Delete:
|
if e.key() == QtCore.Qt.Key.Key_Delete:
|
||||||
self.remove_points()
|
self.remove_points()
|
||||||
elif e.key() == QtCore.Qt.Key_F2:
|
elif e.key() == QtCore.Qt.Key.Key_F2:
|
||||||
self.editing_started()
|
self.editing_started()
|
||||||
else:
|
else:
|
||||||
super().keyPressEvent(e)
|
super().keyPressEvent(e)
|
||||||
@ -91,7 +99,7 @@ class PointSelectWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
item = QtWidgets.QListWidgetItem(f'{self.pts[-1][0]:.5g} - {self.pts[-1][1]:.5g}')
|
item = QtWidgets.QListWidgetItem(f'{self.pts[-1][0]:.5g} - {self.pts[-1][1]:.5g}')
|
||||||
else:
|
else:
|
||||||
item = QtWidgets.QListWidgetItem(f'{self.pts[-1]:.5g}')
|
item = QtWidgets.QListWidgetItem(f'{self.pts[-1]:.5g}')
|
||||||
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
|
item.setFlags(item.flags() ^ QtCore.Qt.ItemFlag.ItemIsEditable)
|
||||||
self.peaktable.blockSignals(True)
|
self.peaktable.blockSignals(True)
|
||||||
self.peaktable.addItem(item)
|
self.peaktable.addItem(item)
|
||||||
self.peaktable.blockSignals(False)
|
self.peaktable.blockSignals(False)
|
||||||
@ -102,21 +110,22 @@ class PointSelectWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def apply(self) -> dict:
|
def apply(self) -> dict:
|
||||||
ret_dic = {'avg_range': [self.left_pt.value(), self.right_pt.value()],
|
ret_dic = {
|
||||||
'avg_mode': {0: 'mean', 1: 'sum', 2: 'integral'}[self.average_combobox.currentIndex()],
|
'avg_range': self.get_limits(),
|
||||||
'special': None, 'idx': None,
|
'avg_mode': self._avg_modes[self.average_combobox.currentIndex()],
|
||||||
'xy': (self.xbutton.isChecked(), self.ybutton.isChecked())}
|
'special': None,
|
||||||
|
'idx': None,
|
||||||
|
'xy': (self.xbutton.isChecked(), self.ybutton.isChecked()),
|
||||||
|
'groupby': self._group_modes[self.group_box.currentIndex()],
|
||||||
|
}
|
||||||
|
|
||||||
if self.groupBox_2.isChecked():
|
if self.special_checkbox.isChecked():
|
||||||
ret_dic['special'] = {0: 'max', 1: 'absmax', 2: 'min', 3: 'absmin'}[self.special_comboBox.currentIndex()]
|
ret_dic['special'] = self._special_values[self.special_comboBox.currentIndex()]
|
||||||
|
|
||||||
if len(self.pts) != 0:
|
if len(self.pts) != 0:
|
||||||
ret_dic['idx'] = self.pts
|
ret_dic['idx'] = self.pts
|
||||||
|
|
||||||
if self.graph_checkbox.isChecked():
|
gid = self.graph_combobox.currentData() if not self.graph_checkbox.isChecked() else ''
|
||||||
gid = ''
|
|
||||||
else:
|
|
||||||
gid = self.graph_combobox.currentData()
|
|
||||||
|
|
||||||
self.points_selected.emit(ret_dic, gid)
|
self.points_selected.emit(ret_dic, gid)
|
||||||
|
|
||||||
@ -199,4 +208,22 @@ class PointSelectWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_graph_checkbox_stateChanged')
|
@QtCore.pyqtSlot(int, name='on_graph_checkbox_stateChanged')
|
||||||
def changed_state(self, checked):
|
def changed_state(self, checked):
|
||||||
self.graph_combobox.setEnabled(checked!=QtCore.Qt.Checked)
|
self.graph_combobox.setEnabled(checked != QtCore.Qt.CheckState.Checked)
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(int, name='on_special_checkbox_stateChanged')
|
||||||
|
def changed_special(self, checked: int):
|
||||||
|
self.graph_combobox.setEnabled(checked != QtCore.Qt.CheckState.Checked)
|
||||||
|
|
||||||
|
def get_limits(self) -> tuple[float, float, str]:
|
||||||
|
try:
|
||||||
|
left = float(self.left_limit.text())
|
||||||
|
except ValueError:
|
||||||
|
left = 0.
|
||||||
|
|
||||||
|
try:
|
||||||
|
right = float(self.right_limit.text())
|
||||||
|
except ValueError:
|
||||||
|
right = 0.
|
||||||
|
|
||||||
|
return left, right, self.limit_combobox.currentText()
|
||||||
|
|
||||||
|
@ -76,38 +76,24 @@ class QPreviewDialog(QtWidgets.QDialog, Ui_ApodEdit):
|
|||||||
self.pivot_lineedit.textEdited.connect(lambda x: self.pvt_line.setValue(float(x)))
|
self.pivot_lineedit.textEdited.connect(lambda x: self.pvt_line.setValue(float(x)))
|
||||||
|
|
||||||
def add_data(self: QPreviewDialog, data: FID | Spectrum) -> bool:
|
def add_data(self: QPreviewDialog, data: FID | Spectrum) -> bool:
|
||||||
|
|
||||||
if isinstance(data, FID):
|
if isinstance(data, FID):
|
||||||
if self._all_freq:
|
valid, (real_plt, imag_plt, real_plt_fft, imag_plt_fft) = self._prep_time(data)
|
||||||
msg = QtWidgets.QMessageBox.warning(self, 'Mixed types',
|
|
||||||
'Timesignals and spectra cannot be edited at the same time.')
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
self._all_time = True
|
|
||||||
self._all_freq = False
|
|
||||||
|
|
||||||
elif isinstance(data, Spectrum):
|
elif isinstance(data, Spectrum):
|
||||||
if self._all_time:
|
valid, (real_plt, imag_plt, real_plt_fft, imag_plt_fft) = self._prep_freq(data)
|
||||||
msg = QtWidgets.QMessageBox.warning(self, 'Mixed types',
|
|
||||||
'Timesignals and spectra cannot be edited at the same time.')
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
self._all_time = False
|
|
||||||
self._all_freq = True
|
|
||||||
|
|
||||||
fid = data.copy()
|
else:
|
||||||
spec = self._temp_fft_time(fid.x, fid.y, self.baseline_box.isChecked())
|
return False
|
||||||
|
|
||||||
|
if not valid:
|
||||||
|
return False
|
||||||
|
|
||||||
x_len = data.x.size
|
x_len = data.x.size
|
||||||
self.zf_spinbox.setMaximum(min(2**17//x_len, 3))
|
self.zf_spinbox.setMaximum(min(2**17//x_len, 3))
|
||||||
|
|
||||||
real_plt = PlotItem(x=fid.x, y=fid.y.real, pen=mkPen('b'))
|
|
||||||
imag_plt = PlotItem(x=fid.x, y=fid.y.imag, pen=mkPen('r'))
|
|
||||||
self.time_graph.addItem(imag_plt)
|
self.time_graph.addItem(imag_plt)
|
||||||
self.time_graph.addItem(real_plt)
|
self.time_graph.addItem(real_plt)
|
||||||
|
|
||||||
real_plt_fft = PlotItem(x=spec[0], y=spec[1].real, pen=mkPen('b'))
|
|
||||||
imag_plt_fft = PlotItem(x=spec[0], y=spec[1].imag, pen=mkPen('r'))
|
|
||||||
self.freq_graph.addItem(imag_plt_fft)
|
self.freq_graph.addItem(imag_plt_fft)
|
||||||
self.freq_graph.addItem(real_plt_fft)
|
self.freq_graph.addItem(real_plt_fft)
|
||||||
|
|
||||||
@ -118,12 +104,52 @@ class QPreviewDialog(QtWidgets.QDialog, Ui_ApodEdit):
|
|||||||
for p in [self._tmp_data_zf, self._tmp_data_ap]:
|
for p in [self._tmp_data_zf, self._tmp_data_ap]:
|
||||||
p.append((data.x, data.y.copy()))
|
p.append((data.x, data.y.copy()))
|
||||||
|
|
||||||
self._tmp_data_ph.append((data.x, data.y, spec[0], spec[1]))
|
|
||||||
|
|
||||||
self.graphs.append((real_plt, imag_plt, real_plt_fft, imag_plt_fft))
|
self.graphs.append((real_plt, imag_plt, real_plt_fft, imag_plt_fft))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
def _prep_time(self, data) -> tuple[bool, tuple]:
|
||||||
|
if self._all_freq:
|
||||||
|
_ = QtWidgets.QMessageBox.warning(self, 'Mixed types',
|
||||||
|
'Time signals and spectra cannot be edited at the same time.')
|
||||||
|
return False, tuple()
|
||||||
|
|
||||||
|
fid = data.copy()
|
||||||
|
spec = self._temp_fft_time(fid.x, fid.y, self.baseline_box.isChecked())
|
||||||
|
self._all_time = True
|
||||||
|
self._all_freq = False
|
||||||
|
|
||||||
|
real_plt = PlotItem(x=fid.x, y=fid.y.real, pen=mkPen('b'))
|
||||||
|
imag_plt = PlotItem(x=fid.x, y=fid.y.imag, pen=mkPen('r'))
|
||||||
|
|
||||||
|
real_plt_fft = PlotItem(x=spec[0], y=spec[1].real, pen=mkPen('b'))
|
||||||
|
imag_plt_fft = PlotItem(x=spec[0], y=spec[1].imag, pen=mkPen('r'))
|
||||||
|
|
||||||
|
self._tmp_data_ph.append((data.x, data.y, spec[0], spec[1]))
|
||||||
|
|
||||||
|
return True, (real_plt, imag_plt, real_plt_fft, imag_plt_fft)
|
||||||
|
|
||||||
|
def _prep_freq(self, data) -> tuple[bool, tuple]:
|
||||||
|
if self._all_time:
|
||||||
|
_ = QtWidgets.QMessageBox.warning(self, 'Mixed types',
|
||||||
|
'Time signals and spectra cannot be edited at the same time.')
|
||||||
|
return False, tuple()
|
||||||
|
|
||||||
|
spec = data.copy()
|
||||||
|
fid = self._temp_fft_time(spec.x, spec.y, self.baseline_box.isChecked())
|
||||||
|
self._all_time = False
|
||||||
|
self._all_freq = True
|
||||||
|
|
||||||
|
real_plt = PlotItem(x=fid[0], y=fid[1].real, pen=mkPen('b'))
|
||||||
|
imag_plt = PlotItem(x=fid[0], y=fid[1].imag, pen=mkPen('r'))
|
||||||
|
|
||||||
|
real_plt_fft = PlotItem(x=spec.x, y=spec.y.real, pen=mkPen('b'))
|
||||||
|
imag_plt_fft = PlotItem(x=spec.x, y=spec.y.imag, pen=mkPen('r'))
|
||||||
|
|
||||||
|
self._tmp_data_ph.append((data.x, data.y, spec.x, spec.y))
|
||||||
|
|
||||||
|
return True, (real_plt, imag_plt, real_plt_fft, imag_plt_fft)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_baseline_box_clicked')
|
@QtCore.pyqtSlot(name='on_baseline_box_clicked')
|
||||||
def _update_bl(self):
|
def _update_bl(self):
|
||||||
if self.baseline_box.isChecked():
|
if self.baseline_box.isChecked():
|
||||||
@ -200,7 +226,7 @@ class QPreviewDialog(QtWidgets.QDialog, Ui_ApodEdit):
|
|||||||
ph1 = self.ph1_spinbox.value()
|
ph1 = self.ph1_spinbox.value()
|
||||||
|
|
||||||
for i, (x, y) in enumerate(self._tmp_data_ap):
|
for i, (x, y) in enumerate(self._tmp_data_ap):
|
||||||
x_fft, y_fft = self._temp_fft_time(x, y, self.baseline_box.isChecked())
|
x_fft, y_fft = self._temp_fft(x, y, self.baseline_box.isChecked())
|
||||||
|
|
||||||
if ph0 != 0:
|
if ph0 != 0:
|
||||||
y = self._temp_phase(x, y, ph0, 0, 0)
|
y = self._temp_phase(x, y, ph0, 0, 0)
|
||||||
@ -213,7 +239,7 @@ class QPreviewDialog(QtWidgets.QDialog, Ui_ApodEdit):
|
|||||||
else:
|
else:
|
||||||
self.pvt_line.hide()
|
self.pvt_line.hide()
|
||||||
for i, (x, y) in enumerate(self._tmp_data_ap):
|
for i, (x, y) in enumerate(self._tmp_data_ap):
|
||||||
self._tmp_data_ph[i] = x, y, *self._temp_fft_time(x, y, self.baseline_box.isChecked())
|
self._tmp_data_ph[i] = x, y, *self._temp_fft(x, y, self.baseline_box.isChecked())
|
||||||
|
|
||||||
self._update_plots()
|
self._update_plots()
|
||||||
|
|
||||||
@ -346,7 +372,6 @@ class QPreviewDialog(QtWidgets.QDialog, Ui_ApodEdit):
|
|||||||
self.data = []
|
self.data = []
|
||||||
self.graphs = []
|
self.graphs = []
|
||||||
self.freq_graph.removeItem(self.pvt_line)
|
self.freq_graph.removeItem(self.pvt_line)
|
||||||
self.time_graph.removeItem(self.pvt_line)
|
|
||||||
|
|
||||||
self.blockSignals(False)
|
self.blockSignals(False)
|
||||||
|
|
||||||
@ -388,13 +413,16 @@ class QPreviewDialog(QtWidgets.QDialog, Ui_ApodEdit):
|
|||||||
|
|
||||||
vb = self.time_graph.getPlotItem().getViewBox()
|
vb = self.time_graph.getPlotItem().getViewBox()
|
||||||
vb.disableAutoRange(axis=vb.YAxis)
|
vb.disableAutoRange(axis=vb.YAxis)
|
||||||
|
if self._all_time is not None:
|
||||||
self.zerofill_box.setVisible(self._all_time)
|
self.zerofill_box.setVisible(self._all_time)
|
||||||
self.apod_box.setVisible(self._all_time)
|
self.apod_box.setVisible(self._all_time)
|
||||||
self.shift_box.setVisible(self._all_time)
|
self.shift_box.setVisible(self._all_time)
|
||||||
self.time_graph.setVisible(self._all_time)
|
self.time_graph.setVisible(self._all_time)
|
||||||
self.logtime_widget.setVisible(self._all_time)
|
self.logtime_widget.setVisible(self._all_time)
|
||||||
|
|
||||||
|
self._temp_baseline = self._temp_baseline_time if self._all_time else self._temp_baseline_freq
|
||||||
|
self._temp_fft = self._temp_fft_time if self._all_time else self._temp_fft_freq
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_logx_time_stateChanged')
|
@QtCore.pyqtSlot(int, name='on_logx_time_stateChanged')
|
||||||
@QtCore.pyqtSlot(int, name='on_logy_time_stateChanged')
|
@QtCore.pyqtSlot(int, name='on_logy_time_stateChanged')
|
||||||
@QtCore.pyqtSlot(int, name='on_logx_freq_stateChanged')
|
@QtCore.pyqtSlot(int, name='on_logx_freq_stateChanged')
|
||||||
@ -414,14 +442,3 @@ class QPreviewDialog(QtWidgets.QDialog, Ui_ApodEdit):
|
|||||||
vb = self.time_graph.getPlotItem().getViewBox()
|
vb = self.time_graph.getPlotItem().getViewBox()
|
||||||
vb.disableAutoRange(axis=vb.YAxis)
|
vb.disableAutoRange(axis=vb.YAxis)
|
||||||
|
|
||||||
|
|
||||||
self._temp_baseline = self._temp_baseline_time if self._all_time else self._temp_baseline_freq
|
|
||||||
self._temp_fft = self._temp_fft_time if self._all_time else self._temp_fft_freq
|
|
||||||
|
|
||||||
self.freq_graph.setVisible(self._all_time)
|
|
||||||
if self._all_freq:
|
|
||||||
self.time_graph.addItem(self.pvt_line)
|
|
||||||
else:
|
|
||||||
self.freq_graph.addItem(self.pvt_line)
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@ from __future__ import annotations
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from numpy import ndarray, iscomplexobj, asarray
|
from numpy import ndarray, iscomplexobj, asarray
|
||||||
from pyqtgraph import PlotDataItem
|
|
||||||
|
|
||||||
from ..Qt import QtGui, QtCore, QtWidgets
|
from ..Qt import QtGui, QtCore, QtWidgets
|
||||||
from .._py.valueeditor import Ui_MaskDialog
|
from .._py.valueeditor import Ui_MaskDialog
|
||||||
|
from ..lib.pg_objects import PlotItem
|
||||||
|
|
||||||
|
|
||||||
class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
||||||
@ -35,12 +35,12 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
|||||||
|
|
||||||
self.tableView.setModel(self.model)
|
self.tableView.setModel(self.model)
|
||||||
self.tableView.setSelectionModel(self.selection_model)
|
self.tableView.setSelectionModel(self.selection_model)
|
||||||
self.tableView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
self.tableView.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
|
||||||
self.tableView.customContextMenuRequested.connect(self.ctx)
|
self.tableView.customContextMenuRequested.connect(self.ctx)
|
||||||
|
|
||||||
self.selection_real = PlotDataItem(x=[], y=[], symbolSize=25, symbol='x',
|
self.selection_real = PlotItem(x=[], y=[], symbolSize=25, symbol='x',
|
||||||
pen=None, symbolPen='#c9308e', symbolBrush='#c9308e')
|
pen=None, symbolPen='#c9308e', symbolBrush='#c9308e')
|
||||||
self.selection_imag = PlotDataItem(x=[], y=[], symbolSize=25, symbol='+',
|
self.selection_imag = PlotItem(x=[], y=[], symbolSize=25, symbol='+',
|
||||||
pen=None, symbolPen='#dcdcdc', symbolBrush='#dcdcdc')
|
pen=None, symbolPen='#dcdcdc', symbolBrush='#dcdcdc')
|
||||||
|
|
||||||
def __call__(self, items: dict):
|
def __call__(self, items: dict):
|
||||||
@ -133,7 +133,7 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
|||||||
def keyPressEvent(self, evt):
|
def keyPressEvent(self, evt):
|
||||||
if evt.matches(QtGui.QKeySequence.Copy):
|
if evt.matches(QtGui.QKeySequence.Copy):
|
||||||
self.copy_selection()
|
self.copy_selection()
|
||||||
elif evt.key() == QtCore.Qt.Key_Delete:
|
elif evt.key() == QtCore.Qt.Key.Key_Delete:
|
||||||
self.delete_item()
|
self.delete_item()
|
||||||
else:
|
else:
|
||||||
super().keyPressEvent(evt)
|
super().keyPressEvent(evt)
|
||||||
@ -229,7 +229,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
"""
|
"""
|
||||||
itemChanged = QtCore.pyqtSignal(int, int, str)
|
itemChanged = QtCore.pyqtSignal(int, int, str)
|
||||||
load_number = 20
|
load_number = 20
|
||||||
maskRole = QtCore.Qt.UserRole+321
|
maskRole = QtCore.Qt.ItemDataRole.UserRole+321
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
@ -240,7 +240,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
self.mask = None
|
self.mask = None
|
||||||
self.headers = ['x', 'y', '\u0394y']
|
self.headers = ['x', 'y', '\u0394y']
|
||||||
for i, hd in enumerate(self.headers):
|
for i, hd in enumerate(self.headers):
|
||||||
self.setHeaderData(i, QtCore.Qt.Horizontal, hd)
|
self.setHeaderData(i, QtCore.Qt.Orientation.Horizontal, hd)
|
||||||
|
|
||||||
def rowCount(self, *args, **kwargs) -> int:
|
def rowCount(self, *args, **kwargs) -> int:
|
||||||
return self.total_rows
|
return self.total_rows
|
||||||
@ -258,25 +258,28 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
self.mask = mask.tolist()
|
self.mask = mask.tolist()
|
||||||
|
|
||||||
self.endResetModel()
|
self.endResetModel()
|
||||||
self.dataChanged.emit(self.index(0, 0), self.index(0, 1), [QtCore.Qt.DisplayRole])
|
self.dataChanged.emit(
|
||||||
|
self.index(0, 0),
|
||||||
|
self.index(0, 1), [QtCore.Qt.ItemDataRole.DisplayRole]
|
||||||
|
)
|
||||||
|
|
||||||
def data(self, idx: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole) -> Any:
|
def data(self, idx: QtCore.QModelIndex, role=QtCore.Qt.ItemDataRole.DisplayRole) -> Any:
|
||||||
if not idx.isValid():
|
if not idx.isValid():
|
||||||
return
|
return
|
||||||
|
|
||||||
row = idx.row()
|
row = idx.row()
|
||||||
if role in [QtCore.Qt.DisplayRole, QtCore.Qt.EditRole]:
|
if role in [QtCore.Qt.ItemDataRole.DisplayRole, QtCore.Qt.ItemDataRole.EditRole]:
|
||||||
val = self._data[row][idx.column()]
|
val = self._data[row][idx.column()]
|
||||||
return self.as_string(val)
|
return self.as_string(val)
|
||||||
|
|
||||||
elif role == QtCore.Qt.BackgroundRole:
|
elif role == QtCore.Qt.ItemDataRole.BackgroundRole:
|
||||||
pal = QtGui.QGuiApplication.palette()
|
pal = QtGui.QGuiApplication.palette()
|
||||||
if not self.mask[row]:
|
if not self.mask[row]:
|
||||||
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Base)
|
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Base)
|
||||||
else:
|
else:
|
||||||
return pal.color(QtGui.QPalette.Base)
|
return pal.color(QtGui.QPalette.Base)
|
||||||
|
|
||||||
elif role == QtCore.Qt.ForegroundRole:
|
elif role == QtCore.Qt.ItemDataRole.ForegroundRole:
|
||||||
pal = QtGui.QGuiApplication.palette()
|
pal = QtGui.QGuiApplication.palette()
|
||||||
if not self.mask[row]:
|
if not self.mask[row]:
|
||||||
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Text)
|
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Text)
|
||||||
@ -289,7 +292,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|
||||||
def setData(self, idx: QtCore.QModelIndex, value: str | bool, role=QtCore.Qt.DisplayRole) -> Any:
|
def setData(self, idx: QtCore.QModelIndex, value: str | bool, role=QtCore.Qt.ItemDataRole.DisplayRole) -> Any:
|
||||||
col, row = idx.column(), idx.row()
|
col, row = idx.column(), idx.row()
|
||||||
|
|
||||||
if role == ValueModel.maskRole:
|
if role == ValueModel.maskRole:
|
||||||
@ -299,7 +302,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
if role == QtCore.Qt.EditRole:
|
if role == QtCore.Qt.ItemDataRole.EditRole:
|
||||||
if value == self.as_string(self._data[row][col]):
|
if value == self.as_string(self._data[row][col]):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -322,9 +325,9 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def headerData(self, section: int, orientation, role=QtCore.Qt.DisplayRole) -> Any:
|
def headerData(self, section: int, orientation, role=QtCore.Qt.ItemDataRole.DisplayRole) -> Any:
|
||||||
if role == QtCore.Qt.DisplayRole:
|
if role == QtCore.Qt.ItemDataRole.DisplayRole:
|
||||||
if orientation == QtCore.Qt.Horizontal:
|
if orientation == QtCore.Qt.Orientation.Horizontal:
|
||||||
return self.headers[section]
|
return self.headers[section]
|
||||||
else:
|
else:
|
||||||
return str(section+1)
|
return str(section+1)
|
||||||
@ -346,7 +349,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
self.endInsertRows()
|
self.endInsertRows()
|
||||||
|
|
||||||
def flags(self, idx: QtCore.QModelIndex) -> QtCore.Qt.ItemFlag:
|
def flags(self, idx: QtCore.QModelIndex) -> QtCore.Qt.ItemFlag:
|
||||||
return QtCore.QAbstractTableModel.flags(self, idx) | QtCore.Qt.ItemIsEditable
|
return QtCore.QAbstractTableModel.flags(self, idx) | QtCore.Qt.ItemFlag.ItemIsEditable
|
||||||
|
|
||||||
def removeRows(self, pos: int, rows: int, parent=None, *args, **kwargs) -> bool:
|
def removeRows(self, pos: int, rows: int, parent=None, *args, **kwargs) -> bool:
|
||||||
self.beginRemoveRows(parent, pos, pos+rows-1)
|
self.beginRemoveRows(parent, pos, pos+rows-1)
|
||||||
@ -382,6 +385,6 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def as_string(value) -> str:
|
def as_string(value) -> str:
|
||||||
if isinstance(value, complex):
|
if isinstance(value, complex):
|
||||||
return f'{value.real:.8g}{value.imag:+.8g}j'
|
return f'{value.real:.13g}{value.imag:+.13g}j'
|
||||||
else:
|
else:
|
||||||
return f'{value:.8g}'
|
return f'{value:.13g}'
|
||||||
|
@ -136,8 +136,8 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
max_x = max(max_x, data.x.max())
|
max_x = max(max_x, data.x.max())
|
||||||
|
|
||||||
item = QtWidgets.QListWidgetItem(name)
|
item = QtWidgets.QListWidgetItem(name)
|
||||||
item.setCheckState(QtCore.Qt.Checked)
|
item.setCheckState(QtCore.Qt.CheckState.Checked)
|
||||||
item.setData(QtCore.Qt.UserRole, key)
|
item.setData(QtCore.Qt.ItemDataRole.UserRole, key)
|
||||||
item.setForeground(mkBrush(c.rgb()))
|
item.setForeground(mkBrush(c.rgb()))
|
||||||
self.listWidget.addItem(item)
|
self.listWidget.addItem(item)
|
||||||
|
|
||||||
@ -191,10 +191,10 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
|
|
||||||
for idx in range(self.listWidget.count()):
|
for idx in range(self.listWidget.count()):
|
||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
if item.checkState() == QtCore.Qt.Unchecked:
|
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
key = item.data(QtCore.Qt.UserRole)
|
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
plot = self._plots[key]
|
plot = self._plots[key]
|
||||||
data, _ = self._dsc[key]
|
data, _ = self._dsc[key]
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
|
|
||||||
tree_item = QtWidgets.QTreeWidgetItem([item.text()])
|
tree_item = QtWidgets.QTreeWidgetItem([item.text()])
|
||||||
values = self._tg_value.get(item.data(QtCore.Qt.UserRole))
|
values = self._tg_value.get(item.data(QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
if values is not None:
|
if values is not None:
|
||||||
for name, pos in values.items():
|
for name, pos in values.items():
|
||||||
@ -223,7 +223,7 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
|
|
||||||
self.tg_tree.addTopLevelItem(tree_item)
|
self.tg_tree.addTopLevelItem(tree_item)
|
||||||
|
|
||||||
key = item.data(QtCore.Qt.UserRole)
|
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
plot = self._plots[key]
|
plot = self._plots[key]
|
||||||
data, _ = self._dsc[key]
|
data, _ = self._dsc[key]
|
||||||
|
|
||||||
@ -251,7 +251,7 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
@QtCore.pyqtSlot(QtWidgets.QListWidgetItem)
|
@QtCore.pyqtSlot(QtWidgets.QListWidgetItem)
|
||||||
def change_visibility(self, item: QtWidgets.QListWidgetItem):
|
def change_visibility(self, item: QtWidgets.QListWidgetItem):
|
||||||
is_checked = bool(item.checkState())
|
is_checked = bool(item.checkState())
|
||||||
plot = self._plots[item.data(QtCore.Qt.UserRole)]
|
plot = self._plots[item.data(QtCore.Qt.ItemDataRole.UserRole)]
|
||||||
for val in plot:
|
for val in plot:
|
||||||
val.setVisible(is_checked)
|
val.setVisible(is_checked)
|
||||||
|
|
||||||
@ -275,10 +275,10 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
self.tnmh_tree.clear()
|
self.tnmh_tree.clear()
|
||||||
for idx in range(self.listWidget.count()):
|
for idx in range(self.listWidget.count()):
|
||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
if item.checkState() == QtCore.Qt.Unchecked:
|
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
key = item.data(QtCore.Qt.UserRole)
|
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
data = self.get_fictive(key, baselines)
|
data = self.get_fictive(key, baselines)
|
||||||
|
|
||||||
@ -292,7 +292,7 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
|
|
||||||
tree_item = QtWidgets.QTreeWidgetItem([item.text()])
|
tree_item = QtWidgets.QTreeWidgetItem([item.text()])
|
||||||
values = self._fit.get(item.data(QtCore.Qt.UserRole))
|
values = self._fit.get(item.data(QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
if values is not None:
|
if values is not None:
|
||||||
child_item = QtWidgets.QTreeWidgetItem([values.parameter_string()])
|
child_item = QtWidgets.QTreeWidgetItem([values.parameter_string()])
|
||||||
@ -305,10 +305,10 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
ret_dic = {}
|
ret_dic = {}
|
||||||
for idx in range(self.listWidget.count()):
|
for idx in range(self.listWidget.count()):
|
||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
if item.checkState() == QtCore.Qt.Unchecked:
|
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
key = item.data(QtCore.Qt.UserRole)
|
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
cp = None
|
cp = None
|
||||||
if self.fictive_export_check.isChecked():
|
if self.fictive_export_check.isChecked():
|
||||||
@ -332,10 +332,10 @@ class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
|||||||
m = []
|
m = []
|
||||||
for idx in range(self.listWidget.count()):
|
for idx in range(self.listWidget.count()):
|
||||||
item = self.listWidget.item(idx)
|
item = self.listWidget.item(idx)
|
||||||
if item.checkState() == QtCore.Qt.Unchecked:
|
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
key = item.data(QtCore.Qt.UserRole)
|
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
data, _ = self._dsc[key]
|
data, _ = self._dsc[key]
|
||||||
try:
|
try:
|
||||||
tg_value = self._tg_value[key][tg_type][0]
|
tg_value = self._tg_value[key][tg_type][0]
|
||||||
|
0
src/gui_qt/editors/__init__.py
Normal file
0
src/gui_qt/editors/__init__.py
Normal file
@ -1,5 +1,6 @@
|
|||||||
# CodeEditor based on QT example, Python syntax highlighter found on Python site
|
# CodeEditor based on QT example, Python syntax highlighter found on Python site
|
||||||
|
import typing
|
||||||
|
from ast import parse
|
||||||
|
|
||||||
from ..Qt import QtGui, QtCore, QtWidgets
|
from ..Qt import QtGui, QtCore, QtWidgets
|
||||||
|
|
||||||
@ -71,7 +72,8 @@ class PythonHighlighter(QtGui.QSyntaxHighlighter):
|
|||||||
(r'\bdef\b\s*(\w+)', 1, STYLES['defclass']),
|
(r'\bdef\b\s*(\w+)', 1, STYLES['defclass']),
|
||||||
# 'class' followed by an identifier
|
# 'class' followed by an identifier
|
||||||
(r'\bclass\b\s*(\w+)', 1, STYLES['defclass']),
|
(r'\bclass\b\s*(\w+)', 1, STYLES['defclass']),
|
||||||
# @ followed by a word
|
|
||||||
|
# decorator @ followed by a word
|
||||||
(r'\s*@(\w+)\s*', 0, STYLES['property']),
|
(r'\s*@(\w+)\s*', 0, STYLES['property']),
|
||||||
|
|
||||||
# Numeric literals
|
# Numeric literals
|
||||||
@ -79,7 +81,6 @@ class PythonHighlighter(QtGui.QSyntaxHighlighter):
|
|||||||
(r'\b[+-]?0[xX][\dA-Fa-f]+[lL]?\b', 0, STYLES['numbers']),
|
(r'\b[+-]?0[xX][\dA-Fa-f]+[lL]?\b', 0, STYLES['numbers']),
|
||||||
(r'\b[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b', 0, STYLES['numbers']),
|
(r'\b[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b', 0, STYLES['numbers']),
|
||||||
|
|
||||||
|
|
||||||
# Double-quoted string, possibly containing escape sequences
|
# Double-quoted string, possibly containing escape sequences
|
||||||
(r'[rf]?"[^"\\]*(\\.[^"\\]*)*"', 0, STYLES['string']),
|
(r'[rf]?"[^"\\]*(\\.[^"\\]*)*"', 0, STYLES['string']),
|
||||||
# Single-quoted string, possibly containing escape sequences
|
# Single-quoted string, possibly containing escape sequences
|
||||||
@ -186,10 +187,10 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
|||||||
self.highlight = PythonHighlighter(self.document())
|
self.highlight = PythonHighlighter(self.document())
|
||||||
|
|
||||||
def keyPressEvent(self, evt):
|
def keyPressEvent(self, evt):
|
||||||
if evt.key() == QtCore.Qt.Key_Tab:
|
if evt.key() == QtCore.Qt.Key.Key_Tab:
|
||||||
# use spaces instead of tab
|
# use spaces instead of tab
|
||||||
self.insertPlainText(' '*4)
|
self.insertPlainText(' '*4)
|
||||||
elif evt.key() == QtCore.Qt.Key_Insert:
|
elif evt.key() == QtCore.Qt.Key.Key_Insert:
|
||||||
self.setOverwriteMode(not self.overwriteMode())
|
self.setOverwriteMode(not self.overwriteMode())
|
||||||
else:
|
else:
|
||||||
super().keyPressEvent(evt)
|
super().keyPressEvent(evt)
|
||||||
@ -224,7 +225,7 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
|||||||
|
|
||||||
def paintevent_linenumber(self, evt):
|
def paintevent_linenumber(self, evt):
|
||||||
painter = QtGui.QPainter(self.current_linenumber)
|
painter = QtGui.QPainter(self.current_linenumber)
|
||||||
painter.fillRect(evt.rect(), QtCore.Qt.lightGray)
|
painter.fillRect(evt.rect(), QtCore.Qt.GlobalColor.lightGray)
|
||||||
|
|
||||||
block = self.firstVisibleBlock()
|
block = self.firstVisibleBlock()
|
||||||
block_number = block.blockNumber()
|
block_number = block.blockNumber()
|
||||||
@ -236,9 +237,9 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
|||||||
while block.isValid() and (top <= evt.rect().bottom()):
|
while block.isValid() and (top <= evt.rect().bottom()):
|
||||||
if block.isVisible() and (bottom >= evt.rect().top()):
|
if block.isVisible() and (bottom >= evt.rect().top()):
|
||||||
number = str(block_number + 1)
|
number = str(block_number + 1)
|
||||||
painter.setPen(QtCore.Qt.black)
|
painter.setPen(QtCore.Qt.GlobalColor.black)
|
||||||
painter.drawText(0, int(top), self.current_linenumber.width() - 3, height,
|
painter.drawText(0, int(top), self.current_linenumber.width() - 3, height,
|
||||||
QtCore.Qt.AlignRight, number)
|
QtCore.Qt.AlignmentFlag.AlignRight, number)
|
||||||
|
|
||||||
block = block.next()
|
block = block.next()
|
||||||
top = bottom
|
top = bottom
|
||||||
@ -251,7 +252,7 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
|||||||
if not self.isReadOnly():
|
if not self.isReadOnly():
|
||||||
selection = QtWidgets.QTextEdit.ExtraSelection()
|
selection = QtWidgets.QTextEdit.ExtraSelection()
|
||||||
|
|
||||||
line_color = QtGui.QColor(QtCore.Qt.yellow).lighter(180)
|
line_color = QtGui.QColor(QtCore.Qt.GlobalColor.yellow).lighter(180)
|
||||||
|
|
||||||
selection.format.setBackground(line_color)
|
selection.format.setBackground(line_color)
|
||||||
selection.format.setProperty(QtGui.QTextFormat.FullWidthSelection, True)
|
selection.format.setProperty(QtGui.QTextFormat.FullWidthSelection, True)
|
||||||
@ -260,3 +261,49 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
|||||||
extra_selections.append(selection)
|
extra_selections.append(selection)
|
||||||
|
|
||||||
self.setExtraSelections(extra_selections)
|
self.setExtraSelections(extra_selections)
|
||||||
|
|
||||||
|
|
||||||
|
class EditorWidget(QtWidgets.QWidget):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
|
layout = QtWidgets.QVBoxLayout()
|
||||||
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
||||||
|
self.editor = CodeEditor(self)
|
||||||
|
layout.addWidget(self.editor)
|
||||||
|
|
||||||
|
self.error_label = QtWidgets.QLabel(self)
|
||||||
|
|
||||||
|
font = QtGui.QFont()
|
||||||
|
font.setBold(True)
|
||||||
|
font.setWeight(75)
|
||||||
|
self.error_label.setFont(font)
|
||||||
|
|
||||||
|
self.error_label.setVisible(False)
|
||||||
|
|
||||||
|
layout.addWidget(self.error_label)
|
||||||
|
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
for attr in ['appendPlainText', 'toPlainText', 'insertPlainText', 'setPlainText']:
|
||||||
|
setattr(self, attr, getattr(self.editor, attr))
|
||||||
|
|
||||||
|
self.editor.textChanged.connect(self._check_syntax)
|
||||||
|
|
||||||
|
def _check_syntax(self) -> (int, tuple[typing.Any]):
|
||||||
|
is_valid = True
|
||||||
|
|
||||||
|
# Compile into an AST and check for syntax errors.
|
||||||
|
try:
|
||||||
|
_ = parse(self.toPlainText(), filename='<string>')
|
||||||
|
|
||||||
|
except SyntaxError as e:
|
||||||
|
self.error_label.setText(f'Syntax error in line {e.lineno}: {e.args[0]}')
|
||||||
|
is_valid = False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.error_label.setText(f'Unexpected error: {e.args[0]}')
|
||||||
|
is_valid = False
|
||||||
|
|
||||||
|
self.error_label.setVisible(not is_valid)
|
30
src/gui_qt/editors/script_editor.py
Normal file
30
src/gui_qt/editors/script_editor.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from .usermodeleditor import QUsermodelEditor
|
||||||
|
from ..Qt import QtWidgets, QtCore, QtGui
|
||||||
|
|
||||||
|
|
||||||
|
class QEditor(QUsermodelEditor):
|
||||||
|
runSignal = QtCore.pyqtSignal(str)
|
||||||
|
|
||||||
|
def __init__(self, path: str | Path = None, parent=None):
|
||||||
|
super().__init__(path, parent=parent)
|
||||||
|
|
||||||
|
self.add_run_button()
|
||||||
|
|
||||||
|
def add_run_button(self):
|
||||||
|
self.disclaimer = QtWidgets.QLabel("This is work in progress and less than perfect :(")
|
||||||
|
self.disclaimer.setStyleSheet('QLabel {color: rgb(255, 0, 0); font-weight: bold; font-size: 2.5em;};')
|
||||||
|
self.centralwidget.layout().insertWidget(0, self.disclaimer)
|
||||||
|
|
||||||
|
self.run_button = QtWidgets.QPushButton("Run")
|
||||||
|
self.centralwidget.layout().addWidget(self.run_button)
|
||||||
|
|
||||||
|
self.run_button.clicked.connect(self.start_script)
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot()
|
||||||
|
def start_script(self):
|
||||||
|
self.runSignal.emit(self.edit_field.toPlainText())
|
||||||
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from ..Qt import QtWidgets, QtCore, QtGui
|
from ..Qt import QtWidgets, QtCore, QtGui
|
||||||
from ..lib.codeeditor import CodeEditor
|
from .codeeditor import EditorWidget
|
||||||
|
|
||||||
|
|
||||||
class QUsermodelEditor(QtWidgets.QMainWindow):
|
class QUsermodelEditor(QtWidgets.QMainWindow):
|
||||||
@ -26,7 +26,7 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
|||||||
layout.setContentsMargins(3, 3, 3, 3)
|
layout.setContentsMargins(3, 3, 3, 3)
|
||||||
layout.setSpacing(3)
|
layout.setSpacing(3)
|
||||||
|
|
||||||
self.edit_field = CodeEditor(self.centralwidget)
|
self.edit_field = EditorWidget(self.centralwidget)
|
||||||
font = QtGui.QFont('default')
|
font = QtGui.QFont('default')
|
||||||
font.setStyleHint(font.Monospace)
|
font.setStyleHint(font.Monospace)
|
||||||
font.setPointSize(10)
|
font.setPointSize(10)
|
||||||
@ -50,18 +50,20 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
|||||||
self.menuFile.addAction('Close', self.close, QtGui.QKeySequence.Quit)
|
self.menuFile.addAction('Close', self.close, QtGui.QKeySequence.Quit)
|
||||||
|
|
||||||
self.resize(800, 600)
|
self.resize(800, 600)
|
||||||
self.setGeometry(QtWidgets.QStyle.alignedRect(
|
self.setGeometry(
|
||||||
QtCore.Qt.LeftToRight, QtCore.Qt.AlignCenter,
|
QtWidgets.QStyle.alignedRect(
|
||||||
self.size(), QtWidgets.qApp.desktop().availableGeometry()
|
QtCore.Qt.LayoutDirection.LeftToRight,
|
||||||
))
|
QtCore.Qt.AlignmentFlag.AlignCenter,
|
||||||
|
self.size(),
|
||||||
|
QtWidgets.qApp.desktop().availableGeometry()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
|
||||||
def is_modified(self):
|
def is_modified(self):
|
||||||
return self.edit_field.document().isModified()
|
return self.edit_field.editor.document().isModified()
|
||||||
|
|
||||||
@is_modified.setter
|
def set_modified(self, val: bool):
|
||||||
def is_modified(self, val: bool):
|
self.edit_field.editor.document().setModified(val)
|
||||||
self.edit_field.document().setModified(val)
|
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def open_file(self):
|
def open_file(self):
|
||||||
@ -75,17 +77,22 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
|||||||
def read_file(self, fname: str | Path):
|
def read_file(self, fname: str | Path):
|
||||||
self.set_fname_opts(fname)
|
self.set_fname_opts(fname)
|
||||||
|
|
||||||
|
if self.fname is not None:
|
||||||
with self.fname.open('r') as f:
|
with self.fname.open('r') as f:
|
||||||
self.edit_field.setPlainText(f.read())
|
self.edit_field.setPlainText(f.read())
|
||||||
|
|
||||||
def set_fname_opts(self, fname: str | Path):
|
def set_fname_opts(self, fname: str | Path):
|
||||||
|
fname = Path(fname)
|
||||||
|
if fname.is_file():
|
||||||
self.fname = Path(fname)
|
self.fname = Path(fname)
|
||||||
self._dir = self.fname.parent
|
self._dir = self.fname.parent
|
||||||
self.setWindowTitle('Edit ' + str(fname))
|
self.setWindowTitle('Edit ' + str(fname))
|
||||||
|
elif fname.is_dir():
|
||||||
|
self._dir = fname
|
||||||
|
|
||||||
|
|
||||||
@property
|
|
||||||
def changes_saved(self) -> bool:
|
def changes_saved(self) -> bool:
|
||||||
if not self.is_modified:
|
if not self.is_modified():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
ret = QtWidgets.QMessageBox.question(self, 'Time to think',
|
ret = QtWidgets.QMessageBox.question(self, 'Time to think',
|
||||||
@ -97,9 +104,9 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
|||||||
self.save_file()
|
self.save_file()
|
||||||
|
|
||||||
if ret == QtWidgets.QMessageBox.No:
|
if ret == QtWidgets.QMessageBox.No:
|
||||||
self.is_modified = False
|
self.set_modified(False)
|
||||||
|
|
||||||
return not self.is_modified
|
return not self.is_modified()
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def save_file(self):
|
def save_file(self):
|
||||||
@ -111,9 +118,9 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
self.set_fname_opts(outfile)
|
self.set_fname_opts(outfile)
|
||||||
|
|
||||||
self.is_modified = False
|
self.set_modified(False)
|
||||||
|
|
||||||
return self.is_modified
|
return self.is_modified()
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def overwrite_file(self):
|
def overwrite_file(self):
|
||||||
@ -123,10 +130,10 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
|||||||
|
|
||||||
self.modelsChanged.emit()
|
self.modelsChanged.emit()
|
||||||
|
|
||||||
self.is_modified = False
|
self.set_modified(False)
|
||||||
|
|
||||||
def closeEvent(self, evt: QtGui.QCloseEvent):
|
def closeEvent(self, evt: QtGui.QCloseEvent):
|
||||||
if not self.changes_saved:
|
if not self.changes_saved():
|
||||||
evt.ignore()
|
evt.ignore()
|
||||||
else:
|
else:
|
||||||
super().closeEvent(evt)
|
super().closeEvent(evt)
|
@ -1,134 +1,11 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from nmreval.utils.text import convert
|
|
||||||
|
|
||||||
from ..Qt import QtCore, QtWidgets, QtGui
|
from ..Qt import QtCore, QtWidgets, QtGui
|
||||||
from .._py.fitmodelwidget import Ui_FitParameter
|
|
||||||
from .._py.save_fitmodel_dialog import Ui_SaveDialog
|
from .._py.save_fitmodel_dialog import Ui_SaveDialog
|
||||||
from ..lib.iconloading import get_icon
|
from ..lib.iconloading import get_icon
|
||||||
from ..lib.tables import TableWidget
|
from ..lib.tables import TableWidget
|
||||||
|
|
||||||
|
|
||||||
class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
|
|
||||||
value_requested = QtCore.pyqtSignal(object)
|
|
||||||
value_changed = QtCore.pyqtSignal(str)
|
|
||||||
state_changed = QtCore.pyqtSignal()
|
|
||||||
replace_single_value = QtCore.pyqtSignal(object)
|
|
||||||
|
|
||||||
def __init__(self, label: str = 'Fitparameter', parent=None, fixed: bool = False):
|
|
||||||
super().__init__(parent)
|
|
||||||
self.setupUi(self)
|
|
||||||
|
|
||||||
self.name = label
|
|
||||||
|
|
||||||
self.parametername.setText(convert(label) + ' ')
|
|
||||||
|
|
||||||
self.parameter_line.setText('1')
|
|
||||||
self.parameter_line.setMaximumWidth(160)
|
|
||||||
self.lineEdit.setMaximumWidth(100)
|
|
||||||
self.lineEdit_2.setMaximumWidth(100)
|
|
||||||
|
|
||||||
self.label_3.setText(f'< {convert(label)} <')
|
|
||||||
|
|
||||||
self.checkBox.stateChanged.connect(self.enableBounds)
|
|
||||||
self.global_checkbox.stateChanged.connect(lambda: self.state_changed.emit())
|
|
||||||
self.parameter_line.editingFinished.connect(self.update_parameter)
|
|
||||||
self.parameter_line.values_requested.connect(lambda: self.value_requested.emit(self))
|
|
||||||
self.parameter_line.replace_single_values.connect(lambda: self.replace_single_value.emit(None))
|
|
||||||
self.parameter_line.editingFinished.connect(lambda: self.value_changed.emit(self.parameter_line.text()))
|
|
||||||
self.fixed_check.toggled.connect(self.set_fixed)
|
|
||||||
|
|
||||||
if fixed:
|
|
||||||
self.fixed_check.hide()
|
|
||||||
|
|
||||||
self.parameter_pos = None
|
|
||||||
self.func_idx = None
|
|
||||||
|
|
||||||
self._linetext = '1'
|
|
||||||
|
|
||||||
self.menu = QtWidgets.QMenu(self)
|
|
||||||
|
|
||||||
def set_parameter_string(self, p: str):
|
|
||||||
self.parameter_line.setText(p)
|
|
||||||
self.parameter_line.setToolTip(p)
|
|
||||||
|
|
||||||
def set_bounds(self, lb: float, ub: float, cbox: bool = True):
|
|
||||||
self.checkBox.setCheckState(QtCore.Qt.Checked if cbox else QtCore.Qt.Unchecked)
|
|
||||||
for val, bds_line in [(lb, self.lineEdit), (ub, self.lineEdit_2)]:
|
|
||||||
if val is not None:
|
|
||||||
bds_line.setText(str(val))
|
|
||||||
else:
|
|
||||||
bds_line.setText('')
|
|
||||||
|
|
||||||
def enableBounds(self, value: int):
|
|
||||||
self.lineEdit.setEnabled(value == 2)
|
|
||||||
self.lineEdit_2.setEnabled(value == 2)
|
|
||||||
|
|
||||||
def set_parameter(self, p: float | None, bds: tuple[float, float, bool] = None,
|
|
||||||
fixed: bool = None, glob: bool = None):
|
|
||||||
ptext = f'{p:.4g}'
|
|
||||||
|
|
||||||
self.set_parameter_string(ptext)
|
|
||||||
|
|
||||||
if bds is not None:
|
|
||||||
self.set_bounds(*bds)
|
|
||||||
|
|
||||||
if fixed is not None:
|
|
||||||
self.fixed_check.setCheckState(QtCore.Qt.Unchecked if fixed else QtCore.Qt.Checked)
|
|
||||||
|
|
||||||
if glob is not None:
|
|
||||||
self.global_checkbox.setCheckState(QtCore.Qt.Checked if glob else QtCore.Qt.Unchecked)
|
|
||||||
|
|
||||||
def get_parameter(self):
|
|
||||||
try:
|
|
||||||
p = float(self.parameter_line.text().replace(',', '.'))
|
|
||||||
except ValueError:
|
|
||||||
p = self.parameter_line.text().replace(',', '.')
|
|
||||||
|
|
||||||
if self.checkBox.isChecked():
|
|
||||||
lb_text = self.lineEdit.text()
|
|
||||||
lb = None
|
|
||||||
if lb_text:
|
|
||||||
try:
|
|
||||||
lb = float(lb_text.replace(',', '.'))
|
|
||||||
except ValueError:
|
|
||||||
lb = lb_text
|
|
||||||
|
|
||||||
ub_text = self.lineEdit_2.text()
|
|
||||||
rb = None
|
|
||||||
if ub_text:
|
|
||||||
try:
|
|
||||||
rb = float(ub_text.replace(',', '.'))
|
|
||||||
except ValueError:
|
|
||||||
rb = ub_text
|
|
||||||
else:
|
|
||||||
lb = rb = None
|
|
||||||
|
|
||||||
bounds = (lb, rb)
|
|
||||||
|
|
||||||
return p, bounds, not self.fixed_check.isChecked(), self.global_checkbox.isChecked()
|
|
||||||
|
|
||||||
@QtCore.pyqtSlot(bool)
|
|
||||||
def set_fixed(self, state: bool):
|
|
||||||
# self.global_checkbox.setVisible(not state)
|
|
||||||
self.frame.setVisible(not state)
|
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
|
||||||
def update_parameter(self):
|
|
||||||
new_value = self.parameter_line.text()
|
|
||||||
if not new_value:
|
|
||||||
self.parameter_line.setText('1')
|
|
||||||
|
|
||||||
try:
|
|
||||||
float(new_value)
|
|
||||||
is_text = False
|
|
||||||
except ValueError:
|
|
||||||
is_text = True
|
|
||||||
self.global_checkbox.setCheckState(False)
|
|
||||||
|
|
||||||
self.set_fixed(is_text)
|
|
||||||
|
|
||||||
|
|
||||||
class QSaveModelDialog(QtWidgets.QDialog, Ui_SaveDialog):
|
class QSaveModelDialog(QtWidgets.QDialog, Ui_SaveDialog):
|
||||||
def __init__(self, types=None, parent=None):
|
def __init__(self, types=None, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
@ -168,30 +45,37 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
|||||||
treeChanged = QtCore.pyqtSignal()
|
treeChanged = QtCore.pyqtSignal()
|
||||||
itemRemoved = QtCore.pyqtSignal(int)
|
itemRemoved = QtCore.pyqtSignal(int)
|
||||||
|
|
||||||
counterRole = QtCore.Qt.UserRole + 1
|
counterRole = QtCore.Qt.ItemDataRole.UserRole + 1
|
||||||
operatorRole = QtCore.Qt.UserRole + 2
|
operatorRole = QtCore.Qt.ItemDataRole.UserRole + 2
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
self.setHeaderHidden(True)
|
self.setHeaderHidden(True)
|
||||||
self.setDragEnabled(True)
|
self.setDragEnabled(True)
|
||||||
self.setDragDropMode(QtWidgets.QTreeWidget.InternalMove)
|
self.setDragDropMode(QtWidgets.QTreeWidget.InternalMove)
|
||||||
self.setDefaultDropAction(QtCore.Qt.MoveAction)
|
self.setDefaultDropAction(QtCore.Qt.DropAction.MoveAction)
|
||||||
|
|
||||||
self.itemSelectionChanged.connect(lambda: self.treeChanged.emit())
|
self.itemSelectionChanged.connect(lambda: self.treeChanged.emit())
|
||||||
|
|
||||||
def keyPressEvent(self, evt):
|
def keyPressEvent(self, evt):
|
||||||
operators = [QtCore.Qt.Key_Plus, QtCore.Qt.Key_Asterisk,
|
operators = [
|
||||||
QtCore.Qt.Key_Minus, QtCore.Qt.Key_Slash]
|
QtCore.Qt.Key.Key_Plus,
|
||||||
|
QtCore.Qt.Key.Key_Asterisk,
|
||||||
|
QtCore.Qt.Key.Key_Minus,
|
||||||
|
QtCore.Qt.Key.Key_Slash
|
||||||
|
]
|
||||||
|
|
||||||
if evt.key() == QtCore.Qt.Key_Delete:
|
if evt.key() == QtCore.Qt.Key.Key_Delete:
|
||||||
for item in self.selectedItems():
|
for item in self.selectedItems():
|
||||||
self.remove_function(item)
|
self.remove_function(item)
|
||||||
|
|
||||||
elif evt.key() == QtCore.Qt.Key_Space:
|
elif evt.key() == QtCore.Qt.Key.Key_Space:
|
||||||
for item in self.treeWidget.selectedItems():
|
for item in self.selectedItems():
|
||||||
item.setCheckState(0, QtCore.Qt.Checked) if item.checkState(
|
cs = item.checkState(0)
|
||||||
0) == QtCore.Qt.Unchecked else item.setCheckState(0, QtCore.Qt.Unchecked)
|
if cs == QtCore.Qt.CheckState.Unchecked:
|
||||||
|
item.setCheckState(0, QtCore.Qt.CheckState.Checked)
|
||||||
|
else:
|
||||||
|
item.setCheckState(0, QtCore.Qt.CheckState.Unchecked)
|
||||||
|
|
||||||
elif evt.key() in operators:
|
elif evt.key() in operators:
|
||||||
idx = operators.index(evt.key())
|
idx = operators.index(evt.key())
|
||||||
@ -242,7 +126,7 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
|||||||
color = QtGui.QColor(color)
|
color = QtGui.QColor(color)
|
||||||
|
|
||||||
it = QtWidgets.QTreeWidgetItem()
|
it = QtWidgets.QTreeWidgetItem()
|
||||||
it.setData(0, QtCore.Qt.UserRole, idx)
|
it.setData(0, QtCore.Qt.ItemDataRole.UserRole, idx)
|
||||||
it.setData(0, self.counterRole, cnt)
|
it.setData(0, self.counterRole, cnt)
|
||||||
it.setData(0, self.operatorRole, op)
|
it.setData(0, self.operatorRole, op)
|
||||||
it.setText(0, name)
|
it.setText(0, name)
|
||||||
@ -253,7 +137,7 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
|||||||
it.setForeground(0, QtGui.QBrush(color))
|
it.setForeground(0, QtGui.QBrush(color))
|
||||||
|
|
||||||
it.setIcon(0, get_icon(self.icons[op]))
|
it.setIcon(0, get_icon(self.icons[op]))
|
||||||
it.setCheckState(0, QtCore.Qt.Checked if active else QtCore.Qt.Unchecked)
|
it.setCheckState(0, QtCore.Qt.CheckState.Checked if active else QtCore.Qt.CheckState.Unchecked)
|
||||||
|
|
||||||
if parent is None:
|
if parent is None:
|
||||||
self.addTopLevelItem(it)
|
self.addTopLevelItem(it)
|
||||||
@ -273,7 +157,7 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
|||||||
def get_selected(self):
|
def get_selected(self):
|
||||||
try:
|
try:
|
||||||
it = self.selectedItems()[0]
|
it = self.selectedItems()[0]
|
||||||
function_nr = it.data(0, QtCore.Qt.UserRole)
|
function_nr = it.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
idx = it.data(0, self.counterRole)
|
idx = it.data(0, self.counterRole)
|
||||||
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
@ -296,10 +180,10 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
|||||||
it = parent.child(i)
|
it = parent.child(i)
|
||||||
|
|
||||||
child = {
|
child = {
|
||||||
'idx': it.data(0, QtCore.Qt.UserRole),
|
'idx': it.data(0, QtCore.Qt.ItemDataRole.UserRole),
|
||||||
'op': it.data(0, self.operatorRole),
|
'op': it.data(0, self.operatorRole),
|
||||||
'pos': pos,
|
'pos': pos,
|
||||||
'active': (it.checkState(0) == QtCore.Qt.Checked),
|
'active': (it.checkState(0) == QtCore.Qt.CheckState.Checked),
|
||||||
'children': []
|
'children': []
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,8 +251,8 @@ class FitTableWidget(TableWidget):
|
|||||||
|
|
||||||
for (sid, name) in set_ids:
|
for (sid, name) in set_ids:
|
||||||
item = QtWidgets.QTableWidgetItem(name)
|
item = QtWidgets.QTableWidgetItem(name)
|
||||||
item.setCheckState(QtCore.Qt.Checked)
|
item.setCheckState(QtCore.Qt.CheckState.Checked)
|
||||||
item.setData(QtCore.Qt.UserRole+1, sid)
|
item.setData(QtCore.Qt.ItemDataRole.UserRole+1, sid)
|
||||||
row = self.rowCount()
|
row = self.rowCount()
|
||||||
self.setRowCount(row+1)
|
self.setRowCount(row+1)
|
||||||
self.setItem(row, 0, item)
|
self.setItem(row, 0, item)
|
||||||
@ -386,15 +270,15 @@ class FitTableWidget(TableWidget):
|
|||||||
|
|
||||||
for i in range(self.rowCount()):
|
for i in range(self.rowCount()):
|
||||||
item = self.item(i, 0)
|
item = self.item(i, 0)
|
||||||
if item.checkState() == QtCore.Qt.Checked:
|
if item.checkState() == QtCore.Qt.CheckState.Checked:
|
||||||
mod = self.cellWidget(i, 1).currentData()
|
mod = self.cellWidget(i, 1).currentData()
|
||||||
if mod is None:
|
if mod is None:
|
||||||
mod = default
|
mod = default
|
||||||
|
|
||||||
if include_name:
|
if include_name:
|
||||||
arg = (item.data(QtCore.Qt.UserRole+1), item.text())
|
arg = (item.data(QtCore.Qt.ItemDataRole.UserRole+1), item.text())
|
||||||
else:
|
else:
|
||||||
arg = item.data(QtCore.Qt.UserRole+1)
|
arg = item.data(QtCore.Qt.ItemDataRole.UserRole+1)
|
||||||
|
|
||||||
if mod not in data:
|
if mod not in data:
|
||||||
data[mod] = []
|
data[mod] = []
|
||||||
@ -407,8 +291,8 @@ class FitTableWidget(TableWidget):
|
|||||||
for i in range(self.rowCount()):
|
for i in range(self.rowCount()):
|
||||||
item = self.item(i, 0)
|
item = self.item(i, 0)
|
||||||
if include_name:
|
if include_name:
|
||||||
ret_val.append((item.data(QtCore.Qt.UserRole+1), item.text()))
|
ret_val.append((item.data(QtCore.Qt.ItemDataRole.UserRole+1), item.text()))
|
||||||
else:
|
else:
|
||||||
ret_val.append(item.data(QtCore.Qt.UserRole+1))
|
ret_val.append(item.data(QtCore.Qt.ItemDataRole.UserRole+1))
|
||||||
|
|
||||||
return ret_val
|
return ret_val
|
||||||
|
@ -1,25 +1,24 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from nmreval.fit.parameter import Parameter
|
from nmreval.fit.parameter import Parameter
|
||||||
from nmreval.utils.text import convert
|
from nmreval.utils.text import convert
|
||||||
|
|
||||||
from ..Qt import QtWidgets, QtCore, QtGui
|
from ..Qt import QtWidgets, QtCore, QtGui
|
||||||
from .._py.fitfuncwidget import Ui_FormFit
|
from .._py.fitfuncwidget import Ui_FormFit
|
||||||
|
from .._py.fitmodelwidget import Ui_FitParameter
|
||||||
from ..lib.forms import SelectionWidget
|
from ..lib.forms import SelectionWidget
|
||||||
from .fit_forms import FitModelWidget
|
|
||||||
|
|
||||||
|
|
||||||
class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||||
value_requested = QtCore.pyqtSignal(int)
|
value_requested = QtCore.pyqtSignal(int)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, func_id: int, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
self.func = None
|
self.func = None
|
||||||
self.func_idx = None
|
self.func_idx = None
|
||||||
|
self.func_id = func_id
|
||||||
self.max_width = QtCore.QSize(0, 0)
|
self.max_width = QtCore.QSize(0, 0)
|
||||||
self.global_parameter = []
|
self.global_parameter = []
|
||||||
self.data_parameter = []
|
self.data_parameter = []
|
||||||
@ -30,16 +29,15 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
|||||||
self.scrollwidget2.setLayout(QtWidgets.QVBoxLayout())
|
self.scrollwidget2.setLayout(QtWidgets.QVBoxLayout())
|
||||||
|
|
||||||
def eventFilter(self, src: QtCore.QObject, evt: QtCore.QEvent):
|
def eventFilter(self, src: QtCore.QObject, evt: QtCore.QEvent):
|
||||||
|
modifiers = QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier
|
||||||
if isinstance(evt, QtGui.QKeyEvent):
|
if isinstance(evt, QtGui.QKeyEvent):
|
||||||
if (evt.key() == QtCore.Qt.Key_Right) and \
|
if (evt.key() == QtCore.Qt.Key.Key_Right) and (evt.modifiers() == modifiers):
|
||||||
(evt.modifiers() == QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier):
|
|
||||||
self.change_single_parameter(src.value, sender=src)
|
self.change_single_parameter(src.value, sender=src)
|
||||||
self.select_next_preview(1)
|
self.select_next_preview(1)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
elif (evt.key() == QtCore.Qt.Key_Left) and \
|
elif (evt.key() == QtCore.Qt.Key.Key_Left) and (evt.modifiers() == modifiers):
|
||||||
(evt.modifiers() == QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier):
|
|
||||||
self.change_single_parameter(src.value, sender=src)
|
self.change_single_parameter(src.value, sender=src)
|
||||||
self.select_next_preview(-1)
|
self.select_next_preview(-1)
|
||||||
|
|
||||||
@ -65,7 +63,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
|||||||
self.glob_values = [1] * len(func.params)
|
self.glob_values = [1] * len(func.params)
|
||||||
|
|
||||||
for k, v in enumerate(func.params):
|
for k, v in enumerate(func.params):
|
||||||
widgt = FitModelWidget(label=v, parent=self.scrollwidget)
|
widgt = ParameterGlobalWidget(name=v, parent=self.scrollwidget)
|
||||||
widgt.parameter_pos = k
|
widgt.parameter_pos = k
|
||||||
widgt.func_idx = idx
|
widgt.func_idx = idx
|
||||||
try:
|
try:
|
||||||
@ -95,7 +93,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
|||||||
for w1, w2 in zip(self.global_parameter, self.data_parameter):
|
for w1, w2 in zip(self.global_parameter, self.data_parameter):
|
||||||
w1.parametername.setFixedSize(self.max_width)
|
w1.parametername.setFixedSize(self.max_width)
|
||||||
w1.checkBox.setFixedSize(self.max_width)
|
w1.checkBox.setFixedSize(self.max_width)
|
||||||
w2.label.setFixedSize(self.max_width)
|
w2.parametername.setFixedSize(self.max_width)
|
||||||
|
|
||||||
if hasattr(func, 'choices') and func.choices is not None:
|
if hasattr(func, 'choices') and func.choices is not None:
|
||||||
cbox = func.choices
|
cbox = func.choices
|
||||||
@ -175,7 +173,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
|||||||
# disable single parameter if it is set global, enable if global is unset
|
# disable single parameter if it is set global, enable if global is unset
|
||||||
widget = self.sender()
|
widget = self.sender()
|
||||||
idx = self.global_parameter.index(widget)
|
idx = self.global_parameter.index(widget)
|
||||||
enable = (widget.global_checkbox.checkState() == QtCore.Qt.Unchecked)
|
enable = (widget.global_checkbox.checkState() == QtCore.Qt.CheckState.Unchecked)
|
||||||
self.data_parameter[idx].setEnabled(enable)
|
self.data_parameter[idx].setEnabled(enable)
|
||||||
|
|
||||||
def select_next_preview(self, direction):
|
def select_next_preview(self, direction):
|
||||||
@ -215,7 +213,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
|||||||
param_general = []
|
param_general = []
|
||||||
|
|
||||||
for g in self.global_parameter:
|
for g in self.global_parameter:
|
||||||
if isinstance(g, FitModelWidget):
|
if isinstance(g, ParameterGlobalWidget):
|
||||||
p_i, bds_i, fixed_i, global_i = g.get_parameter()
|
p_i, bds_i, fixed_i, global_i = g.get_parameter()
|
||||||
parameter_i = Parameter(name=g.name, value=p_i, lb=bds_i[0], ub=bds_i[1], var=fixed_i)
|
parameter_i = Parameter(name=g.name, value=p_i, lb=bds_i[0], ub=bds_i[1], var=fixed_i)
|
||||||
param_general.append(parameter_i)
|
param_general.append(parameter_i)
|
||||||
@ -236,7 +234,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
|||||||
p = []
|
p = []
|
||||||
|
|
||||||
for i, (p_i, g) in enumerate(zip(parameter, self.global_parameter)):
|
for i, (p_i, g) in enumerate(zip(parameter, self.global_parameter)):
|
||||||
if isinstance(g, FitModelWidget):
|
if isinstance(g, ParameterGlobalWidget):
|
||||||
if (p_i is None) or is_global[i]:
|
if (p_i is None) or is_global[i]:
|
||||||
# set has no oen value
|
# set has no oen value
|
||||||
p.append(param_general[i].copy())
|
p.append(param_general[i].copy())
|
||||||
@ -303,9 +301,11 @@ class ParameterSingleWidget(QtWidgets.QWidget):
|
|||||||
self._init_ui()
|
self._init_ui()
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.label.setText(convert(name))
|
self.parametername.setText(convert(name))
|
||||||
self.label.setToolTip('If this is bold then this parameter is only for this data. '
|
self.parametername.setToolTip(
|
||||||
'Otherwise, the general parameter is used and displayed')
|
'If this is bold then this parameter is only for this data. '
|
||||||
|
'Otherwise, the general parameter is used and displayed'
|
||||||
|
)
|
||||||
|
|
||||||
# self.value_line.setValidator(QtGui.QDoubleValidator())
|
# self.value_line.setValidator(QtGui.QDoubleValidator())
|
||||||
self.value_line.textChanged.connect(lambda: self.valueChanged.emit(self.value) if self.value is not None else 0)
|
self.value_line.textChanged.connect(lambda: self.valueChanged.emit(self.value) if self.value is not None else 0)
|
||||||
@ -316,8 +316,8 @@ class ParameterSingleWidget(QtWidgets.QWidget):
|
|||||||
layout.setContentsMargins(2, 2, 2, 2)
|
layout.setContentsMargins(2, 2, 2, 2)
|
||||||
layout.setSpacing(2)
|
layout.setSpacing(2)
|
||||||
|
|
||||||
self.label = QtWidgets.QLabel(self)
|
self.parametername = QtWidgets.QLabel(self)
|
||||||
layout.addWidget(self.label)
|
layout.addWidget(self.parametername)
|
||||||
|
|
||||||
layout.addSpacerItem(QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum))
|
layout.addSpacerItem(QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum))
|
||||||
|
|
||||||
@ -343,9 +343,137 @@ class ParameterSingleWidget(QtWidgets.QWidget):
|
|||||||
def value(self, val):
|
def value(self, val):
|
||||||
# self.value_line.setText(f'{float(val):.5g}')
|
# self.value_line.setText(f'{float(val):.5g}')
|
||||||
self.value_line.setText(f'{val}')
|
self.value_line.setText(f'{val}')
|
||||||
|
self.value_line.setCursorPosition(0)
|
||||||
|
|
||||||
def show_as_local_parameter(self, is_local: bool):
|
def show_as_local_parameter(self, is_local: bool):
|
||||||
if is_local:
|
if is_local:
|
||||||
self.label.setStyleSheet('font-weight: bold;')
|
self.parametername.setStyleSheet('font-weight: bold;')
|
||||||
else:
|
else:
|
||||||
self.label.setStyleSheet('')
|
self.parametername.setStyleSheet('')
|
||||||
|
|
||||||
|
|
||||||
|
class ParameterGlobalWidget(QtWidgets.QWidget, Ui_FitParameter):
|
||||||
|
"""
|
||||||
|
Widget to show a global parameter
|
||||||
|
"""
|
||||||
|
|
||||||
|
value_requested = QtCore.pyqtSignal(object)
|
||||||
|
value_changed = QtCore.pyqtSignal(str)
|
||||||
|
state_changed = QtCore.pyqtSignal()
|
||||||
|
replace_single_value = QtCore.pyqtSignal(object)
|
||||||
|
|
||||||
|
def __init__(self, name: str = 'Fitparameter', parent=None, fixed: bool = False):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setupUi(self)
|
||||||
|
|
||||||
|
self.name = name
|
||||||
|
self.reset_button.setVisible(False)
|
||||||
|
|
||||||
|
self.parametername.setText(convert(name) + ' ')
|
||||||
|
|
||||||
|
self.parameter_line.setText('1')
|
||||||
|
self.parameter_line.setMaximumWidth(160)
|
||||||
|
self.lineEdit.setMaximumWidth(100)
|
||||||
|
self.lineEdit_2.setMaximumWidth(100)
|
||||||
|
|
||||||
|
self.label_3.setText(f'< {convert(name)} <')
|
||||||
|
|
||||||
|
self.checkBox.stateChanged.connect(self.enableBounds)
|
||||||
|
self.global_checkbox.stateChanged.connect(lambda: self.state_changed.emit())
|
||||||
|
self.parameter_line.editingFinished.connect(self.update_parameter)
|
||||||
|
self.parameter_line.values_requested.connect(lambda: self.value_requested.emit(self))
|
||||||
|
self.parameter_line.replace_single_values.connect(lambda: self.replace_single_value.emit(None))
|
||||||
|
self.parameter_line.editingFinished.connect(lambda: self.value_changed.emit(self.parameter_line.text()))
|
||||||
|
self.fixed_check.toggled.connect(self.set_fixed)
|
||||||
|
|
||||||
|
if fixed:
|
||||||
|
self.fixed_check.hide()
|
||||||
|
|
||||||
|
self.reset_button.setVisible(False)
|
||||||
|
|
||||||
|
self.parameter_pos = None
|
||||||
|
self.func_idx = None
|
||||||
|
|
||||||
|
self._linetext = '1'
|
||||||
|
|
||||||
|
self.menu = QtWidgets.QMenu(self)
|
||||||
|
|
||||||
|
def set_parameter_string(self, p: str):
|
||||||
|
self.parameter_line.setText(p)
|
||||||
|
self.parameter_line.setToolTip(p)
|
||||||
|
|
||||||
|
def set_bounds(self, lb: float, ub: float, cbox: bool = True):
|
||||||
|
self.checkBox.setCheckState(QtCore.Qt.CheckState.Checked if cbox else QtCore.Qt.CheckState.Unchecked)
|
||||||
|
for val, bds_line in [(lb, self.lineEdit), (ub, self.lineEdit_2)]:
|
||||||
|
if val is not None:
|
||||||
|
bds_line.setText(str(val))
|
||||||
|
else:
|
||||||
|
bds_line.setText('')
|
||||||
|
|
||||||
|
def enableBounds(self, value: int):
|
||||||
|
self.lineEdit.setEnabled(value == 2)
|
||||||
|
self.lineEdit_2.setEnabled(value == 2)
|
||||||
|
|
||||||
|
def set_parameter(self, p: float | None, bds: tuple[float, float, bool] = None,
|
||||||
|
fixed: bool = None, glob: bool = None):
|
||||||
|
ptext = f'{p:.4g}'
|
||||||
|
|
||||||
|
self.set_parameter_string(ptext)
|
||||||
|
|
||||||
|
if bds is not None:
|
||||||
|
self.set_bounds(*bds)
|
||||||
|
|
||||||
|
if fixed is not None:
|
||||||
|
self.fixed_check.setCheckState(QtCore.Qt.CheckState.Unchecked if fixed else QtCore.Qt.CheckState.Checked)
|
||||||
|
|
||||||
|
if glob is not None:
|
||||||
|
self.global_checkbox.setCheckState(QtCore.Qt.CheckState.Checked if glob else QtCore.Qt.CheckState.Unchecked)
|
||||||
|
|
||||||
|
def get_parameter(self):
|
||||||
|
try:
|
||||||
|
p = float(self.parameter_line.text().replace(',', '.'))
|
||||||
|
except ValueError:
|
||||||
|
p = self.parameter_line.text().replace(',', '.')
|
||||||
|
|
||||||
|
if self.checkBox.isChecked():
|
||||||
|
lb_text = self.lineEdit.text()
|
||||||
|
lb = None
|
||||||
|
if lb_text:
|
||||||
|
try:
|
||||||
|
lb = float(lb_text.replace(',', '.'))
|
||||||
|
except ValueError:
|
||||||
|
lb = lb_text
|
||||||
|
|
||||||
|
ub_text = self.lineEdit_2.text()
|
||||||
|
rb = None
|
||||||
|
if ub_text:
|
||||||
|
try:
|
||||||
|
rb = float(ub_text.replace(',', '.'))
|
||||||
|
except ValueError:
|
||||||
|
rb = ub_text
|
||||||
|
else:
|
||||||
|
lb = rb = None
|
||||||
|
|
||||||
|
bounds = (lb, rb)
|
||||||
|
|
||||||
|
return p, bounds, not self.fixed_check.isChecked(), self.global_checkbox.isChecked()
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(bool)
|
||||||
|
def set_fixed(self, state: bool):
|
||||||
|
# self.global_checkbox.setVisible(not state)
|
||||||
|
self.frame.setVisible(not state)
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot()
|
||||||
|
def update_parameter(self):
|
||||||
|
new_value = self.parameter_line.text()
|
||||||
|
if not new_value:
|
||||||
|
self.parameter_line.setText('1')
|
||||||
|
|
||||||
|
try:
|
||||||
|
float(new_value)
|
||||||
|
is_text = False
|
||||||
|
except ValueError:
|
||||||
|
is_text = True
|
||||||
|
self.global_checkbox.setCheckState(False)
|
||||||
|
|
||||||
|
self.set_fixed(is_text or self.fixed_check.isChecked())
|
||||||
|
99
src/gui_qt/fit/fit_toolbar.py
Normal file
99
src/gui_qt/fit/fit_toolbar.py
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
from ..Qt import QtWidgets, QtGui, QtCore
|
||||||
|
from ..lib.iconloading import get_icon
|
||||||
|
from ..lib.pg_objects import RegionItem
|
||||||
|
|
||||||
|
|
||||||
|
class FitToolbar(QtWidgets.QToolBar):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
fitaction: QtWidgets.QAction,
|
||||||
|
limit_menu: QtWidgets.QMenu,
|
||||||
|
parent=None,
|
||||||
|
):
|
||||||
|
super().__init__('Fit', parent=parent)
|
||||||
|
|
||||||
|
self.fit_action = fitaction
|
||||||
|
self.region = RegionItem()
|
||||||
|
self.addAction(fitaction)
|
||||||
|
|
||||||
|
self.fitlim_button = QtWidgets.QToolButton(self)
|
||||||
|
self.fitlim_button.setMenu(limit_menu)
|
||||||
|
self.fitlim_button.setPopupMode(self.fitlim_button.InstantPopup)
|
||||||
|
self.fitlim_button.setIcon(get_icon('fit_region'))
|
||||||
|
self.addWidget(self.fitlim_button)
|
||||||
|
|
||||||
|
self.label = QtWidgets.QLabel(self)
|
||||||
|
self.label.setText('L: ')
|
||||||
|
self.addWidget(self.label)
|
||||||
|
self.label.setEnabled(False)
|
||||||
|
|
||||||
|
self.lineedit = QtWidgets.QLineEdit(self)
|
||||||
|
self.lineedit.setValidator(QtGui.QDoubleValidator())
|
||||||
|
self.lineedit.setMaximumWidth(92)
|
||||||
|
self.addWidget(self.lineedit)
|
||||||
|
self.lineedit.setEnabled(False)
|
||||||
|
|
||||||
|
self.label2 = QtWidgets.QLabel(self)
|
||||||
|
self.label2.setText(' R: ')
|
||||||
|
self.addWidget(self.label2)
|
||||||
|
self.label2.setEnabled(False)
|
||||||
|
|
||||||
|
self.lineedit2 = QtWidgets.QLineEdit(self)
|
||||||
|
self.lineedit2.setValidator(QtGui.QDoubleValidator())
|
||||||
|
self.addWidget(self.lineedit2)
|
||||||
|
self.lineedit2.setMaximumWidth(92)
|
||||||
|
self.lineedit2.setEnabled(False)
|
||||||
|
|
||||||
|
self.limit_group = QtWidgets.QActionGroup(self)
|
||||||
|
for ac in limit_menu.actions():
|
||||||
|
self.limit_group.addAction(ac)
|
||||||
|
|
||||||
|
self.limit_group.triggered.connect(self.change_limit_type)
|
||||||
|
|
||||||
|
self.region.sigRegionChanged.connect(self.change_labels)
|
||||||
|
self.change_labels()
|
||||||
|
|
||||||
|
self.lineedit.textChanged.connect(self.move_region)
|
||||||
|
self.lineedit2.textChanged.connect(self.move_region)
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(QtWidgets.QAction)
|
||||||
|
def change_limit_type(self, action: QtWidgets.QAction):
|
||||||
|
is_custom = (action.text() in ['Custom', 'Exclude region'])
|
||||||
|
print(is_custom)
|
||||||
|
|
||||||
|
for w in [self.label, self.label2, self.lineedit, self.lineedit2]:
|
||||||
|
w.setEnabled(is_custom)
|
||||||
|
|
||||||
|
def change_labels(self):
|
||||||
|
r = self.region.getRegion()
|
||||||
|
self.lineedit.blockSignals(True)
|
||||||
|
self.lineedit.setText(f'{r[0]:.4g}')
|
||||||
|
self.lineedit.blockSignals(False)
|
||||||
|
|
||||||
|
self.lineedit2.blockSignals(True)
|
||||||
|
self.lineedit2.setText(f'{r[1]:.4g}')
|
||||||
|
self.lineedit2.blockSignals(False)
|
||||||
|
|
||||||
|
def move_region(self):
|
||||||
|
try:
|
||||||
|
r_min = float(self.lineedit.text())
|
||||||
|
except ValueError:
|
||||||
|
r_min = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
r_max = float(self.lineedit2.text())
|
||||||
|
except ValueError:
|
||||||
|
r_max = None
|
||||||
|
|
||||||
|
if r_min is not None and r_max is not None:
|
||||||
|
self.region.setRegion((r_min, r_max), use_log=True)
|
||||||
|
|
||||||
|
def get_limit(self):
|
||||||
|
action_text = self.limit_group.checkedAction().text()
|
||||||
|
|
||||||
|
return {
|
||||||
|
'None': 'none',
|
||||||
|
'Visible x range': 'x',
|
||||||
|
'Custom': ('in', self.region.getRegion()),
|
||||||
|
'Exclude region': ('out', self.region.getRegion()),
|
||||||
|
}[action_text]
|
@ -6,6 +6,7 @@ from nmreval.configs import config_paths
|
|||||||
from nmreval import models
|
from nmreval import models
|
||||||
from nmreval.lib.importer import find_models
|
from nmreval.lib.importer import find_models
|
||||||
from nmreval.lib.colors import BaseColor, Tab10
|
from nmreval.lib.colors import BaseColor, Tab10
|
||||||
|
from nmreval.lib.logger import logger
|
||||||
from nmreval.utils.text import convert
|
from nmreval.utils.text import convert
|
||||||
|
|
||||||
from ..lib.iconloading import get_icon
|
from ..lib.iconloading import get_icon
|
||||||
@ -50,8 +51,17 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
user_defined = []
|
user_defined = []
|
||||||
try:
|
try:
|
||||||
user_defined = find_models(config_paths() / 'usermodels.py')
|
user_defined = find_models(config_paths() / 'usermodels.py')
|
||||||
except FileNotFoundError:
|
except Exception as e:
|
||||||
pass
|
import traceback, sys
|
||||||
|
|
||||||
|
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||||
|
|
||||||
|
_ = QtWidgets.QMessageBox.warning(
|
||||||
|
self,
|
||||||
|
'No user functions',
|
||||||
|
f'Loading user-defined function failed with exception:\n'
|
||||||
|
f'{"".join(traceback.format_exception(exc_type, exc_value, exc_traceback, limit=1))}')
|
||||||
|
logger.exception("Invalid usermodels.py", exc_info=e)
|
||||||
|
|
||||||
for model in user_defined:
|
for model in user_defined:
|
||||||
name = model.__name__
|
name = model.__name__
|
||||||
@ -155,7 +165,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
self.iscomplex = False
|
self.iscomplex = False
|
||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
f = self.functions[item.data(0, QtCore.Qt.UserRole)]
|
f = self.functions[item.data(0, QtCore.Qt.ItemDataRole.UserRole)]
|
||||||
if hasattr(f, 'iscomplex') and f.iscomplex:
|
if hasattr(f, 'iscomplex') and f.iscomplex:
|
||||||
self.iscomplex = True
|
self.iscomplex = True
|
||||||
break
|
break
|
||||||
@ -216,7 +226,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
iterator = QtWidgets.QTreeWidgetItemIterator(self.functree)
|
iterator = QtWidgets.QTreeWidgetItemIterator(self.functree)
|
||||||
while iterator.value():
|
while iterator.value():
|
||||||
item = iterator.value()
|
item = iterator.value()
|
||||||
f = self.functions[item.data(0, QtCore.Qt.UserRole)]
|
f = self.functions[item.data(0, QtCore.Qt.ItemDataRole.UserRole)]
|
||||||
cnt = item.data(0, self.functree.counterRole)
|
cnt = item.data(0, self.functree.counterRole)
|
||||||
all_parameters[f'{f.name}_{cnt}'] = [(convert(pp, new='str'), (cnt, i)) for i, pp in enumerate(f.params)]
|
all_parameters[f'{f.name}_{cnt}'] = [(convert(pp, new='str'), (cnt, i)) for i, pp in enumerate(f.params)]
|
||||||
|
|
||||||
@ -225,7 +235,19 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
return all_parameters
|
return all_parameters
|
||||||
|
|
||||||
def get_complex_state(self):
|
def get_complex_state(self):
|
||||||
return self.complex_comboBox.currentIndex() if self.iscomplex else None
|
iscomplex = False
|
||||||
|
iterator = QtWidgets.QTreeWidgetItemIterator(self.functree)
|
||||||
|
while iterator.value():
|
||||||
|
item = iterator.value()
|
||||||
|
if item.checkState(0) != QtCore.Qt.CheckState.Unchecked:
|
||||||
|
f = self.functions[item.data(0, QtCore.Qt.ItemDataRole.UserRole)]
|
||||||
|
if hasattr(f, 'iscomplex') and f.iscomplex:
|
||||||
|
iscomplex = True
|
||||||
|
break
|
||||||
|
|
||||||
|
iterator += 1
|
||||||
|
|
||||||
|
return self.complex_comboBox.currentIndex() if iscomplex else None
|
||||||
|
|
||||||
def set_complex_state(self, state):
|
def set_complex_state(self, state):
|
||||||
if state is not None:
|
if state is not None:
|
||||||
|
@ -9,7 +9,6 @@ import numpy as np
|
|||||||
from pyqtgraph import mkPen
|
from pyqtgraph import mkPen
|
||||||
|
|
||||||
from nmreval.fit._meta import MultiModel, ModelFactory
|
from nmreval.fit._meta import MultiModel, ModelFactory
|
||||||
from nmreval.fit.data import Data
|
|
||||||
from nmreval.fit.model import Model
|
from nmreval.fit.model import Model
|
||||||
from nmreval.fit.parameter import Parameters
|
from nmreval.fit.parameter import Parameters
|
||||||
from nmreval.fit.result import FitResult
|
from nmreval.fit.result import FitResult
|
||||||
@ -42,8 +41,8 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
self._management = mgmt
|
self._management = mgmt
|
||||||
|
|
||||||
self._current_model = next(QFitDialog.model_cnt)
|
self._current_model = next(QFitDialog.model_cnt)
|
||||||
self.show_combobox.setItemData(0, self._current_model, QtCore.Qt.UserRole)
|
self.show_combobox.setItemData(0, self._current_model, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
self.default_combobox.setItemData(0, self._current_model, QtCore.Qt.UserRole)
|
self.default_combobox.setItemData(0, self._current_model, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
self.data_table = FitTableWidget(self.data_widget)
|
self.data_table = FitTableWidget(self.data_widget)
|
||||||
self.data_widget.addWidget(self.data_table)
|
self.data_widget.addWidget(self.data_table)
|
||||||
@ -78,8 +77,12 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
"""
|
"""
|
||||||
w = self.param_widgets[idx]
|
w = self.param_widgets[idx]
|
||||||
self.stackedWidget.removeWidget(w)
|
self.stackedWidget.removeWidget(w)
|
||||||
|
w.setParent(None)
|
||||||
w.deleteLater()
|
w.deleteLater()
|
||||||
del self.param_widgets[idx]
|
del self.param_widgets[idx]
|
||||||
|
_, func_id = self.functionwidget.get_selected()
|
||||||
|
|
||||||
|
self.get_functions()
|
||||||
|
|
||||||
self._current_function = None
|
self._current_function = None
|
||||||
if len(self.param_widgets) == 0:
|
if len(self.param_widgets) == 0:
|
||||||
@ -105,7 +108,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
if function is None:
|
if function is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
dialog = QFitParameterWidget(self.stackedWidget)
|
dialog = QFitParameterWidget(function_id, self.stackedWidget)
|
||||||
data_names = self.data_table.data_list(include_name=True)
|
data_names = self.data_table.data_list(include_name=True)
|
||||||
|
|
||||||
dialog.set_function(function, function_idx)
|
dialog.set_function(function, function_idx)
|
||||||
@ -150,9 +153,9 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
|
|
||||||
# deselect all fit sets
|
# deselect all fit sets
|
||||||
for i in range(self.data_table.rowCount()):
|
for i in range(self.data_table.rowCount()):
|
||||||
data_id = self.data_table.item(i, 0).data(QtCore.Qt.UserRole+1)
|
data_id = self.data_table.item(i, 0).data(QtCore.Qt.ItemDataRole.UserRole+1)
|
||||||
if self._management[data_id].mode == 'fit' or self._management[data_id].has_relation(Relations.isFitPartOf):
|
if self._management[data_id].mode == 'fit' or self._management[data_id].has_relation(Relations.isFitPartOf):
|
||||||
self.data_table.item(i, 0).setCheckState(QtCore.Qt.Unchecked)
|
self.data_table.item(i, 0).setCheckState(QtCore.Qt.CheckState.Unchecked)
|
||||||
|
|
||||||
if self.models:
|
if self.models:
|
||||||
for m in self.models.keys():
|
for m in self.models.keys():
|
||||||
@ -176,7 +179,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
|
|
||||||
self.default_combobox.addItem('Model '+idx, userData=idx)
|
self.default_combobox.addItem('Model '+idx, userData=idx)
|
||||||
self.show_combobox.addItem('Model '+idx, userData=idx)
|
self.show_combobox.addItem('Model '+idx, userData=idx)
|
||||||
self.show_combobox.setItemData(self.show_combobox.count()-1, idx, QtCore.Qt.UserRole)
|
self.show_combobox.setItemData(self.show_combobox.count()-1, idx, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
self.show_combobox.setCurrentIndex(self.show_combobox.count()-1)
|
self.show_combobox.setCurrentIndex(self.show_combobox.count()-1)
|
||||||
|
|
||||||
self._current_model = idx
|
self._current_model = idx
|
||||||
@ -190,7 +193,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
self.get_functions()
|
self.get_functions()
|
||||||
self.functionwidget.clear()
|
self.functionwidget.clear()
|
||||||
|
|
||||||
self._current_model = self.show_combobox.itemData(idx, QtCore.Qt.UserRole)
|
self._current_model = self.show_combobox.itemData(idx, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
if self._current_model in self.models and len(self.models[self._current_model]):
|
if self._current_model in self.models and len(self.models[self._current_model]):
|
||||||
for el in self.models[self._current_model]:
|
for el in self.models[self._current_model]:
|
||||||
self.functionwidget.add_function(**el)
|
self.functionwidget.add_function(**el)
|
||||||
@ -207,9 +210,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
|
|
||||||
for m in self.models[model_id]:
|
for m in self.models[model_id]:
|
||||||
func_id = m['cnt']
|
func_id = m['cnt']
|
||||||
self.stackedWidget.removeWidget(self.param_widgets[func_id])
|
self.remove_function(func_id)
|
||||||
|
|
||||||
self.param_widgets.pop(func_id)
|
|
||||||
|
|
||||||
self._complex.pop(model_id)
|
self._complex.pop(model_id)
|
||||||
self._func_list.pop(model_id)
|
self._func_list.pop(model_id)
|
||||||
@ -220,8 +221,14 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
if len(self.models) == 1:
|
if len(self.models) == 1:
|
||||||
self.model_frame.hide()
|
self.model_frame.hide()
|
||||||
|
|
||||||
def _prepare(self, model: list, function_use: list = None,
|
def _prepare(
|
||||||
parameter: dict = None, add_idx: bool = False, cnt: int = 0) -> tuple[dict, int]:
|
self,
|
||||||
|
model: list,
|
||||||
|
function_use: list = None,
|
||||||
|
parameter: dict = None,
|
||||||
|
add_idx: bool = False,
|
||||||
|
cnt: int = 0,
|
||||||
|
) -> tuple[dict, int]:
|
||||||
|
|
||||||
if parameter is None:
|
if parameter is None:
|
||||||
parameter = {
|
parameter = {
|
||||||
@ -264,7 +271,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
|
|
||||||
if f['children']:
|
if f['children']:
|
||||||
# recurse for children
|
# recurse for children
|
||||||
_, cnt = self._prepare(f['children'], parameter=parameter, add_idx=add_idx, cnt=cnt)
|
_, cnt = self._prepare(f['children'], parameter=parameter, function_use=function_use, add_idx=add_idx, cnt=cnt)
|
||||||
|
|
||||||
return parameter, cnt
|
return parameter, cnt
|
||||||
|
|
||||||
@ -276,17 +283,20 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
|
|
||||||
func_dict = {}
|
func_dict = {}
|
||||||
for model_name, model_parameter in self.models.items():
|
for model_name, model_parameter in self.models.items():
|
||||||
func, order, param_len = ModelFactory.create_from_list(model_parameter)
|
func, order, param_len, _ = ModelFactory.create_from_list(model_parameter)
|
||||||
|
multiple_funcs = isinstance(func, MultiModel)
|
||||||
if func is None:
|
if func is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
func = Model(func)
|
func = Model(func)
|
||||||
|
|
||||||
if model_name in data:
|
if model_name in data:
|
||||||
parameter, _ = self._prepare(model_parameter, function_use=data[model_name], add_idx=isinstance(func, MultiModel))
|
parameter, _ = self._prepare(model_parameter, function_use=data[model_name], add_idx=multiple_funcs)
|
||||||
|
|
||||||
if parameter is None:
|
if parameter is None or not isinstance(parameter, dict):
|
||||||
|
return
|
||||||
|
|
||||||
|
if ('data_parameter' not in parameter) or ('global_parameter' not in parameter):
|
||||||
return
|
return
|
||||||
|
|
||||||
for (data_parameter, _) in parameter['data_parameter'].values():
|
for (data_parameter, _) in parameter['data_parameter'].values():
|
||||||
@ -385,7 +395,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
|
|
||||||
func_dict = {}
|
func_dict = {}
|
||||||
for k, mod in self.models.items():
|
for k, mod in self.models.items():
|
||||||
func, order, param_len = ModelFactory.create_from_list(mod)
|
func, order, param_len, _ = ModelFactory.create_from_list(mod)
|
||||||
multiple_funcs = isinstance(func, MultiModel)
|
multiple_funcs = isinstance(func, MultiModel)
|
||||||
|
|
||||||
if k in data:
|
if k in data:
|
||||||
@ -493,7 +503,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
|||||||
if model_p['active']:
|
if model_p['active']:
|
||||||
cnt += self.param_widgets[model_p['cnt']].set_parameter(fit_id, param[cnt:])
|
cnt += self.param_widgets[model_p['cnt']].set_parameter(fit_id, param[cnt:])
|
||||||
if model_p['children']:
|
if model_p['children']:
|
||||||
cnt += self.set_parameter_iter(fit_id, param, model_p['children'], cnt=cnt)
|
cnt = self.set_parameter_iter(fit_id, param, model_p['children'], cnt=cnt)
|
||||||
|
|
||||||
return cnt
|
return cnt
|
||||||
|
|
||||||
|
@ -8,9 +8,9 @@ from typing import Any
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from gui_qt.Qt import QtCore, QtWidgets, QtGui
|
from ..Qt import QtCore, QtWidgets, QtGui
|
||||||
from gui_qt._py.fitcreationdialog import Ui_Dialog
|
from .._py.fitcreationdialog import Ui_Dialog
|
||||||
from gui_qt.lib.namespace import QNamespaceWidget
|
from ..editors.namespace import QNamespaceWidget
|
||||||
|
|
||||||
__all__ = ['QUserFitCreator']
|
__all__ = ['QUserFitCreator']
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
return self
|
return self
|
||||||
|
|
||||||
def update_function(self):
|
def update_function(self):
|
||||||
prev_text = self.plainTextEdit.toPlainText().split('\n')
|
prev_text = self.editor.toPlainText().split('\n')
|
||||||
func_body = ''
|
func_body = ''
|
||||||
in_body = False
|
in_body = False
|
||||||
for line in prev_text:
|
for line in prev_text:
|
||||||
@ -89,9 +89,12 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
else:
|
else:
|
||||||
k += f' def func(x):\n'
|
k += f' def func(x):\n'
|
||||||
|
|
||||||
|
if func_body:
|
||||||
k += func_body
|
k += func_body
|
||||||
|
else:
|
||||||
|
k += ' return x'
|
||||||
|
|
||||||
self.plainTextEdit.setPlainText(k)
|
self.editor.setPlainText(k)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
QtWidgets.QMessageBox.warning(self, 'Failure', f'Error found: {e.args[0]}')
|
QtWidgets.QMessageBox.warning(self, 'Failure', f'Error found: {e.args[0]}')
|
||||||
|
|
||||||
@ -215,7 +218,7 @@ class KwargsWidget(QtWidgets.QWidget):
|
|||||||
for i in range(self.choices.count()):
|
for i in range(self.choices.count()):
|
||||||
kwargs.append(self.choices.widget(i).get_strings())
|
kwargs.append(self.choices.widget(i).get_strings())
|
||||||
if kwargs:
|
if kwargs:
|
||||||
return f" choices = {', '.join(kwargs)}\n"
|
return f" choices = [{', '.join(kwargs)}]\n"
|
||||||
else:
|
else:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
@ -475,12 +478,3 @@ class DescWidget(QtWidgets.QWidget):
|
|||||||
f" equation = r'{self.eq_lineedit.text()}'\n"
|
f" equation = r'{self.eq_lineedit.text()}'\n"
|
||||||
|
|
||||||
return stringi
|
return stringi
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
import sys
|
|
||||||
app = QtWidgets.QApplication([])
|
|
||||||
win = QUserFitCreator()
|
|
||||||
win.show()
|
|
||||||
|
|
||||||
sys.exit(app.exec())
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from math import isnan
|
from math import isnan
|
||||||
|
|
||||||
from pyqtgraph import mkBrush, mkPen
|
from pyqtgraph import mkBrush, mkPen, mkColor
|
||||||
|
from numpy import abs as np_abs, isfinite as np_isfinite
|
||||||
|
|
||||||
from nmreval.utils.text import convert
|
from nmreval.utils.text import convert
|
||||||
from ..lib.graph_items import logTickValues
|
from ..lib.graph_items import logTickValues
|
||||||
@ -15,7 +18,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
closed = QtCore.pyqtSignal(dict, list, str, bool, bool, list)
|
closed = QtCore.pyqtSignal(dict, list, str, bool, bool, list)
|
||||||
redoFit = QtCore.pyqtSignal(dict)
|
redoFit = QtCore.pyqtSignal(dict)
|
||||||
|
|
||||||
def __init__(self, results: list, management, parent=None):
|
def __init__(self, results: list, sub_colors: dict, management, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
|
||||||
@ -27,12 +30,14 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.extrapolate_box.stateChanged.connect(lambda x: self.maxx_line.setEnabled(x))
|
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.minx_line.setEnabled(x))
|
||||||
self.extrapolate_box.stateChanged.connect(lambda x: self.numx_line.setEnabled(x))
|
self.extrapolate_box.stateChanged.connect(lambda x: self.numx_line.setEnabled(x))
|
||||||
|
self.extrapolate_box.stateChanged.connect(lambda x: self.newx_log_checkbox.setEnabled(x))
|
||||||
|
|
||||||
self._previous_fits = {}
|
self._previous_fits = {}
|
||||||
self._opts = []
|
self._opts = []
|
||||||
self._results = {}
|
self._results = {}
|
||||||
self.graph_opts = {}
|
self.graph_opts = {}
|
||||||
self.last_idx = None
|
self.last_idx = None
|
||||||
|
self.func_colors = sub_colors
|
||||||
|
|
||||||
self.fit_plot = self.graphicsView.addPlot(row=1, col=0, title='Fit')
|
self.fit_plot = self.graphicsView.addPlot(row=1, col=0, title='Fit')
|
||||||
self.resid_plot = self.graphicsView.addPlot(row=0, col=0, title='Residual')
|
self.resid_plot = self.graphicsView.addPlot(row=0, col=0, title='Residual')
|
||||||
@ -44,21 +49,29 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.graphicsView.ci.layout.setRowStretchFactor(0, 1)
|
self.graphicsView.ci.layout.setRowStretchFactor(0, 1)
|
||||||
self.graphicsView.ci.layout.setRowStretchFactor(1, 2)
|
self.graphicsView.ci.layout.setRowStretchFactor(1, 2)
|
||||||
|
|
||||||
self.resid_graph = PlotItem(x=[], y=[],
|
self.resid_graph = PlotItem(
|
||||||
|
x=[], y=[],
|
||||||
symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)),
|
symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)),
|
||||||
pen=None)
|
pen=None
|
||||||
self.resid_graph_imag = PlotItem(x=[], y=[],
|
)
|
||||||
|
self.resid_graph_imag = PlotItem(
|
||||||
|
x=[], y=[],
|
||||||
symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)),
|
symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)),
|
||||||
pen=None)
|
pen=None
|
||||||
|
)
|
||||||
self.resid_plot.addItem(self.resid_graph)
|
self.resid_plot.addItem(self.resid_graph)
|
||||||
self.resid_plot.addItem(self.resid_graph_imag)
|
self.resid_plot.addItem(self.resid_graph_imag)
|
||||||
|
|
||||||
self.data_graph = PlotItem(x=[], y=[],
|
self.data_graph = PlotItem(
|
||||||
|
x=[], y=[],
|
||||||
symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)),
|
symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)),
|
||||||
pen=None)
|
pen=None
|
||||||
self.data_graph_imag = PlotItem(x=[], y=[],
|
)
|
||||||
|
self.data_graph_imag = PlotItem(
|
||||||
|
x=[], y=[],
|
||||||
symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)),
|
symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)),
|
||||||
pen=None)
|
pen=None
|
||||||
|
)
|
||||||
self.fit_plot.addItem(self.data_graph)
|
self.fit_plot.addItem(self.data_graph)
|
||||||
self.fit_plot.addItem(self.data_graph_imag)
|
self.fit_plot.addItem(self.data_graph_imag)
|
||||||
|
|
||||||
@ -69,21 +82,26 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
self.cmap = RdBuCMap(vmin=-1, vmax=1)
|
self.cmap = RdBuCMap(vmin=-1, vmax=1)
|
||||||
|
|
||||||
self.graph_checkBox.stateChanged.connect(lambda x: self.graph_comboBox.setEnabled(x == QtCore.Qt.Unchecked))
|
self.graph_checkBox.stateChanged.connect(
|
||||||
|
lambda x: self.graph_comboBox.setEnabled(x == QtCore.Qt.CheckState.Unchecked)
|
||||||
|
)
|
||||||
|
|
||||||
self.logy_box.stateChanged.connect(lambda x: self.fit_plot.setLogMode(y=bool(x)))
|
self.logy_box.stateChanged.connect(lambda x: self.fit_plot.setLogMode(y=bool(x)))
|
||||||
self.logx_box.stateChanged.connect(lambda x: self.fit_plot.setLogMode(x=bool(x)))
|
self.logx_box.stateChanged.connect(lambda x: self.fit_plot.setLogMode(x=bool(x)))
|
||||||
self.resid_plot.setXLink(self.fit_plot)
|
self.resid_plot.setXLink(self.fit_plot)
|
||||||
|
|
||||||
|
self.buttonGroup.buttonToggled.connect(self._plot_residuals)
|
||||||
|
|
||||||
self.set_results(results)
|
self.set_results(results)
|
||||||
|
|
||||||
def __call__(self, results: list):
|
def __call__(self, results: list, sub_colors: dict):
|
||||||
self._previous_fits = {}
|
self._previous_fits = {}
|
||||||
self.sets_comboBox.blockSignals(True)
|
self.sets_comboBox.blockSignals(True)
|
||||||
self.sets_comboBox.clear()
|
self.sets_comboBox.clear()
|
||||||
self.sets_comboBox.blockSignals(False)
|
self.sets_comboBox.blockSignals(False)
|
||||||
self._results = {}
|
self._results = {}
|
||||||
self._opts = {}
|
self._opts = {}
|
||||||
|
self.func_colors = sub_colors
|
||||||
|
|
||||||
self.set_results(results)
|
self.set_results(results)
|
||||||
|
|
||||||
@ -112,7 +130,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_sets_comboBox_currentIndexChanged')
|
@QtCore.pyqtSlot(int, name='on_sets_comboBox_currentIndexChanged')
|
||||||
def set_parameter(self, idx: int):
|
def set_parameter(self, idx: int):
|
||||||
set_id = self.sets_comboBox.itemData(idx, QtCore.Qt.UserRole)
|
set_id = self.sets_comboBox.itemData(idx, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
res = self._results[set_id]
|
res = self._results[set_id]
|
||||||
self.param_tableWidget.setRowCount(len(res.parameter))
|
self.param_tableWidget.setRowCount(len(res.parameter))
|
||||||
@ -138,11 +156,11 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
def change_opts(self, _):
|
def change_opts(self, _):
|
||||||
idx = self.sets_comboBox.currentIndex()
|
idx = self.sets_comboBox.currentIndex()
|
||||||
|
|
||||||
self._opts[idx] = (self.reject_fit_checkBox.checkState() == QtCore.Qt.Checked,
|
self._opts[idx] = (self.reject_fit_checkBox.checkState() == QtCore.Qt.CheckState.Checked,
|
||||||
self.del_prev_checkBox.checkState() == QtCore.Qt.Checked)
|
self.del_prev_checkBox.checkState() == QtCore.Qt.CheckState.Checked)
|
||||||
|
|
||||||
def show_results(self, idx):
|
def show_results(self, idx):
|
||||||
set_id = self.sets_comboBox.itemData(idx, QtCore.Qt.UserRole)
|
set_id = self.sets_comboBox.itemData(idx, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
self.set_plot(set_id)
|
self.set_plot(set_id)
|
||||||
self.set_correlation(set_id)
|
self.set_correlation(set_id)
|
||||||
self.set_statistics(set_id)
|
self.set_statistics(set_id)
|
||||||
@ -153,6 +171,15 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.del_prev_checkBox.setChecked(self._opts[idx][1])
|
self.del_prev_checkBox.setChecked(self._opts[idx][1])
|
||||||
self.del_prev_checkBox.blockSignals(False)
|
self.del_prev_checkBox.blockSignals(False)
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(name='on_autoscale_box_clicked')
|
||||||
|
def reset_fit_ranges(self):
|
||||||
|
for i in range(self.sets_comboBox.count()):
|
||||||
|
graph_id = self.sets_comboBox.itemData(i)
|
||||||
|
if graph_id in self.graph_opts:
|
||||||
|
self.graph_opts.pop(graph_id)
|
||||||
|
|
||||||
|
self.fit_plot.enableAutoRange()
|
||||||
|
|
||||||
def set_plot(self, idx: str):
|
def set_plot(self, idx: str):
|
||||||
if self.last_idx is not None:
|
if self.last_idx is not None:
|
||||||
self.graph_opts[self.last_idx] = (
|
self.graph_opts[self.last_idx] = (
|
||||||
@ -175,27 +202,26 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.data_graph_imag.setData(x=res.x_data, y=res.y_data.imag)
|
self.data_graph_imag.setData(x=res.x_data, y=res.y_data.imag)
|
||||||
self.fit_graph.setData(x=res.x, y=res.y.real)
|
self.fit_graph.setData(x=res.x, y=res.y.real)
|
||||||
self.fit_graph_imag.setData(x=res.x, y=res.y.imag)
|
self.fit_graph_imag.setData(x=res.x, y=res.y.imag)
|
||||||
self.resid_graph.setData(x=res.x_data, y=res.residual.real)
|
|
||||||
self.resid_graph_imag.setData(x=res.x_data, y=res.residual.imag)
|
|
||||||
|
|
||||||
for i, f in enumerate(sub_funcs):
|
for f, c in zip(sub_funcs, self.func_colors[idx]):
|
||||||
item = PlotItem(x=f.x, y=f.y.real, pen=mkPen({'color': i, 'style': 2}))
|
col = mkColor(*[c_i*255 for c_i in c])
|
||||||
|
item = PlotItem(x=f.x, y=f.y.real, pen=mkPen({'color': col, 'style': 2}))
|
||||||
self.fit_plot.addItem(item)
|
self.fit_plot.addItem(item)
|
||||||
item = PlotItem(x=f.x, y=f.y.imag, pen=mkPen({'color': i, 'style': 2}))
|
item = PlotItem(x=f.x, y=f.y.imag, pen=mkPen({'color': col, 'style': 2}))
|
||||||
self.fit_plot.addItem(item)
|
self.fit_plot.addItem(item)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.resid_graph.setData(x=res.x_data, y=res.residual)
|
|
||||||
self.resid_graph_imag.setData(x=[], y=[])
|
|
||||||
self.data_graph.setData(x=res.x_data, y=res.y_data)
|
self.data_graph.setData(x=res.x_data, y=res.y_data)
|
||||||
self.data_graph_imag.setData(x=[], y=[])
|
self.data_graph_imag.setData(x=[], y=[])
|
||||||
self.fit_graph.setData(x=res.x, y=res.y)
|
self.fit_graph.setData(x=res.x, y=res.y)
|
||||||
self.fit_graph_imag.setData(x=[], y=[])
|
self.fit_graph_imag.setData(x=[], y=[])
|
||||||
|
|
||||||
for i, f in enumerate(sub_funcs):
|
for f, c in zip(sub_funcs, self.func_colors[idx]):
|
||||||
item = PlotItem(x=f.x, y=f.y, pen=mkPen({'color': i, 'style': 2}))
|
item = PlotItem(x=f.x, y=f.y, pen=mkPen({'color': mkColor(*[c_i*255 for c_i in c]), 'style': 2}))
|
||||||
self.fit_plot.addItem(item)
|
self.fit_plot.addItem(item)
|
||||||
|
|
||||||
|
self._plot_residuals(idx)
|
||||||
|
|
||||||
self.logx_box.blockSignals(True)
|
self.logx_box.blockSignals(True)
|
||||||
self.logx_box.setChecked(res.islog)
|
self.logx_box.setChecked(res.islog)
|
||||||
self.logx_box.blockSignals(False)
|
self.logx_box.blockSignals(False)
|
||||||
@ -213,6 +239,29 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.logy_box.blockSignals(True)
|
self.logy_box.blockSignals(True)
|
||||||
self.logy_box.setChecked(logy)
|
self.logy_box.setChecked(logy)
|
||||||
self.logy_box.blockSignals(False)
|
self.logy_box.blockSignals(False)
|
||||||
|
else:
|
||||||
|
self.fit_plot.enableAutoRange()
|
||||||
|
|
||||||
|
def _plot_residuals(self, idx: str = None):
|
||||||
|
if idx is None or isinstance(idx, QtWidgets.QAbstractButton):
|
||||||
|
idx = self.sets_comboBox.currentData(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
|
res = self._results[idx]
|
||||||
|
if res.iscomplex:
|
||||||
|
if self.rel_dev_button.isChecked():
|
||||||
|
self.resid_graph.setData(x=res.x_data, y=res.residual.real/np_abs(res.y_data.real))
|
||||||
|
if all(np_isfinite(res.y_data.imag)):
|
||||||
|
self.resid_graph_imag.setData(x=res.x_data, y=res.residual.imag/np_abs(res.y_data.imag))
|
||||||
|
else:
|
||||||
|
self.resid_graph.setData(x=res.x_data, y=res.residual.real)
|
||||||
|
self.resid_graph_imag.setData(x=res.x_data, y=res.residual.imag)
|
||||||
|
|
||||||
|
else:
|
||||||
|
if self.rel_dev_button.isChecked():
|
||||||
|
self.resid_graph.setData(x=res.x_data, y=res.residual / np_abs(res.y_data))
|
||||||
|
else:
|
||||||
|
self.resid_graph.setData(x=res.x_data, y=res.residual)
|
||||||
|
self.resid_graph_imag.setData(x=[], y=[])
|
||||||
|
|
||||||
def set_correlation(self, idx: str):
|
def set_correlation(self, idx: str):
|
||||||
while self.corr_tableWidget.rowCount():
|
while self.corr_tableWidget.rowCount():
|
||||||
@ -247,20 +296,20 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.stats_tableWidget.setRowCount(len(res.statistics)+3)
|
self.stats_tableWidget.setRowCount(len(res.statistics)+3)
|
||||||
|
|
||||||
it = QtWidgets.QTableWidgetItem(f'{res.dof}')
|
it = QtWidgets.QTableWidgetItem(f'{res.dof}')
|
||||||
it.setFlags(it.flags() ^ QtCore.Qt.ItemIsEditable)
|
it.setFlags(it.flags() ^ QtCore.Qt.ItemFlag.ItemIsEditable)
|
||||||
self.stats_tableWidget.setVerticalHeaderItem(0, QtWidgets.QTableWidgetItem('DoF'))
|
self.stats_tableWidget.setVerticalHeaderItem(0, QtWidgets.QTableWidgetItem('DoF'))
|
||||||
self.stats_tableWidget.setItem(0, 0, it)
|
self.stats_tableWidget.setItem(0, 0, it)
|
||||||
|
|
||||||
for col, (name, _, dof) in enumerate(self._previous_fits[idx], start=1):
|
for col, (name, _, dof) in enumerate(self._previous_fits[idx], start=1):
|
||||||
self.stats_tableWidget.setHorizontalHeaderItem(0, QtWidgets.QTableWidgetItem(name))
|
self.stats_tableWidget.setHorizontalHeaderItem(0, QtWidgets.QTableWidgetItem(name))
|
||||||
it = QtWidgets.QTableWidgetItem(f'{dof}')
|
it = QtWidgets.QTableWidgetItem(f'{dof}')
|
||||||
it.setFlags(it.flags() ^ QtCore.Qt.ItemIsEditable)
|
it.setFlags(it.flags() ^ QtCore.Qt.ItemFlag.ItemIsEditable)
|
||||||
self.stats_tableWidget.setItem(0, col, it)
|
self.stats_tableWidget.setItem(0, col, it)
|
||||||
|
|
||||||
for row, (k, v) in enumerate(res.statistics.items(), start=1):
|
for row, (k, v) in enumerate(res.statistics.items(), start=1):
|
||||||
self.stats_tableWidget.setVerticalHeaderItem(row, QtWidgets.QTableWidgetItem(k))
|
self.stats_tableWidget.setVerticalHeaderItem(row, QtWidgets.QTableWidgetItem(k))
|
||||||
it = QtWidgets.QTableWidgetItem(f'{v:.4f}')
|
it = QtWidgets.QTableWidgetItem(f'{v:.4f}')
|
||||||
it.setFlags(it.flags() ^ QtCore.Qt.ItemIsEditable)
|
it.setFlags(it.flags() ^ QtCore.Qt.ItemFlag.ItemIsEditable)
|
||||||
self.stats_tableWidget.setItem(row, 0, it)
|
self.stats_tableWidget.setItem(row, 0, it)
|
||||||
|
|
||||||
best_idx = -1
|
best_idx = -1
|
||||||
@ -271,7 +320,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
else:
|
else:
|
||||||
best_idx = col if best_val > stats[k] else max(0, best_idx)
|
best_idx = col if best_val > stats[k] else max(0, best_idx)
|
||||||
it = QtWidgets.QTableWidgetItem(f'{stats[k]:.4f}')
|
it = QtWidgets.QTableWidgetItem(f'{stats[k]:.4f}')
|
||||||
it.setFlags(it.flags() ^ QtCore.Qt.ItemIsEditable)
|
it.setFlags(it.flags() ^ QtCore.Qt.ItemFlag.ItemIsEditable)
|
||||||
self.stats_tableWidget.setItem(row, col, it)
|
self.stats_tableWidget.setItem(row, col, it)
|
||||||
|
|
||||||
if best_idx > -1:
|
if best_idx > -1:
|
||||||
@ -288,11 +337,11 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
for col, (_, stats, dof) in enumerate(self._previous_fits[idx], start=1):
|
for col, (_, stats, dof) in enumerate(self._previous_fits[idx], start=1):
|
||||||
f_value, prob_f = res.f_test(stats['chi^2'], dof)
|
f_value, prob_f = res.f_test(stats['chi^2'], dof)
|
||||||
it = QtWidgets.QTableWidgetItem(f'{f_value:.4g}')
|
it = QtWidgets.QTableWidgetItem(f'{f_value:.4g}')
|
||||||
it.setFlags(it.flags() ^ QtCore.Qt.ItemIsEditable)
|
it.setFlags(it.flags() ^ QtCore.Qt.ItemFlag.ItemIsEditable)
|
||||||
self.corr_tableWidget.setItem(row, col, it)
|
self.corr_tableWidget.setItem(row, col, it)
|
||||||
|
|
||||||
it = QtWidgets.QTableWidgetItem(f'{prob_f:.4g}')
|
it = QtWidgets.QTableWidgetItem(f'{prob_f:.4g}')
|
||||||
it.setFlags(it.flags() ^ QtCore.Qt.ItemIsEditable)
|
it.setFlags(it.flags() ^ QtCore.Qt.ItemFlag.ItemIsEditable)
|
||||||
if prob_f < 0.05:
|
if prob_f < 0.05:
|
||||||
it.setBackground(QtGui.QColor('green'))
|
it.setBackground(QtGui.QColor('green'))
|
||||||
it.setForeground(QtGui.QColor('white'))
|
it.setForeground(QtGui.QColor('white'))
|
||||||
@ -308,16 +357,16 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
elif button_type == self.buttonBox.Ok:
|
elif button_type == self.buttonBox.Ok:
|
||||||
graph = '-1'
|
graph = '-1'
|
||||||
if self.parameter_checkbox.isChecked():
|
if self.parameter_checkbox.isChecked():
|
||||||
if self.graph_checkBox.checkState() == QtCore.Qt.Checked:
|
if self.graph_checkBox.checkState() == QtCore.Qt.CheckState.Checked:
|
||||||
graph = ''
|
graph = ''
|
||||||
else:
|
else:
|
||||||
graph = self.graph_comboBox.currentData()
|
graph = self.graph_comboBox.currentData()
|
||||||
|
|
||||||
plot_fits = self.curve_checkbox.isChecked()
|
plot_fits = self.curve_checkbox.isChecked()
|
||||||
|
|
||||||
parts = self.partial_checkBox.checkState() == QtCore.Qt.Checked
|
parts = self.partial_checkBox.checkState() == QtCore.Qt.CheckState.Checked
|
||||||
|
|
||||||
extrapolate = [None, None, None]
|
extrapolate = [None, None, None, None]
|
||||||
error = []
|
error = []
|
||||||
if self.extrapolate_box.isChecked():
|
if self.extrapolate_box.isChecked():
|
||||||
try:
|
try:
|
||||||
@ -333,6 +382,8 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
error.append('Number of points is missing')
|
error.append('Number of points is missing')
|
||||||
|
|
||||||
|
extrapolate[3] = self.newx_log_checkbox.isChecked()
|
||||||
|
|
||||||
if error:
|
if error:
|
||||||
msg = QtWidgets.QMessageBox.warning(self, 'Error', 'Extrapolation failed because:\n' + '\n'.join(error))
|
msg = QtWidgets.QMessageBox.warning(self, 'Error', 'Extrapolation failed because:\n' + '\n'.join(error))
|
||||||
return
|
return
|
||||||
@ -370,10 +421,13 @@ class FitExtension(QtWidgets.QDialog):
|
|||||||
self.num_pts.setValidator(QtGui.QIntValidator())
|
self.num_pts.setValidator(QtGui.QIntValidator())
|
||||||
gridLayout.addWidget(self.num_pts, 2, 1, 1, 1)
|
gridLayout.addWidget(self.num_pts, 2, 1, 1, 1)
|
||||||
|
|
||||||
|
self.logx_checkbox = QtWidgets.QCheckBox('Log-spaced?')
|
||||||
|
gridLayout.addWidget(self.logx_checkbox, 3, 0, 1, 2)
|
||||||
|
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox()
|
self.buttonBox = QtWidgets.QDialogButtonBox()
|
||||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
||||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok)
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok)
|
||||||
gridLayout.addWidget(self.buttonBox, 3, 0, 1, 2)
|
gridLayout.addWidget(self.buttonBox, 4, 0, 1, 2)
|
||||||
|
|
||||||
self.setLayout(gridLayout)
|
self.setLayout(gridLayout)
|
||||||
|
|
||||||
@ -381,12 +435,13 @@ class FitExtension(QtWidgets.QDialog):
|
|||||||
self.buttonBox.rejected.connect(self.reject)
|
self.buttonBox.rejected.connect(self.reject)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def values(self):
|
def values(self) -> tuple[float, float, int, bool] | None:
|
||||||
try:
|
try:
|
||||||
xmin = float(self.min_line.text())
|
xmin = float(self.min_line.text())
|
||||||
xmax = float(self.max_line.text())
|
xmax = float(self.max_line.text())
|
||||||
nums = int(self.num_pts.text())
|
nums = int(self.num_pts.text())
|
||||||
|
logx = self.logx_checkbox.isChecked()
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return xmin, xmax, nums
|
return xmin, xmax, nums, logx
|
||||||
|
@ -27,6 +27,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
mouseDoubleClicked = QtCore.pyqtSignal()
|
mouseDoubleClicked = QtCore.pyqtSignal()
|
||||||
positionClicked = QtCore.pyqtSignal(tuple, bool)
|
positionClicked = QtCore.pyqtSignal(tuple, bool)
|
||||||
aboutToClose = QtCore.pyqtSignal(list)
|
aboutToClose = QtCore.pyqtSignal(list)
|
||||||
|
newData = QtCore.pyqtSignal(list, str)
|
||||||
|
|
||||||
counter = itertools.count()
|
counter = itertools.count()
|
||||||
|
|
||||||
@ -55,6 +56,16 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
self._external_items = []
|
self._external_items = []
|
||||||
self.closable = True
|
self.closable = True
|
||||||
|
|
||||||
|
"""
|
||||||
|
TODO
|
||||||
|
this does not work properly and leads to lots of errors
|
||||||
|
because PlotDataItems do not have a viewBox anymore which is called in getData
|
||||||
|
|
||||||
|
# desperate attempts to improve memory usage during paintEvents
|
||||||
|
self.graphic.setAntialiasing(False)
|
||||||
|
self.plotItem.setDownsampling(auto=True)
|
||||||
|
self.plotItem.setClipToView(True)
|
||||||
|
"""
|
||||||
self._block = False
|
self._block = False
|
||||||
|
|
||||||
self.log = [False, False]
|
self.log = [False, False]
|
||||||
@ -62,7 +73,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
self.scene = self.plotItem.scene()
|
self.scene = self.plotItem.scene()
|
||||||
self.scene.sigMouseMoved.connect(self.move_mouse)
|
self.scene.sigMouseMoved.connect(self.move_mouse)
|
||||||
|
|
||||||
self.checkBox.stateChanged.connect(lambda x: self.legend.setVisible(x == QtCore.Qt.Checked))
|
self.checkBox.stateChanged.connect(lambda x: self.legend.setVisible(x == QtCore.Qt.CheckState.Checked))
|
||||||
self.label_button.toggled.connect(lambda x: self.label_widget.setVisible(x))
|
self.label_button.toggled.connect(lambda x: self.label_widget.setVisible(x))
|
||||||
self.limit_button.toggled.connect(lambda x: self.limit_widget.setVisible(x))
|
self.limit_button.toggled.connect(lambda x: self.limit_widget.setVisible(x))
|
||||||
self.gridbutton.toggled.connect(lambda x: self.graphic.showGrid(x=x, y=x))
|
self.gridbutton.toggled.connect(lambda x: self.graphic.showGrid(x=x, y=x))
|
||||||
@ -77,6 +88,9 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
|
|
||||||
self.bwbutton.toggled.connect(self.change_background)
|
self.bwbutton.toggled.connect(self.change_background)
|
||||||
|
|
||||||
|
self.setAcceptDrops(True)
|
||||||
|
self.graphic.installEventFilter(self)
|
||||||
|
|
||||||
def _init_gui(self):
|
def _init_gui(self):
|
||||||
self.setWindowTitle('Graph ' + str(next(QGraphWindow.counter)))
|
self.setWindowTitle('Graph ' + str(next(QGraphWindow.counter)))
|
||||||
|
|
||||||
@ -109,6 +123,34 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
for lineedit in [self.xmin_lineedit, self.xmax_lineedit, self.ymin_lineedit, self.ymax_lineedit]:
|
for lineedit in [self.xmin_lineedit, self.xmax_lineedit, self.ymin_lineedit, self.ymax_lineedit]:
|
||||||
lineedit.setValidator(QtGui.QDoubleValidator())
|
lineedit.setValidator(QtGui.QDoubleValidator())
|
||||||
|
|
||||||
|
def eventFilter(self, obj: QtCore.QObject, evt: QtCore.QEvent):
|
||||||
|
"""
|
||||||
|
Catch drag and Drop to prevent anything inside self.graphic to accept the events.
|
||||||
|
Without event filter, we cannot process it here and start file reading
|
||||||
|
"""
|
||||||
|
if evt.type() == QtCore.QEvent.Type.DragEnter:
|
||||||
|
evt.accept()
|
||||||
|
return True
|
||||||
|
|
||||||
|
elif evt.type() == QtCore.QEvent.Type.Drop:
|
||||||
|
return self._handle_drop(evt)
|
||||||
|
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def dropEvent(self, evt: QtGui.QDropEvent):
|
||||||
|
return self._handle_drop(evt)
|
||||||
|
|
||||||
|
def _handle_drop(self, evt: QtGui.QDropEvent):
|
||||||
|
if evt.mimeData().hasUrls():
|
||||||
|
files = [str(url.toLocalFile()) for url in evt.mimeData().urls()]
|
||||||
|
self.newData.emit(files, self.id)
|
||||||
|
|
||||||
|
evt.accept()
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
def __contains__(self, item: str):
|
def __contains__(self, item: str):
|
||||||
return item in self.sets
|
return item in self.sets
|
||||||
|
|
||||||
@ -167,7 +209,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
self._block = state
|
self._block = state
|
||||||
|
|
||||||
if not self._block:
|
if not self._block:
|
||||||
self.graphic.enableAutoRange()
|
# self.graphic.enableAutoRange()
|
||||||
self._update_zorder()
|
self._update_zorder()
|
||||||
self.show_legend()
|
self.show_legend()
|
||||||
else:
|
else:
|
||||||
@ -178,6 +220,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
name = [name]
|
name = [name]
|
||||||
plots = [plots]
|
plots = [plots]
|
||||||
toplevel = len(self.sets)
|
toplevel = len(self.sets)
|
||||||
|
|
||||||
self.listWidget.blockSignals(True)
|
self.listWidget.blockSignals(True)
|
||||||
for (real_plot, imag_plot, err_plot), n in zip(plots, name):
|
for (real_plot, imag_plot, err_plot), n in zip(plots, name):
|
||||||
self.sets.append(n)
|
self.sets.append(n)
|
||||||
@ -194,9 +237,13 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
self.error_plots[n] = err_plot
|
self.error_plots[n] = err_plot
|
||||||
|
|
||||||
list_item = QtWidgets.QListWidgetItem(real_plot.opts.get('name', ''))
|
list_item = QtWidgets.QListWidgetItem(real_plot.opts.get('name', ''))
|
||||||
list_item.setData(QtCore.Qt.UserRole, n)
|
list_item.setData(QtCore.Qt.ItemDataRole.UserRole, n)
|
||||||
list_item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable)
|
list_item.setFlags(
|
||||||
list_item.setCheckState(QtCore.Qt.Checked)
|
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||||
|
)
|
||||||
|
list_item.setCheckState(QtCore.Qt.CheckState.Checked)
|
||||||
self.listWidget.addItem(list_item)
|
self.listWidget.addItem(list_item)
|
||||||
|
|
||||||
toplevel += 1
|
toplevel += 1
|
||||||
@ -228,7 +275,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
|
|
||||||
for i in range(self.listWidget.count()-1, 0, -1):
|
for i in range(self.listWidget.count()-1, 0, -1):
|
||||||
item = self.listWidget.item(i)
|
item = self.listWidget.item(i)
|
||||||
if item.data(QtCore.Qt.UserRole) in name:
|
if item.data(QtCore.Qt.ItemDataRole.UserRole) in name:
|
||||||
self.listWidget.takeItem(i)
|
self.listWidget.takeItem(i)
|
||||||
|
|
||||||
self.listWidget.blockSignals(False)
|
self.listWidget.blockSignals(False)
|
||||||
@ -293,6 +340,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
if item in self.graphic.items():
|
if item in self.graphic.items():
|
||||||
self.graphic.removeItem(item)
|
self.graphic.removeItem(item)
|
||||||
|
|
||||||
|
self.show_legend()
|
||||||
|
|
||||||
@QtCore.pyqtSlot(bool, name='on_imag_button_toggled')
|
@QtCore.pyqtSlot(bool, name='on_imag_button_toggled')
|
||||||
@QtCore.pyqtSlot(bool, name='on_real_button_toggled')
|
@QtCore.pyqtSlot(bool, name='on_real_button_toggled')
|
||||||
def set_imag_visible(self, visible: bool):
|
def set_imag_visible(self, visible: bool):
|
||||||
@ -420,24 +469,37 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
_y = pos.y()
|
_y = pos.y()
|
||||||
self.mousePositionChanged.emit(_x, _y)
|
self.mousePositionChanged.emit(_x, _y)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_title_lineedit_returnPressed')
|
@QtCore.pyqtSlot(str, name='on_title_lineedit_textChanged')
|
||||||
@QtCore.pyqtSlot(name='on_xaxis_linedit_returnPressed')
|
@QtCore.pyqtSlot(str, name='on_xaxis_linedit_textChanged')
|
||||||
@QtCore.pyqtSlot(name='on_yaxis_linedit_returnPressed')
|
@QtCore.pyqtSlot(str, name='on_yaxis_linedit_textChanged')
|
||||||
def labels_changed(self):
|
def labels_changed(self, text: str):
|
||||||
label = {self.title_lineedit: 'title', self.xaxis_linedit: 'x', self.yaxis_linedit: 'y'}[self.sender()]
|
label = {
|
||||||
self.set_label(**{label: self.sender().text()})
|
self.title_lineedit: 'title',
|
||||||
|
self.xaxis_linedit: 'x',
|
||||||
|
self.yaxis_linedit: 'y',
|
||||||
|
}[self.sender()]
|
||||||
|
self.set_label(**{label: text})
|
||||||
|
|
||||||
def set_label(self, x=None, y=None, title=None):
|
def set_label(self, x: str = None, y: str = None, title: str = None):
|
||||||
if title is not None:
|
if title is not None:
|
||||||
self.plotItem.setTitle(convert(title, old='tex', new='html'), **{'size': '10pt', 'color': self._fgcolor})
|
self.plotItem.setTitle(
|
||||||
|
convert(title, old='tex', new='html'),
|
||||||
|
**{'size': '10pt', 'color': self._fgcolor},
|
||||||
|
)
|
||||||
|
|
||||||
if x is not None:
|
if x is not None:
|
||||||
self.plotItem.setLabel('bottom', convert(x, old='tex', new='html'),
|
self.plotItem.setLabel(
|
||||||
**{'font-size': '10pt', 'color': self._fgcolor.name()})
|
'bottom',
|
||||||
|
convert(x, old='tex', new='html'),
|
||||||
|
**{'font-size': '10pt', 'color': self._fgcolor.name()},
|
||||||
|
)
|
||||||
|
|
||||||
if y is not None:
|
if y is not None:
|
||||||
self.plotItem.setLabel('left', convert(y, old='tex', new='html'),
|
self.plotItem.setLabel(
|
||||||
**{'font-size': '10pt', 'color': self._fgcolor.name()})
|
'left',
|
||||||
|
convert(y, old='tex', new='html'),
|
||||||
|
**{'font-size': '10pt', 'color': self._fgcolor.name()},
|
||||||
|
)
|
||||||
|
|
||||||
def set_logmode(self, xmode: bool = None, ymode: bool = None):
|
def set_logmode(self, xmode: bool = None, ymode: bool = None):
|
||||||
r = self.ranges
|
r = self.ranges
|
||||||
@ -463,8 +525,6 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
self.plotItem.updateLogMode()
|
self.plotItem.updateLogMode()
|
||||||
self.set_range(x=r[0], y=r[1])
|
self.set_range(x=r[0], y=r[1])
|
||||||
|
|
||||||
self.plotItem.enableAutoRange()
|
|
||||||
|
|
||||||
def enable_picking(self, enabled: bool):
|
def enable_picking(self, enabled: bool):
|
||||||
if enabled:
|
if enabled:
|
||||||
self.scene.sigMouseClicked.connect(self.position_picked)
|
self.scene.sigMouseClicked.connect(self.position_picked)
|
||||||
@ -479,6 +539,10 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
|
|
||||||
if self.graphic.plotItem.sceneBoundingRect().contains(evt.scenePos()) and evt.button() == 1:
|
if self.graphic.plotItem.sceneBoundingRect().contains(evt.scenePos()) and evt.button() == 1:
|
||||||
pos = vb.mapSceneToView(evt.scenePos())
|
pos = vb.mapSceneToView(evt.scenePos())
|
||||||
|
|
||||||
|
if not _inside_range(pos.x(), pos.y(), vb.viewRange()):
|
||||||
|
return
|
||||||
|
|
||||||
_x, _y = pos.x(), pos.y()
|
_x, _y = pos.x(), pos.y()
|
||||||
|
|
||||||
if self.log[0]:
|
if self.log[0]:
|
||||||
@ -545,7 +609,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
|
|
||||||
for i in range(self.listWidget.count()):
|
for i in range(self.listWidget.count()):
|
||||||
item = self.listWidget.item(i)
|
item = self.listWidget.item(i)
|
||||||
if item.data(QtCore.Qt.UserRole) == sid:
|
if item.data(QtCore.Qt.ItemDataRole.UserRole) == sid:
|
||||||
item.setText(convert(name, old='tex', new='html'))
|
item.setText(convert(name, old='tex', new='html'))
|
||||||
|
|
||||||
self.listWidget.blockSignals(False)
|
self.listWidget.blockSignals(False)
|
||||||
@ -610,11 +674,14 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
if os.path.exists(outfile):
|
if os.path.exists(outfile):
|
||||||
if QtWidgets.QMessageBox.warning(self, 'Export graphic',
|
if QtWidgets.QMessageBox.warning(
|
||||||
|
self,
|
||||||
|
'Export graphic',
|
||||||
f'{os.path.split(outfile)[1]} already exists.\n'
|
f'{os.path.split(outfile)[1]} already exists.\n'
|
||||||
f'Do you REALLY want to replace it?',
|
f'Do you REALLY want to replace it?',
|
||||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
|
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
|
||||||
QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
QtWidgets.QMessageBox.No
|
||||||
|
) == QtWidgets.QMessageBox.No:
|
||||||
return
|
return
|
||||||
|
|
||||||
bg_color = self._bgcolor
|
bg_color = self._bgcolor
|
||||||
@ -656,16 +723,20 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
logger.exception(f'{item} could not exported because {e.args}')
|
logger.exception(f'{item} could not exported because {e.args}')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if item_dic:
|
||||||
if len(item) == 2:
|
if len(item) == 2:
|
||||||
# plot can show errorbars
|
# plot can show errorbars
|
||||||
|
if len(item_dic['x']):
|
||||||
item_dic['yerr'] = item[1].opts['topData']
|
item_dic['yerr'] = item[1].opts['topData']
|
||||||
|
else:
|
||||||
if item_dic:
|
item_dic['yerr'] = []
|
||||||
dic['items'].append(item_dic)
|
dic['items'].append(item_dic)
|
||||||
|
|
||||||
for item in self._external_items:
|
for item in self._external_items:
|
||||||
try:
|
try:
|
||||||
dic['items'].append(item.get_data_opts())
|
item_dic = item.get_data_opts()
|
||||||
|
if item_dic:
|
||||||
|
dic['items'].append(item_dic)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(f'{item} could not be exported because {e.args}')
|
logger.exception(f'{item} could not be exported because {e.args}')
|
||||||
continue
|
continue
|
||||||
@ -691,6 +762,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
'plots': (self.real_button.isChecked(), self.imag_button.isChecked(), self.error_button.isChecked()),
|
'plots': (self.real_button.isChecked(), self.imag_button.isChecked(), self.error_button.isChecked()),
|
||||||
'children': self.sets,
|
'children': self.sets,
|
||||||
'active': self._active,
|
'active': self._active,
|
||||||
|
'invert': (self.plotItem.vb.state['xInverted'], self.plotItem.vb.state['yInverted']),
|
||||||
}
|
}
|
||||||
|
|
||||||
in_legend = []
|
in_legend = []
|
||||||
@ -737,7 +809,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
|
|
||||||
graph.graphic.showGrid(x=state['grid'], y=state['grid'])
|
graph.graphic.showGrid(x=state['grid'], y=state['grid'])
|
||||||
|
|
||||||
graph.checkBox.setCheckState(QtCore.Qt.Checked if state['legend'] else QtCore.Qt.Unchecked)
|
graph.checkBox.setCheckState(QtCore.Qt.CheckState.Checked if state['legend'] else QtCore.Qt.CheckState.Unchecked)
|
||||||
|
|
||||||
graph.real_button.setChecked(state['plots'][0])
|
graph.real_button.setChecked(state['plots'][0])
|
||||||
graph.imag_button.setChecked(state['plots'][1])
|
graph.imag_button.setChecked(state['plots'][1])
|
||||||
@ -786,3 +858,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
self.set_color(foreground=self._prev_colors[0], background=self._prev_colors[1])
|
self.set_color(foreground=self._prev_colors[0], background=self._prev_colors[1])
|
||||||
self._prev_colors = temp
|
self._prev_colors = temp
|
||||||
|
|
||||||
|
|
||||||
|
def _inside_range(x: float, y: float, ranges: list[list[float]]) -> bool:
|
||||||
|
x_range, y_range = ranges
|
||||||
|
return (x_range[0] <= x <= x_range[1]) and (y_range[0] <= y <= y_range[1])
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from nmreval.io.asciireader import AsciiReader
|
from nmreval.io.asciireader import AsciiReader
|
||||||
from nmreval.utils import NUMBER_RE
|
from nmreval.utils import NUMBER_RE, numbers_from_string
|
||||||
|
|
||||||
from ..Qt import QtGui, QtCore, QtWidgets
|
from ..Qt import QtGui, QtCore, QtWidgets
|
||||||
from .._py.asciidialog import Ui_ascii_reader
|
from .._py.asciidialog import Ui_ascii_reader
|
||||||
@ -38,7 +38,7 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
self.changestaggeredrange(0)
|
self.changestaggeredrange(0)
|
||||||
|
|
||||||
self.ascii_table.contextMenuEvent = self.ctx_table
|
self.ascii_table.contextMenuEvent = self.ctx_table
|
||||||
self.ascii_table.horizontalHeader().setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
|
self.ascii_table.horizontalHeader().setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu)
|
||||||
self.ascii_table.horizontalHeader().customContextMenuRequested.connect(self.ctx_table)
|
self.ascii_table.horizontalHeader().customContextMenuRequested.connect(self.ctx_table)
|
||||||
|
|
||||||
self.skip = False
|
self.skip = False
|
||||||
@ -65,7 +65,7 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
self.set_column_names(1)
|
self.set_column_names(1)
|
||||||
|
|
||||||
self.skippy_checkbox.blockSignals(True)
|
self.skippy_checkbox.blockSignals(True)
|
||||||
self.skippy_checkbox.setCheckState(QtCore.Qt.Unchecked)
|
self.skippy_checkbox.setCheckState(QtCore.Qt.CheckState.Unchecked)
|
||||||
self.skippy_checkbox.blockSignals(False)
|
self.skippy_checkbox.blockSignals(False)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@ -132,7 +132,10 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
self.ascii_table.setHorizontalHeaderLabels(map(str, range(1, self.ascii_table.columnCount() + 1)))
|
self.ascii_table.setHorizontalHeaderLabels(map(str, range(1, self.ascii_table.columnCount() + 1)))
|
||||||
if self.column_checkBox.isChecked() and self.line_spinBox.isEnabled():
|
if self.column_checkBox.isChecked() and self.line_spinBox.isEnabled():
|
||||||
header_line = self.reader.header[self.line_spinBox.value()-1]
|
header_line = self.reader.header[self.line_spinBox.value()-1]
|
||||||
self.ascii_table.setHorizontalHeaderLabels(header_line.split())
|
header_line = header_line.strip('\n\t\r, ')
|
||||||
|
header_line = re.sub(r'[\t ;,]+', ';', header_line)
|
||||||
|
|
||||||
|
self.ascii_table.setHorizontalHeaderLabels(header_line.split(';'))
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_staggered_checkBox_stateChanged')
|
@QtCore.pyqtSlot(int, name='on_staggered_checkBox_stateChanged')
|
||||||
def changestaggeredrange(self, state: int):
|
def changestaggeredrange(self, state: int):
|
||||||
@ -178,11 +181,12 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def accept(self):
|
def accept(self):
|
||||||
if self.apply():
|
if self.apply():
|
||||||
self.close()
|
super().accept()
|
||||||
|
|
||||||
def apply(self):
|
def apply(self):
|
||||||
# default row for x is the first row, it will be superseded if an integer number is given.
|
# default row for x is the first row, it will be superseded if an integer number is given.
|
||||||
x = self.x_lineedit.text()
|
x = self.x_lineedit.text()
|
||||||
|
is_valid = True
|
||||||
if x:
|
if x:
|
||||||
try:
|
try:
|
||||||
x = int(x)-1
|
x = int(x)-1
|
||||||
@ -191,16 +195,35 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
else:
|
else:
|
||||||
x = None
|
x = None
|
||||||
|
|
||||||
|
if not self.check_column_numbers(x, max(self.reader.width)):
|
||||||
|
_ = QtWidgets.QMessageBox.information(self, 'Improper input',
|
||||||
|
f'Input for x axis is invalid')
|
||||||
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
y = [int(t)-1 for t in self.y_lineedit.text().split(' ')]
|
y = [int(t)-1 for t in self.y_lineedit.text().split(' ')]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
y = None
|
y = None
|
||||||
|
|
||||||
|
if not self.check_column_numbers(y, max(self.reader.width)):
|
||||||
|
_ = QtWidgets.QMessageBox.information(self, 'Improper input',
|
||||||
|
f'Input for y axis is invalid')
|
||||||
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
y_err = [int(t)-1 for t in self.deltay_lineEdit.text().split(' ')]
|
y_err = [int(t)-1 for t in self.deltay_lineEdit.text().split(' ')]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
y_err = None
|
y_err = None
|
||||||
|
|
||||||
|
mode = self.buttonGroup.checkedButton().text()
|
||||||
|
if mode != 'Points':
|
||||||
|
y_err = None
|
||||||
|
|
||||||
|
if not self.check_column_numbers(y, max(self.reader.width)):
|
||||||
|
_ = QtWidgets.QMessageBox.information(self, 'Improper input',
|
||||||
|
f'Input for y_err axis is invalid')
|
||||||
|
return False
|
||||||
|
|
||||||
col_header = None
|
col_header = None
|
||||||
if self.column_checkBox.isChecked():
|
if self.column_checkBox.isChecked():
|
||||||
col_header = []
|
col_header = []
|
||||||
@ -211,28 +234,29 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
col_header.append(i)
|
col_header.append(i)
|
||||||
|
|
||||||
if y is not None and col_header is not None:
|
if y is not None and col_header is not None:
|
||||||
col_header = [col_header[i] for i in range(len(col_header)) if i in y]
|
col_header = [col_header[i] for i in range(len(col_header))]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
ret_dic = self.reader.export(
|
ret_dic = self.reader.export(
|
||||||
x=x,
|
x=x,
|
||||||
y=y,
|
y=y,
|
||||||
yerr=y_err,
|
yerr=y_err,
|
||||||
mode=self.buttonGroup.checkedButton().text(),
|
mode=mode,
|
||||||
col_names=col_header,
|
col_names=col_header,
|
||||||
num_value=self.get_numerical_value(),
|
num_value=self.get_numerical_value(),
|
||||||
)
|
)
|
||||||
self.data_read.emit(ret_dic)
|
self.data_read.emit(ret_dic)
|
||||||
|
|
||||||
except ImportError as e:
|
except Exception as e:
|
||||||
_ = QtWidgets.QMessageBox.information(self, 'Reading failed',
|
_ = QtWidgets.QMessageBox.information(self, 'Reading failed',
|
||||||
f'Import data failed with {e.args}')
|
f'Import data failed with\n {e.args[0]}')
|
||||||
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_buttonGroup_buttonClicked')
|
@QtCore.pyqtSlot(int, name='on_buttonGroup_buttonClicked')
|
||||||
def show_error(self, val: int):
|
def show_error(self, val: int):
|
||||||
self.deltay_lineEdit.setEnabled(val == -3)
|
self.deltay_lineEdit.setEnabled(val == -2)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_skippy_checkbox_stateChanged')
|
@QtCore.pyqtSlot(int, name='on_skippy_checkbox_stateChanged')
|
||||||
def skip_next_dial(self, _: int):
|
def skip_next_dial(self, _: int):
|
||||||
@ -243,19 +267,31 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
if self.reader is None:
|
if self.reader is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
success = True
|
||||||
pattern = re.compile(pattern)
|
|
||||||
self.regex_input.setStyleSheet('color: rgb(0, 0, 0)')
|
|
||||||
self._matches = [m for m in pattern.finditer(str(self.reader.fname.stem))]
|
|
||||||
except re.error:
|
|
||||||
self._matches = []
|
self._matches = []
|
||||||
|
|
||||||
if self._matches:
|
if pattern:
|
||||||
|
try:
|
||||||
|
re_pattern = re.compile(pattern)
|
||||||
|
except re.error:
|
||||||
|
success = False
|
||||||
|
else:
|
||||||
|
self._matches = [m for m in re_pattern.finditer(str(self.reader.fname.stem))]
|
||||||
|
else:
|
||||||
|
success = False
|
||||||
|
|
||||||
|
# matches exist and have numbers in them
|
||||||
|
if self._matches and all([len(numbers_from_string(m.group())) for m in self._matches]):
|
||||||
self.re_match_index.blockSignals(True)
|
self.re_match_index.blockSignals(True)
|
||||||
self.re_match_index.setMaximum(len(self._matches))
|
self.re_match_index.setMaximum(len(self._matches))
|
||||||
self.re_match_index.blockSignals(False)
|
self.re_match_index.blockSignals(False)
|
||||||
else:
|
else:
|
||||||
self.regex_input.setStyleSheet('color: rgb(255, 0, 0)')
|
success = False
|
||||||
|
|
||||||
|
if success:
|
||||||
|
self.regex_input.setStyleSheet('color: rgb(0, 0, 0)')
|
||||||
|
else:
|
||||||
|
self.regex_input.setStyleSheet('background-color: rgba(255, 0, 0, 50)')
|
||||||
|
|
||||||
self.show_match(self.re_match_index.value())
|
self.show_match(self.re_match_index.value())
|
||||||
|
|
||||||
@ -269,12 +305,32 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
|||||||
else:
|
else:
|
||||||
self.label_8.setText(fname)
|
self.label_8.setText(fname)
|
||||||
|
|
||||||
def get_numerical_value(self):
|
def get_numerical_value(self) -> float:
|
||||||
val = 0
|
val = 0
|
||||||
if self.re_button.isChecked() and self._matches:
|
if self.re_button.isChecked() and self._matches:
|
||||||
m = self._matches[self.re_match_index.value()-1]
|
m = self._matches[self.re_match_index.value()-1]
|
||||||
val = float(NUMBER_RE.search(m.group()).group().replace('p', '.'))
|
val = numbers_from_string(m.group())
|
||||||
|
# numbers_from returns list of floats we use first match if available
|
||||||
|
val = val[0] if val else 0.0
|
||||||
elif self.custom_button.isChecked():
|
elif self.custom_button.isChecked():
|
||||||
val = float(self.custom_input.text())
|
val = float(self.custom_input.text())
|
||||||
|
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
def check_column_numbers(self, values: int | list[int] | str | None, num_column: int) -> bool:
|
||||||
|
is_valid = False
|
||||||
|
if values is None:
|
||||||
|
is_valid = True
|
||||||
|
elif values == 'index':
|
||||||
|
is_valid = True
|
||||||
|
|
||||||
|
elif isinstance(values, int):
|
||||||
|
is_valid = values < num_column
|
||||||
|
elif isinstance(values, list):
|
||||||
|
try:
|
||||||
|
is_valid = all(v < num_column for v in values)
|
||||||
|
except TypeError:
|
||||||
|
is_valid = False
|
||||||
|
|
||||||
|
return is_valid
|
||||||
|
|
||||||
|
@ -78,14 +78,22 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
for opts in self.sample.steps:
|
for opts in self.sample.steps:
|
||||||
item = QtWidgets.QListWidgetItem()
|
item = QtWidgets.QListWidgetItem()
|
||||||
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable)
|
item.setFlags(
|
||||||
item.setCheckState(QtCore.Qt.Unchecked)
|
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||||
|
)
|
||||||
|
item.setCheckState(QtCore.Qt.CheckState.Unchecked)
|
||||||
|
|
||||||
if opts[0] == 'i':
|
if opts[0] == 'i':
|
||||||
item.setFlags(QtCore.Qt.NoItemFlags)
|
item.setFlags(QtCore.Qt.ItemFlag.NoItemFlags)
|
||||||
item.setText(f'{opts[1]:.2f} K for {opts[2] / 60:.0f} min')
|
item.setText(f'{opts[1]:.2f} K for {opts[2] / 60:.0f} min')
|
||||||
else:
|
else:
|
||||||
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable)
|
item.setFlags(
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||||
|
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||||
|
)
|
||||||
item.setText(f'{opts[2]:.2f} K to {opts[3]:.2f} K with {opts[1]} K/min')
|
item.setText(f'{opts[2]:.2f} K to {opts[3]:.2f} K with {opts[1]} K/min')
|
||||||
|
|
||||||
self.step_listWidget.addItem(item)
|
self.step_listWidget.addItem(item)
|
||||||
@ -97,7 +105,12 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
if empty:
|
if empty:
|
||||||
self.empty = self.calibrator.set_measurement(empty, mode='empty')
|
self.empty = self.calibrator.set_measurement(empty, mode='empty')
|
||||||
|
|
||||||
|
# avoid ValueError breaking data update
|
||||||
|
if self.empty.fname.is_relative_to(Path.home()):
|
||||||
self.empty_label.setText('~/' + str(self.empty.fname.relative_to(Path.home())))
|
self.empty_label.setText('~/' + str(self.empty.fname.relative_to(Path.home())))
|
||||||
|
else:
|
||||||
|
self.empty_label.setText(str(self.empty.fname))
|
||||||
|
|
||||||
self.update_plots()
|
self.update_plots()
|
||||||
|
|
||||||
@ -118,8 +131,8 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
self.references.append(ref)
|
self.references.append(ref)
|
||||||
item = QtWidgets.QTableWidgetItem(str(ref.fname.name))
|
item = QtWidgets.QTableWidgetItem(str(ref.fname.name))
|
||||||
item.setData(QtCore.Qt.UserRole, ref.fname)
|
item.setData(QtCore.Qt.ItemDataRole.UserRole, ref.fname)
|
||||||
item.setFlags(QtCore.Qt.ItemIsEnabled)
|
item.setFlags(QtCore.Qt.ItemFlag.ItemIsEnabled)
|
||||||
|
|
||||||
rowcnt = self.reference_tableWidget.rowCount()
|
rowcnt = self.reference_tableWidget.rowCount()
|
||||||
self.reference_tableWidget.setRowCount(rowcnt+1)
|
self.reference_tableWidget.setRowCount(rowcnt+1)
|
||||||
@ -132,7 +145,7 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
@QtCore.pyqtSlot(name='on_ref_remove_pushButton_clicked')
|
@QtCore.pyqtSlot(name='on_ref_remove_pushButton_clicked')
|
||||||
def remove_reference(self):
|
def remove_reference(self):
|
||||||
idx = self.reference_tableWidget.currentRow()
|
idx = self.reference_tableWidget.currentRow()
|
||||||
self.calibrator.remove_reference(self.reference_tableWidget.item(idx, 0).data(QtCore.Qt.UserRole))
|
self.calibrator.remove_reference(self.reference_tableWidget.item(idx, 0).data(QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
self.reference_tableWidget.removeRow(idx)
|
self.reference_tableWidget.removeRow(idx)
|
||||||
self.update_plots()
|
self.update_plots()
|
||||||
@ -145,10 +158,10 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
for row in range(self.step_listWidget.count()):
|
for row in range(self.step_listWidget.count()):
|
||||||
if idx == row:
|
if idx == row:
|
||||||
continue
|
continue
|
||||||
self.step_listWidget.item(row).setCheckState(QtCore.Qt.Unchecked)
|
self.step_listWidget.item(row).setCheckState(QtCore.Qt.CheckState.Unchecked)
|
||||||
self.step_listWidget.blockSignals(False)
|
self.step_listWidget.blockSignals(False)
|
||||||
|
|
||||||
if item.checkState() == QtCore.Qt.Checked:
|
if item.checkState() == QtCore.Qt.CheckState.Checked:
|
||||||
mode, rate, _, _ = self.sample.steps[idx]
|
mode, rate, _, _ = self.sample.steps[idx]
|
||||||
self.current_run = (rate, mode)
|
self.current_run = (rate, mode)
|
||||||
self.sample_idx = idx
|
self.sample_idx = idx
|
||||||
@ -217,6 +230,8 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
if empty_data is not None:
|
if empty_data is not None:
|
||||||
self.empty_sample.setData(x=empty_data[0], y=empty_data[1])
|
self.empty_sample.setData(x=empty_data[0], y=empty_data[1])
|
||||||
|
else:
|
||||||
|
self.empty_sample.setData(x=[], y=[])
|
||||||
|
|
||||||
self.calib_graph.clear()
|
self.calib_graph.clear()
|
||||||
|
|
||||||
@ -249,11 +264,16 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if self.cp_checkBox.isChecked() and self.references:
|
||||||
|
y_label = 'cp'
|
||||||
|
else:
|
||||||
|
y_label = 'q'
|
||||||
|
|
||||||
rate, mode = self.current_run
|
rate, mode = self.current_run
|
||||||
new_val = DSC(sample_data[0], sample_data[1], value=rate, name=f'{self.fname.stem} {rate} ({mode})')
|
new_val = DSC(sample_data[0], sample_data[1], value=rate, name=f'{self.fname.stem} {rate}K-min ({mode}, {y_label})')
|
||||||
|
|
||||||
if filesave:
|
if filesave:
|
||||||
new_val.savetxt(self.fname.with_name(f'{self.fname.stem} {rate}K-min {mode}.dat'.replace(' ', '_')))
|
new_val.savetxt(self.fname.with_name(f'{self.fname.stem}_{rate}K-min_{y_label}{mode}.dat'.replace(' ', '_')))
|
||||||
close_after = False
|
close_after = False
|
||||||
else:
|
else:
|
||||||
self.data_read.emit([new_val])
|
self.data_read.emit([new_val])
|
||||||
|
@ -28,14 +28,19 @@ class GraceExporter:
|
|||||||
new_g.set_log(x=self.__opts['log'][0], y=self.__opts['log'][1])
|
new_g.set_log(x=self.__opts['log'][0], y=self.__opts['log'][1])
|
||||||
|
|
||||||
new_g.set_onoff('legend', self.__opts['legend'])
|
new_g.set_onoff('legend', self.__opts['legend'])
|
||||||
new_g.set_property(**{'title': f'"{convert(self.__opts["labels"][2], old="html", new="agr")}"',
|
new_g.set_property(**{
|
||||||
|
'title': f'"{convert(self.__opts["labels"][2], old="html", new="agr")}"',
|
||||||
'legend loctype': 'view',
|
'legend loctype': 'view',
|
||||||
'legend': ', '.join(str(i) for i in new_g.world_to_view(self.__opts['legend_pos']))})
|
'legend': ', '.join(str(i) for i in new_g.world_to_view(self.__opts['legend_pos']))
|
||||||
|
})
|
||||||
|
|
||||||
for i, ax in enumerate('xy'):
|
for i, ax in enumerate('xy'):
|
||||||
new_g.set_axis_property(ax, **{'label': f'"{convert(self.__opts["labels"][i], old="html", new="agr")}"',
|
new_g.set_axis_property(ax, **{
|
||||||
|
'label': f'"{convert(self.__opts["labels"][i], old="html", new="agr")}"',
|
||||||
'tick major': self.__opts['ticks'][i][0],
|
'tick major': self.__opts['ticks'][i][0],
|
||||||
'tick minor ticks': self.__opts['ticks'][i][1],})
|
'tick minor ticks': self.__opts['ticks'][i][1],
|
||||||
|
'invert': 'on' if self.__opts['invert'][i] else 'off',
|
||||||
|
})
|
||||||
new_g.set_axis_onoff(ax, 'tick major grid', self.__opts['grid'])
|
new_g.set_axis_onoff(ax, 'tick major grid', self.__opts['grid'])
|
||||||
g_idx = new_g.idx
|
g_idx = new_g.idx
|
||||||
else:
|
else:
|
||||||
@ -59,8 +64,13 @@ class GraceExporter:
|
|||||||
colors[c_num] = (f'color{c_num}', sc)
|
colors[c_num] = (f'color{c_num}', sc)
|
||||||
new_colors.append((c_num, f'color{c_num}', sc))
|
new_colors.append((c_num, f'color{c_num}', sc))
|
||||||
|
|
||||||
new_s.set_symbol(**{'symbol': item['symbol'].value, 'size': item['symbolsize'] / 10., 'color': c_num,
|
new_s.set_symbol(**{
|
||||||
'fill color': c_num, 'fill pattern': 1})
|
'symbol': item['symbol'].value,
|
||||||
|
'size': item['symbolsize'] / 10.,
|
||||||
|
'color': c_num,
|
||||||
|
'fill color': c_num,
|
||||||
|
'fill pattern': 1
|
||||||
|
})
|
||||||
new_s.set_onoff('errorbar', self.__opts['plots'][2])
|
new_s.set_onoff('errorbar', self.__opts['plots'][2])
|
||||||
|
|
||||||
lc = item['linecolor']
|
lc = item['linecolor']
|
||||||
@ -74,12 +84,17 @@ class GraceExporter:
|
|||||||
colors[c_num + 1] = ()
|
colors[c_num + 1] = ()
|
||||||
new_colors.append((c_num, f'color{c_num + 1}', sc))
|
new_colors.append((c_num, f'color{c_num + 1}', sc))
|
||||||
|
|
||||||
new_s.set_line(**{'color': c_num, 'linewidth': item['linewidth'],
|
new_s.set_line(**{
|
||||||
'linestyle': item['linestyle'].to_agr()})
|
'color': c_num,
|
||||||
|
'linewidth': item['linewidth'],
|
||||||
|
'linestyle': item['linestyle'].to_agr()
|
||||||
|
})
|
||||||
|
|
||||||
if plot_label:
|
if plot_label:
|
||||||
new_s.set_property(comment=f'"{item["name"]}"',
|
new_s.set_property(
|
||||||
legend=f'"{convert(item["name"], old="tex", new="agr")}"')
|
comment=f'"{item["name"]}"',
|
||||||
|
legend=f'"{convert(item["name"], old="tex", new="agr")}"'
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
new_s.set_property(comment=f'"{item["name"]}"')
|
new_s.set_property(comment=f'"{item["name"]}"')
|
||||||
|
|
||||||
|
@ -22,12 +22,22 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog):
|
|||||||
self.start_lineedit.setValidator(QtGui.QDoubleValidator())
|
self.start_lineedit.setValidator(QtGui.QDoubleValidator())
|
||||||
self.stop_lineedit.setValidator(QtGui.QDoubleValidator())
|
self.stop_lineedit.setValidator(QtGui.QDoubleValidator())
|
||||||
|
|
||||||
|
self.graph_checkbox.stateChanged.connect(
|
||||||
|
lambda x: self.graph_comboBox.setEnabled(x == QtCore.Qt.CheckState.Unchecked)
|
||||||
|
)
|
||||||
|
|
||||||
self.listWidget.installEventFilter(self)
|
self.listWidget.installEventFilter(self)
|
||||||
|
|
||||||
|
def __call__(self, path=None):
|
||||||
|
if path is None:
|
||||||
|
path = pathlib.Path().home()
|
||||||
|
self.path = path
|
||||||
|
self.listWidget.clear()
|
||||||
|
|
||||||
def eventFilter(self, src: QtCore.QObject, evt: QtCore.QEvent) -> bool:
|
def eventFilter(self, src: QtCore.QObject, evt: QtCore.QEvent) -> bool:
|
||||||
# intercept key press in listwidget to allow deletion with Del
|
# intercept key press in listwidget to allow deletion with Del
|
||||||
if evt.type() == QtCore.QEvent.KeyPress:
|
if evt.type() == QtCore.QEvent.Type.KeyPress:
|
||||||
if evt.key() == QtCore.Qt.Key_Delete:
|
if evt.key() == QtCore.Qt.Key.Key_Delete:
|
||||||
self.listWidget.takeItem(self.listWidget.currentRow())
|
self.listWidget.takeItem(self.listWidget.currentRow())
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -39,21 +49,25 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_region_checkBox_stateChanged')
|
@QtCore.pyqtSlot(int, name='on_region_checkBox_stateChanged')
|
||||||
def use_region(self, state: int):
|
def use_region(self, state: int):
|
||||||
self.start_lineedit.setEnabled(state == QtCore.Qt.Checked)
|
self.start_lineedit.setEnabled(state == QtCore.Qt.CheckState.Checked)
|
||||||
self.stop_lineedit.setEnabled(state == QtCore.Qt.Checked)
|
self.stop_lineedit.setEnabled(state == QtCore.Qt.CheckState.Checked)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_file_pushbutton_clicked')
|
@QtCore.pyqtSlot(name='on_file_pushbutton_clicked')
|
||||||
@QtCore.pyqtSlot(name='on_dir_pushbutton_clicked')
|
@QtCore.pyqtSlot(name='on_dir_pushbutton_clicked')
|
||||||
def get_input(self):
|
def get_input(self):
|
||||||
if self.sender() == self.file_pushbutton:
|
if self.sender() == self.file_pushbutton:
|
||||||
infiles, _ = QtWidgets.QFileDialog.getOpenFileNames(caption='Select HDF files',
|
infiles, _ = QtWidgets.QFileDialog.getOpenFileNames(
|
||||||
|
caption='Select HDF files',
|
||||||
directory=str(self.path),
|
directory=str(self.path),
|
||||||
filter='HDF files (*.h5)')
|
filter='HDF files (*.h5)',
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
infiles = QtWidgets.QFileDialog.getExistingDirectory(caption='Select input directory',
|
infiles = QtWidgets.QFileDialog.getExistingDirectory(
|
||||||
|
caption='Select input directory',
|
||||||
directory=str(self.path),
|
directory=str(self.path),
|
||||||
options=QtWidgets.QFileDialog.ShowDirsOnly)
|
options=QtWidgets.QFileDialog.ShowDirsOnly,
|
||||||
|
)
|
||||||
infiles = [infiles] if infiles else infiles
|
infiles = [infiles] if infiles else infiles
|
||||||
|
|
||||||
if infiles:
|
if infiles:
|
||||||
@ -63,9 +77,12 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_savebutton_clicked')
|
@QtCore.pyqtSlot(name='on_savebutton_clicked')
|
||||||
def save_path(self):
|
def save_path(self):
|
||||||
outfile = QtWidgets.QFileDialog.getExistingDirectory(self, caption='Select directory',
|
outfile = QtWidgets.QFileDialog.getExistingDirectory(
|
||||||
|
self,
|
||||||
|
caption='Select directory',
|
||||||
directory=self.label.text(),
|
directory=self.label.text(),
|
||||||
options=QtWidgets.QFileDialog.ShowDirsOnly)
|
options=QtWidgets.QFileDialog.ShowDirsOnly,
|
||||||
|
)
|
||||||
if outfile:
|
if outfile:
|
||||||
self.label.setText(outfile)
|
self.label.setText(outfile)
|
||||||
|
|
||||||
@ -82,11 +99,11 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog):
|
|||||||
if self.region_box.isChecked():
|
if self.region_box.isChecked():
|
||||||
start = None
|
start = None
|
||||||
if self.start_lineedit.text():
|
if self.start_lineedit.text():
|
||||||
start = float(self.start_lineedit.text())
|
start = float(self.start_lineedit.text())*1e-6
|
||||||
|
|
||||||
stop = None
|
stop = None
|
||||||
if self.stop_lineedit.text():
|
if self.stop_lineedit.text():
|
||||||
stop = float(self.stop_lineedit.text())
|
stop = float(self.stop_lineedit.text())*1e-6
|
||||||
region = (start, stop)
|
region = (start, stop)
|
||||||
|
|
||||||
fc_eval = FCReader(items)
|
fc_eval = FCReader(items)
|
||||||
@ -105,9 +122,10 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog):
|
|||||||
|
|
||||||
ret_vals = []
|
ret_vals = []
|
||||||
ret_vals.extend(fc_eval.get_parameter(path=self.label.text(), kind='temp', parameter=save_variables))
|
ret_vals.extend(fc_eval.get_parameter(path=self.label.text(), kind='temp', parameter=save_variables))
|
||||||
|
print(ret_vals)
|
||||||
|
|
||||||
grp = ''
|
grp = ''
|
||||||
if self.graph_checkbox.isChecked():
|
if not self.graph_checkbox.isChecked():
|
||||||
grp = self.graph_comboBox.currentData(QtCore.Qt.UserRole)
|
grp = self.graph_comboBox.currentData(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
self.data_read.emit(ret_vals, grp)
|
self.data_read.emit(ret_vals, grp)
|
||||||
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
from ..Qt import QtCore
|
from ..Qt import QtCore, QtWidgets
|
||||||
from .asciireader import QAsciiReader
|
from .asciireader import QAsciiReader
|
||||||
from .hdfreader import QHdfViewer
|
from .hdfreader import QHdfViewer
|
||||||
from .bdsreader import QBDSReader
|
from .bdsreader import QBDSReader
|
||||||
@ -26,8 +26,12 @@ class QFileReader(QtCore.QObject):
|
|||||||
self.reader = {}
|
self.reader = {}
|
||||||
|
|
||||||
for ext, reader in [
|
for ext, reader in [
|
||||||
('txt', QAsciiReader), ('dsc', QDSCReader), ('agr', QGraceReader),
|
('txt', QAsciiReader),
|
||||||
('bds', QBDSReader), ('hdf', QHdfViewer), ('nmr', QNMRReader)
|
('dsc', QDSCReader),
|
||||||
|
('agr', QGraceReader),
|
||||||
|
('bds', QBDSReader),
|
||||||
|
('hdf', QHdfViewer),
|
||||||
|
('nmr', QNMRReader),
|
||||||
]:
|
]:
|
||||||
self.register(ext, reader)
|
self.register(ext, reader)
|
||||||
|
|
||||||
@ -47,6 +51,7 @@ class QFileReader(QtCore.QObject):
|
|||||||
if not isinstance(fname, list):
|
if not isinstance(fname, list):
|
||||||
fname = [fname]
|
fname = [fname]
|
||||||
|
|
||||||
|
status = QtWidgets.QDialog.Accepted
|
||||||
for f in fname:
|
for f in fname:
|
||||||
f = Path(f)
|
f = Path(f)
|
||||||
dtype = self.guess_type(f)
|
dtype = self.guess_type(f)
|
||||||
@ -57,7 +62,10 @@ class QFileReader(QtCore.QObject):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# If QAsciiReader.skip = True it accepts automatically and returns None
|
# If QAsciiReader.skip = True it accepts automatically and returns None
|
||||||
r(f).exec()
|
if status == QtWidgets.QDialog.DialogCode.Rejected and isinstance(r, QAsciiReader) and self.reader['txt'].skip:
|
||||||
|
break
|
||||||
|
status = r(f).exec()
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
207
src/gui_qt/lib/backup.py
Normal file
207
src/gui_qt/lib/backup.py
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
import os
|
||||||
|
import sqlite3
|
||||||
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from nmreval.configs import config_paths
|
||||||
|
from ..Qt import QtCore, QtWidgets
|
||||||
|
|
||||||
|
DB_FILE = '/tmp/nmreval.db'
|
||||||
|
|
||||||
|
|
||||||
|
class BackupManager(QtCore.QObject):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.create_table()
|
||||||
|
self._pid = None
|
||||||
|
|
||||||
|
def create_table(self):
|
||||||
|
con = sqlite3.connect(DB_FILE)
|
||||||
|
con.execute(
|
||||||
|
"CREATE TABLE IF NOT EXISTS sessions "
|
||||||
|
"(pid INTEGER NOT NULL, backup_file TEXT NOT NULL, last_save TEXT);"
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_entry(self, pid: int):
|
||||||
|
backup_path = config_paths() / f'autosave_{datetime.now().strftime("%Y-%m-%d_%H%M%S")}_{pid}.nmr'
|
||||||
|
|
||||||
|
con = sqlite3.connect(DB_FILE)
|
||||||
|
con.execute('INSERT INTO sessions VALUES(?, ?, ?);',
|
||||||
|
(pid, str(backup_path), None))
|
||||||
|
con.commit()
|
||||||
|
con.close()
|
||||||
|
self._pid = pid
|
||||||
|
|
||||||
|
return backup_path
|
||||||
|
|
||||||
|
def update_last_save(self):
|
||||||
|
con = sqlite3.connect(DB_FILE)
|
||||||
|
con.execute(
|
||||||
|
'UPDATE sessions SET last_save = ? WHERE pid = ?',
|
||||||
|
(datetime.now().strftime("%Y-%m-%d %H:%M:%S"), self._pid)
|
||||||
|
)
|
||||||
|
con.commit()
|
||||||
|
con.close()
|
||||||
|
|
||||||
|
def search_unsaved(self):
|
||||||
|
con = sqlite3.connect(DB_FILE)
|
||||||
|
cursor = con.cursor()
|
||||||
|
res = cursor.execute('SELECT sessions.* FROM sessions;')
|
||||||
|
con.commit()
|
||||||
|
data = res.fetchall()
|
||||||
|
con.close()
|
||||||
|
|
||||||
|
missing_processes = []
|
||||||
|
|
||||||
|
for pid, fname, save_date in data:
|
||||||
|
try:
|
||||||
|
os.kill(pid, 0)
|
||||||
|
except ProcessLookupError:
|
||||||
|
if Path(fname).exists():
|
||||||
|
missing_processes.append((pid, fname, save_date))
|
||||||
|
else:
|
||||||
|
# remove entries without valid file
|
||||||
|
self.remove_row(pid)
|
||||||
|
|
||||||
|
if missing_processes:
|
||||||
|
msg = QLonelyBackupWindow()
|
||||||
|
msg.add_files(missing_processes)
|
||||||
|
msg.exec()
|
||||||
|
toberead = msg.recover
|
||||||
|
|
||||||
|
for pid in toberead[0]:
|
||||||
|
self.remove_file(pid)
|
||||||
|
|
||||||
|
for pid in toberead[1]:
|
||||||
|
self.remove_row(pid)
|
||||||
|
|
||||||
|
return list(toberead[1].values())
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
def remove_row(self, pid):
|
||||||
|
con = sqlite3.connect(DB_FILE)
|
||||||
|
con.execute('DELETE FROM sessions WHERE pid = ?', (pid,))
|
||||||
|
con.commit()
|
||||||
|
con.close()
|
||||||
|
|
||||||
|
def remove_file(self, pid: int = None):
|
||||||
|
if pid is None:
|
||||||
|
pid = self._pid
|
||||||
|
|
||||||
|
con = sqlite3.connect(DB_FILE)
|
||||||
|
cursor = con.cursor()
|
||||||
|
|
||||||
|
# remove backup file
|
||||||
|
res = cursor.execute('SELECT sessions.backup_file FROM sessions WHERE pid = ?', (pid,))
|
||||||
|
con.commit()
|
||||||
|
|
||||||
|
fname = Path(res.fetchone()[0])
|
||||||
|
con.close()
|
||||||
|
|
||||||
|
fname.unlink(missing_ok=True)
|
||||||
|
|
||||||
|
# because autosave backups in a *.nmr.0 file and then moves it to *.nmr we look also for this one.
|
||||||
|
fname.with_suffix('.nmr.0').unlink(missing_ok=True)
|
||||||
|
|
||||||
|
# after removal of file also remove entry
|
||||||
|
self.remove_row(pid)
|
||||||
|
|
||||||
|
def delete_db_if_empty(self):
|
||||||
|
con = sqlite3.connect(DB_FILE)
|
||||||
|
cursor = con.cursor()
|
||||||
|
res = cursor.execute('SELECT COUNT(sessions.pid) FROM sessions GROUP BY sessions.pid;')
|
||||||
|
con.commit()
|
||||||
|
|
||||||
|
remaining_processes = res.fetchone()
|
||||||
|
con.close()
|
||||||
|
if remaining_processes is None:
|
||||||
|
Path(DB_FILE).unlink()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.remove_file()
|
||||||
|
self.delete_db_if_empty()
|
||||||
|
|
||||||
|
|
||||||
|
class QLonelyBackupWindow(QtWidgets.QDialog):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
self.recover = [[], {}] # list of pid to delete, dict of files to read {pid: file}
|
||||||
|
|
||||||
|
self.setWindowTitle('Adopt a file!')
|
||||||
|
self.resize(720, 320)
|
||||||
|
|
||||||
|
layout = QtWidgets.QVBoxLayout(self)
|
||||||
|
self.label = QtWidgets.QLabel(self)
|
||||||
|
self.label.setText('Abandoned backup file(s) looking for a loving home!\n'
|
||||||
|
'(Files will all be loaded to same instance)')
|
||||||
|
layout.addWidget(self.label)
|
||||||
|
|
||||||
|
self.table = QtWidgets.QTableWidget(self)
|
||||||
|
self.table.setColumnCount(4)
|
||||||
|
self.table.setHorizontalHeaderLabels(['File name', 'Last saved', 'File size', 'Action'])
|
||||||
|
self.table.setGridStyle(QtCore.Qt.PenStyle.DashLine)
|
||||||
|
# self.table.horizontalHeader().setStretchLastSection(True)
|
||||||
|
self.table.verticalHeader().setVisible(False)
|
||||||
|
self.table.horizontalHeader().setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
|
||||||
|
layout.addWidget(self.table)
|
||||||
|
|
||||||
|
self.buttons = QtWidgets.QDialogButtonBox(self)
|
||||||
|
self.buttons.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
||||||
|
self.buttons.setStandardButtons(QtWidgets.QDialogButtonBox.Ok)
|
||||||
|
layout.addWidget(self.buttons)
|
||||||
|
|
||||||
|
self.buttons.accepted.connect(self.accept)
|
||||||
|
|
||||||
|
def add_files(self, entries):
|
||||||
|
self.table.setRowCount(len(entries))
|
||||||
|
for i, (pid, path, date) in enumerate(entries):
|
||||||
|
path = Path(path)
|
||||||
|
item1 = QtWidgets.QTableWidgetItem(path.name)
|
||||||
|
item1.setFlags(QtCore.Qt.ItemFlag.ItemIsEnabled)
|
||||||
|
item1.setData(QtCore.Qt.ItemDataRole.UserRole, pid)
|
||||||
|
item1.setData(QtCore.Qt.ItemDataRole.UserRole+1, path)
|
||||||
|
self.table.setItem(i, 0, item1)
|
||||||
|
|
||||||
|
item2 = QtWidgets.QTableWidgetItem(date)
|
||||||
|
item2.setFlags(QtCore.Qt.ItemFlag.ItemIsEnabled)
|
||||||
|
self.table.setItem(i, 1, item2)
|
||||||
|
|
||||||
|
size = path.stat().st_size
|
||||||
|
size_cnt = 0
|
||||||
|
while size > 1024:
|
||||||
|
# make file size human-readable
|
||||||
|
size /= 1024
|
||||||
|
size_cnt += 1
|
||||||
|
if size_cnt == 5:
|
||||||
|
break
|
||||||
|
|
||||||
|
byte = ['bytes', 'kB', 'MiB', 'GiB', 'TiB', 'PiB'][size_cnt]
|
||||||
|
|
||||||
|
item3 = QtWidgets.QTableWidgetItem(f'{size:.2f} {byte}')
|
||||||
|
item3.setFlags(QtCore.Qt.ItemFlag.ItemIsEnabled)
|
||||||
|
self.table.setItem(i, 2, item3)
|
||||||
|
|
||||||
|
cw = QtWidgets.QComboBox(self)
|
||||||
|
cw.addItems(['Load', 'Delete', 'Keep for later'])
|
||||||
|
self.table.setCellWidget(i, 3, cw)
|
||||||
|
|
||||||
|
self.table.resizeColumnsToContents()
|
||||||
|
|
||||||
|
def accept(self):
|
||||||
|
for i in range(self.table.rowCount()):
|
||||||
|
decision = self.table.cellWidget(i, 3).currentIndex()
|
||||||
|
item = self.table.item(i, 0)
|
||||||
|
pid = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
if decision == 0:
|
||||||
|
# load file
|
||||||
|
self.recover[1][pid] = item.data(QtCore.Qt.ItemDataRole.UserRole+1)
|
||||||
|
elif decision == 1:
|
||||||
|
# delete
|
||||||
|
self.recover[0].append(pid)
|
||||||
|
else:
|
||||||
|
# do nothing
|
||||||
|
pass
|
||||||
|
|
||||||
|
super().accept()
|
||||||
|
|
@ -1,17 +1,21 @@
|
|||||||
import sys
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from .codeeditor import _make_textformats
|
from PyQt5 import QtWidgets
|
||||||
|
|
||||||
|
from ..editors.codeeditor import _make_textformats
|
||||||
from ..Qt import QtWidgets, QtCore, QtGui
|
from ..Qt import QtWidgets, QtCore, QtGui
|
||||||
from nmreval.configs import config_paths
|
from nmreval.configs import config_paths
|
||||||
|
|
||||||
|
|
||||||
STYLES = {'INFO': _make_textformats('black'),
|
STYLES = {
|
||||||
|
'INFO': _make_textformats('black'),
|
||||||
'WARNING': _make_textformats('blue'),
|
'WARNING': _make_textformats('blue'),
|
||||||
'ERROR': _make_textformats('red', 'bold'),
|
'ERROR': _make_textformats('red', 'bold'),
|
||||||
'DEBUG': _make_textformats('black', 'italic'),
|
'DEBUG': _make_textformats('black', 'italic'),
|
||||||
'file': _make_textformats('red', 'italic'),
|
'file': _make_textformats('red', 'italic'),
|
||||||
'PyError': _make_textformats('red', 'bold-italic')}
|
'PyError': _make_textformats('red', 'bold-italic'),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class LogHighlighter(QtGui.QSyntaxHighlighter):
|
class LogHighlighter(QtGui.QSyntaxHighlighter):
|
||||||
@ -112,3 +116,28 @@ class QLog(QtWidgets.QDialog):
|
|||||||
|
|
||||||
for lines in text[-100:]:
|
for lines in text[-100:]:
|
||||||
self.plainTextEdit.appendPlainText(lines[:-1])
|
self.plainTextEdit.appendPlainText(lines[:-1])
|
||||||
|
|
||||||
|
|
||||||
|
class ConsoleDock(QtWidgets.QDockWidget):
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
|
self.code = QtWidgets.QPlainTextEdit(parent)
|
||||||
|
self.code.highlight = LogHighlighter(self.code.document())
|
||||||
|
self.code.setReadOnly(True)
|
||||||
|
self.code.setMaximumBlockCount(50)
|
||||||
|
self.setWidget(self.code)
|
||||||
|
|
||||||
|
|
||||||
|
class QTextHandler(logging.Handler):
|
||||||
|
def __init__(self, parent):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.console = ConsoleDock(parent)
|
||||||
|
self.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
|
||||||
|
self.setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
def emit(self, record):
|
||||||
|
msg = self.format(record)
|
||||||
|
self.console.code.appendPlainText(msg)
|
||||||
|
self.console.show()
|
||||||
|
@ -7,8 +7,11 @@ from ..graphs.graphwindow import QGraphWindow
|
|||||||
|
|
||||||
|
|
||||||
class MdiAreaTile(QtWidgets.QMdiArea):
|
class MdiAreaTile(QtWidgets.QMdiArea):
|
||||||
|
newData = QtCore.pyqtSignal(list)
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
|
self.setAcceptDrops(True)
|
||||||
|
|
||||||
def tileSubWindowsVertically(self):
|
def tileSubWindowsVertically(self):
|
||||||
window_list = self.subWindowList()
|
window_list = self.subWindowList()
|
||||||
@ -47,3 +50,8 @@ class MdiAreaTile(QtWidgets.QMdiArea):
|
|||||||
if isinstance(wdgt, QGraphWindow) and wdgt.id == key:
|
if isinstance(wdgt, QGraphWindow) and wdgt.id == key:
|
||||||
self.setActiveSubWindow(win)
|
self.setActiveSubWindow(win)
|
||||||
break
|
break
|
||||||
|
|
||||||
|
def dropEvent(self, evt):
|
||||||
|
if evt.mimeData().hasUrls():
|
||||||
|
files = [str(url.toLocalFile()) for url in evt.mimeData().urls()]
|
||||||
|
self.newData.emit(files)
|
||||||
|
@ -4,6 +4,8 @@ from collections import namedtuple
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
import nmreval
|
||||||
|
|
||||||
from nmreval import models
|
from nmreval import models
|
||||||
from nmreval.configs import config_paths
|
from nmreval.configs import config_paths
|
||||||
from nmreval.lib.importer import find_models, import_
|
from nmreval.lib.importer import find_models, import_
|
||||||
@ -22,17 +24,20 @@ class Namespace:
|
|||||||
|
|
||||||
if basic:
|
if basic:
|
||||||
self.add_namespace(
|
self.add_namespace(
|
||||||
{'x': (None, 'x values'),
|
{
|
||||||
|
'x': (None, 'x values'),
|
||||||
'y': (None, 'x values'),
|
'y': (None, 'x values'),
|
||||||
'y_err': (None, 'y error values'),
|
'y_err': (None, 'y error values'),
|
||||||
'fit': (None, 'dictionary of fit parameter', 'fit["PIKA"]'),
|
'fit': (None, 'dictionary of fit parameter', 'fit["PIKA"]'),
|
||||||
'np': (np, 'numpy module'),
|
'np': (np, 'numpy module'),
|
||||||
|
'nmreval': (nmreval, 'built-in classes and stuff')
|
||||||
},
|
},
|
||||||
parents=('Basic', 'General'),
|
parents=('Basic', 'General'),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.add_namespace(
|
self.add_namespace(
|
||||||
{'sin': (np.sin, 'Sine', 'sin(PIKA)'),
|
{
|
||||||
|
'sin': (np.sin, 'Sine', 'sin(PIKA)'),
|
||||||
'cos': (np.cos, 'Cosine', 'cos(PIKA)'),
|
'cos': (np.cos, 'Cosine', 'cos(PIKA)'),
|
||||||
'tan': (np.tan, 'Tangens', 'tan(PIKA)'),
|
'tan': (np.tan, 'Tangens', 'tan(PIKA)'),
|
||||||
'ln': (np.log, 'Natural Logarithm', 'ln(PIKA)'),
|
'ln': (np.log, 'Natural Logarithm', 'ln(PIKA)'),
|
||||||
@ -45,7 +50,8 @@ class Namespace:
|
|||||||
parents=('Basic', 'Functions'))
|
parents=('Basic', 'Functions'))
|
||||||
|
|
||||||
self.add_namespace(
|
self.add_namespace(
|
||||||
{'max': (np.max, 'Maximum value', 'max(PIKA)'),
|
{
|
||||||
|
'max': (np.max, 'Maximum value', 'max(PIKA)'),
|
||||||
'min': (np.min, 'Minimum value', 'min(PIKA)'),
|
'min': (np.min, 'Minimum value', 'min(PIKA)'),
|
||||||
'argmax': (np.argmax, 'Index of maximum value', 'argmax(PIKA)'),
|
'argmax': (np.argmax, 'Index of maximum value', 'argmax(PIKA)'),
|
||||||
'argmin': (np.argmax, 'Index of minimum value', 'argmin(PIKA)'),
|
'argmin': (np.argmax, 'Index of minimum value', 'argmin(PIKA)'),
|
||||||
@ -54,19 +60,24 @@ class Namespace:
|
|||||||
|
|
||||||
if const:
|
if const:
|
||||||
self.add_namespace(
|
self.add_namespace(
|
||||||
{'e': (constants.e, 'e / As'),
|
{
|
||||||
|
'e': (constants.e, 'e / As'),
|
||||||
'eps0': (constants.epsilon0, 'epsilon0 / As/Vm'),
|
'eps0': (constants.epsilon0, 'epsilon0 / As/Vm'),
|
||||||
'Eu': (constants.Eu,), 'h': (constants.h, 'h / eVs'),
|
'Eu': (constants.Eu,),
|
||||||
'hbar': (constants.hbar, 'hbar / eVs'), 'kB': (constants.kB, 'kB / eV/K'),
|
'h': (constants.h, 'h / eVs'),
|
||||||
'mu0': (constants.mu0, 'mu0 / Vs/Am'), 'NA': (constants.NA, 'NA / 1/mol'),
|
'hbar': (constants.hbar, 'hbar / eVs'),
|
||||||
'pi': (constants.pi,), 'R': (constants.R, 'R / eV'),
|
'kB': (constants.kB, 'kB / eV/K'),
|
||||||
|
'mu0': (constants.mu0, 'mu0 / Vs/Am'),
|
||||||
|
'NA': (constants.NA, 'NA / 1/mol'),
|
||||||
|
'pi': (constants.pi,),
|
||||||
|
'R': (constants.R, 'R / eV'),
|
||||||
},
|
},
|
||||||
parents=('Constants', 'Maybe useful'),
|
parents=('Constants', 'Maybe useful'),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.add_namespace(
|
self.add_namespace(
|
||||||
{f'gamma["{k}"]': (v, k, f'gamma["{k}"]') for k, v in constants.gamma.items()},
|
{f'gamma["{k}"]': (v, k, f'gamma["{k}"]') for k, v in constants.gamma.items()},
|
||||||
parents=('Constants', 'Magnetogyric ratios (in 1/(sT))')
|
parents=('Constants', 'Gyromagnetic ratios (in 1/(sT))')
|
||||||
)
|
)
|
||||||
|
|
||||||
if fitfuncs:
|
if fitfuncs:
|
||||||
@ -199,7 +210,7 @@ class QNamespaceWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
|
|
||||||
for entry in subspace:
|
for entry in subspace:
|
||||||
key_item = QtWidgets.QTableWidgetItem(entry)
|
key_item = QtWidgets.QTableWidgetItem(entry)
|
||||||
key_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
|
key_item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled)
|
||||||
|
|
||||||
vals = self.namespace.namespace[entry]
|
vals = self.namespace.namespace[entry]
|
||||||
|
|
||||||
@ -214,12 +225,12 @@ class QNamespaceWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
display = vals[1]
|
display = vals[1]
|
||||||
|
|
||||||
value_item = QtWidgets.QTableWidgetItem(display)
|
value_item = QtWidgets.QTableWidgetItem(display)
|
||||||
value_item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled)
|
value_item.setFlags(QtCore.Qt.ItemFlag.ItemIsSelectable | QtCore.Qt.ItemFlag.ItemIsEnabled)
|
||||||
|
|
||||||
key_item.setData(QtCore.Qt.UserRole, alias)
|
key_item.setData(QtCore.Qt.ItemDataRole.UserRole, alias)
|
||||||
key_item.setData(QtCore.Qt.UserRole+1, entry)
|
key_item.setData(QtCore.Qt.ItemDataRole.UserRole+1, entry)
|
||||||
value_item.setData(QtCore.Qt.UserRole, alias)
|
value_item.setData(QtCore.Qt.ItemDataRole.UserRole, alias)
|
||||||
value_item.setData(QtCore.Qt.UserRole+1, entry)
|
value_item.setData(QtCore.Qt.ItemDataRole.UserRole+1, entry)
|
||||||
|
|
||||||
row = self.namespace_table.rowCount()
|
row = self.namespace_table.rowCount()
|
||||||
self.namespace_table.setRowCount(row+1)
|
self.namespace_table.setRowCount(row+1)
|
||||||
@ -241,5 +252,5 @@ class QNamespaceWidget(QtWidgets.QWidget, Ui_Form):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(QtWidgets.QTableWidgetItem, name='on_namespace_table_itemDoubleClicked')
|
@QtCore.pyqtSlot(QtWidgets.QTableWidgetItem, name='on_namespace_table_itemDoubleClicked')
|
||||||
def item_selected(self, item: QtWidgets.QTableWidgetItem):
|
def item_selected(self, item: QtWidgets.QTableWidgetItem):
|
||||||
self.selected.emit(item.data(QtCore.Qt.UserRole))
|
self.selected.emit(item.data(QtCore.Qt.ItemDataRole.UserRole))
|
||||||
self.sendKey.emit(item.data(QtCore.Qt.UserRole+1))
|
self.sendKey.emit(item.data(QtCore.Qt.ItemDataRole.UserRole+1))
|
||||||
|
@ -183,6 +183,8 @@ class PlotItem(PlotDataItem):
|
|||||||
brush = self.opts['symbolBrush']
|
brush = self.opts['symbolBrush']
|
||||||
if isinstance(brush, tuple):
|
if isinstance(brush, tuple):
|
||||||
self.opts['symbolcolor'] = brush
|
self.opts['symbolcolor'] = brush
|
||||||
|
elif isinstance(brush, str):
|
||||||
|
self.opts['symbolcolor'] = int(f'0x{brush[1:3]}', 16), int(f'0x{brush[3:5]}', 16), int(f'0x{brush[5:7]}', 16)
|
||||||
else:
|
else:
|
||||||
c = brush.color()
|
c = brush.color()
|
||||||
self.opts['symbolcolor'] = c.red(), c.green(), c.blue()
|
self.opts['symbolcolor'] = c.red(), c.green(), c.blue()
|
||||||
@ -340,7 +342,8 @@ class PlotItem(PlotDataItem):
|
|||||||
|
|
||||||
opts = self.opts
|
opts = self.opts
|
||||||
item_dic = {
|
item_dic = {
|
||||||
'x': x, 'y': y,
|
'x': x,
|
||||||
|
'y': y,
|
||||||
'name': opts.get('name', ''),
|
'name': opts.get('name', ''),
|
||||||
'symbolsize': opts['symbolSize'],
|
'symbolsize': opts['symbolSize'],
|
||||||
}
|
}
|
||||||
|
556
src/gui_qt/lib/pokemon.py
Normal file
556
src/gui_qt/lib/pokemon.py
Normal file
@ -0,0 +1,556 @@
|
|||||||
|
import sqlite3
|
||||||
|
import urllib.request
|
||||||
|
from functools import cache
|
||||||
|
|
||||||
|
from PyQt5 import QtWidgets, QtGui, QtCore
|
||||||
|
from numpy.random import randint
|
||||||
|
|
||||||
|
from gui_qt._py.pokewindow import Ui_Dialog
|
||||||
|
from gui_qt._py.pokeentry import Ui_Form
|
||||||
|
|
||||||
|
|
||||||
|
def get_connection(db):
|
||||||
|
connection = sqlite3.connect(db)
|
||||||
|
connection.row_factory = sqlite3.Row
|
||||||
|
|
||||||
|
return connection
|
||||||
|
|
||||||
|
|
||||||
|
class QPoke(QtWidgets.QDialog, Ui_Dialog):
|
||||||
|
types = {None: ('', '')}
|
||||||
|
stats = {}
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
|
from importlib.resources import path
|
||||||
|
with path('resources', 'pokemon.sqlite') as fp:
|
||||||
|
self._db = str(fp)
|
||||||
|
PokemonEntry._db = str(fp)
|
||||||
|
|
||||||
|
self.setupUi(self)
|
||||||
|
|
||||||
|
self._fetch_names()
|
||||||
|
|
||||||
|
self.add_pokedexes()
|
||||||
|
|
||||||
|
self.tableWidget_2.itemSelectionChanged.connect(self.show_pokemon)
|
||||||
|
|
||||||
|
self.comboBox_2.currentIndexChanged.connect(self.collect_pokemon)
|
||||||
|
self.comboBox.currentIndexChanged.connect(self.collect_pokemon)
|
||||||
|
|
||||||
|
self.pushButton.clicked.connect(self.randomize)
|
||||||
|
|
||||||
|
self.collect_pokemon()
|
||||||
|
|
||||||
|
def _fetch_names(self):
|
||||||
|
connection = get_connection(self._db)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT * FROM types'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.comboBox.addItem('All types', -1)
|
||||||
|
for entry in cursor.fetchall():
|
||||||
|
self.types[entry['id']] = (entry['name_de'], entry['name_en'])
|
||||||
|
self.comboBox.addItem(entry['name_en'], entry['id'])
|
||||||
|
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
def add_pokedexes(self):
|
||||||
|
connection = get_connection(self._db)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute('SELECT * FROM pokedex_list')
|
||||||
|
|
||||||
|
for entry in cursor.fetchall():
|
||||||
|
self.comboBox_2.addItem(entry['name_en'], entry['id'])
|
||||||
|
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
def fill_list(self, idx: int = 0):
|
||||||
|
pokedex_id = self.comboBox_2.itemData(idx, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
pokedex = self.get_pokedex(pokedex_id)
|
||||||
|
|
||||||
|
self.tableWidget_2.clear()
|
||||||
|
self.tableWidget_2.setColumnCount(4)
|
||||||
|
self.tableWidget_2.setRowCount(0)
|
||||||
|
|
||||||
|
for pokemon in pokedex:
|
||||||
|
poke_id = pokemon['species_id']
|
||||||
|
row_count = self.tableWidget_2.rowCount()
|
||||||
|
self.tableWidget_2.setRowCount(row_count + 1)
|
||||||
|
item = QtWidgets.QTableWidgetItem(f'#{pokemon["entry_number"]:04d}')
|
||||||
|
item.setData(QtCore.Qt.ItemDataRole.UserRole, poke_id)
|
||||||
|
self.tableWidget_2.setItem(row_count, 0, item)
|
||||||
|
|
||||||
|
item = QtWidgets.QTableWidgetItem(pokemon['name_en'])
|
||||||
|
item.setToolTip(pokemon['name_de'])
|
||||||
|
self.tableWidget_2.setItem(row_count, 1, item)
|
||||||
|
|
||||||
|
poke_type = self.types[pokemon['type1']]
|
||||||
|
item = QtWidgets.QTableWidgetItem(poke_type[1])
|
||||||
|
item.setToolTip(poke_type[0])
|
||||||
|
self.tableWidget_2.setItem(row_count, 2, item)
|
||||||
|
|
||||||
|
try:
|
||||||
|
poke_type = self.types[pokemon['type2']]
|
||||||
|
item = QtWidgets.QTableWidgetItem(poke_type[1])
|
||||||
|
item.setToolTip(poke_type[0])
|
||||||
|
self.tableWidget_2.setItem(row_count, 3, item)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.tableWidget_2.resizeColumnsToContents()
|
||||||
|
|
||||||
|
def collect_pokemon(self, *args):
|
||||||
|
pokedex_id = self.comboBox_2.currentData(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
type_id = self.comboBox.currentData(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
|
connection = get_connection(self._db)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
if pokedex_id == 1:
|
||||||
|
if type_id == -1:
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT *, pokemon_list.species_id AS entry_number '
|
||||||
|
'FROM pokemon_list '
|
||||||
|
'ORDER BY entry_number'
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT *, pokemon_list.species_id AS entry_number '
|
||||||
|
'FROM pokemon_list '
|
||||||
|
'WHERE pokemon_list.type1 = ? OR pokemon_list.type2 = ? '
|
||||||
|
'ORDER BY entry_number',
|
||||||
|
(type_id, type_id)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if type_id == -1:
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT pokemon_list.*, pp.entry_number '
|
||||||
|
'FROM pokemon_list '
|
||||||
|
'JOIN pokedex_pokemon pp ON pp.species_id = pokemon_list.species_id '
|
||||||
|
'WHERE pp.pokedex_id = ? '
|
||||||
|
'ORDER BY pp.entry_number',
|
||||||
|
(pokedex_id,)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT pokemon_list.*, pp.entry_number '
|
||||||
|
'FROM pokemon_list '
|
||||||
|
'JOIN pokedex_pokemon pp ON pp.species_id = pokemon_list.species_id '
|
||||||
|
'WHERE pp.pokedex_id = ? AND (pokemon_list.type1 = ? OR pokemon_list.type2 = ?) '
|
||||||
|
'ORDER BY pp.entry_number',
|
||||||
|
(pokedex_id, type_id, type_id)
|
||||||
|
)
|
||||||
|
|
||||||
|
result = cursor.fetchall()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
self.fill_sorter(result)
|
||||||
|
|
||||||
|
def fill_sorter(self, result):
|
||||||
|
self.tableWidget_2.clearContents()
|
||||||
|
self.tableWidget_2.setRowCount(0)
|
||||||
|
|
||||||
|
self.tableWidget_2.setSortingEnabled(False)
|
||||||
|
|
||||||
|
for entry in result:
|
||||||
|
row = self.tableWidget_2.rowCount()
|
||||||
|
self.tableWidget_2.setRowCount(row+1)
|
||||||
|
|
||||||
|
item = QtWidgets.QTableWidgetItem(f"{entry['entry_number']:04d}")
|
||||||
|
item.setData(QtCore.Qt.ItemDataRole.UserRole, entry['species_id'])
|
||||||
|
item.setData(QtCore.Qt.ItemDataRole.UserRole+1, entry['pokemon_id'])
|
||||||
|
self.tableWidget_2.setItem(row, 0, item)
|
||||||
|
|
||||||
|
name_en = entry['name_en']
|
||||||
|
if entry['full_name_en']:
|
||||||
|
name_en = entry['full_name_en']
|
||||||
|
elif entry['form_en']:
|
||||||
|
name_en += f" {entry['form_en']}"
|
||||||
|
|
||||||
|
name_de = entry['name_de']
|
||||||
|
if entry['full_name_de']:
|
||||||
|
name_de = entry['full_name_de']
|
||||||
|
elif entry['form_de']:
|
||||||
|
name_de += f" {entry['form_de']}"
|
||||||
|
|
||||||
|
item = QtWidgets.QTableWidgetItem(name_en)
|
||||||
|
item.setToolTip(name_de)
|
||||||
|
self.tableWidget_2.setItem(row, 1, item)
|
||||||
|
|
||||||
|
type_en = []
|
||||||
|
type_de = []
|
||||||
|
for t_id in ('type1', 'type2'):
|
||||||
|
t_de, t_en = self.types[entry[t_id]]
|
||||||
|
if t_en:
|
||||||
|
type_en.append(t_en)
|
||||||
|
type_de.append(t_de)
|
||||||
|
|
||||||
|
item = QtWidgets.QTableWidgetItem(' / '.join(type_en))
|
||||||
|
item.setToolTip('\n'.join(type_en))
|
||||||
|
self.tableWidget_2.setItem(row, 2, item)
|
||||||
|
|
||||||
|
total = 0
|
||||||
|
for i, stat_name in enumerate(('hit_points', 'attack', 'defense', 'sp_atk', 'sp_def', 'speed')):
|
||||||
|
stat_value = entry[stat_name]
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
item.setData(QtCore.Qt.ItemDataRole.DisplayRole, stat_value)
|
||||||
|
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||||
|
self.tableWidget_2.setItem(row, i+4, item)
|
||||||
|
total += stat_value
|
||||||
|
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
item.setData(QtCore.Qt.ItemDataRole.DisplayRole, total)
|
||||||
|
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||||
|
self.tableWidget_2.setItem(row, 3, item)
|
||||||
|
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
item.setData(QtCore.Qt.ItemDataRole.DisplayRole, entry['height'] / 10)
|
||||||
|
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||||
|
self.tableWidget_2.setItem(row, 10, item)
|
||||||
|
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
item.setData(QtCore.Qt.ItemDataRole.DisplayRole, entry['weight'] / 10)
|
||||||
|
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||||
|
self.tableWidget_2.setItem(row, 11, item)
|
||||||
|
|
||||||
|
item = QtWidgets.QTableWidgetItem()
|
||||||
|
item.setData(QtCore.Qt.ItemDataRole.DisplayRole, round(entry['weight']/entry['height']**2 * 10, 2))
|
||||||
|
item.setTextAlignment(QtCore.Qt.AlignmentFlag.AlignRight | QtCore.Qt.AlignmentFlag.AlignVCenter)
|
||||||
|
self.tableWidget_2.setItem(row, 12, item)
|
||||||
|
|
||||||
|
self.tableWidget_2.resizeColumnToContents(1)
|
||||||
|
self.tableWidget_2.resizeColumnToContents(2)
|
||||||
|
self.tableWidget_2.setSortingEnabled(True)
|
||||||
|
|
||||||
|
def randomize(self):
|
||||||
|
select = randint(0, self.tableWidget_2.rowCount())
|
||||||
|
self.show_pokemon(select)
|
||||||
|
|
||||||
|
def show_pokemon(self, row: int = None):
|
||||||
|
table = self.tableWidget_2
|
||||||
|
if row is None:
|
||||||
|
row = table.currentRow()
|
||||||
|
|
||||||
|
species_id = table.item(row, 0).data(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
poke_id = table.item(row, 0).data(QtCore.Qt.ItemDataRole.UserRole+1)
|
||||||
|
pokemon_name = table.item(row, 1).text()
|
||||||
|
|
||||||
|
connection = get_connection(self._db)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT p.id FROM pokemon p WHERE p.species_id = ?',
|
||||||
|
(species_id,)
|
||||||
|
)
|
||||||
|
|
||||||
|
pokemon = cursor.fetchall()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
self.tabWidget.setCurrentIndex(0)
|
||||||
|
for i in range(1, self.tabWidget.count()):
|
||||||
|
self.tabWidget.setTabVisible(i, False)
|
||||||
|
|
||||||
|
widget_idx = 0
|
||||||
|
|
||||||
|
for i, p in enumerate(pokemon):
|
||||||
|
entry_widget = self.tabWidget.widget(i)
|
||||||
|
|
||||||
|
if poke_id == p[0]:
|
||||||
|
widget_idx = i
|
||||||
|
|
||||||
|
if entry_widget is None:
|
||||||
|
self.tabWidget.addTab(PokemonEntry(p[0]), '')
|
||||||
|
|
||||||
|
self.tabWidget.setTabText(i, pokemon_name)
|
||||||
|
self.tabWidget.setTabVisible(i, True)
|
||||||
|
name = self.tabWidget.widget(i).create_pokemon(p[0])
|
||||||
|
self.tabWidget.setTabText(i, name)
|
||||||
|
self.tabWidget.setCurrentIndex(widget_idx)
|
||||||
|
|
||||||
|
|
||||||
|
class PokemonEntry(QtWidgets.QWidget, Ui_Form):
|
||||||
|
_db = ''
|
||||||
|
|
||||||
|
def __init__(self, pokemon_id: int, parent=None):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
|
||||||
|
self.setupUi(self)
|
||||||
|
|
||||||
|
self.bars = [
|
||||||
|
None, self.hp_bar, self.attack_bar, self.defense_bar, self.spec_attack_bar, self.spec_defense_bar, self.speed_bar
|
||||||
|
]
|
||||||
|
self.ability_labels = [None, self.ability1_label, self.ability2_label, self.ability3_label]
|
||||||
|
self.type_labels = [None, self.type1_label, self.type2_label]
|
||||||
|
|
||||||
|
self.create_pokemon(pokemon_id)
|
||||||
|
|
||||||
|
def create_pokemon(self, poke_id):
|
||||||
|
pokemon = self.get_pokemon(poke_id)
|
||||||
|
species = self.get_species(pokemon['species_id'])
|
||||||
|
|
||||||
|
self.nationaldex_label.setText(f"{pokemon['species_id']:04d}")
|
||||||
|
|
||||||
|
self.species_label.setText(species['genus_en'])
|
||||||
|
self.species_label.setToolTip(species['genus_de'])
|
||||||
|
|
||||||
|
self.height_label.setText(f"{pokemon['height'] / 10} m")
|
||||||
|
self.weight_label.setText(f"{pokemon['weight'] / 10} kg")
|
||||||
|
|
||||||
|
if species['gender_ratio'] == -1:
|
||||||
|
gender = "Gender unknown"
|
||||||
|
else:
|
||||||
|
gender = f"{species['gender_ratio']*12.5:0.2f}% female, {100-species['gender_ratio']*12.5:0.2f}% male"
|
||||||
|
|
||||||
|
self.gender_label.setText(gender)
|
||||||
|
|
||||||
|
if not QtGui.QPixmapCache.find(str(poke_id)):
|
||||||
|
image = b''
|
||||||
|
if pokemon['artwork'] is not None:
|
||||||
|
try:
|
||||||
|
res = urllib.request.urlopen(pokemon['artwork'])
|
||||||
|
image = res.read()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
pixmap = QtGui.QPixmap()
|
||||||
|
pixmap.loadFromData(image)
|
||||||
|
sc_pixmap = pixmap.scaled(400, 400, QtCore.Qt.AspectRatioMode.KeepAspectRatio)
|
||||||
|
|
||||||
|
QtGui.QPixmapCache.insert(str(poke_id), sc_pixmap)
|
||||||
|
|
||||||
|
self.artwork_label.setPixmap(QtGui.QPixmapCache.find(str(poke_id)))
|
||||||
|
|
||||||
|
stats = self.get_stats(poke_id)
|
||||||
|
for (stat_id, stat_value) in stats:
|
||||||
|
self.bars[stat_id].setValue(stat_value)
|
||||||
|
|
||||||
|
abilities = self.get_abilities(poke_id)
|
||||||
|
for lab in self.ability_labels[1:]:
|
||||||
|
lab.setVisible(False)
|
||||||
|
for (slot, is_hidden, name_de, name_en) in abilities:
|
||||||
|
self.ability_labels[slot].setVisible(True)
|
||||||
|
t = name_en
|
||||||
|
if is_hidden:
|
||||||
|
t += ' (hidden ability)'
|
||||||
|
self.ability_labels[slot].setText(t)
|
||||||
|
self.ability_labels[slot].setToolTip(name_de)
|
||||||
|
|
||||||
|
form, types = self.get_form_and_type(poke_id)
|
||||||
|
for lab in self.type_labels[1:]:
|
||||||
|
lab.setVisible(False)
|
||||||
|
|
||||||
|
for (type_id, slot) in types:
|
||||||
|
self.type_labels[slot].setVisible(True)
|
||||||
|
self.type_labels[slot].setText(QPoke.types[type_id][1])
|
||||||
|
self.type_labels[slot].setToolTip(QPoke.types[type_id][0])
|
||||||
|
|
||||||
|
evolutions = self.make_evolution(pokemon['evolution_id'])
|
||||||
|
|
||||||
|
self.tableWidget.clear()
|
||||||
|
self.tableWidget.setColumnCount(4)
|
||||||
|
self.tableWidget.setRowCount(len(evolutions))
|
||||||
|
|
||||||
|
for i, e in enumerate(evolutions):
|
||||||
|
item = QtWidgets.QTableWidgetItem(f'{e[0]} (#{e[1]:04d})')
|
||||||
|
self.tableWidget.setItem(i, 0, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem('to')
|
||||||
|
self.tableWidget.setItem(i, 1, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem(f'{e[2]} (#{e[3]:04d})')
|
||||||
|
self.tableWidget.setItem(i, 2, item)
|
||||||
|
item = QtWidgets.QTableWidgetItem(f'{e[4]}')
|
||||||
|
self.tableWidget.setItem(i, 3, item)
|
||||||
|
|
||||||
|
self.tableWidget.resizeColumnsToContents()
|
||||||
|
self.tableWidget.resizeRowsToContents()
|
||||||
|
|
||||||
|
if form['full_name_en'] is not None:
|
||||||
|
return form['full_name_en']
|
||||||
|
elif form['form_en'] is not None:
|
||||||
|
return f"{species['name_en']} ({form['form_en']})"
|
||||||
|
else:
|
||||||
|
return species['name_en']
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_pokedex(self, pokedex_id):
|
||||||
|
connection = get_connection(self._db)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT pokemon_list.*, pp.entry_number FROM pokemon_list '
|
||||||
|
'JOIN pokedex_pokemon pp ON pp.species_id = pokemon_list.species_id '
|
||||||
|
'WHERE pp.pokedex_id = ? '
|
||||||
|
'ORDER BY pp.entry_number',
|
||||||
|
(pokedex_id,)
|
||||||
|
)
|
||||||
|
res = cursor.fetchall()
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_abilities(self, pokemon_id):
|
||||||
|
conn = get_connection(self._db)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT slot, ís_hidden, name_de, name_en FROM pokemon_ability '
|
||||||
|
'JOIN main.ability ON pokemon_ability.ability_id = ability.id '
|
||||||
|
'WHERE pokemon_id = ?',
|
||||||
|
(pokemon_id,)
|
||||||
|
)
|
||||||
|
|
||||||
|
abilities = cursor.fetchall()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return abilities
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_pokemon(self, poke_id):
|
||||||
|
connection = get_connection(self._db)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT p.species_id, p.height, p.weight, p.artwork, p.evolution_id FROM pokemon p WHERE p.id = ?',
|
||||||
|
(poke_id,)
|
||||||
|
)
|
||||||
|
pokemon = cursor.fetchone()
|
||||||
|
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
return pokemon
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_species(self, species_id):
|
||||||
|
connection = get_connection(self._db)
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT s.id, s.name_en, s.name_de, s.genus_de, s.genus_en, s.color_id, s.is_mythical, s.is_legendary, s.generation, s.gender_ratio '
|
||||||
|
'FROM species s '
|
||||||
|
'WHERE s.id = ?',
|
||||||
|
(species_id,)
|
||||||
|
)
|
||||||
|
|
||||||
|
species = cursor.fetchone()
|
||||||
|
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
return species
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_stats(self, pokemon_id):
|
||||||
|
conn = get_connection(self._db)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT stat_id, value FROM pokemon_stat WHERE pokemon_id = ?',
|
||||||
|
(pokemon_id,)
|
||||||
|
)
|
||||||
|
stats = cursor.fetchall()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return stats
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def get_form_and_type(self, pokemon_id):
|
||||||
|
conn = get_connection(self._db)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT id, full_name_en, form_en FROM form WHERE pokemon_id = ? AND is_default = 1',
|
||||||
|
(pokemon_id,)
|
||||||
|
)
|
||||||
|
|
||||||
|
form = cursor.fetchone()
|
||||||
|
|
||||||
|
cursor.execute(
|
||||||
|
'SELECT type_id, slot FROM form_type WHERE form_id = ?',
|
||||||
|
(form['id'],)
|
||||||
|
)
|
||||||
|
types = cursor.fetchall()
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return form, types
|
||||||
|
|
||||||
|
@cache
|
||||||
|
def make_evolution(self, poke_id: int):
|
||||||
|
steps = []
|
||||||
|
|
||||||
|
conn = get_connection(self._db)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
cursor.execute('SELECT * FROM evolution_names WHERE id = ?', (poke_id,))
|
||||||
|
chain = cursor.fetchall()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
trigger_texts = [
|
||||||
|
None,
|
||||||
|
'Level up',
|
||||||
|
'Trade',
|
||||||
|
'',
|
||||||
|
'Empty spot in party',
|
||||||
|
'Spin',
|
||||||
|
'Train in the Tower of Darkness',
|
||||||
|
'Train in the Tower of Water',
|
||||||
|
'Land three critical hits in a battle',
|
||||||
|
'Go somewhere after taking damage',
|
||||||
|
'',
|
||||||
|
'Use Psyshield Bash 20 times in Agile Style',
|
||||||
|
'Use Barb Barrage 20 times in Strong Style',
|
||||||
|
'Receive 294 recoil damage in battle',
|
||||||
|
]
|
||||||
|
|
||||||
|
special_pokemon = {
|
||||||
|
24: 'Use Rage Fist 20 times',
|
||||||
|
317: "Defeat 3 Bisharp that are holding Leader's Crest",
|
||||||
|
528: 'Collect 999 Coins from Roaming Form',
|
||||||
|
484: "Walk 1,000 steps in Let's Go mode",
|
||||||
|
485: "Walk 1,000 steps in Let's Go mode",
|
||||||
|
495: "Walk 1,000 steps in Let's Go mode",
|
||||||
|
499: "Walk 1,000 steps in Let's Go mode",
|
||||||
|
504: "Level up while in multiplayer"
|
||||||
|
}
|
||||||
|
|
||||||
|
condition_text = {
|
||||||
|
'min_level': lambda x: f"Lv. {x['min_level']}",
|
||||||
|
'min_happiness': lambda _: f"high Friendship",
|
||||||
|
'min_beauty': lambda _: f"needs max. Beauty",
|
||||||
|
'min_affection': lambda x: f"{x['min_affection']} Affection",
|
||||||
|
'location_en': lambda x: f"at {x['location_en']}",
|
||||||
|
'held_item_en': lambda x: f"hold {x['held_item_en']}",
|
||||||
|
'item_en': lambda x: f'Use {x["item_en"]}',
|
||||||
|
'known_move_en': lambda x: f"know {x['known_move_en']}",
|
||||||
|
'move_type_en': lambda x: f"know {x['move_type_en']} move",
|
||||||
|
'party_species_en': lambda x: f"{x['party_species_en']} in party",
|
||||||
|
'party_type_en': lambda x: f"{x['party_type_en']} in party",
|
||||||
|
'time_of_day': lambda x: f"at {x['time_of_day']}",
|
||||||
|
'trade_species_en': lambda x: f"with {x['trade_species_en']}",
|
||||||
|
'needs_rain': lambda _: 'during rain',
|
||||||
|
'upside_down': lambda _: 'hold controller upside-down',
|
||||||
|
'relative_stats': lambda x: {1: 'attack > defense', 0: 'attack = defense', -1: 'attack < defense'}[x['relative_stats']],
|
||||||
|
}
|
||||||
|
|
||||||
|
for c in chain:
|
||||||
|
lvl0 = c["name_en"]
|
||||||
|
if c['gender'] == 1:
|
||||||
|
lvl0 += ' (female)'
|
||||||
|
elif c['gender'] == 2:
|
||||||
|
lvl0 += ' (male)'
|
||||||
|
|
||||||
|
trig = c['trigger']
|
||||||
|
|
||||||
|
if trig == 10:
|
||||||
|
level_text = [special_pokemon[poke_id]]
|
||||||
|
else:
|
||||||
|
level_text = [trigger_texts[trig]]
|
||||||
|
|
||||||
|
for k, v in condition_text.items():
|
||||||
|
if c[k] is not None:
|
||||||
|
level_text.append(v(c))
|
||||||
|
|
||||||
|
steps.append(
|
||||||
|
(lvl0, c['evolves_from'], c['evolve_en'], c['species_id'], ', '.join(filter(lambda x: x, level_text)))
|
||||||
|
)
|
||||||
|
|
||||||
|
return steps
|
@ -34,9 +34,9 @@ class SciSpinBox(QtWidgets.QDoubleSpinBox):
|
|||||||
|
|
||||||
new_value = self._prev_value
|
new_value = self._prev_value
|
||||||
if new_value != 0.0:
|
if new_value != 0.0:
|
||||||
new_value *= 10**(step/19.)
|
new_value *= 10**(step/99.)
|
||||||
else:
|
else:
|
||||||
new_value = 0.001
|
new_value = 0.00001
|
||||||
|
|
||||||
self.setValue(new_value)
|
self.setValue(new_value)
|
||||||
self.lineEdit().setText(f'{new_value:.3e}')
|
self.lineEdit().setText(f'{new_value:.3e}')
|
||||||
|
288
src/gui_qt/lib/update.py
Normal file
288
src/gui_qt/lib/update.py
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import urllib.request
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from os import getenv, stat
|
||||||
|
from os.path import exists
|
||||||
|
from pathlib import Path
|
||||||
|
from urllib.error import HTTPError
|
||||||
|
|
||||||
|
from PyQt5 import QtWidgets, QtCore
|
||||||
|
|
||||||
|
from nmreval.lib.logger import logger
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateDialog(QtWidgets.QDialog):
|
||||||
|
startDownload = QtCore.pyqtSignal(tuple)
|
||||||
|
restartSignal = QtCore.pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, filename: str = None, parent=None):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
self._init_ui()
|
||||||
|
|
||||||
|
if filename is None:
|
||||||
|
filename = getenv('APPIMAGE')
|
||||||
|
self._appfile = filename
|
||||||
|
|
||||||
|
self.updater = Updater()
|
||||||
|
|
||||||
|
self.thread = QtCore.QThread(self)
|
||||||
|
self.thread.start()
|
||||||
|
self.helper = Downloader()
|
||||||
|
self.startDownload.connect(self.helper.run_download)
|
||||||
|
self.helper.progressChanged.connect(self.status.setText)
|
||||||
|
self.helper.finished.connect(self.finish_update)
|
||||||
|
self.helper.started.connect(self.status.show)
|
||||||
|
self.helper.moveToThread(self.thread)
|
||||||
|
|
||||||
|
self.look_for_updates(self._appfile)
|
||||||
|
|
||||||
|
def _init_ui(self):
|
||||||
|
self.setWindowTitle('Updates')
|
||||||
|
|
||||||
|
layout = QtWidgets.QVBoxLayout()
|
||||||
|
|
||||||
|
self.label = QtWidgets.QLabel()
|
||||||
|
layout.addWidget(self.label)
|
||||||
|
|
||||||
|
layout.addSpacing(10)
|
||||||
|
|
||||||
|
self.status = QtWidgets.QLabel()
|
||||||
|
self.status.hide()
|
||||||
|
layout.addWidget(self.status)
|
||||||
|
layout.addSpacing(10)
|
||||||
|
|
||||||
|
self.dialog_button = QtWidgets.QDialogButtonBox()
|
||||||
|
self.dialog_button.accepted.connect(self.update_appimage)
|
||||||
|
self.dialog_button.rejected.connect(self.close)
|
||||||
|
layout.addWidget(self.dialog_button)
|
||||||
|
|
||||||
|
self.setLayout(layout)
|
||||||
|
|
||||||
|
def look_for_updates(self, filename=None):
|
||||||
|
logger.info(f'Looking for updates, compare to file {filename}')
|
||||||
|
# Download zsync file of latest Appimage, look for SHA-1 hash and compare with hash of AppImage
|
||||||
|
is_updateble, m_time_file, m_time_zsync = self.updater.get_update_information(filename)
|
||||||
|
|
||||||
|
label_text = ''
|
||||||
|
|
||||||
|
if is_updateble is None:
|
||||||
|
label_text += '<p>Could not determine if this version is newer, please update manually (if necessary).</p>'
|
||||||
|
dialog_bttns = QtWidgets.QDialogButtonBox.Close
|
||||||
|
elif is_updateble:
|
||||||
|
label_text += '<p>Different version available. Press Ok to download this version, Cancel to ignore.</p>'
|
||||||
|
dialog_bttns = QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel
|
||||||
|
else:
|
||||||
|
label_text += '<p>Version may be already up-to-date.</p>'
|
||||||
|
dialog_bttns = QtWidgets.QDialogButtonBox.Close
|
||||||
|
|
||||||
|
if m_time_zsync is None:
|
||||||
|
label_text += '<p>Creation date of remote version is unknown.</p>'
|
||||||
|
else:
|
||||||
|
label_text += f'<p>Date of most recent AppImage: {m_time_zsync.strftime("%d %B %Y %H:%M")}</p>'
|
||||||
|
|
||||||
|
if m_time_file is None:
|
||||||
|
label_text += 'No AppImage file found, press Ok to download latest version.'
|
||||||
|
dialog_bttns = QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Close
|
||||||
|
else:
|
||||||
|
label_text += f'<p>Date of used AppImage: {m_time_file.strftime("%d %B %Y %H:%M")}</p>'
|
||||||
|
|
||||||
|
self.label.setText(label_text)
|
||||||
|
self.dialog_button.setStandardButtons(dialog_bttns)
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot()
|
||||||
|
def update_appimage(self):
|
||||||
|
if self._appfile is None:
|
||||||
|
args = (self.updater.zsync_url,)
|
||||||
|
else:
|
||||||
|
# this breaks the download for some reason
|
||||||
|
args = (self.updater.zsync_url, self._appfile)
|
||||||
|
|
||||||
|
self.dialog_button.setEnabled(False)
|
||||||
|
|
||||||
|
self.startDownload.emit(args)
|
||||||
|
self.status.show()
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(int, str)
|
||||||
|
def finish_update(self, retcode: int, file_loc: str):
|
||||||
|
restart = QRestartWindow(state=retcode, file_loc=file_loc, parent=self)
|
||||||
|
res = restart.exec()
|
||||||
|
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
if res == QtWidgets.QMessageBox.Ok:
|
||||||
|
self.restartSignal.emit()
|
||||||
|
|
||||||
|
def closeEvent(self, evt):
|
||||||
|
self.thread.quit()
|
||||||
|
self.thread.wait()
|
||||||
|
|
||||||
|
super().closeEvent(evt)
|
||||||
|
|
||||||
|
|
||||||
|
class QRestartWindow(QtWidgets.QMessageBox):
|
||||||
|
def __init__(self, state: int, file_loc: str, parent=None):
|
||||||
|
super().__init__(parent=parent)
|
||||||
|
self._appfile = file_loc
|
||||||
|
|
||||||
|
if state:
|
||||||
|
self.setText('Download failed')
|
||||||
|
self.setDetailedText(f'Status code of failure is {state}')
|
||||||
|
self.setStandardButtons(QtWidgets.QMessageBox.Close)
|
||||||
|
self.setIcon(QtWidgets.QMessageBox.Warning)
|
||||||
|
else:
|
||||||
|
self.setText('Download completed!')
|
||||||
|
self.setInformativeText("Press Restart to use new AppImage")
|
||||||
|
self.setDetailedText(f'Location of AppImage: {file_loc}')
|
||||||
|
|
||||||
|
self.setIcon(QtWidgets.QMessageBox.Information)
|
||||||
|
|
||||||
|
self.setStandardButtons(QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Close)
|
||||||
|
restart_button = self.button(QtWidgets.QMessageBox.Ok)
|
||||||
|
restart_button.setText('Restart')
|
||||||
|
|
||||||
|
self.buttonClicked.connect(self.maybe_close)
|
||||||
|
|
||||||
|
def maybe_close(self):
|
||||||
|
if self.clickedButton() == self.button(QtWidgets.QMessageBox.Ok):
|
||||||
|
app = QtWidgets.QApplication.instance()
|
||||||
|
app.quit()
|
||||||
|
subprocess.Popen(self._appfile)
|
||||||
|
|
||||||
|
|
||||||
|
class Downloader(QtCore.QObject):
|
||||||
|
started = QtCore.pyqtSignal()
|
||||||
|
finished = QtCore.pyqtSignal(int, str)
|
||||||
|
progressChanged = QtCore.pyqtSignal(str)
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(tuple)
|
||||||
|
def run_download(self, args: tuple[str]):
|
||||||
|
status = 0
|
||||||
|
appimage_location = args[0][:-6]
|
||||||
|
logger.info(f'Download {appimage_location}')
|
||||||
|
if len(args) == 2:
|
||||||
|
new_file = Path(args[1])
|
||||||
|
else:
|
||||||
|
new_file = Path.home() / 'Downloads' / 'NMReval-latest-x86_64.AppImage'
|
||||||
|
|
||||||
|
if new_file.exists():
|
||||||
|
os.rename(new_file, new_file.with_suffix('.AppImage.old'))
|
||||||
|
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(appimage_location) as response:
|
||||||
|
with new_file.open('wb') as f:
|
||||||
|
f.write(response.read())
|
||||||
|
|
||||||
|
new_file.chmod(0o755)
|
||||||
|
except HTTPError as e:
|
||||||
|
logger.exception(f'Download failed with {e}')
|
||||||
|
status = 3
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(f'Download failed with {e.args}')
|
||||||
|
status = 1
|
||||||
|
|
||||||
|
if status != 0:
|
||||||
|
logger.warning('Download failed, restore previous AppImage')
|
||||||
|
try:
|
||||||
|
os.rename(new_file.with_suffix('.AppImage.old'), new_file)
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
# zsync does not support https
|
||||||
|
|
||||||
|
self.finished.emit(status, str(new_file))
|
||||||
|
|
||||||
|
|
||||||
|
class Updater:
|
||||||
|
host = 'gitea.pkm.physik.tu-darmstadt.de/api/packages/IPKM/generic/NMReval/latest/'
|
||||||
|
version = 'NMReval-latest-x86_64'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def zsync_url(self):
|
||||||
|
return f'https://{Updater.host}/{Updater.version}.AppImage.zsync'
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_zsync():
|
||||||
|
url_zsync = f'https://{Updater.host}/{Updater.version}.AppImage.zsync'
|
||||||
|
m_time_zsync = None
|
||||||
|
checksum_zsync = None
|
||||||
|
zsync_file = None
|
||||||
|
filename = None
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(url_zsync) as response:
|
||||||
|
zsync_file = response.read()
|
||||||
|
except HTTPError as e:
|
||||||
|
logger.error(f'Request for zsync returned code {e}')
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(f'Download of zsync failed with exception {e.args}')
|
||||||
|
|
||||||
|
if zsync_file is not None:
|
||||||
|
for line in zsync_file.split(b'\n'):
|
||||||
|
try:
|
||||||
|
kw, val = line.split(b': ')
|
||||||
|
time_string = str(val, encoding='utf-8')
|
||||||
|
time_format = '%a, %d %b %Y %H:%M:%S %z'
|
||||||
|
if kw == b'MTime':
|
||||||
|
try:
|
||||||
|
m_time_zsync = datetime.strptime(time_string, time_format).astimezone(None)
|
||||||
|
except ValueError:
|
||||||
|
logger.warning(f'zsync time "{time_string}" does not match "{time_format}"')
|
||||||
|
elif kw == b'SHA-1':
|
||||||
|
checksum_zsync = str(val, encoding='utf-8')
|
||||||
|
elif kw == b'Filename':
|
||||||
|
filename = str(val, encoding='utf-8')
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
# stop when empty line is reached
|
||||||
|
break
|
||||||
|
|
||||||
|
return m_time_zsync, checksum_zsync, filename
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_appimage_info(filename: str):
|
||||||
|
if filename is None:
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
if not exists(filename):
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
stat_mtime = stat(filename).st_mtime
|
||||||
|
m_time_file = datetime.fromtimestamp(stat_mtime).replace(microsecond=0)
|
||||||
|
with open(filename, 'rb') as f:
|
||||||
|
checksum_file = hashlib.sha1(f.read()).hexdigest()
|
||||||
|
if checksum_file is None:
|
||||||
|
logger.warning('No checksum for AppImage calculated')
|
||||||
|
|
||||||
|
return m_time_file, checksum_file
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_update_information(filename: str) -> tuple[(bool | None), datetime, datetime]:
|
||||||
|
m_time_zsync, checksum_zsync, appname = Updater.get_zsync()
|
||||||
|
m_time_file, checksum_file = Updater.get_appimage_info(filename)
|
||||||
|
|
||||||
|
logger.debug(f'zsync information {m_time_zsync}, {checksum_zsync}, {appname}')
|
||||||
|
logger.debug(f'file information {m_time_file}, {checksum_file}')
|
||||||
|
|
||||||
|
if not ((checksum_file is not None) and (checksum_zsync is not None)):
|
||||||
|
return None, m_time_file, m_time_zsync
|
||||||
|
else:
|
||||||
|
return checksum_file != checksum_zsync, m_time_file, m_time_zsync
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import sys
|
||||||
|
from gui_qt import App
|
||||||
|
|
||||||
|
app = App(['Team Rocket FTW!'])
|
||||||
|
|
||||||
|
updater = UpdateDialog()
|
||||||
|
updater.show()
|
||||||
|
|
||||||
|
sys.exit(app.exec())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,27 +1,16 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
|
||||||
import urllib.request
|
|
||||||
from os import getenv, stat
|
|
||||||
from os.path import exists
|
|
||||||
import hashlib
|
|
||||||
import subprocess
|
|
||||||
from datetime import datetime
|
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from pathlib import Path
|
|
||||||
from urllib.error import HTTPError
|
|
||||||
from numpy import linspace
|
from numpy import linspace
|
||||||
from scipy.interpolate import interp1d
|
from scipy.interpolate import interp1d
|
||||||
|
|
||||||
from nmreval.lib.logger import logger
|
|
||||||
|
|
||||||
from ..Qt import QtGui, QtWidgets, QtCore
|
from ..Qt import QtGui, QtWidgets, QtCore
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def busy_cursor():
|
def busy_cursor():
|
||||||
try:
|
try:
|
||||||
cursor = QtGui.QCursor(QtCore.Qt.ForbiddenCursor)
|
cursor = QtGui.QCursor(QtCore.Qt.CursorShape.ForbiddenCursor)
|
||||||
QtWidgets.QApplication.setOverrideCursor(cursor)
|
QtWidgets.QApplication.setOverrideCursor(cursor)
|
||||||
yield
|
yield
|
||||||
|
|
||||||
@ -63,225 +52,3 @@ class RdBuCMap:
|
|||||||
return col
|
return col
|
||||||
|
|
||||||
|
|
||||||
class UpdateDialog(QtWidgets.QDialog):
|
|
||||||
startDownload = QtCore.pyqtSignal(tuple)
|
|
||||||
|
|
||||||
def __init__(self, filename: str = None, parent=None):
|
|
||||||
super().__init__(parent=parent)
|
|
||||||
self._init_ui()
|
|
||||||
|
|
||||||
if filename is None:
|
|
||||||
filename = getenv('APPIMAGE')
|
|
||||||
self._appfile = filename
|
|
||||||
|
|
||||||
self.updater = Updater()
|
|
||||||
|
|
||||||
self.thread = QtCore.QThread(self)
|
|
||||||
self.thread.start()
|
|
||||||
self.helper = Downloader()
|
|
||||||
self.startDownload.connect(self.helper.run_download)
|
|
||||||
self.helper.progressChanged.connect(self.status.setText)
|
|
||||||
self.helper.finished.connect(self.finish_update)
|
|
||||||
self.helper.started.connect(self.status.show)
|
|
||||||
self.helper.moveToThread(self.thread)
|
|
||||||
|
|
||||||
self.look_for_updates(self._appfile)
|
|
||||||
|
|
||||||
def _init_ui(self):
|
|
||||||
self.setWindowTitle('Updates')
|
|
||||||
|
|
||||||
layout = QtWidgets.QVBoxLayout()
|
|
||||||
|
|
||||||
self.label = QtWidgets.QLabel()
|
|
||||||
layout.addWidget(self.label)
|
|
||||||
|
|
||||||
layout.addSpacing(10)
|
|
||||||
|
|
||||||
self.status = QtWidgets.QLabel()
|
|
||||||
self.status.hide()
|
|
||||||
layout.addWidget(self.status)
|
|
||||||
layout.addSpacing(10)
|
|
||||||
|
|
||||||
self.dialog_button = QtWidgets.QDialogButtonBox()
|
|
||||||
self.dialog_button.accepted.connect(self.update_appimage)
|
|
||||||
self.dialog_button.rejected.connect(self.close)
|
|
||||||
layout.addWidget(self.dialog_button)
|
|
||||||
|
|
||||||
self.setLayout(layout)
|
|
||||||
|
|
||||||
def look_for_updates(self, filename=None):
|
|
||||||
logger.info(f'Looking for updates, compare to file {filename}')
|
|
||||||
# Download zsync file of latest Appimage, look for SHA-1 hash and compare with hash of AppImage
|
|
||||||
is_updateble, m_time_file, m_time_zsync = self.updater.get_update_information(filename)
|
|
||||||
|
|
||||||
label_text = ''
|
|
||||||
|
|
||||||
if is_updateble is None:
|
|
||||||
label_text += '<p>Could not determine if this version is newer, please update manually (if necessary).</p>'
|
|
||||||
dialog_bttns = QtWidgets.QDialogButtonBox.Close
|
|
||||||
elif is_updateble:
|
|
||||||
label_text += '<p>Newer version available. Press Ok to download new version, Cancel to ignore.</p>'
|
|
||||||
dialog_bttns = QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel
|
|
||||||
else:
|
|
||||||
label_text += '<p>Version may be already up-to-date.</p>'
|
|
||||||
dialog_bttns = QtWidgets.QDialogButtonBox.Close
|
|
||||||
|
|
||||||
if m_time_zsync is None:
|
|
||||||
label_text += '<p>Creation date of remote version is unknown.</p>'
|
|
||||||
else:
|
|
||||||
label_text += f'<p>Date of most recent AppImage: {m_time_zsync.strftime("%d %B %Y %H:%M")}</p>'
|
|
||||||
|
|
||||||
if m_time_file is None:
|
|
||||||
label_text += 'No AppImage file found, press Ok to download latest version.'
|
|
||||||
dialog_bttns = QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Close
|
|
||||||
else:
|
|
||||||
label_text += f'<p>Date of used AppImage: {m_time_file.strftime("%d %B %Y %H:%M")}</p>'
|
|
||||||
|
|
||||||
self.label.setText(label_text)
|
|
||||||
self.dialog_button.setStandardButtons(dialog_bttns)
|
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
|
||||||
def update_appimage(self):
|
|
||||||
if self._appfile is None:
|
|
||||||
args = (self.updater.zsync_url,)
|
|
||||||
else:
|
|
||||||
# this breaks the download for some reason
|
|
||||||
args = (self.updater.zsync_url, self._appfile)
|
|
||||||
|
|
||||||
self.dialog_button.setEnabled(False)
|
|
||||||
|
|
||||||
self.startDownload.emit(args)
|
|
||||||
self.status.show()
|
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int, str)
|
|
||||||
def finish_update(self, retcode: int, file_loc: str):
|
|
||||||
if retcode == 0:
|
|
||||||
self.status.setText(f'Download complete.New AppImage lies in <p><em>{file_loc}</em>.</p>')
|
|
||||||
else:
|
|
||||||
self.status.setText(f'Download failed :( with return code {retcode}.')
|
|
||||||
self.dialog_button.setStandardButtons(QtWidgets.QDialogButtonBox.Close)
|
|
||||||
self.dialog_button.setEnabled(True)
|
|
||||||
|
|
||||||
def closeEvent(self, evt):
|
|
||||||
self.thread.quit()
|
|
||||||
self.thread.wait()
|
|
||||||
|
|
||||||
super().closeEvent(evt)
|
|
||||||
|
|
||||||
|
|
||||||
class Downloader(QtCore.QObject):
|
|
||||||
started = QtCore.pyqtSignal()
|
|
||||||
finished = QtCore.pyqtSignal(int, str)
|
|
||||||
progressChanged = QtCore.pyqtSignal(str)
|
|
||||||
|
|
||||||
@QtCore.pyqtSlot(tuple)
|
|
||||||
def run_download(self, args: tuple[str]):
|
|
||||||
status = 0
|
|
||||||
appimage_location = args[0][:-6]
|
|
||||||
logger.info(f'Download {appimage_location}')
|
|
||||||
if len(args) == 2:
|
|
||||||
new_file = Path(args[1])
|
|
||||||
else:
|
|
||||||
new_file = Path.home() / 'Downloads' / 'NMReval-latest-x86_64.AppImage'
|
|
||||||
|
|
||||||
if new_file.exists():
|
|
||||||
os.rename(new_file, new_file.with_suffix('.AppImage.old'))
|
|
||||||
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(appimage_location) as response:
|
|
||||||
with new_file.open('wb') as f:
|
|
||||||
f.write(response.read())
|
|
||||||
|
|
||||||
new_file.chmod(0o755)
|
|
||||||
except HTTPError as e:
|
|
||||||
logger.exception(f'Download failed with {e}')
|
|
||||||
status = 3
|
|
||||||
except Exception as e:
|
|
||||||
logger.exception(f'Download failed with {e.args}')
|
|
||||||
status = 1
|
|
||||||
|
|
||||||
if status != 0:
|
|
||||||
logger.warning('Download failed, restore previous AppImage')
|
|
||||||
try:
|
|
||||||
os.rename(new_file.with_suffix('.AppImage.old'), new_file)
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
# zsync does not support https
|
|
||||||
|
|
||||||
self.finished.emit(status, str(new_file))
|
|
||||||
|
|
||||||
|
|
||||||
class Updater:
|
|
||||||
host = 'gitea.pkm.physik.tu-darmstadt.de/api/packages/IPKM/generic/NMReval/latest/'
|
|
||||||
version = 'NMReval-latest-x86_64'
|
|
||||||
|
|
||||||
@property
|
|
||||||
def zsync_url(self):
|
|
||||||
return f'https://{Updater.host}/{Updater.version}.AppImage.zsync'
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_zsync():
|
|
||||||
url_zsync = f'https://{Updater.host}/{Updater.version}.AppImage.zsync'
|
|
||||||
m_time_zsync = None
|
|
||||||
checksum_zsync = None
|
|
||||||
zsync_file = None
|
|
||||||
filename = None
|
|
||||||
try:
|
|
||||||
with urllib.request.urlopen(url_zsync) as response:
|
|
||||||
zsync_file = response.read()
|
|
||||||
except HTTPError as e:
|
|
||||||
logger.error(f'Request for zsync returned code {e}')
|
|
||||||
except Exception as e:
|
|
||||||
logger.exception(f'Download of zsync failed with exception {e.args}')
|
|
||||||
|
|
||||||
if zsync_file is not None:
|
|
||||||
for line in zsync_file.split(b'\n'):
|
|
||||||
try:
|
|
||||||
kw, val = line.split(b': ')
|
|
||||||
time_string = str(val, encoding='utf-8')
|
|
||||||
time_format = '%a, %d %b %Y %H:%M:%S %z'
|
|
||||||
if kw == b'MTime':
|
|
||||||
try:
|
|
||||||
m_time_zsync = datetime.strptime(time_string, time_format).astimezone(None)
|
|
||||||
except ValueError:
|
|
||||||
logger.warning(f'zsync time "{time_string}" does not match "{time_format}"')
|
|
||||||
elif kw == b'SHA-1':
|
|
||||||
checksum_zsync = str(val, encoding='utf-8')
|
|
||||||
elif kw == b'Filename':
|
|
||||||
filename = str(val, encoding='utf-8')
|
|
||||||
|
|
||||||
except ValueError:
|
|
||||||
# stop when empty line is reached
|
|
||||||
break
|
|
||||||
|
|
||||||
return m_time_zsync, checksum_zsync, filename
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_appimage_info(filename: str):
|
|
||||||
if filename is None:
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
if not exists(filename):
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
stat_mtime = stat(filename).st_mtime
|
|
||||||
m_time_file = datetime.fromtimestamp(stat_mtime).replace(microsecond=0)
|
|
||||||
with open(filename, 'rb') as f:
|
|
||||||
checksum_file = hashlib.sha1(f.read()).hexdigest()
|
|
||||||
if checksum_file is None:
|
|
||||||
logger.warning('No checksum for AppImage calculated')
|
|
||||||
|
|
||||||
return m_time_file, checksum_file
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def get_update_information(filename: str) -> tuple[(bool | None), datetime, datetime]:
|
|
||||||
m_time_zsync, checksum_zsync, appname = Updater.get_zsync()
|
|
||||||
m_time_file, checksum_file = Updater.get_appimage_info(filename)
|
|
||||||
|
|
||||||
logger.debug(f'zsync information {m_time_zsync}, {checksum_zsync}, {appname}')
|
|
||||||
logger.debug(f'file information {m_time_file}, {checksum_file}')
|
|
||||||
|
|
||||||
if not ((checksum_file is not None) and (checksum_zsync is not None)):
|
|
||||||
return None, m_time_file, m_time_zsync
|
|
||||||
else:
|
|
||||||
return checksum_file != checksum_zsync, m_time_file, m_time_zsync
|
|
||||||
|
3
src/gui_qt/main/console.py
Normal file
3
src/gui_qt/main/console.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -13,17 +12,18 @@ from nmreval.lib.logger import logger
|
|||||||
from nmreval.io.sessionwriter import NMRWriter
|
from nmreval.io.sessionwriter import NMRWriter
|
||||||
|
|
||||||
from .management import UpperManagement
|
from .management import UpperManagement
|
||||||
|
from ..lib.logger import QTextHandler
|
||||||
from ..Qt import QtGui, QtPrintSupport
|
from ..Qt import QtGui, QtPrintSupport
|
||||||
from ..data.shift_graphs import QShift
|
from ..data.shift_graphs import QShift
|
||||||
from ..data.signaledit import QPreviewDialog, QBaselineDialog
|
from ..data.signaledit import QPreviewDialog, QBaselineDialog
|
||||||
from ..dsc.glass_dialog import TgCalculator
|
from ..dsc.glass_dialog import TgCalculator
|
||||||
|
from ..fit.fit_toolbar import FitToolbar
|
||||||
from ..fit.result import FitExtension, QFitResult
|
from ..fit.result import FitExtension, QFitResult
|
||||||
from ..graphs.graphwindow import QGraphWindow
|
from ..graphs.graphwindow import QGraphWindow
|
||||||
from ..graphs.movedialog import QMover
|
from ..graphs.movedialog import QMover
|
||||||
from ..io.fcbatchreader import QFCReader
|
from ..io.fcbatchreader import QFCReader
|
||||||
from ..io.filedialog import *
|
from ..io.filedialog import *
|
||||||
from ..lib.iconloading import make_action_icons, get_icon
|
from ..lib.iconloading import make_action_icons, get_icon
|
||||||
from ..lib.pg_objects import RegionItem
|
|
||||||
from ..lib.starter import make_starter
|
from ..lib.starter import make_starter
|
||||||
from ..math.binning import BinningWindow
|
from ..math.binning import BinningWindow
|
||||||
from ..math.evaluation import QEvalDialog
|
from ..math.evaluation import QEvalDialog
|
||||||
@ -33,7 +33,7 @@ from ..math.smooth import QSmooth
|
|||||||
from ..nmr.coupling_calc import QCoupCalcDialog
|
from ..nmr.coupling_calc import QCoupCalcDialog
|
||||||
from ..nmr.t1_from_tau import QRelaxCalc
|
from ..nmr.t1_from_tau import QRelaxCalc
|
||||||
from .._py.basewindow import Ui_BaseWindow
|
from .._py.basewindow import Ui_BaseWindow
|
||||||
from ..lib.utils import UpdateDialog, Updater
|
from ..lib.update import UpdateDialog
|
||||||
|
|
||||||
|
|
||||||
class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||||
@ -42,7 +42,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
save_ses_sig = QtCore.pyqtSignal(str)
|
save_ses_sig = QtCore.pyqtSignal(str)
|
||||||
rest_ses_sig = QtCore.pyqtSignal(str)
|
rest_ses_sig = QtCore.pyqtSignal(str)
|
||||||
|
|
||||||
def __init__(self, parents=None, path=None):
|
def __init__(self, parents=None, path=None, bck_file=None):
|
||||||
super().__init__(parent=parents)
|
super().__init__(parent=parents)
|
||||||
|
|
||||||
if path is None:
|
if path is None:
|
||||||
@ -62,6 +62,13 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self.fitresult_dialog = None
|
self.fitresult_dialog = None
|
||||||
self.eval = None
|
self.eval = None
|
||||||
self.editor = None
|
self.editor = None
|
||||||
|
self._interpol_dialog = None
|
||||||
|
self.fc_reader = None
|
||||||
|
|
||||||
|
self.logtext = QTextHandler(self)
|
||||||
|
logger.addHandler(self.logtext)
|
||||||
|
self.addDockWidget(QtCore.Qt.DockWidgetArea.BottomDockWidgetArea, self.logtext.console)
|
||||||
|
self.logtext.console.hide()
|
||||||
|
|
||||||
self.movedialog = QMover(self)
|
self.movedialog = QMover(self)
|
||||||
|
|
||||||
@ -75,21 +82,16 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self._init_gui()
|
self._init_gui()
|
||||||
self._init_signals()
|
self._init_signals()
|
||||||
|
|
||||||
if os.getenv('APPIMAGE') is not None:
|
|
||||||
if Updater.get_update_information(os.getenv('APPIMAGE'))[0]:
|
|
||||||
self.look_for_update()
|
|
||||||
|
|
||||||
self.check_for_backup()
|
|
||||||
|
|
||||||
self.__timer = QtCore.QTimer()
|
|
||||||
self.__backup_path = config_paths() / f'{datetime.datetime.now().strftime("%Y-%m-%d_%H%M%S")}.nmr'
|
|
||||||
self.__timer.start(3*60*1000) # every three minutes
|
|
||||||
self.__timer.timeout.connect(self._autosave)
|
|
||||||
|
|
||||||
self.fit_timer = QtCore.QTimer()
|
self.fit_timer = QtCore.QTimer()
|
||||||
self.fit_timer.setInterval(500)
|
self.fit_timer.setInterval(500)
|
||||||
self.fit_timer.timeout.connect(
|
self.fit_timer.timeout.connect(
|
||||||
lambda: self.status.setText(f'Fit running... ({self.management.fitter.step} evaluations)'))
|
lambda: self.status.setText(f'Fit running... ({self.management.fitter.step} evaluations)')
|
||||||
|
)
|
||||||
|
|
||||||
|
self.__backup_path = pathlib.Path(bck_file)
|
||||||
|
if os.getenv('APPIMAGE'):
|
||||||
|
# ignore AppImages if not running from AppImage
|
||||||
|
self.look_for_update()
|
||||||
|
|
||||||
def _init_gui(self):
|
def _init_gui(self):
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
@ -102,14 +104,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self.norm_toolbutton.setIcon(get_icon('normal'))
|
self.norm_toolbutton.setIcon(get_icon('normal'))
|
||||||
self.toolbar_edit.addWidget(self.norm_toolbutton)
|
self.toolbar_edit.addWidget(self.norm_toolbutton)
|
||||||
|
|
||||||
self.fitlim_button = QtWidgets.QToolButton(self)
|
|
||||||
self.fitlim_button.setMenu(self.menuLimits)
|
|
||||||
self.fitlim_button.setPopupMode(self.fitlim_button.InstantPopup)
|
|
||||||
self.fitlim_button.setIcon(get_icon('fit_region'))
|
|
||||||
self.toolBar_fit.addWidget(self.fitlim_button)
|
|
||||||
|
|
||||||
self.area.dragEnterEvent = self.dragEnterEvent
|
|
||||||
|
|
||||||
while self.tabWidget.count() > 2:
|
while self.tabWidget.count() > 2:
|
||||||
self.tabWidget.removeTab(self.tabWidget.count()-1)
|
self.tabWidget.removeTab(self.tabWidget.count()-1)
|
||||||
|
|
||||||
@ -127,26 +121,26 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
# noinspection PyUnresolvedReferences
|
# noinspection PyUnresolvedReferences
|
||||||
self.statusBar.addWidget(self.mousepos)
|
self.statusBar.addWidget(self.mousepos)
|
||||||
|
|
||||||
self.fitregion = RegionItem()
|
|
||||||
self._fit_plot_id = None
|
self._fit_plot_id = None
|
||||||
|
|
||||||
self.setGeometry(QtWidgets.QStyle.alignedRect(QtCore.Qt.LeftToRight, QtCore.Qt.AlignCenter,
|
self.fit_toolbar = FitToolbar(self.action_FitWidget, self.menuLimits, self)
|
||||||
self.size(), QtWidgets.qApp.desktop().availableGeometry()))
|
self.addToolBar(self.fit_toolbar)
|
||||||
|
|
||||||
|
self.setGeometry(QtWidgets.QStyle.alignedRect(
|
||||||
|
QtCore.Qt.LayoutDirection.LeftToRight,
|
||||||
|
QtCore.Qt.AlignmentFlag.AlignCenter,
|
||||||
|
self.size(),
|
||||||
|
QtWidgets.qApp.desktop().availableGeometry()),
|
||||||
|
)
|
||||||
|
|
||||||
self.datawidget.management = self.management
|
self.datawidget.management = self.management
|
||||||
self.integralwidget.management = self.management
|
self.integralwidget.management = self.management
|
||||||
# self.drawingswidget.graphs = self.management.graphs
|
|
||||||
|
|
||||||
self.ac_group = QtWidgets.QActionGroup(self)
|
self.ac_group = QtWidgets.QActionGroup(self)
|
||||||
self.ac_group.addAction(self.action_lm_fit)
|
self.ac_group.addAction(self.action_lm_fit)
|
||||||
self.ac_group.addAction(self.action_nm_fit)
|
self.ac_group.addAction(self.action_nm_fit)
|
||||||
self.ac_group.addAction(self.action_odr_fit)
|
self.ac_group.addAction(self.action_odr_fit)
|
||||||
|
|
||||||
self.ac_group2 = QtWidgets.QActionGroup(self)
|
|
||||||
self.ac_group2.addAction(self.action_no_range)
|
|
||||||
self.ac_group2.addAction(self.action_x_range)
|
|
||||||
self.ac_group2.addAction(self.action_custom_range)
|
|
||||||
|
|
||||||
def _init_signals(self):
|
def _init_signals(self):
|
||||||
self.actionRedo = self.management.undostack.createRedoAction(self)
|
self.actionRedo = self.management.undostack.createRedoAction(self)
|
||||||
icon = QtGui.QIcon.fromTheme("edit-redo")
|
icon = QtGui.QIcon.fromTheme("edit-redo")
|
||||||
@ -161,7 +155,8 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self.menuData.insertAction(self.actionRedo, self.actionUndo)
|
self.menuData.insertAction(self.actionRedo, self.actionUndo)
|
||||||
|
|
||||||
self.action_save_fit_parameter.triggered.connect(self.save_fit_parameter)
|
self.action_save_fit_parameter.triggered.connect(self.save_fit_parameter)
|
||||||
self.ac_group2.triggered.connect(self.change_fit_limits)
|
# noinspection PyUnresolvedReferences
|
||||||
|
self.fit_toolbar.limit_group.triggered.connect(self.change_fit_limits)
|
||||||
|
|
||||||
self.t1action.triggered.connect(lambda: self._show_tab('t1_temp'))
|
self.t1action.triggered.connect(lambda: self._show_tab('t1_temp'))
|
||||||
self.action_edit.triggered.connect(self.do_preview)
|
self.action_edit.triggered.connect(self.do_preview)
|
||||||
@ -201,6 +196,8 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self.management.unset_state.connect(lambda x: self.datawidget.uncheck_sets(x))
|
self.management.unset_state.connect(lambda x: self.datawidget.uncheck_sets(x))
|
||||||
self.management.fitFinished.connect(self.show_fit_results)
|
self.management.fitFinished.connect(self.show_fit_results)
|
||||||
|
|
||||||
|
self.area.newData.connect(lambda x: self.management.load_files(x))
|
||||||
|
|
||||||
self.fit_dialog._management = self.management
|
self.fit_dialog._management = self.management
|
||||||
self.fit_dialog.preview_emit.connect(self.show_fit_preview)
|
self.fit_dialog.preview_emit.connect(self.show_fit_preview)
|
||||||
self.fit_dialog.fitStartSig.connect(self.start_fit)
|
self.fit_dialog.fitStartSig.connect(self.start_fit)
|
||||||
@ -233,14 +230,13 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self.actionNext_window.triggered.connect(lambda: self.area.activateNextSubWindow())
|
self.actionNext_window.triggered.connect(lambda: self.area.activateNextSubWindow())
|
||||||
self.actionPrevious.triggered.connect(lambda: self.area.activatePreviousSubWindow())
|
self.actionPrevious.triggered.connect(lambda: self.area.activatePreviousSubWindow())
|
||||||
|
|
||||||
self.closeSignal.connect(self.close)
|
|
||||||
|
|
||||||
self.action_norm_max.triggered.connect(lambda: self.management.apply('norm', ('max',)))
|
self.action_norm_max.triggered.connect(lambda: self.management.apply('norm', ('max',)))
|
||||||
self.action_norm_max_abs.triggered.connect(lambda: self.management.apply('norm', ('maxabs',)))
|
self.action_norm_max_abs.triggered.connect(lambda: self.management.apply('norm', ('maxabs',)))
|
||||||
self.action_norm_first.triggered.connect(lambda: self.management.apply('norm', ('first',)))
|
self.action_norm_first.triggered.connect(lambda: self.management.apply('norm', ('first',)))
|
||||||
self.action_norm_last.triggered.connect(lambda: self.management.apply('norm', ('last',)))
|
self.action_norm_last.triggered.connect(lambda: self.management.apply('norm', ('last',)))
|
||||||
self.action_norm_area.triggered.connect(lambda: self.management.apply('norm', ('area',)))
|
self.action_norm_area.triggered.connect(lambda: self.management.apply('norm', ('area',)))
|
||||||
self.action_cut.triggered.connect(lambda: self.management.cut())
|
self.action_cut_xaxis.triggered.connect(lambda: self.management.cut(True, False))
|
||||||
|
self.action_cut_yaxis.triggered.connect(lambda: self.management.cut(False, True))
|
||||||
|
|
||||||
self.actionConcatenate_sets.triggered.connect(lambda: self.management.cat())
|
self.actionConcatenate_sets.triggered.connect(lambda: self.management.cat())
|
||||||
|
|
||||||
@ -259,8 +255,11 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
|
|
||||||
filedialog.set_graphs(self.management.graphs.list())
|
filedialog.set_graphs(self.management.graphs.list())
|
||||||
|
|
||||||
filedialog.exec()
|
accepted = filedialog.exec()
|
||||||
|
if accepted:
|
||||||
fname = filedialog.selectedFiles()
|
fname = filedialog.selectedFiles()
|
||||||
|
else:
|
||||||
|
fname = []
|
||||||
|
|
||||||
if fname:
|
if fname:
|
||||||
self.path = Path(fname[0]).parent
|
self.path = Path(fname[0]).parent
|
||||||
@ -268,12 +267,15 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_actionOpen_FC_triggered')
|
@QtCore.pyqtSlot(name='on_actionOpen_FC_triggered')
|
||||||
def read_fc(self):
|
def read_fc(self):
|
||||||
reader = QFCReader(path=self.path, parent=self)
|
if self.fc_reader is None:
|
||||||
reader.add_graphs(self.management.graphs.list())
|
self.fc_reader = QFCReader(path=self.path, parent=self)
|
||||||
reader.data_read.connect(self.management.add_new_data)
|
self.fc_reader.data_read.connect(self.management.add_new_data)
|
||||||
reader.exec()
|
else:
|
||||||
|
self.fc_reader(path=self.path)
|
||||||
|
self.fc_reader.add_graphs(self.management.graphs.list())
|
||||||
|
self.fc_reader.exec()
|
||||||
|
|
||||||
del reader
|
self.path = self.fc_reader.path
|
||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_actionPrint_triggered')
|
@QtCore.pyqtSlot(name='on_actionPrint_triggered')
|
||||||
def print(self):
|
def print(self):
|
||||||
@ -371,25 +373,29 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
val_figure = self.valuewidget.connected_figure
|
val_figure = self.valuewidget.connected_figure
|
||||||
self.valuewidget.remove_graph()
|
self.valuewidget.remove_graph()
|
||||||
|
|
||||||
|
_remove_pts = False
|
||||||
|
_remove_t1 = False
|
||||||
|
_move_to_data_tab = False
|
||||||
|
|
||||||
w = None
|
w = None
|
||||||
for w in self.area.subWindowList():
|
for w in self.area.subWindowList():
|
||||||
wdgt = w.widget()
|
wdgt = w.widget()
|
||||||
if wdgt.id == gid:
|
if wdgt.id == gid:
|
||||||
wdgt.disconnect()
|
wdgt.disconnect()
|
||||||
wdgt.scene.disconnect()
|
wdgt.scene.disconnect()
|
||||||
|
|
||||||
if wdgt == self.current_graph_widget:
|
if wdgt == self.current_graph_widget:
|
||||||
if self.ptsselectwidget.connected_figure == gid:
|
if self.ptsselectwidget.connected_figure == gid:
|
||||||
self.ptsselectwidget.connected_figure = None
|
self.ptsselectwidget.connected_figure = None
|
||||||
for line in self.ptsselectwidget.pts_lines:
|
for line in self.ptsselectwidget.pts_lines:
|
||||||
self.current_graph_widget.remove_external(line)
|
self.current_graph_widget.remove_external(line)
|
||||||
|
_remove_pts = True
|
||||||
self.tabWidget.removeTab(self.tabWidget.indexOf(self.ptsselectwidget))
|
|
||||||
|
|
||||||
if self.t1tauwidget.connected_figure == gid:
|
if self.t1tauwidget.connected_figure == gid:
|
||||||
self.t1tauwidget.connected_figure = None
|
self.t1tauwidget.connected_figure = None
|
||||||
self.current_graph_widget.add_external(self.t1tauwidget.min_pos)
|
self.current_graph_widget.remove_external(self.t1tauwidget.min_pos)
|
||||||
self.current_graph_widget.add_external(self.t1tauwidget.parabola)
|
self.current_graph_widget.remove_external(self.t1tauwidget.parabola)
|
||||||
self.tabWidget.removeTab(self.tabWidget.indexOf(self.t1tauwidget))
|
_remove_t1 = True
|
||||||
|
|
||||||
if self.fit_dialog.connected_figure == gid:
|
if self.fit_dialog.connected_figure == gid:
|
||||||
self.fit_dialog.connected_figure = None
|
self.fit_dialog.connected_figure = None
|
||||||
@ -397,9 +403,10 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self.current_graph_widget.remove_external(item)
|
self.current_graph_widget.remove_external(item)
|
||||||
|
|
||||||
if val_figure == gid:
|
if val_figure == gid:
|
||||||
|
self.valuewidget.connected_figure = None
|
||||||
self.current_graph_widget.remove_external(self.valuewidget.selection_real)
|
self.current_graph_widget.remove_external(self.valuewidget.selection_real)
|
||||||
self.current_graph_widget.remove_external(self.valuewidget.selection_imag)
|
self.current_graph_widget.remove_external(self.valuewidget.selection_imag)
|
||||||
self.tabWidget.setCurrentIndex(0)
|
_move_to_data_tab = True
|
||||||
|
|
||||||
self.current_graph_widget.enable_picking(False)
|
self.current_graph_widget.enable_picking(False)
|
||||||
|
|
||||||
@ -415,6 +422,13 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if _remove_t1:
|
||||||
|
self.tabWidget.removeTab(self.tabWidget.indexOf(self.t1tauwidget))
|
||||||
|
if _remove_pts:
|
||||||
|
self.tabWidget.removeTab(self.tabWidget.indexOf(self.ptsselectwidget))
|
||||||
|
if _move_to_data_tab:
|
||||||
|
self.tabWidget.setCurrentIndex(0)
|
||||||
|
|
||||||
if w is not None:
|
if w is not None:
|
||||||
self.area.removeSubWindow(w)
|
self.area.removeSubWindow(w)
|
||||||
w.close()
|
w.close()
|
||||||
@ -452,6 +466,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
w.mousePositionChanged.connect(self.mousemoved)
|
w.mousePositionChanged.connect(self.mousemoved)
|
||||||
w.aboutToClose.connect(self.management.delete_sets)
|
w.aboutToClose.connect(self.management.delete_sets)
|
||||||
w.positionClicked.connect(self.point_selected)
|
w.positionClicked.connect(self.point_selected)
|
||||||
|
w.newData.connect(lambda x, y: self.management.load_files(x, new_plot=y))
|
||||||
w.show()
|
w.show()
|
||||||
|
|
||||||
graph_list = self.management.graphs.list()
|
graph_list = self.management.graphs.list()
|
||||||
@ -564,10 +579,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self.ptsselectwidget.connected_figure = self.management.current_graph
|
self.ptsselectwidget.connected_figure = self.management.current_graph
|
||||||
pick_required = True
|
pick_required = True
|
||||||
else:
|
else:
|
||||||
if self.ptsselectwidget.connected_figure:
|
if self.ptsselectwidget.connected_figure in self.management.graphs:
|
||||||
g = self.management.graphs[self.ptsselectwidget.connected_figure]
|
g = self.management.graphs[self.ptsselectwidget.connected_figure]
|
||||||
for line in self.ptsselectwidget.pts_lines:
|
for line in self.ptsselectwidget.pts_lines:
|
||||||
g.remove_external(line)
|
g.remove_external(line)
|
||||||
|
else:
|
||||||
|
self.ptsselectwidget.connected_figure = None
|
||||||
# self.ptsselectwidget.clear()
|
# self.ptsselectwidget.clear()
|
||||||
|
|
||||||
return pick_required, block_window
|
return pick_required, block_window
|
||||||
@ -580,10 +597,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self.management.graphs[current_graph].add_external(self.valuewidget.selection_real)
|
self.management.graphs[current_graph].add_external(self.valuewidget.selection_real)
|
||||||
self.management.graphs[current_graph].add_external(self.valuewidget.selection_imag)
|
self.management.graphs[current_graph].add_external(self.valuewidget.selection_imag)
|
||||||
else:
|
else:
|
||||||
if self.valuewidget.connected_figure is not None:
|
if self.valuewidget.connected_figure in self.management.graphs:
|
||||||
conn_fig = self.valuewidget.connected_figure
|
conn_fig = self.valuewidget.connected_figure
|
||||||
self.management.graphs[conn_fig].remove_external(self.valuewidget.selection_real)
|
self.management.graphs[conn_fig].remove_external(self.valuewidget.selection_real)
|
||||||
self.management.graphs[conn_fig].remove_external(self.valuewidget.selection_imag)
|
self.management.graphs[conn_fig].remove_external(self.valuewidget.selection_imag)
|
||||||
|
else:
|
||||||
|
self.valuewidget.connected_figure = None
|
||||||
|
|
||||||
def _select_integralwidget(self, onoff: bool, pick_required: bool, block_window: bool) -> tuple[bool, bool]:
|
def _select_integralwidget(self, onoff: bool, pick_required: bool, block_window: bool) -> tuple[bool, bool]:
|
||||||
if self.current_graph_widget is None:
|
if self.current_graph_widget is None:
|
||||||
@ -597,11 +616,13 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
pick_required = True
|
pick_required = True
|
||||||
block_window = True
|
block_window = True
|
||||||
else:
|
else:
|
||||||
if self.integralwidget.connected_figure:
|
if self.integralwidget.connected_figure in self.management.graphs:
|
||||||
g = self.management.graphs[self.integralwidget.connected_figure]
|
g = self.management.graphs[self.integralwidget.connected_figure]
|
||||||
for line in self.integralwidget.lines:
|
for line in self.integralwidget.lines:
|
||||||
g.remove_external(line[0])
|
g.remove_external(line[0])
|
||||||
g.remove_external(line[1])
|
g.remove_external(line[1])
|
||||||
|
else:
|
||||||
|
self.integralwidget.connected_figure = None
|
||||||
self.integralwidget.clear()
|
self.integralwidget.clear()
|
||||||
|
|
||||||
return pick_required, block_window
|
return pick_required, block_window
|
||||||
@ -630,10 +651,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
pick_required = True
|
pick_required = True
|
||||||
block_window = True
|
block_window = True
|
||||||
else:
|
else:
|
||||||
if self.t1tauwidget.connected_figure:
|
if self.t1tauwidget.connected_figure in self.management.graphs:
|
||||||
g = self.management.graphs[self.t1tauwidget.connected_figure]
|
g = self.management.graphs[self.t1tauwidget.connected_figure]
|
||||||
g.remove_external(self.t1tauwidget.min_pos)
|
g.remove_external(self.t1tauwidget.min_pos)
|
||||||
g.remove_external(self.t1tauwidget.parabola)
|
g.remove_external(self.t1tauwidget.parabola)
|
||||||
|
else:
|
||||||
|
self.t1tauwidget.connected_figure = None
|
||||||
|
|
||||||
return pick_required, block_window
|
return pick_required, block_window
|
||||||
|
|
||||||
@ -654,8 +677,9 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
from ..math.skipping import QSkipDialog
|
from ..math.skipping import QSkipDialog
|
||||||
|
|
||||||
dial = QSkipDialog(self)
|
dial = QSkipDialog(self)
|
||||||
dial.exec()
|
res = dial.exec()
|
||||||
|
|
||||||
|
if res:
|
||||||
self.management.skip_points(**dial.get_arguments())
|
self.management.skip_points(**dial.get_arguments())
|
||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_action_coup_calc_triggered')
|
@QtCore.pyqtSlot(name='on_action_coup_calc_triggered')
|
||||||
@ -682,10 +706,13 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
return
|
return
|
||||||
|
|
||||||
gnames = self.management.graphs.tree()
|
gnames = self.management.graphs.tree()
|
||||||
dialog = InterpolDialog(parent=self)
|
if self._interpol_dialog is None:
|
||||||
dialog.set_data(gnames, self.current_graph_widget.id)
|
self._interpol_dialog = InterpolDialog(parent=self)
|
||||||
dialog.new_data.connect(self.management.interpolate_data)
|
self._interpol_dialog.new_data.connect(self.management.interpolate_data)
|
||||||
dialog.show()
|
else:
|
||||||
|
self._interpol_dialog()
|
||||||
|
self._interpol_dialog.set_data(gnames, self.current_graph_widget.id)
|
||||||
|
self._interpol_dialog.show()
|
||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_action_calc_triggered')
|
@QtCore.pyqtSlot(name='on_action_calc_triggered')
|
||||||
def open_eval_dialog(self):
|
def open_eval_dialog(self):
|
||||||
@ -836,10 +863,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
def item_from_graph(self, item, graph_id):
|
def item_from_graph(self, item, graph_id):
|
||||||
self.management.graphs[graph_id].remove_external(item)
|
self.management.graphs[graph_id].remove_external(item)
|
||||||
|
|
||||||
def closeEvent(self, evt):
|
|
||||||
# self._write_settings()
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int)
|
@QtCore.pyqtSlot(int)
|
||||||
def request_data(self, idx):
|
def request_data(self, idx):
|
||||||
idd = self.datawidget.get_indexes(idx=idx-1)
|
idd = self.datawidget.get_indexes(idx=idx-1)
|
||||||
@ -879,30 +902,29 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
self.fit_dialog.load(self.management.active_sets)
|
self.fit_dialog.load(self.management.active_sets)
|
||||||
for item in self.fit_dialog.preview_lines:
|
for item in self.fit_dialog.preview_lines:
|
||||||
self.current_graph_widget.add_external(item)
|
self.current_graph_widget.add_external(item)
|
||||||
if self.action_custom_range.isChecked():
|
if self.action_custom_range.isChecked() or self.actionExclude_region.isChecked():
|
||||||
self.current_graph_widget.add_external(self.fitregion)
|
self.current_graph_widget.add_external(self.fit_toolbar.region)
|
||||||
|
|
||||||
block_window = True
|
block_window = True
|
||||||
else:
|
else:
|
||||||
for item in self.fit_dialog.preview_lines:
|
for item in self.fit_dialog.preview_lines:
|
||||||
self.current_graph_widget.remove_external(item)
|
self.current_graph_widget.remove_external(item)
|
||||||
self.current_graph_widget.remove_external(self.fitregion)
|
self.current_graph_widget.remove_external(self.fit_toolbar.region)
|
||||||
|
|
||||||
return block_window
|
return block_window
|
||||||
|
|
||||||
@QtCore.pyqtSlot(QtWidgets.QAction)
|
@QtCore.pyqtSlot(QtWidgets.QAction)
|
||||||
def change_fit_limits(self, action: QtWidgets.QAction):
|
def change_fit_limits(self, action: QtWidgets.QAction):
|
||||||
if action == self.action_custom_range and self.fit_dialog.isVisible():
|
if self.current_graph_widget is None:
|
||||||
self.current_graph_widget.add_external(self.fitregion)
|
return
|
||||||
|
|
||||||
|
if action in [self.action_custom_range, self.actionExclude_region] and self.fit_dialog.isVisible():
|
||||||
|
self.current_graph_widget.add_external(self.fit_toolbar.region)
|
||||||
else:
|
else:
|
||||||
self.current_graph_widget.remove_external(self.fitregion)
|
self.current_graph_widget.remove_external(self.fit_toolbar.region)
|
||||||
|
|
||||||
def start_fit(self, parameter, links, fit_options):
|
def start_fit(self, parameter, links, fit_options):
|
||||||
fit_options['limits'] = {
|
fit_options['limits'] = self.fit_toolbar.get_limit()
|
||||||
self.action_no_range: 'none',
|
|
||||||
self.action_x_range: 'x',
|
|
||||||
self.action_custom_range: self.fitregion.getRegion()
|
|
||||||
}[self.ac_group2.checkedAction()]
|
|
||||||
|
|
||||||
fit_options['fit_mode'] = {
|
fit_options['fit_mode'] = {
|
||||||
self.action_lm_fit: 'lsq',
|
self.action_lm_fit: 'lsq',
|
||||||
@ -938,19 +960,19 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
for item in self.fit_dialog.preview_lines:
|
for item in self.fit_dialog.preview_lines:
|
||||||
g.add_external(item)
|
g.add_external(item)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(list)
|
@QtCore.pyqtSlot(list, dict)
|
||||||
def show_fit_results(self, results: list):
|
def show_fit_results(self, results: list, sub_colors: dict[str, tuple[float, float, float]]):
|
||||||
self.fit_dialog.fit_button.setEnabled(True)
|
self.fit_dialog.fit_button.setEnabled(True)
|
||||||
self.fit_timer.stop()
|
self.fit_timer.stop()
|
||||||
self.status.setText('')
|
self.status.setText('')
|
||||||
if results:
|
if results:
|
||||||
if self.fitresult_dialog is None:
|
if self.fitresult_dialog is None:
|
||||||
self.fitresult_dialog = QFitResult(results, self.management, parent=self)
|
self.fitresult_dialog = QFitResult(results, sub_colors, self.management, parent=self)
|
||||||
self.fitresult_dialog.add_graphs(self.management.graphs.list())
|
self.fitresult_dialog.add_graphs(self.management.graphs.list())
|
||||||
self.fitresult_dialog.closed.connect(self.accepts_fit)
|
self.fitresult_dialog.closed.connect(self.accepts_fit)
|
||||||
self.fitresult_dialog.redoFit.connect(self.management.redo_fits)
|
self.fitresult_dialog.redoFit.connect(self.management.redo_fits)
|
||||||
else:
|
else:
|
||||||
self.fitresult_dialog(results)
|
self.fitresult_dialog(results, sub_colors)
|
||||||
self.fitresult_dialog.add_graphs(self.management.graphs.list())
|
self.fitresult_dialog.add_graphs(self.management.graphs.list())
|
||||||
self.fitresult_dialog.show()
|
self.fitresult_dialog.show()
|
||||||
|
|
||||||
@ -963,21 +985,34 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
@QtCore.pyqtSlot(name='on_actionFunction_editor_triggered')
|
@QtCore.pyqtSlot(name='on_actionFunction_editor_triggered')
|
||||||
def edit_models(self):
|
def edit_models(self):
|
||||||
if self.editor is None:
|
if self.editor is None:
|
||||||
from ..lib.usermodeleditor import QUsermodelEditor
|
from ..editors.usermodeleditor import QUsermodelEditor
|
||||||
|
|
||||||
self.editor = QUsermodelEditor(config_paths() / 'usermodels.py', parent=self)
|
self.editor = QUsermodelEditor(config_paths() / 'usermodels.py', parent=self)
|
||||||
self.editor.modelsChanged.connect(lambda: self.fit_dialog.read_and_load_functions())
|
self.editor.modelsChanged.connect(lambda: self.fit_dialog.read_and_load_functions())
|
||||||
self.editor.setWindowModality(QtCore.Qt.ApplicationModal)
|
self.editor.setWindowModality(QtCore.Qt.WindowModality.ApplicationModal)
|
||||||
self.editor.show()
|
self.editor.show()
|
||||||
|
|
||||||
@QtCore.pyqtSlot(list)
|
@QtCore.pyqtSlot(name='on_actionUse_script_triggered')
|
||||||
def extend_fit(self, sets: list):
|
def open_editor(self):
|
||||||
|
from ..editors.script_editor import QEditor
|
||||||
|
|
||||||
|
editor = QEditor(self.path, parent=self)
|
||||||
|
editor.runSignal.connect(self.management.run_script)
|
||||||
|
editor.show()
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(list, bool)
|
||||||
|
def extend_fit(self, sets: list, only_subplots: bool):
|
||||||
|
if only_subplots:
|
||||||
|
self.management.extend_fits(sets, None, True)
|
||||||
|
return
|
||||||
|
|
||||||
w = FitExtension(self)
|
w = FitExtension(self)
|
||||||
res = w.exec()
|
res = w.exec()
|
||||||
if res:
|
if res:
|
||||||
p = w.values
|
p = w.values
|
||||||
x = linspace(p[0], p[1], num=p[2])
|
spacefunc = geomspace if p[3] else linspace
|
||||||
self.management.extend_fits(sets, x)
|
x = spacefunc(p[0], p[1], num=p[2])
|
||||||
|
self.management.extend_fits(sets, x, False)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_action_create_fit_function_triggered')
|
@QtCore.pyqtSlot(name='on_action_create_fit_function_triggered')
|
||||||
def open_fitmodel_wizard(self):
|
def open_fitmodel_wizard(self):
|
||||||
@ -1001,9 +1036,10 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
@QtCore.pyqtSlot(name='on_actionDocumentation_triggered')
|
@QtCore.pyqtSlot(name='on_actionDocumentation_triggered')
|
||||||
def open_doc():
|
def open_doc():
|
||||||
docpath = '/autohome/dominik/auswerteprogramm3/doc/_build/html/index.html'
|
pass
|
||||||
import webbrowser
|
# docpath = '/autohome/dominik/auswerteprogramm3/doc/_build/html/index.html'
|
||||||
webbrowser.open(docpath)
|
# import webbrowser
|
||||||
|
# webbrowser.open(docpath)
|
||||||
|
|
||||||
def dropEvent(self, evt):
|
def dropEvent(self, evt):
|
||||||
if evt.mimeData().hasUrls():
|
if evt.mimeData().hasUrls():
|
||||||
@ -1032,13 +1068,13 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
if self.sender() == self.actionLife:
|
if self.sender() == self.actionLife:
|
||||||
from ..lib.gol import QGameOfLife
|
from ..lib.gol import QGameOfLife
|
||||||
game = QGameOfLife(parent=self)
|
game = QGameOfLife(parent=self)
|
||||||
game.setWindowModality(QtCore.Qt.NonModal)
|
game.setWindowModality(QtCore.Qt.WindowModality.NonModal)
|
||||||
game.show()
|
game.show()
|
||||||
|
|
||||||
elif self.sender() == self.actionMine:
|
elif self.sender() == self.actionMine:
|
||||||
from ..lib.stuff import QMines
|
from ..lib.stuff import QMines
|
||||||
game = QMines(parent=self)
|
game = QMines(parent=self)
|
||||||
game.setWindowModality(QtCore.Qt.NonModal)
|
game.setWindowModality(QtCore.Qt.WindowModality.NonModal)
|
||||||
game.show()
|
game.show()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -1066,9 +1102,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
def close(self):
|
def close(self):
|
||||||
write_state({'History': {'recent path': str(self.path)}})
|
write_state({'History': {'recent path': str(self.path)}})
|
||||||
|
|
||||||
# remove backup file when closing
|
|
||||||
self.__backup_path.unlink(missing_ok=True)
|
|
||||||
|
|
||||||
super().close()
|
super().close()
|
||||||
|
|
||||||
def read_state(self):
|
def read_state(self):
|
||||||
@ -1092,40 +1125,16 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
|||||||
|
|
||||||
QLog(parent=self).show()
|
QLog(parent=self).show()
|
||||||
|
|
||||||
def _autosave(self):
|
def autosave(self) -> bool:
|
||||||
# TODO better separate thread may it takes some time to save
|
|
||||||
self.status.setText('Autosave...')
|
self.status.setText('Autosave...')
|
||||||
success = NMRWriter(self.management.graphs, self.management.data).export(self.__backup_path.with_suffix('.nmr.0'))
|
success = NMRWriter(self.management.graphs, self.management.data).export(self.__backup_path.with_suffix('.nmr.0'))
|
||||||
|
|
||||||
if success:
|
if success:
|
||||||
self.__backup_path.with_suffix('.nmr.0').rename(self.__backup_path)
|
self.__backup_path.with_suffix('.nmr.0').rename(self.__backup_path)
|
||||||
|
|
||||||
self.status.setText('')
|
self.status.setText('')
|
||||||
|
|
||||||
def check_for_backup(self):
|
return success
|
||||||
backups = []
|
|
||||||
for filename in config_paths().glob('*.nmr'):
|
|
||||||
try:
|
|
||||||
backups.append((filename, datetime.datetime.strptime(filename.stem, "%Y-%m-%d_%H%M%S")))
|
|
||||||
except ValueError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if backups:
|
|
||||||
backup_by_date = sorted(backups, key=lambda x: x[1])
|
|
||||||
msg = QtWidgets.QMessageBox.information(
|
|
||||||
self, 'Backup found',
|
|
||||||
f'{len(backups)} backup files in directory {backup_by_date[-1][0].parent} found.\n\n'
|
|
||||||
f'Latest backup date: {backup_by_date[-1][1]}\n\n'
|
|
||||||
f'Press Ok to load, Cancel to delete backup, Close to do nothing.',
|
|
||||||
QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel | QtWidgets.QMessageBox.Close
|
|
||||||
)
|
|
||||||
|
|
||||||
if msg == QtWidgets.QMessageBox.Ok:
|
|
||||||
self.management.load_files([str(backup_by_date[-1][0])])
|
|
||||||
backup_by_date[-1][0].unlink()
|
|
||||||
elif msg == QtWidgets.QMessageBox.Cancel:
|
|
||||||
backup_by_date[-1][0].unlink()
|
|
||||||
else:
|
|
||||||
pass
|
|
||||||
|
|
||||||
@QtCore.pyqtSlot(name='on_actionCreate_starter_triggered')
|
@QtCore.pyqtSlot(name='on_actionCreate_starter_triggered')
|
||||||
def create_starter(self):
|
def create_starter(self):
|
||||||
|
@ -85,7 +85,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
newData = QtCore.pyqtSignal([list, str], [list, str, bool])
|
newData = QtCore.pyqtSignal([list, str], [list, str, bool])
|
||||||
deleteData = QtCore.pyqtSignal(list)
|
deleteData = QtCore.pyqtSignal(list)
|
||||||
dataChanged = QtCore.pyqtSignal(str)
|
dataChanged = QtCore.pyqtSignal(str)
|
||||||
fitFinished = QtCore.pyqtSignal(list)
|
fitFinished = QtCore.pyqtSignal(list, dict)
|
||||||
stopFit = QtCore.pyqtSignal()
|
stopFit = QtCore.pyqtSignal()
|
||||||
properties_collected = QtCore.pyqtSignal(dict)
|
properties_collected = QtCore.pyqtSignal(dict)
|
||||||
unset_state = QtCore.pyqtSignal(list)
|
unset_state = QtCore.pyqtSignal(list)
|
||||||
@ -279,13 +279,16 @@ class UpperManagement(QtCore.QObject):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
@QtCore.pyqtSlot(list, str)
|
@QtCore.pyqtSlot(list, str)
|
||||||
def copy_sets(self, sets: list = None, src: str = None):
|
def copy_sets(self, sets: list = None, src: str = None, dest: str = None):
|
||||||
if sets is None:
|
|
||||||
sets = self.graphs[self.current_graph].active[:]
|
|
||||||
|
|
||||||
if src is None:
|
if src is None:
|
||||||
src = self.current_graph
|
src = self.current_graph
|
||||||
|
|
||||||
|
if sets is None:
|
||||||
|
sets = self.graphs[src].active[:]
|
||||||
|
|
||||||
|
if dest is None:
|
||||||
|
dest = src
|
||||||
|
|
||||||
new_ids = []
|
new_ids = []
|
||||||
for s in sets:
|
for s in sets:
|
||||||
copy_of_s = self.data[s].copy(full=True)
|
copy_of_s = self.data[s].copy(full=True)
|
||||||
@ -293,10 +296,23 @@ class UpperManagement(QtCore.QObject):
|
|||||||
new_ids.append(copy_of_s.id)
|
new_ids.append(copy_of_s.id)
|
||||||
self.data[copy_of_s.id] = copy_of_s
|
self.data[copy_of_s.id] = copy_of_s
|
||||||
|
|
||||||
self.newData.emit(new_ids, src)
|
self.newData.emit(new_ids, dest)
|
||||||
|
|
||||||
return new_ids
|
return new_ids
|
||||||
|
|
||||||
|
def copy_graph(self, gid):
|
||||||
|
# Use state of old graph but removes actual references to old graph
|
||||||
|
src_state = self.graphs[gid].get_state()
|
||||||
|
src_state.pop('id')
|
||||||
|
src_state['children'] = []
|
||||||
|
src_state['active'] = []
|
||||||
|
|
||||||
|
new_graph = QGraphWindow.set_state(src_state)
|
||||||
|
self.graphs[new_graph.id] = new_graph
|
||||||
|
self.restoreGraph.emit(new_graph.id)
|
||||||
|
|
||||||
|
self.copy_sets(src=gid, dest=new_graph.id)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(list)
|
@QtCore.pyqtSlot(list)
|
||||||
@QtCore.pyqtSlot(str)
|
@QtCore.pyqtSlot(str)
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
@ -314,18 +330,22 @@ class UpperManagement(QtCore.QObject):
|
|||||||
if k in self.data:
|
if k in self.data:
|
||||||
parent_graph = self.data[k].graph
|
parent_graph = self.data[k].graph
|
||||||
if parent_graph not in rm_set_by_graph:
|
if parent_graph not in rm_set_by_graph:
|
||||||
rm_set_by_graph[parent_graph] = []
|
rm_set_by_graph[parent_graph] = set()
|
||||||
|
|
||||||
rm_set_by_graph[parent_graph].append(k)
|
rm_set_by_graph[parent_graph].add(k)
|
||||||
|
|
||||||
elif k in self.graphs:
|
elif k in self.graphs:
|
||||||
rm_graphs.append(k)
|
rm_graphs.append(k)
|
||||||
|
if k not in rm_set_by_graph:
|
||||||
|
rm_set_by_graph[k] = set()
|
||||||
|
for ss in self.graphs[k].sets:
|
||||||
|
rm_set_by_graph[k].add(ss)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.warning(f'delete_sets: {k} is not in data or graph found')
|
logger.warning(f'delete_sets: {k} is not in data or graph found')
|
||||||
|
|
||||||
for gid, sid_list in rm_set_by_graph.items():
|
for gid, sid_list in rm_set_by_graph.items():
|
||||||
cmd = DeleteCommand(self.data, sid_list, self.graphs, gid, self.newData, self.deleteData)
|
cmd = DeleteCommand(self.data, list(sid_list), self.graphs, gid, self.newData, self.deleteData)
|
||||||
self.undostack.push(cmd)
|
self.undostack.push(cmd)
|
||||||
|
|
||||||
for k in rm_graphs:
|
for k in rm_graphs:
|
||||||
@ -343,6 +363,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
group_set = set()
|
group_set = set()
|
||||||
name_set = set()
|
name_set = set()
|
||||||
value_set = set()
|
value_set = set()
|
||||||
|
graph_set = set()
|
||||||
|
|
||||||
if src_sets is None:
|
if src_sets is None:
|
||||||
if self.current_graph:
|
if self.current_graph:
|
||||||
@ -360,6 +381,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
name_set.add(data_i.name)
|
name_set.add(data_i.name)
|
||||||
group_set.add(data_i.group)
|
group_set.add(data_i.group)
|
||||||
value_set.add(data_i.value)
|
value_set.add(data_i.value)
|
||||||
|
graph_set.add(data_i.graph)
|
||||||
|
|
||||||
if joined is not None:
|
if joined is not None:
|
||||||
joined.group = '+'.join(group_set)
|
joined.group = '+'.join(group_set)
|
||||||
@ -370,7 +392,9 @@ class UpperManagement(QtCore.QObject):
|
|||||||
else:
|
else:
|
||||||
joined.value = 0.0
|
joined.value = 0.0
|
||||||
|
|
||||||
self.newData.emit([self.add(joined)], self.current_graph)
|
dest_graph = graph_set.pop() if len(graph_set) == 1 else self.current_graph
|
||||||
|
|
||||||
|
self.newData.emit([self.add(joined)], dest_graph)
|
||||||
|
|
||||||
def get_data(self, sid: str, xy_only: bool = False):
|
def get_data(self, sid: str, xy_only: bool = False):
|
||||||
"""
|
"""
|
||||||
@ -404,6 +428,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
self.graphs[d.graph].update_legend(identifier, name)
|
self.graphs[d.graph].update_legend(identifier, name)
|
||||||
elif identifier in self.graphs:
|
elif identifier in self.graphs:
|
||||||
self.graphs[identifier].title = name
|
self.graphs[identifier].title = name
|
||||||
|
self.graphs.valueChanged.emit()
|
||||||
else:
|
else:
|
||||||
raise KeyError('Unknown ID ' + str(identifier))
|
raise KeyError('Unknown ID ' + str(identifier))
|
||||||
|
|
||||||
@ -425,10 +450,17 @@ class UpperManagement(QtCore.QObject):
|
|||||||
self.undostack.push(single_undo)
|
self.undostack.push(single_undo)
|
||||||
self.undostack.endMacro()
|
self.undostack.endMacro()
|
||||||
|
|
||||||
def cut(self):
|
def cut(self, x: bool = False, y: bool = False) -> None:
|
||||||
if self.current_graph:
|
if self.current_graph:
|
||||||
xlim, _ = self.graphs[self.current_graph].ranges
|
xlim, ylim = self.graphs[self.current_graph].ranges
|
||||||
self.apply('cut', xlim)
|
|
||||||
|
if x is False:
|
||||||
|
xlim = (None, None)
|
||||||
|
|
||||||
|
if y is False:
|
||||||
|
ylim = (None, None)
|
||||||
|
|
||||||
|
self.apply('cut', (*xlim, *ylim))
|
||||||
|
|
||||||
@QtCore.pyqtSlot()
|
@QtCore.pyqtSlot()
|
||||||
def unmask(self):
|
def unmask(self):
|
||||||
@ -449,6 +481,11 @@ class UpperManagement(QtCore.QObject):
|
|||||||
|
|
||||||
self.fitter.fitmethod = fit_mode
|
self.fitter.fitmethod = fit_mode
|
||||||
|
|
||||||
|
# sets are not in active order but in order they first appeared in fit dialog
|
||||||
|
# iterate over order of set id in active order and access parameter inside loop
|
||||||
|
# instead of directly looping
|
||||||
|
list_ids = list(self.active_id)
|
||||||
|
|
||||||
# all-encompassing error catch
|
# all-encompassing error catch
|
||||||
try:
|
try:
|
||||||
for model_id, model_p in parameter.items():
|
for model_id, model_p in parameter.items():
|
||||||
@ -457,27 +494,16 @@ class UpperManagement(QtCore.QObject):
|
|||||||
|
|
||||||
m_complex = model_p['complex']
|
m_complex = model_p['complex']
|
||||||
|
|
||||||
# sets are not in active order but in order they first appeared in fit dialog
|
for set_id in list_ids:
|
||||||
# iterate over order of set id in active order and access parameter inside loop
|
if set_id not in model_p['data_parameter']:
|
||||||
# instead of directly looping
|
continue
|
||||||
try:
|
|
||||||
list_ids = list(self.active_id)
|
|
||||||
set_order = [self.active_id.index(i) for i in model_p['data_parameter'].keys()]
|
|
||||||
except ValueError as e:
|
|
||||||
raise Exception('Getting order failed') from e
|
|
||||||
|
|
||||||
for pos in set_order:
|
|
||||||
set_id = list_ids[pos]
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data_i = self.data[set_id]
|
data_i = self.data[set_id]
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
raise KeyError(f'{set_id} not found') from e
|
raise KeyError(f'{set_id} not found') from e
|
||||||
|
|
||||||
try:
|
|
||||||
set_params = model_p['data_parameter'][set_id]
|
set_params = model_p['data_parameter'][set_id]
|
||||||
except KeyError as e:
|
|
||||||
raise KeyError(f'No parameter found for {set_id}') from e
|
|
||||||
|
|
||||||
if we_option.lower() == 'deltay':
|
if we_option.lower() == 'deltay':
|
||||||
we = data_i.y_err**2
|
we = data_i.y_err**2
|
||||||
@ -485,29 +511,46 @@ class UpperManagement(QtCore.QObject):
|
|||||||
we = we_option
|
we = we_option
|
||||||
|
|
||||||
if m_complex is None or m_complex == 1:
|
if m_complex is None or m_complex == 1:
|
||||||
|
# model is not complex: m_complex = None
|
||||||
|
# model is complex, fit real part: m_complex = 1
|
||||||
_y = data_i.y.real
|
_y = data_i.y.real
|
||||||
elif m_complex == 2 and np.iscomplexobj(data_i.y):
|
data_complex = 1
|
||||||
|
elif m_complex == 2:
|
||||||
|
# model is complex, fit imag part: m_complex = 2
|
||||||
|
if np.iscomplexobj(data_i.y):
|
||||||
|
# data is complex, use imag part
|
||||||
_y = data_i.y.imag
|
_y = data_i.y.imag
|
||||||
|
data_complex = 2
|
||||||
else:
|
else:
|
||||||
|
# data is real
|
||||||
_y = data_i.y
|
_y = data_i.y
|
||||||
|
data_complex = 1
|
||||||
|
else:
|
||||||
|
# model is complex, fit complex: m_complex = 0
|
||||||
|
# use data as given (complex or not)
|
||||||
|
_y = data_i.y
|
||||||
|
data_complex = 0
|
||||||
|
|
||||||
_x = data_i.x
|
_x = data_i.x
|
||||||
|
|
||||||
|
# options for fit limits 'none', 'x', ('in', custom region), ('out', excluded region)
|
||||||
if fit_limits == 'none':
|
if fit_limits == 'none':
|
||||||
inside = slice(None)
|
inside = slice(None)
|
||||||
elif fit_limits == 'x':
|
elif fit_limits == 'x':
|
||||||
x_lim, _ = self.graphs[self.current_graph].ranges
|
x_lim, _ = self.graphs[self.current_graph].ranges
|
||||||
inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
|
inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
|
||||||
|
elif fit_limits[0] == 'in':
|
||||||
|
inside = np.where((_x >= fit_limits[1][0]) & (_x <= fit_limits[1][1]))
|
||||||
else:
|
else:
|
||||||
inside = np.where((_x >= fit_limits[0]) & (_x <= fit_limits[1]))
|
inside = np.where((_x < fit_limits[1][0]) | (_x > fit_limits[1][1]))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if isinstance(we, str):
|
if isinstance(we, str):
|
||||||
d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id)
|
d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id, complex_type=data_complex)
|
||||||
else:
|
else:
|
||||||
d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id)
|
d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id, complex_type=data_complex)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise Exception(f'Setting data failed for {set_id}')
|
raise Exception(f'Setting data failed for {data_i.name}') from e
|
||||||
|
|
||||||
d.set_model(m)
|
d.set_model(m)
|
||||||
try:
|
try:
|
||||||
@ -523,7 +566,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error('Fit preparation failed', *e.args)
|
logger.error(f'Fit preparation failed with error: {e.args}')
|
||||||
QtWidgets.QMessageBox.warning(QtWidgets.QWidget(),
|
QtWidgets.QMessageBox.warning(QtWidgets.QWidget(),
|
||||||
'Fit prep failed',
|
'Fit prep failed',
|
||||||
f'Fit preparation failed:\n'
|
f'Fit preparation failed:\n'
|
||||||
@ -551,13 +594,23 @@ class UpperManagement(QtCore.QObject):
|
|||||||
def end_fit(self, result: list, success: bool):
|
def end_fit(self, result: list, success: bool):
|
||||||
if success:
|
if success:
|
||||||
logger.info('Successful fit')
|
logger.info('Successful fit')
|
||||||
self.fitFinished.emit(result)
|
|
||||||
|
sub_colors = {}
|
||||||
|
for k, v in self.__fit_options[0].items():
|
||||||
|
sub_colors.update({set_id: v['color'] for set_id in v['data_parameter']})
|
||||||
|
|
||||||
|
self.fitFinished.emit(result, sub_colors)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
e = result[0]
|
e = result[0]
|
||||||
logger.exception(e, exc_info=True)
|
logger.exception(e, exc_info=True)
|
||||||
QtWidgets.QMessageBox.warning(QtWidgets.QWidget(), 'Fit failed',
|
QtWidgets.QMessageBox.warning(
|
||||||
f'Fit kaput with exception: \n\n{e!r}')
|
QtWidgets.QWidget(),
|
||||||
self.fitFinished.emit([])
|
'Fit failed',
|
||||||
|
f'Fit kaput with exception: \n\n{e!r}'
|
||||||
|
)
|
||||||
|
self.fitFinished.emit([], {})
|
||||||
|
|
||||||
self._fit_active = False
|
self._fit_active = False
|
||||||
|
|
||||||
@QtCore.pyqtSlot(dict)
|
@QtCore.pyqtSlot(dict)
|
||||||
@ -595,7 +648,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
if not all(e is None for e in extrapolate):
|
if not all(e is None for e in extrapolate):
|
||||||
spacefunc = np.geomspace if fit.islog else np.linspace
|
spacefunc = np.geomspace if extrapolate[3] else np.linspace
|
||||||
|
|
||||||
xmin = fit.x.min()
|
xmin = fit.x.min()
|
||||||
xmax = fit.x.max()
|
xmax = fit.x.max()
|
||||||
@ -658,16 +711,20 @@ class UpperManagement(QtCore.QObject):
|
|||||||
|
|
||||||
self.newData.emit(f_id_list, gid)
|
self.newData.emit(f_id_list, gid)
|
||||||
|
|
||||||
def extend_fits(self, set_id: list, x_range: np.ndarray):
|
def extend_fits(self, set_id: list, x_range: np.ndarray | None, only_subplots: bool):
|
||||||
graphs = {}
|
graphs = {}
|
||||||
for sid in set_id:
|
for sid in set_id:
|
||||||
data = self[sid]
|
data = fit = self[sid]
|
||||||
fit = data.copy(full=True, keep_color=True)
|
|
||||||
fit.data = fit.data.with_new_x(x_range)
|
|
||||||
|
|
||||||
graph_id = data.graph
|
graph_id = data.graph
|
||||||
if graph_id not in graphs:
|
if graph_id not in graphs:
|
||||||
graphs[graph_id] = []
|
graphs[graph_id] = []
|
||||||
|
|
||||||
|
if not only_subplots:
|
||||||
|
fit = data.copy(full=True, keep_color=True)
|
||||||
|
if x_range is not None:
|
||||||
|
fit.data = fit.data.with_new_x(x_range)
|
||||||
|
|
||||||
graphs[graph_id].append(self.add(fit))
|
graphs[graph_id].append(self.add(fit))
|
||||||
|
|
||||||
color_scheme = available_cycles['colorblind']
|
color_scheme = available_cycles['colorblind']
|
||||||
@ -734,14 +791,27 @@ class UpperManagement(QtCore.QObject):
|
|||||||
_active = self.graphs[self.current_graph].active
|
_active = self.graphs[self.current_graph].active
|
||||||
|
|
||||||
new_datasets = {}
|
new_datasets = {}
|
||||||
|
groupby = params.pop('groupby')
|
||||||
|
|
||||||
for sid in _active:
|
for sid in _active:
|
||||||
data_i = self.data[sid]
|
data_i = self.data[sid]
|
||||||
|
pts = data_i.points(params)
|
||||||
|
|
||||||
|
if groupby == 'group':
|
||||||
if data_i.group not in new_datasets:
|
if data_i.group not in new_datasets:
|
||||||
new_datasets[data_i.group] = [], []
|
new_datasets[data_i.group] = [], []
|
||||||
new_x_axis, _temp = new_datasets[data_i.group]
|
new_x_axis, _temp = new_datasets[data_i.group]
|
||||||
|
if pts:
|
||||||
new_x_axis.append(data_i.value)
|
new_x_axis.append(data_i.value)
|
||||||
_temp.append(data_i.points(params))
|
_temp.append(pts)
|
||||||
|
|
||||||
|
else:
|
||||||
|
for (_x, _y, _yerr) in pts:
|
||||||
|
if _x not in new_datasets:
|
||||||
|
new_datasets[_x] = [], []
|
||||||
|
new_x_axis, _temp = new_datasets[_x]
|
||||||
|
new_x_axis.append(data_i.value)
|
||||||
|
_temp.append([[_x, _y, _yerr]])
|
||||||
|
|
||||||
key_list = []
|
key_list = []
|
||||||
for label, (new_x_axis, _temp) in new_datasets.items():
|
for label, (new_x_axis, _temp) in new_datasets.items():
|
||||||
@ -822,9 +892,23 @@ class UpperManagement(QtCore.QObject):
|
|||||||
new_x = self.data[new_axis[0]].x
|
new_x = self.data[new_axis[0]].x
|
||||||
|
|
||||||
new_key = []
|
new_key = []
|
||||||
|
missed = []
|
||||||
for ids in data_ids:
|
for ids in data_ids:
|
||||||
|
try:
|
||||||
k = self.add(interpolate(self.data[ids], new_x, xlog=xlog, ylog=ylog, kind=mode, extrapolate=True))
|
k = self.add(interpolate(self.data[ids], new_x, xlog=xlog, ylog=ylog, kind=mode, extrapolate=True))
|
||||||
new_key.append(k)
|
new_key.append(k)
|
||||||
|
except ValueError:
|
||||||
|
missed.append(self.data[ids].name)
|
||||||
|
|
||||||
|
if missed:
|
||||||
|
missed_str = '\n'.join(missed)
|
||||||
|
_ = QtWidgets.QMessageBox.warning(
|
||||||
|
QtWidgets.QWidget(),
|
||||||
|
'Interpolation failed',
|
||||||
|
f'Interpolation failed for the following sets:\n\n'
|
||||||
|
f'{missed_str}\n\n'
|
||||||
|
f'(Probably because of duplicate x values)'
|
||||||
|
)
|
||||||
|
|
||||||
self.newData.emit(new_key, dest_graph)
|
self.newData.emit(new_key, dest_graph)
|
||||||
|
|
||||||
@ -960,7 +1044,7 @@ class UpperManagement(QtCore.QObject):
|
|||||||
else:
|
else:
|
||||||
data = self.data[sets[0]]
|
data = self.data[sets[0]]
|
||||||
if isinstance(data.data, new_type):
|
if isinstance(data.data, new_type):
|
||||||
error_list.append(f'{data.name} is alreade of type {new_type.__name__}')
|
error_list.append(f'{data.name} is already of type {new_type.__name__}')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
new_data = new_type(data.x, np.zeros(data.x.size))
|
new_data = new_type(data.x, np.zeros(data.x.size))
|
||||||
@ -994,6 +1078,8 @@ class UpperManagement(QtCore.QObject):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(list, list, bool)
|
@QtCore.pyqtSlot(list, list, bool)
|
||||||
def eval_expression(self, cmds: list, set_ids: list, overwrite: bool):
|
def eval_expression(self, cmds: list, set_ids: list, overwrite: bool):
|
||||||
|
if self.namespace is None:
|
||||||
|
self.namespace = self.get_namespace()
|
||||||
ns = self.namespace.flatten()
|
ns = self.namespace.flatten()
|
||||||
|
|
||||||
if overwrite:
|
if overwrite:
|
||||||
@ -1026,13 +1112,28 @@ class UpperManagement(QtCore.QObject):
|
|||||||
|
|
||||||
if failures:
|
if failures:
|
||||||
err_msg = QtWidgets.QMessageBox(parent=self.sender())
|
err_msg = QtWidgets.QMessageBox(parent=self.sender())
|
||||||
err_msg.setText('One or more errors occured during evaluation.')
|
err_msg.setText('One or more errors occurred during evaluation.')
|
||||||
err_msg.setDetailedText('\n'.join(f'{d.name} failed with error: {err.args}' for d, err in failures))
|
err_msg.setDetailedText('\n'.join(f'{d.name} failed with error: {err.args}' for d, err in failures))
|
||||||
err_msg.exec()
|
err_msg.exec()
|
||||||
|
|
||||||
self.sender().success = not failures
|
self.sender().success = not failures
|
||||||
self.sender().add_data(self.active_sets)
|
self.sender().add_data(self.active_sets)
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(str)
|
||||||
|
def run_script(self, text):
|
||||||
|
self.namespace = self.get_namespace()
|
||||||
|
ns = self.namespace.flatten()
|
||||||
|
ns['return_list'] = []
|
||||||
|
|
||||||
|
# custom namespace must be available in global namespace of exec, otherwise imports do not work in functions
|
||||||
|
exec(text, ns, ns)
|
||||||
|
|
||||||
|
new_sets = []
|
||||||
|
for new_data in ns['return_list']:
|
||||||
|
new_sets.append(self.add(new_data))
|
||||||
|
|
||||||
|
self.newData.emit(new_sets, '')
|
||||||
|
|
||||||
@QtCore.pyqtSlot(list, dict)
|
@QtCore.pyqtSlot(list, dict)
|
||||||
def create_from_function(self, cmds: list, opts: dict):
|
def create_from_function(self, cmds: list, opts: dict):
|
||||||
ns = dict(self.namespace.flatten())
|
ns = dict(self.namespace.flatten())
|
||||||
|
@ -16,6 +16,12 @@ class InterpolDialog(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
self.step_lineEdit.setValidator(QtGui.QIntValidator())
|
self.step_lineEdit.setValidator(QtGui.QIntValidator())
|
||||||
|
|
||||||
self._data = {}
|
self._data = {}
|
||||||
|
self._src_id = None
|
||||||
|
self._dest_graph = ''
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
self.listWidget.clear()
|
||||||
|
self._data = {}
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_xaxis_comboBox_currentIndexChanged')
|
@QtCore.pyqtSlot(int, name='on_xaxis_comboBox_currentIndexChanged')
|
||||||
def change_x_source(self, idx: int):
|
def change_x_source(self, idx: int):
|
||||||
@ -25,29 +31,41 @@ class InterpolDialog(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
def set_data(self, data, current_gid):
|
def set_data(self, data, current_gid):
|
||||||
self.graph_combobox.blockSignals(True)
|
self.graph_combobox.blockSignals(True)
|
||||||
self._data = {}
|
self._data = {}
|
||||||
|
dest_idx = 0
|
||||||
for (gid, graph_name), sets in data.items():
|
for (gid, graph_name), sets in data.items():
|
||||||
self.graph_combobox.addItem(graph_name, userData=gid)
|
self.graph_combobox.addItem(graph_name, userData=gid)
|
||||||
self.dest_combobox.addItem(graph_name, userData=gid)
|
self.dest_combobox.addItem(graph_name, userData=gid)
|
||||||
|
if self._dest_graph == gid:
|
||||||
|
dest_idx = self.dest_combobox.currentIndex()
|
||||||
if gid == current_gid:
|
if gid == current_gid:
|
||||||
self.make_list(sets)
|
self.make_list(sets)
|
||||||
self._data[gid] = sets
|
self._data[gid] = sets
|
||||||
self.graph_combobox.blockSignals(False)
|
self.graph_combobox.blockSignals(False)
|
||||||
self.change_graph(0)
|
self.change_graph(dest_idx)
|
||||||
|
|
||||||
def make_list(self, current_sets):
|
def make_list(self, current_sets):
|
||||||
for sid, set_name in current_sets:
|
for sid, set_name in current_sets:
|
||||||
item = QtWidgets.QListWidgetItem(set_name)
|
item = QtWidgets.QListWidgetItem(set_name)
|
||||||
item.setData(QtCore.Qt.UserRole, sid)
|
item.setData(QtCore.Qt.ItemDataRole.UserRole, sid)
|
||||||
item.setCheckState(QtCore.Qt.Checked)
|
item.setCheckState(QtCore.Qt.CheckState.Checked)
|
||||||
self.listWidget.addItem(item)
|
self.listWidget.addItem(item)
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_graph_combobox_currentIndexChanged')
|
@QtCore.pyqtSlot(int, name='on_graph_combobox_currentIndexChanged')
|
||||||
def change_graph(self, idx: int):
|
def change_graph(self, idx: int):
|
||||||
self.set_combobox.clear()
|
self.set_combobox.clear()
|
||||||
gid = self.graph_combobox.itemData(idx, QtCore.Qt.UserRole)
|
gid = self.graph_combobox.itemData(idx, QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
set_idx = -1
|
||||||
if gid is not None:
|
if gid is not None:
|
||||||
for set_key, set_name in self._data[gid]:
|
for i, (set_key, set_name) in enumerate(self._data[gid]):
|
||||||
|
print(self._src_id, set_key, set_name, i)
|
||||||
self.set_combobox.addItem(set_name, userData=set_key)
|
self.set_combobox.addItem(set_name, userData=set_key)
|
||||||
|
print(self.set_combobox.currentIndex())
|
||||||
|
if self._src_id == set_key:
|
||||||
|
set_idx = i
|
||||||
|
|
||||||
|
print(set_idx)
|
||||||
|
if set_idx > -1:
|
||||||
|
self.set_combobox.setCurrentIndex(set_idx)
|
||||||
|
|
||||||
def collect_parameter(self):
|
def collect_parameter(self):
|
||||||
xlog = self.xlog_checkBox.isChecked()
|
xlog = self.xlog_checkBox.isChecked()
|
||||||
@ -71,21 +89,35 @@ class InterpolDialog(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
x_src = (start, stop, step, loggy)
|
x_src = (start, stop, step, loggy)
|
||||||
else:
|
else:
|
||||||
x_src = (self.set_combobox.currentData(QtCore.Qt.UserRole),)
|
self._src_id = self.set_combobox.currentData(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
x_src = (self._src_id,)
|
||||||
|
|
||||||
dest_graph = self.dest_combobox.currentData(QtCore.Qt.UserRole)
|
self._dest_graph = self.dest_combobox.currentData(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
use_data = []
|
use_data = []
|
||||||
for i in range(self.listWidget.count()):
|
for i in range(self.listWidget.count()):
|
||||||
item = self.listWidget.item(i)
|
item = self.listWidget.item(i)
|
||||||
if item.checkState() == QtCore.Qt.Checked:
|
if item.checkState() == QtCore.Qt.CheckState.Checked:
|
||||||
use_data.append(item.data(QtCore.Qt.UserRole))
|
use_data.append(item.data(QtCore.Qt.ItemDataRole.UserRole))
|
||||||
|
|
||||||
self.new_data.emit(use_data, mode, xlog, ylog, x_src, dest_graph)
|
self.new_data.emit(use_data, mode, xlog, ylog, x_src, self._dest_graph)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def accept(self):
|
def _save_state(self):
|
||||||
|
self._src_id = self.set_combobox.currentData(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
self._dest_graph = self.dest_combobox.currentData(QtCore.Qt.ItemDataRole.UserRole)
|
||||||
|
|
||||||
|
@QtCore.pyqtSlot(QtWidgets.QAbstractButton, name='on_buttonBox_clicked')
|
||||||
|
def check_next_actions(self, bttn: QtWidgets.QAbstractButton):
|
||||||
|
role = self.buttonBox.buttonRole(bttn)
|
||||||
|
self._save_state()
|
||||||
|
|
||||||
|
if role == self.buttonBox.ButtonRole.RejectRole:
|
||||||
|
self.close()
|
||||||
|
else:
|
||||||
success = self.collect_parameter()
|
success = self.collect_parameter()
|
||||||
if success:
|
|
||||||
super().accept()
|
if success and role == self.buttonBox.ButtonRole.AcceptRole:
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
@ -12,10 +12,10 @@ class QSmooth(QtWidgets.QDialog, Ui_SmoothDialog):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_comboBox_currentIndexChanged')
|
@QtCore.pyqtSlot(int, name='on_comboBox_currentIndexChanged')
|
||||||
def change_mode(self, idx: int):
|
def change_mode(self, idx: int):
|
||||||
if idx == 2:
|
if idx == 1:
|
||||||
self.widget.show()
|
self.widget.show()
|
||||||
self.widget_2.hide()
|
self.widget_2.hide()
|
||||||
elif idx == 3:
|
elif idx == 2:
|
||||||
self.widget.show()
|
self.widget.show()
|
||||||
self.widget_2.show()
|
self.widget_2.show()
|
||||||
else:
|
else:
|
||||||
@ -29,12 +29,24 @@ class QSmooth(QtWidgets.QDialog, Ui_SmoothDialog):
|
|||||||
idx = self.comboBox.currentIndex()
|
idx = self.comboBox.currentIndex()
|
||||||
|
|
||||||
# this order must match the combobox
|
# this order must match the combobox
|
||||||
para['mode'] = ['mean', 'savgol', 'loess', 'median', 'std', 'var', 'max', 'min', 'sum'][idx]
|
para['mode'] = [
|
||||||
|
'mean',
|
||||||
|
'savgol',
|
||||||
|
'loess',
|
||||||
|
'median',
|
||||||
|
'std',
|
||||||
|
'var',
|
||||||
|
'max',
|
||||||
|
'min',
|
||||||
|
'sum',
|
||||||
|
][idx]
|
||||||
|
|
||||||
if idx == 2:
|
# Savitzky-Golay needs also polynomial degree
|
||||||
|
if idx == 1:
|
||||||
para['deg'] = self.polynom_spinBox.value()
|
para['deg'] = self.polynom_spinBox.value()
|
||||||
|
|
||||||
if idx == 3:
|
# LOESS needs also polynomial degree and number of iterations
|
||||||
|
if idx == 2:
|
||||||
para['deg'] = self.polynom_spinBox.value()
|
para['deg'] = self.polynom_spinBox.value()
|
||||||
para['it'] = self.iter_spinBox.value()
|
para['it'] = self.iter_spinBox.value()
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from nmreval.nmr.coupling import *
|
from nmreval.nmr.coupling import *
|
||||||
from nmreval.distributions import ColeCole, ColeDavidson, HavriliakNegami, KWW, LogGaussian
|
from nmreval.distributions import ColeCole, ColeDavidson, HavriliakNegami, KWW, LogGaussian, GGAlpha
|
||||||
from nmreval.utils import pi
|
from nmreval.utils import pi
|
||||||
from nmreval.utils.text import convert
|
from nmreval.utils.text import convert
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ class QRelaxCalc(QtWidgets.QDialog, Ui_Dialog):
|
|||||||
|
|
||||||
self.graphs = {}
|
self.graphs = {}
|
||||||
|
|
||||||
self.specdens = [ColeCole, ColeDavidson, HavriliakNegami, KWW, LogGaussian]
|
self.specdens = [ColeCole, ColeDavidson, HavriliakNegami, KWW, LogGaussian, GGAlpha]
|
||||||
self.coupling = [Quadrupolar, HomoDipolar, Czjzek]
|
self.coupling = [Quadrupolar, HomoDipolar, Czjzek]
|
||||||
self.tau_parameter = []
|
self.tau_parameter = []
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
self.t1calculator = RelaxationEvaluation()
|
self.t1calculator = RelaxationEvaluation()
|
||||||
|
|
||||||
self.sd_parameter = []
|
self.sd_parameter = []
|
||||||
self.sdmodels = [Debye, ColeCole, ColeDavidson, KWW, HavriliakNegami, LogGaussian]
|
self.sdmodels = [Debye, ColeCole, ColeDavidson, KWW, HavriliakNegami, LogGaussian, GGAlpha]
|
||||||
for i in self.sdmodels:
|
for i in self.sdmodels:
|
||||||
self.specdens_combobox.addItem(i.name)
|
self.specdens_combobox.addItem(i.name)
|
||||||
self.specdens_combobox.currentIndexChanged.connect(self.update_specdens)
|
self.specdens_combobox.currentIndexChanged.connect(self.update_specdens)
|
||||||
@ -51,8 +51,14 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
self.conv_y = QT1Widget.time_conversion[self.t1_combobox.currentIndex()]
|
self.conv_y = QT1Widget.time_conversion[self.t1_combobox.currentIndex()]
|
||||||
|
|
||||||
self.minimum = (1, np.inf)
|
self.minimum = (1, np.inf)
|
||||||
self.min_pos = PlotItem(x=np.array([]), y=np.array([]),
|
self.min_pos = PlotItem(
|
||||||
symbol='+', symbolBrush=mkBrush(color='r'), symbolPen=mkPen(color='r'), symbolSize=14)
|
x=np.array([]),
|
||||||
|
y=np.array([]),
|
||||||
|
symbol='+',
|
||||||
|
symbolBrush=mkBrush(color='r'),
|
||||||
|
symbolPen=mkPen(color='r'),
|
||||||
|
symbolSize=14,
|
||||||
|
)
|
||||||
self.parabola = PlotItem(x=np.array([]), y=np.array([]))
|
self.parabola = PlotItem(x=np.array([]), y=np.array([]))
|
||||||
|
|
||||||
self.lineEdit_2.setValidator(QtGui.QDoubleValidator())
|
self.lineEdit_2.setValidator(QtGui.QDoubleValidator())
|
||||||
@ -83,10 +89,10 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
right_b = min(np.argmin(y)+3, len(x)-1)
|
right_b = min(np.argmin(y)+3, len(x)-1)
|
||||||
|
|
||||||
self.lineEdit_2.blockSignals(True)
|
self.lineEdit_2.blockSignals(True)
|
||||||
self.lineEdit_2.setText('{:.2f}'.format(x[left_b]))
|
self.lineEdit_2.setText(f'{x[left_b]:.2f}')
|
||||||
self.lineEdit_2.blockSignals(False)
|
self.lineEdit_2.blockSignals(False)
|
||||||
self.lineEdit_3.blockSignals(True)
|
self.lineEdit_3.blockSignals(True)
|
||||||
self.lineEdit_3.setText('{:.2f}'.format(x[right_b]))
|
self.lineEdit_3.setText(f'{x[right_b]:.2f}')
|
||||||
self.lineEdit_3.blockSignals(False)
|
self.lineEdit_3.blockSignals(False)
|
||||||
|
|
||||||
self.t1calculator.set_data(x, y)
|
self.t1calculator.set_data(x, y)
|
||||||
@ -110,6 +116,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
|
|
||||||
if self.sdmodels[idx].parameter is not None:
|
if self.sdmodels[idx].parameter is not None:
|
||||||
for name in self.sdmodels[idx].parameter:
|
for name in self.sdmodels[idx].parameter:
|
||||||
|
print(name)
|
||||||
_temp = FormWidget(parent=self, name=name, fixable=True)
|
_temp = FormWidget(parent=self, name=name, fixable=True)
|
||||||
_temp.value = 1
|
_temp.value = 1
|
||||||
_temp.setChecked(True)
|
_temp.setChecked(True)
|
||||||
@ -133,7 +140,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
try:
|
try:
|
||||||
for i, v, in enumerate(values):
|
for i, v, in enumerate(values):
|
||||||
self.sd_parameter[i].blockSignals(True)
|
self.sd_parameter[i].blockSignals(True)
|
||||||
self.sd_parameter[i].value = '{:.3g}'.format(round(v, 3))
|
self.sd_parameter[i].value = f'{v:.3g}'
|
||||||
self.sd_parameter[i].blockSignals(False)
|
self.sd_parameter[i].blockSignals(False)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
@ -219,7 +226,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
self.update_model()
|
self.update_model()
|
||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_interpol_combobox_currentIndexChanged')
|
@QtCore.pyqtSlot(int, name='on_interpol_combobox_currentIndexChanged')
|
||||||
def determine_minimum(self, idx):
|
def determine_minimum(self, idx: int):
|
||||||
if idx == 0:
|
if idx == 0:
|
||||||
self.checkBox_interpol.setChecked(False)
|
self.checkBox_interpol.setChecked(False)
|
||||||
self.checkBox_interpol.hide()
|
self.checkBox_interpol.hide()
|
||||||
@ -229,9 +236,10 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
self.checkBox_interpol.show()
|
self.checkBox_interpol.show()
|
||||||
self.frame.show()
|
self.frame.show()
|
||||||
try:
|
try:
|
||||||
m, i_func = self.t1calculator.calculate_t1_min(interpolate=idx,
|
m, i_func = self.t1calculator.calculate_t1_min(
|
||||||
trange=(float(self.lineEdit_2.text()),
|
interpolate=idx,
|
||||||
float(self.lineEdit_3.text())))
|
trange=(float(self.lineEdit_2.text()), float(self.lineEdit_3.text())),
|
||||||
|
)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
m, i_func = self.t1calculator.calculate_t1_min(interpolate=None)
|
m, i_func = self.t1calculator.calculate_t1_min(interpolate=None)
|
||||||
|
|
||||||
@ -273,11 +281,13 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
return
|
return
|
||||||
|
|
||||||
with busy_cursor():
|
with busy_cursor():
|
||||||
calc_stretching, mini = self.t1calculator.get_increase(height=self.minimum[1],
|
calc_stretching, mini = self.t1calculator.get_increase(
|
||||||
|
height=self.minimum[1],
|
||||||
idx=var_idx, mode=notfix,
|
idx=var_idx, mode=notfix,
|
||||||
omega=2*np.pi*self.frequency,
|
omega=2*np.pi*self.frequency,
|
||||||
dist_parameter=sd_args, prefactor=cp_args,
|
dist_parameter=sd_args, prefactor=cp_args,
|
||||||
coupling_kwargs=cp_kwargs)
|
coupling_kwargs=cp_kwargs
|
||||||
|
)
|
||||||
|
|
||||||
self.label_t1min.setText(f'{mini:.4g} s')
|
self.label_t1min.setText(f'{mini:.4g} s')
|
||||||
|
|
||||||
@ -292,9 +302,13 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
sd_args, _ = self.get_sd_values()
|
sd_args, _ = self.get_sd_values()
|
||||||
cp_args, cp_kwargs, _ = self.get_cp_values()
|
cp_args, cp_kwargs, _ = self.get_cp_values()
|
||||||
tau_mode = ['fit', 'peak', 'mean', 'logmean'][self.tau_combox.currentIndex()]
|
tau_mode = ['fit', 'peak', 'mean', 'logmean'][self.tau_combox.currentIndex()]
|
||||||
corr, opts = self.t1calculator.correlation_from_t1(omega=2*np.pi*self.frequency, dist_parameter=sd_args,
|
corr, opts = self.t1calculator.correlation_from_t1(
|
||||||
|
omega=2*np.pi*self.frequency,
|
||||||
|
dist_parameter=sd_args,
|
||||||
coupling_param=cp_args, coupling_kwargs=cp_kwargs,
|
coupling_param=cp_args, coupling_kwargs=cp_kwargs,
|
||||||
mode=tau_mode, interpolate=self.checkBox_interpol.isChecked())
|
mode=tau_mode,
|
||||||
|
interpolate=self.checkBox_interpol.isChecked()
|
||||||
|
)
|
||||||
|
|
||||||
name = self.name + '-' + str(self.t1calculator) + '('
|
name = self.name + '-' + str(self.t1calculator) + '('
|
||||||
name += ','.join([f'{a:.3g}' for a in sd_args])
|
name += ','.join([f'{a:.3g}' for a in sd_args])
|
||||||
@ -332,4 +346,4 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
|||||||
|
|
||||||
@QtCore.pyqtSlot(int, name='on_graph_checkbox_stateChanged')
|
@QtCore.pyqtSlot(int, name='on_graph_checkbox_stateChanged')
|
||||||
def changed_state(self, checked):
|
def changed_state(self, checked):
|
||||||
self.graph_combobox.setEnabled(checked != QtCore.Qt.Checked)
|
self.graph_combobox.setEnabled(checked != QtCore.Qt.CheckState.Checked)
|
||||||
|
@ -156,3 +156,20 @@ double energyDistCorrelation(double x, void *user_data) {
|
|||||||
return normalDist(x, e_m, e_b) * exp(-t * r);
|
return normalDist(x, e_m, e_b) * exp(-t * r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generalised Gamma Function
|
||||||
|
double genGammaAlphaDist(double x, void *user_data) {
|
||||||
|
double *c = (double *)user_data;
|
||||||
|
|
||||||
|
double omega = c[0];
|
||||||
|
double tau0 = c[1];
|
||||||
|
double alpha = c[2];
|
||||||
|
double beta = c[3];
|
||||||
|
|
||||||
|
double b_to_a = beta / alpha;
|
||||||
|
double tau_to_tau0 = tau / tau0;
|
||||||
|
|
||||||
|
double norm = exp(-lgamma(b_to_a) + b_to_a * log(b_to_a)) * alpha;
|
||||||
|
|
||||||
|
return norm * exp(-b_to_a * pow(tau_to_tau0, alpha)) * pow(tau_to_tau0, beta);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -273,9 +273,14 @@ class Points:
|
|||||||
def length(self):
|
def length(self):
|
||||||
return len(self._x)
|
return len(self._x)
|
||||||
|
|
||||||
def points(self, idx: list = None, special: str = None,
|
def points(
|
||||||
avg_range: tuple[int, int] = (0, 0), avg_mode: str = 'mean',
|
self,
|
||||||
pts: list = None) -> list[tuple]:
|
idx: list = None,
|
||||||
|
special: str = None,
|
||||||
|
avg_range: tuple[int, int] = (0, 0),
|
||||||
|
avg_mode: str = 'mean',
|
||||||
|
pts: list = None,
|
||||||
|
) -> list[tuple]:
|
||||||
"""
|
"""
|
||||||
Return (x, y) values at specified positions.
|
Return (x, y) values at specified positions.
|
||||||
|
|
||||||
@ -294,7 +299,7 @@ class Points:
|
|||||||
|
|
||||||
avg_range (tuple of int) :
|
avg_range (tuple of int) :
|
||||||
Region for average of y values. Tuple (a, b) uses ``y[i-a:i+b+1]`` around index `i`. Default is (0, 0).
|
Region for average of y values. Tuple (a, b) uses ``y[i-a:i+b+1]`` around index `i`. Default is (0, 0).
|
||||||
avg_mode (str {'mean', 'sum', 'integral'} , optional) :
|
avg_mode (str {'mean', 'sum', 'integral', 'std'} , optional) :
|
||||||
Averaging type
|
Averaging type
|
||||||
|
|
||||||
`mean` : Arithmetic average
|
`mean` : Arithmetic average
|
||||||
@ -303,6 +308,8 @@ class Points:
|
|||||||
|
|
||||||
'integral`: Integration over range using Simpson's rule
|
'integral`: Integration over range using Simpson's rule
|
||||||
|
|
||||||
|
'std': Standard deviation
|
||||||
|
|
||||||
pts (list, optional) :
|
pts (list, optional) :
|
||||||
If given, points will be appended.
|
If given, points will be appended.
|
||||||
|
|
||||||
@ -313,66 +320,90 @@ class Points:
|
|||||||
if (idx is None) and (special is None):
|
if (idx is None) and (special is None):
|
||||||
raise ValueError('Either `idx` or `special` must be given')
|
raise ValueError('Either `idx` or `special` must be given')
|
||||||
|
|
||||||
if avg_mode not in ['mean', 'sum', 'integral']:
|
if avg_mode not in ['mean', 'sum', 'integral', 'std']:
|
||||||
raise ValueError(f'Parameter `avg_mode` is `mean`, `sum`, `integral`, not `{avg_mode}`' )
|
raise ValueError(f'Parameter `avg_mode` is `mean`, `sum`, `integral`, `std`, not `{avg_mode}`' )
|
||||||
|
|
||||||
if pts is None:
|
if pts is None:
|
||||||
pts = []
|
pts = []
|
||||||
|
|
||||||
|
_tmp_x = self._x[self.mask]
|
||||||
|
x_order = np.argsort(_tmp_x)
|
||||||
|
_tmp_x = _tmp_x[x_order]
|
||||||
|
_tmp_y = self._y[self.mask][x_order]
|
||||||
|
_tmp_yerr = self._y_err[self.mask][x_order]
|
||||||
|
|
||||||
if idx is not None:
|
if idx is not None:
|
||||||
for x in idx:
|
for idx_i in idx:
|
||||||
if isinstance(x, tuple):
|
if isinstance(idx_i, tuple):
|
||||||
x_idx = np.argmin(np.abs(self._x[self.mask] - (x[0]+x[1])/2))
|
in_region = np.where((_tmp_x - idx_i[0] > 0) & (idx_i[1] - _tmp_x > 0))[0]
|
||||||
left_b = np.argmin(np.abs(self._x[self.mask] - x[0]))
|
if len(in_region) > 0:
|
||||||
right_b = np.argmin(np.abs(self._x[self.mask] - x[1]))
|
x_idx = in_region[in_region.size//2]
|
||||||
|
left_b = in_region[0]
|
||||||
|
right_b = in_region[-1] + 1
|
||||||
else:
|
else:
|
||||||
x_idx = np.argmin(np.abs(self._x[self.mask]-x))
|
continue
|
||||||
|
|
||||||
|
else:
|
||||||
|
x_idx = np.argmin(np.abs(_tmp_x-idx_i))
|
||||||
left_b = int(max(0, x_idx - avg_range[0]))
|
left_b = int(max(0, x_idx - avg_range[0]))
|
||||||
right_b = int(min(len(self), x_idx + avg_range[1] + 1))
|
right_b = int(min(len(self), x_idx + avg_range[1] + 1))
|
||||||
|
|
||||||
if left_b < right_b:
|
if left_b < right_b:
|
||||||
pts.append([self._x[x_idx], *self._average(avg_mode, x_idx, left_b, right_b)])
|
pts.append([_tmp_x[x_idx], *self._average(_tmp_x, _tmp_y, _tmp_yerr, avg_mode, x_idx, left_b, right_b)])
|
||||||
else:
|
else:
|
||||||
pts.append([self._x[x_idx], self._y[x_idx], self._y_err[x_idx]])
|
pts.append([_tmp_x[x_idx], _tmp_y[x_idx], self._y_err[x_idx]])
|
||||||
|
|
||||||
if special is not None:
|
if special is not None:
|
||||||
if special not in ['max', 'min', 'absmax', 'absmin']:
|
if special not in ['max', 'min', 'absmax', 'absmin']:
|
||||||
raise ValueError('Parameter "special" must be "max", "min", "absmax", "absmin".')
|
raise ValueError('Parameter "special" must be "max", "min", "absmax", "absmin".')
|
||||||
|
|
||||||
if special == 'max':
|
if special == 'max':
|
||||||
x_idx = np.argmax(self._y.real[self.mask])
|
x_idx = np.argmax(_tmp_y.real)
|
||||||
elif special == 'min':
|
elif special == 'min':
|
||||||
x_idx = np.argmax(self._y.real[self.mask])
|
x_idx = np.argmax(_tmp_y.real)
|
||||||
elif special == 'absmax':
|
elif special == 'absmax':
|
||||||
x_idx = np.argmax(np.abs(self._y[self.mask]))
|
x_idx = np.argmax(np.abs(_tmp_y))
|
||||||
else:
|
else:
|
||||||
x_idx = np.argmin(np.abs(self._y[self.mask]))
|
x_idx = np.argmin(np.abs(_tmp_y))
|
||||||
|
|
||||||
left_b = int(max(0, x_idx - avg_range[0]))
|
left_b = int(max(0, x_idx - avg_range[0]))
|
||||||
right_b = int(min(len(self), x_idx + avg_range[1] + 1))
|
right_b = int(min(len(self), x_idx + avg_range[1] + 1))
|
||||||
|
|
||||||
pts.append([self._x[self.mask][x_idx], *self._average(avg_mode, x_idx, left_b, right_b)])
|
pts.append([_tmp_x[x_idx], *self._average(_tmp_x, _tmp_y, _tmp_yerr, avg_mode, x_idx, left_b, right_b)])
|
||||||
|
|
||||||
return pts
|
return pts
|
||||||
|
|
||||||
def _average(self, mode: str, idx, left: int, right: int) -> tuple[float, float]:
|
@staticmethod
|
||||||
|
def _average(
|
||||||
|
x: np.ndarray,
|
||||||
|
y: np.ndarray,
|
||||||
|
y_err: np.ndarray,
|
||||||
|
mode: str,
|
||||||
|
idx: int,
|
||||||
|
left: int,
|
||||||
|
right: int,
|
||||||
|
) -> tuple[float, float]:
|
||||||
if mode == 'mean':
|
if mode == 'mean':
|
||||||
y_mean = np.mean(self._y[self.mask][left:right].real)
|
y_mean = np.mean(y[left:right].real)
|
||||||
y_err = np.linalg.norm(self._y_err[self.mask][left:right]) / (right - left)
|
y_err_mean = np.linalg.norm(y_err[left:right]) / (right - left)
|
||||||
|
|
||||||
elif mode == 'sum':
|
elif mode == 'sum':
|
||||||
y_mean = np.sum(self._y[self.mask][left:right].real)
|
y_mean = np.sum(y[left:right].real)
|
||||||
y_err = np.linalg.norm(self._y_err[self.mask][left:right])
|
y_err_mean = np.linalg.norm(y_err[left:right])
|
||||||
|
|
||||||
elif mode == 'integral':
|
elif mode == 'integral':
|
||||||
y_mean = simpson(self._y[self.mask][left:right].real, x=self._x[left:right])
|
y_mean = simpson(y[left:right].real, x=x[left:right])
|
||||||
y_err = np.linalg.norm(cumulative_trapezoid(self._y_err[self.mask][left:right].real, x=self._x[left:right]))
|
y_err_mean = np.linalg.norm(cumulative_trapezoid(y_err[left:right].real, x=x[left:right]))
|
||||||
|
|
||||||
|
elif mode == 'std':
|
||||||
|
y_mean = np.std(y[left:right])
|
||||||
|
y_err_mean = 0.
|
||||||
|
|
||||||
else:
|
else:
|
||||||
y_mean = self._y[self.mask][idx].real
|
y_mean = y[idx].real
|
||||||
y_err = self._y_err[self.mask][idx]
|
y_err_mean = y_err[idx]
|
||||||
|
|
||||||
return y_mean, y_err
|
return y_mean, y_err_mean
|
||||||
|
|
||||||
def concatenate(self, other):
|
def concatenate(self, other):
|
||||||
"""
|
"""
|
||||||
@ -520,26 +551,37 @@ class Points:
|
|||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def cut(self, low_lim: float = None, high_lim: float = None):
|
def cut(self, x_low: float = None, x_high: float = None, y_low: float = None, y_high: float = None):
|
||||||
"""
|
"""
|
||||||
Cut
|
Cut
|
||||||
Args:
|
Args:
|
||||||
low_lim:
|
x_low: Lower limit
|
||||||
high_lim:
|
x_high: Upper limit for x values
|
||||||
|
y_low: Lower limit
|
||||||
|
y_high: Upper limit for x valuew
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if low_lim is None and high_lim is None:
|
|
||||||
|
if x_low is None and x_high is None and y_low is None and y_high is None:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
if low_lim is None:
|
if x_low is None:
|
||||||
low_lim = np.min(self._x)
|
x_low = np.min(self._x)-1
|
||||||
|
|
||||||
if high_lim is None:
|
if x_high is None:
|
||||||
high_lim = np.max(self._x)
|
x_high = np.max(self._x)+1
|
||||||
|
|
||||||
_mask = np.ma.masked_inside(self._x, low_lim, high_lim).mask
|
if y_low is None:
|
||||||
|
y_low = np.min(self._y.real)-1
|
||||||
|
|
||||||
|
if y_high is None:
|
||||||
|
y_high = np.max(self._y.real)+1
|
||||||
|
|
||||||
|
x_mask = (self._x >= x_low) & (self._x <= x_high)
|
||||||
|
y_mask = (self._y.real >= y_low) & (self._y.real <= y_high)
|
||||||
|
_mask = x_mask & y_mask
|
||||||
|
|
||||||
self._x = self._x[_mask]
|
self._x = self._x[_mask]
|
||||||
self._y = self._y[_mask]
|
self._y = self._y[_mask]
|
||||||
@ -690,7 +732,8 @@ class Points:
|
|||||||
np.savetxt(path, self.toarray(err=err), header=header, fmt='%.10e')
|
np.savetxt(path, self.toarray(err=err), header=header, fmt='%.10e')
|
||||||
else:
|
else:
|
||||||
with path.open('w') as f:
|
with path.open('w') as f:
|
||||||
f.write(header)
|
f.write('# ' + '\n# '.join(header.split('\n')))
|
||||||
|
f.write('\n')
|
||||||
for i, l in enumerate(self.toarray(err=err)):
|
for i, l in enumerate(self.toarray(err=err)):
|
||||||
if self.mask[i]:
|
if self.mask[i]:
|
||||||
f.write('\t'.join(map(lambda _x: f'{_x:.10e}', l.tolist())) + '\n')
|
f.write('\t'.join(map(lambda _x: f'{_x:.10e}', l.tolist())) + '\n')
|
||||||
@ -698,9 +741,11 @@ class Points:
|
|||||||
f.write('# ' + '\t'.join(map(lambda _x: f'{_x:.10e}', l.tolist())) + '\n')
|
f.write('# ' + '\t'.join(map(lambda _x: f'{_x:.10e}', l.tolist())) + '\n')
|
||||||
|
|
||||||
def get_state(self) -> dict:
|
def get_state(self) -> dict:
|
||||||
ret_dic = {'x': self._x.tolist(),
|
ret_dic = {
|
||||||
|
'x': self._x.tolist(),
|
||||||
'y': self._y.tolist(),
|
'y': self._y.tolist(),
|
||||||
'mask': (np.where(~self.mask)[0]).tolist()}
|
'mask': (np.where(~self.mask)[0]).tolist()
|
||||||
|
}
|
||||||
|
|
||||||
if np.all(self._y_err == 0):
|
if np.all(self._y_err == 0):
|
||||||
ret_dic['y_err'] = 0.0
|
ret_dic['y_err'] = 0.0
|
||||||
|
@ -26,3 +26,4 @@ from .coledavidson import ColeDavidson
|
|||||||
from .debye import Debye
|
from .debye import Debye
|
||||||
from .kww import KWW
|
from .kww import KWW
|
||||||
from .loggaussian import LogGaussian
|
from .loggaussian import LogGaussian
|
||||||
|
from .gengamma import GGAlpha
|
||||||
|
@ -3,7 +3,12 @@ from ctypes import c_double, cast, pointer, c_void_p
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy import LowLevelCallable
|
from scipy import LowLevelCallable
|
||||||
from scipy.integrate import quad, simps as simpson
|
|
||||||
|
from scipy.integrate import quad
|
||||||
|
try:
|
||||||
|
from scipy.integrate import simps as simpson
|
||||||
|
except ImportError:
|
||||||
|
from scipy.integrate import simpson
|
||||||
|
|
||||||
from .base import Distribution
|
from .base import Distribution
|
||||||
from ..lib.utils import ArrayLike
|
from ..lib.utils import ArrayLike
|
||||||
@ -90,7 +95,7 @@ def _integrate_c(func, omega: np.ndarray, temperature: np.ndarray, tau0: float,
|
|||||||
for o, t in product(omega, temperature):
|
for o, t in product(omega, temperature):
|
||||||
c = (c_double * 5)(o, tau0, e_m, e_b, t)
|
c = (c_double * 5)(o, tau0, e_m, e_b, t)
|
||||||
user_data = cast(pointer(c), c_void_p)
|
user_data = cast(pointer(c), c_void_p)
|
||||||
area = quad(LowLevelCallable(func, user_data), 0, np.infty, epsabs=1e-13)[0]
|
area = quad(LowLevelCallable(func, user_data), 0, np.inf, epsabs=1e-13)[0]
|
||||||
|
|
||||||
res.append(area)
|
res.append(area)
|
||||||
|
|
||||||
@ -106,7 +111,7 @@ def _integrate_py(func, axis, temp, tau0, e_m, e_b):
|
|||||||
e_axis = np.linspace(max(0., e_m - 50*e_b), e_m + 50*e_b, num=5001)
|
e_axis = np.linspace(max(0., e_m - 50*e_b), e_m + 50*e_b, num=5001)
|
||||||
ret_val = []
|
ret_val = []
|
||||||
for o, tt in product(x, temperature):
|
for o, tt in product(x, temperature):
|
||||||
ret_val.append(simpson(func(e_axis, o, tau0, e_m, e_b, tt), e_axis))
|
ret_val.append(simpson(y=func(e_axis, o, tau0, e_m, e_b, tt), x=e_axis))
|
||||||
|
|
||||||
ret_val = np.array(ret_val).reshape(x.shape[0], temperature.shape[0])
|
ret_val = np.array(ret_val).reshape(x.shape[0], temperature.shape[0])
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ try:
|
|||||||
from scipy.integrate import simpson
|
from scipy.integrate import simpson
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from scipy.integrate import simps as simpson
|
from scipy.integrate import simps as simpson
|
||||||
from scipy.special import gammaln
|
from scipy.special import gammaln, gamma as scipy_gamma
|
||||||
|
|
||||||
from nmreval.distributions.base import Distribution
|
from nmreval.distributions.base import Distribution
|
||||||
from nmreval.math.logfourier import logft
|
from nmreval.math.logfourier import logft
|
||||||
@ -20,10 +20,10 @@ class AbstractGG(Distribution, ABC):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def correlation(cls, t, tau0, *args):
|
def correlation(cls, t, tau0, *args):
|
||||||
tt = np.asanyarray(t)
|
tt = np.atleast_1d(t)
|
||||||
taus, ln_tau = AbstractGG._prepare_integration(tau0)
|
taus, ln_tau = AbstractGG._prepare_integration(tau0)
|
||||||
g_tau = cls.distribution(taus, tau0, *args)
|
g_tau = cls.distribution(taus, tau0, *args)
|
||||||
ret_val = np.array([simpson(np.exp(-t_i/taus) * g_tau, ln_tau) for t_i in tt])
|
ret_val = np.array([simpson(np.exp(-t_i/taus) * g_tau, x=ln_tau) for t_i in tt]).squeeze()
|
||||||
|
|
||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
@ -32,30 +32,41 @@ class AbstractGG(Distribution, ABC):
|
|||||||
r"""
|
r"""
|
||||||
Calculate spectral density \int G(ln(tau) tau/(1+(w*tau)^2) dln(tau)
|
Calculate spectral density \int G(ln(tau) tau/(1+(w*tau)^2) dln(tau)
|
||||||
"""
|
"""
|
||||||
w = np.asanyarray(omega)
|
_w = np.atleast_1d(omega)
|
||||||
taus, ln_tau = AbstractGG._prepare_integration(tau0)
|
_t = np.atleast_1d(tau0)
|
||||||
g_tau = cls.distribution(taus, tau0, *args)
|
ret_val = np.zeros((_w.size, _t.size), dtype=complex)
|
||||||
|
|
||||||
ret_val = np.array([simpson(g_tau / (1 - 1j*w_i*taus), ln_tau) for w_i in w])
|
for (i, tau_i) in enumerate(_t):
|
||||||
|
taus, ln_tau = AbstractGG._prepare_integration(tau_i)
|
||||||
|
g_tau = cls.distribution(taus, tau_i, *args)
|
||||||
|
|
||||||
return ret_val
|
ret_val[:, i].real = np.array([simpson(g_tau * taus / (1 + (w_i*taus)**2), x=ln_tau) for w_i in _w])
|
||||||
|
ret_val[:, i].imag = np.array([simpson(g_tau * w_i * taus / (1 + (w_i*taus)**2), x=ln_tau) for w_i in _w])
|
||||||
|
|
||||||
|
return ret_val.squeeze()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def specdens(cls, omega, tau0, *args):
|
def specdens(cls, omega: float | np.ndarray, tau0: float | np.ndarray, *args) -> float | np.ndarray:
|
||||||
r"""
|
r"""
|
||||||
Calculate spectral density \int G(ln(tau) tau/(1+(w*tau)^2) dln(tau)
|
Calculate spectral density \int G(ln(tau) tau/(1+(w*tau)^2) dln(tau)
|
||||||
"""
|
"""
|
||||||
w = np.asanyarray(omega)
|
_w = np.atleast_1d(omega)
|
||||||
taus, ln_tau = AbstractGG._prepare_integration(tau0)
|
_t = np.atleast_1d(tau0)
|
||||||
g_tau = cls.distribution(taus, tau0, *args)
|
ret_val = np.zeros((_w.size, _t.size))
|
||||||
|
|
||||||
ret_val = np.array([simpson(g_tau * taus / (1 + (w_i*taus)**2), ln_tau) for w_i in w])
|
for (i, tau_i) in enumerate(_t):
|
||||||
|
taus, ln_tau = AbstractGG._prepare_integration(tau_i)
|
||||||
|
g_tau = cls.distribution(taus, tau_i, *args)
|
||||||
|
|
||||||
return ret_val
|
ret_val[:, i] = np.array([simpson(g_tau * taus / (1 + (w_i*taus)**2), x=ln_tau) for w_i in _w])
|
||||||
|
|
||||||
|
return ret_val.squeeze()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _prepare_integration(
|
def _prepare_integration(
|
||||||
tau0: float, limits: tuple[int, int] = (20, 20), num_steps: int = 4001
|
tau0: float,
|
||||||
|
limits: tuple[int, int] = (20, 20),
|
||||||
|
num_steps: int = 4001,
|
||||||
) -> tuple[np.ndarray, np.ndarray]:
|
) -> tuple[np.ndarray, np.ndarray]:
|
||||||
"""
|
"""
|
||||||
Create array of correlation times for integration over ln(tau)
|
Create array of correlation times for integration over ln(tau)
|
||||||
@ -66,7 +77,6 @@ class AbstractGG(Distribution, ABC):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
array of taus and array of ln(tau)
|
array of taus and array of ln(tau)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ln_tau0 = np.log(tau0)
|
ln_tau0 = np.log(tau0)
|
||||||
@ -77,23 +87,29 @@ class AbstractGG(Distribution, ABC):
|
|||||||
|
|
||||||
# noinspection PyMethodOverriding
|
# noinspection PyMethodOverriding
|
||||||
class GGAlpha(AbstractGG):
|
class GGAlpha(AbstractGG):
|
||||||
name = r'General \Gamma (\alpha)'
|
name = r'General Gamma (alpha)'
|
||||||
parameter = [r'\tau', r'\alpha', r'\beta']
|
parameter = [r'\alpha', r'\beta']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def distribution(taus: float | np.ndarray, tau: float, alpha: float, beta: float) -> float | np.ndarray:
|
def distribution(taus: float | np.ndarray, tau: float, alpha: float, beta: float) -> float | np.ndarray:
|
||||||
b_to_a = beta / alpha
|
b_to_a = beta / alpha
|
||||||
norm = np.exp(gammaln(b_to_a) - b_to_a * np.log(b_to_a)) / alpha
|
inv_norm = alpha * np.exp(-gammaln(b_to_a) + b_to_a * np.log(b_to_a))
|
||||||
t_to_t0 = taus / tau
|
t_to_t0 = taus / tau
|
||||||
ret_val = np.exp(-b_to_a * t_to_t0**alpha) * t_to_t0**beta
|
ret_val = np.exp(-b_to_a * t_to_t0**alpha) * t_to_t0**beta
|
||||||
|
|
||||||
return ret_val / norm
|
return ret_val * inv_norm
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def mean(tau: float | np.ndarray, alpha: float, beta: float) -> float | np.ndarray:
|
||||||
|
beta_by_alpha = beta/alpha
|
||||||
|
inv_alpha = 1/alpha
|
||||||
|
return tau * (1/beta_by_alpha)**inv_alpha * scipy_gamma(beta_by_alpha + inv_alpha) / scipy_gamma(beta_by_alpha)
|
||||||
|
|
||||||
|
|
||||||
# noinspection PyMethodOverriding
|
# noinspection PyMethodOverriding
|
||||||
class GGAlphaEW(AbstractGG):
|
class GGAlphaEW(AbstractGG):
|
||||||
name = r'General \Gamma (\alpha + EW)'
|
name = r'General Gamma (alpha + EW)'
|
||||||
parameter = [r'\tau', r'\alpha', r'\beta', r'\sigma', r'\gamma']
|
parameter = [r'\alpha', r'\beta', r'\sigma', r'\gamma']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def distribution(tau: float | np.ndarray, tau0: float,
|
def distribution(tau: float | np.ndarray, tau0: float,
|
||||||
@ -117,8 +133,8 @@ class GGAlphaEW(AbstractGG):
|
|||||||
|
|
||||||
# noinspection PyMethodOverriding
|
# noinspection PyMethodOverriding
|
||||||
class GGBeta(AbstractGG):
|
class GGBeta(AbstractGG):
|
||||||
name = r'General \Gamma (\beta)'
|
name = r'General Gamma (beta)'
|
||||||
parameter = [r'\tau', 'a', 'b']
|
parameter = ['a', 'b']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def distribution(tau: float | np.ndarray, tau0: float, a: float, b: float) -> float | np.ndarray:
|
def distribution(tau: float | np.ndarray, tau0: float, a: float, b: float) -> float | np.ndarray:
|
||||||
|
@ -9,7 +9,13 @@ from inspect import signature, Parameter
|
|||||||
class ModelFactory:
|
class ModelFactory:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_from_list(funcs: list, left=None, func_order=None, param_len=None, left_cnt=None):
|
def create_from_list(
|
||||||
|
funcs: list,
|
||||||
|
left=None,
|
||||||
|
func_order: list[int] = None,
|
||||||
|
param_len: list[int] = None,
|
||||||
|
left_cnt: int = 0,
|
||||||
|
):
|
||||||
if func_order is None:
|
if func_order is None:
|
||||||
func_order = []
|
func_order = []
|
||||||
|
|
||||||
@ -20,32 +26,50 @@ class ModelFactory:
|
|||||||
if not func['active']:
|
if not func['active']:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
func_order.append(func['cnt'])
|
|
||||||
param_len.append(len(func['func'].params))
|
|
||||||
|
|
||||||
if func['children']:
|
if func['children']:
|
||||||
right, _, _ = ModelFactory.create_from_list(func['children'], left_cnt=func['pos'],
|
f = func.copy()
|
||||||
func_order=func_order, param_len=param_len)
|
f['children'] = []
|
||||||
right_cnt = None
|
right, _, _, right_cnt = ModelFactory.create_from_list(
|
||||||
right = MultiModel(func['func'], right, func['children'][0]['op'], left_idx=func['cnt'], right_idx=None)
|
[f] + func['children'],
|
||||||
|
left_cnt=func['pos'],
|
||||||
|
func_order=func_order,
|
||||||
|
param_len=param_len,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
right = func['func']
|
right = func['func']
|
||||||
right_cnt = func['cnt']
|
right_cnt = func['cnt']
|
||||||
|
|
||||||
|
func_order.append(func['cnt'])
|
||||||
|
param_len.append(len(func['func'].params))
|
||||||
|
|
||||||
if left is None:
|
if left is None:
|
||||||
left = right
|
left = right
|
||||||
left_cnt = right_cnt
|
left_cnt = right_cnt
|
||||||
else:
|
else:
|
||||||
left = MultiModel(left, right, func['op'],
|
left = MultiModel(left, right, func['op'], left_idx=left_cnt, right_idx=right_cnt)
|
||||||
left_idx=left_cnt, right_idx=right_cnt)
|
|
||||||
|
|
||||||
return left, func_order, param_len
|
return left, func_order, param_len, left_cnt
|
||||||
|
|
||||||
|
|
||||||
class MultiModel:
|
class MultiModel:
|
||||||
op_repr = {operator.add: ' + ', operator.mul: ' * ', operator.sub: ' - ', operator.truediv: ' / '}
|
op_repr = {
|
||||||
str_op = {'+': operator.add, '*': operator.mul, '-': operator.sub, '/': operator.truediv}
|
operator.add: ' + ',
|
||||||
int_op = {0: operator.add, 1: operator.mul, 2: operator.sub, 3: operator.truediv}
|
operator.mul: ' * ',
|
||||||
|
operator.sub: ' - ',
|
||||||
|
operator.truediv: ' / ',
|
||||||
|
}
|
||||||
|
str_op = {
|
||||||
|
'+': operator.add,
|
||||||
|
'*': operator.mul,
|
||||||
|
'-': operator.sub,
|
||||||
|
'/': operator.truediv,
|
||||||
|
}
|
||||||
|
int_op = {
|
||||||
|
0: operator.add,
|
||||||
|
1: operator.mul,
|
||||||
|
2: operator.sub,
|
||||||
|
3: operator.truediv,
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
left: Any,
|
left: Any,
|
||||||
@ -69,6 +93,9 @@ class MultiModel:
|
|||||||
if self._op is None:
|
if self._op is None:
|
||||||
raise ValueError('Invalid binary operator.')
|
raise ValueError('Invalid binary operator.')
|
||||||
|
|
||||||
|
if right_idx is None:
|
||||||
|
right_idx = left_idx + 1
|
||||||
|
|
||||||
self.name = '('
|
self.name = '('
|
||||||
self.params = []
|
self.params = []
|
||||||
self.bounds = []
|
self.bounds = []
|
||||||
|
@ -6,10 +6,13 @@ from .model import Model
|
|||||||
from .parameter import Parameters, Parameter
|
from .parameter import Parameters, Parameter
|
||||||
|
|
||||||
|
|
||||||
class Data(object):
|
class Data:
|
||||||
def __init__(self, x, y, we=None, idx=None):
|
def __init__(self, x, y, we=None, idx=None, complex_type: int = 0):
|
||||||
self.x = np.asarray(x)
|
self.x = np.asarray(x)
|
||||||
self.y = np.asarray(y)
|
self.y = np.asarray(y)
|
||||||
|
if self.x.size == 0 or self.y.size == 0:
|
||||||
|
raise ValueError("Data is empty")
|
||||||
|
|
||||||
if self.y.shape[0] != self.x.shape[0]:
|
if self.y.shape[0] != self.x.shape[0]:
|
||||||
raise ValueError(f'x and y have different lengths {self.x.shape[0]} and {self.y.shape[0]}')
|
raise ValueError(f'x and y have different lengths {self.x.shape[0]} and {self.y.shape[0]}')
|
||||||
|
|
||||||
@ -20,6 +23,7 @@ class Data(object):
|
|||||||
self.parameter = Parameters()
|
self.parameter = Parameters()
|
||||||
self.para_keys: list = []
|
self.para_keys: list = []
|
||||||
self.fun_kwargs = {}
|
self.fun_kwargs = {}
|
||||||
|
self.complex_type = complex_type
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return self.y.shape[0]
|
return self.y.shape[0]
|
||||||
|
@ -234,6 +234,10 @@ class FitRoutine(object):
|
|||||||
# get variable parameter for fitter
|
# get variable parameter for fitter
|
||||||
p0_k, lb_k, ub_k, var_pars_k = self._prep_data(data)
|
p0_k, lb_k, ub_k, var_pars_k = self._prep_data(data)
|
||||||
|
|
||||||
|
if p0_k is None:
|
||||||
|
self.make_results(data, data.para_keys, var_pars_k, data.para_keys, (len(data.para_keys), len(data.para_keys)),
|
||||||
|
err=None, corr=None, partial_corr=None)
|
||||||
|
else:
|
||||||
if mode == 'lsq':
|
if mode == 'lsq':
|
||||||
self._least_squares_single(data, p0_k, lb_k, ub_k, var_pars_k)
|
self._least_squares_single(data, p0_k, lb_k, ub_k, var_pars_k)
|
||||||
|
|
||||||
@ -247,6 +251,12 @@ class FitRoutine(object):
|
|||||||
else:
|
else:
|
||||||
data_pars, p0, lb, ub, var_pars = self._prep_global(data_groups, linked_parameter)
|
data_pars, p0, lb, ub, var_pars = self._prep_global(data_groups, linked_parameter)
|
||||||
|
|
||||||
|
if not p0:
|
||||||
|
for data_k, p_k in zip(data_groups, data_pars):
|
||||||
|
self.make_results(data_k, p_k, [], p_k, (len(p_k), len(p_k)),
|
||||||
|
err=None, corr=None, partial_corr=None)
|
||||||
|
|
||||||
|
else:
|
||||||
if mode == 'lsq':
|
if mode == 'lsq':
|
||||||
self._least_squares_global(data_groups, p0, lb, ub, var_pars, data_pars)
|
self._least_squares_global(data_groups, p0, lb, ub, var_pars, data_pars)
|
||||||
|
|
||||||
@ -291,7 +301,10 @@ class FitRoutine(object):
|
|||||||
vals.append([v_k.scaled_value, v_k.lb / v_k.scale, v_k.ub / v_k.scale])
|
vals.append([v_k.scaled_value, v_k.lb / v_k.scale, v_k.ub / v_k.scale])
|
||||||
var_pars.append(p_k)
|
var_pars.append(p_k)
|
||||||
|
|
||||||
|
if vals:
|
||||||
pp, lb, ub = zip(*vals)
|
pp, lb, ub = zip(*vals)
|
||||||
|
else:
|
||||||
|
pp = lb = ub = None
|
||||||
|
|
||||||
return pp, lb, ub, var_pars
|
return pp, lb, ub, var_pars
|
||||||
|
|
||||||
@ -319,10 +332,10 @@ class FitRoutine(object):
|
|||||||
actual_pars.append(p_k_used)
|
actual_pars.append(p_k_used)
|
||||||
# parameter is variable and was not found before as shared parameter
|
# parameter is variable and was not found before as shared parameter
|
||||||
if v_k_used.var and p_k_used not in var:
|
if v_k_used.var and p_k_used not in var:
|
||||||
|
var.append(p_k_used)
|
||||||
p0.append(v_k_used.scaled_value)
|
p0.append(v_k_used.scaled_value)
|
||||||
lb.append(v_k_used.lb / v_k_used.scale)
|
lb.append(v_k_used.lb / v_k_used.scale)
|
||||||
ub.append(v_k_used.ub / v_k_used.scale)
|
ub.append(v_k_used.ub / v_k_used.scale)
|
||||||
var.append(p_k_used)
|
|
||||||
|
|
||||||
data_pars.append(actual_pars)
|
data_pars.append(actual_pars)
|
||||||
|
|
||||||
@ -348,7 +361,7 @@ class FitRoutine(object):
|
|||||||
with np.errstate(all='ignore'):
|
with np.errstate(all='ignore'):
|
||||||
res = optimize.least_squares(cost, p0, bounds=(lb, ub), max_nfev=500 * len(p0))
|
res = optimize.least_squares(cost, p0, bounds=(lb, ub), max_nfev=500 * len(p0))
|
||||||
|
|
||||||
err, corr, partial_corr = self._calc_error(res.jac, np.sum(res.fun**2), *res.jac.shape)
|
err, corr, partial_corr = _calc_error(res.jac, np.sum(res.fun**2), *res.jac.shape)
|
||||||
self.make_results(data, res.x, var, data.para_keys, res.jac.shape,
|
self.make_results(data, res.x, var, data.para_keys, res.jac.shape,
|
||||||
err=err, corr=corr, partial_corr=partial_corr)
|
err=err, corr=corr, partial_corr=partial_corr)
|
||||||
|
|
||||||
@ -362,7 +375,7 @@ class FitRoutine(object):
|
|||||||
with np.errstate(all='ignore'):
|
with np.errstate(all='ignore'):
|
||||||
res = optimize.least_squares(cost, p0, bounds=(lb, ub), max_nfev=500 * len(p0))
|
res = optimize.least_squares(cost, p0, bounds=(lb, ub), max_nfev=500 * len(p0))
|
||||||
|
|
||||||
err, corr, partial_corr = self._calc_error(res.jac, np.sum(res.fun**2), *res.jac.shape)
|
err, corr, partial_corr = _calc_error(res.jac, np.sum(res.fun**2), *res.jac.shape)
|
||||||
for v, var_pars_k in zip(data, data_pars):
|
for v, var_pars_k in zip(data, data_pars):
|
||||||
self.make_results(v, res.x, var, var_pars_k, res.jac.shape,
|
self.make_results(v, res.x, var, var_pars_k, res.jac.shape,
|
||||||
err=err, corr=corr, partial_corr=partial_corr)
|
err=err, corr=corr, partial_corr=partial_corr)
|
||||||
@ -445,9 +458,17 @@ class FitRoutine(object):
|
|||||||
self.make_results(v, res.beta, var, var_pars_k, (sum(len(d) for d in data), len(p0)),
|
self.make_results(v, res.beta, var, var_pars_k, (sum(len(d) for d in data), len(p0)),
|
||||||
err=res.sd_beta, corr=corr, partial_corr=partial_corr)
|
err=res.sd_beta, corr=corr, partial_corr=partial_corr)
|
||||||
|
|
||||||
def make_results(self, data, p, var_pars, used_pars, shape,
|
def make_results(
|
||||||
err=None, corr=None, partial_corr=None):
|
self,
|
||||||
|
data: Data,
|
||||||
|
p: list[float],
|
||||||
|
var_pars: list[str],
|
||||||
|
used_pars: list[str],
|
||||||
|
shape: tuple[int, int],
|
||||||
|
err: list[float] = None,
|
||||||
|
corr: np.ndarray = None,
|
||||||
|
partial_corr: np.ndarray = None,
|
||||||
|
):
|
||||||
if err is None:
|
if err is None:
|
||||||
err = [0] * len(p)
|
err = [0] * len(p)
|
||||||
|
|
||||||
@ -472,7 +493,7 @@ class FitRoutine(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
# reshape the correlation matrices
|
# reshape the correlation matrices
|
||||||
if corr is None:
|
if corr is None or not corr_idx:
|
||||||
actual_corr = None
|
actual_corr = None
|
||||||
actual_pcorr = None
|
actual_pcorr = None
|
||||||
else:
|
else:
|
||||||
@ -485,21 +506,23 @@ class FitRoutine(object):
|
|||||||
model = data.get_model()
|
model = data.get_model()
|
||||||
|
|
||||||
self.result[idx] = FitResultCreator.make_with_model(
|
self.result[idx] = FitResultCreator.make_with_model(
|
||||||
model,
|
model=model,
|
||||||
data.x,
|
x_orig=data.x,
|
||||||
data.y,
|
y_orig=data.y,
|
||||||
actual_parameters,
|
p=actual_parameters,
|
||||||
data.fun_kwargs,
|
fun_kwargs=data.fun_kwargs,
|
||||||
data.we_string,
|
we=data.we_string,
|
||||||
data.idx,
|
idx=data.idx,
|
||||||
*shape,
|
nobs=shape[0],
|
||||||
|
nvar=shape[1],
|
||||||
corr=actual_corr,
|
corr=actual_corr,
|
||||||
pcorr=actual_pcorr,
|
pcorr=actual_pcorr,
|
||||||
|
data_mode=data.complex_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.result
|
return self.result
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _calc_error(jac, chi, nobs, nvars):
|
def _calc_error(jac, chi, nobs, nvars):
|
||||||
# copy of scipy.curve_fit to calculate covariance
|
# copy of scipy.curve_fit to calculate covariance
|
||||||
# noinspection PyTupleAssignmentBalance
|
# noinspection PyTupleAssignmentBalance
|
||||||
|
@ -9,7 +9,7 @@ from ._meta import MultiModel
|
|||||||
from .parameter import Parameters, Parameter
|
from .parameter import Parameters, Parameter
|
||||||
|
|
||||||
|
|
||||||
class Model(object):
|
class Model:
|
||||||
def __init__(self, model, *args, **kwargs):
|
def __init__(self, model, *args, **kwargs):
|
||||||
self.idx = kwargs.pop('idx', None)
|
self.idx = kwargs.pop('idx', None)
|
||||||
|
|
||||||
|
@ -102,12 +102,10 @@ class Parameters(dict):
|
|||||||
p._expr = expression
|
p._expr = expression
|
||||||
|
|
||||||
def prepare_bounds(self):
|
def prepare_bounds(self):
|
||||||
print('prepare_bounds')
|
|
||||||
original_values = list(self.values())
|
original_values = list(self.values())
|
||||||
for param in original_values:
|
for param in original_values:
|
||||||
already_with_expression = False
|
already_with_expression = False
|
||||||
for mode, value in (('lower', param.lb), ('upper', param.ub)):
|
for mode, value in (('lower', param.lb), ('upper', param.ub)):
|
||||||
print(mode, value)
|
|
||||||
if already_with_expression:
|
if already_with_expression:
|
||||||
raise ValueError('Only one boundary can be an expression')
|
raise ValueError('Only one boundary can be an expression')
|
||||||
already_with_expression = self.parse(param, value, bnd=mode)
|
already_with_expression = self.parse(param, value, bnd=mode)
|
||||||
|
@ -11,6 +11,7 @@ from scipy.stats import f as fdist
|
|||||||
from scipy.interpolate import interp1d
|
from scipy.interpolate import interp1d
|
||||||
|
|
||||||
from ._meta import MultiModel
|
from ._meta import MultiModel
|
||||||
|
from .model import Model
|
||||||
from .parameter import Parameter
|
from .parameter import Parameter
|
||||||
from ..data.points import Points
|
from ..data.points import Points
|
||||||
from ..data.signals import Signal
|
from ..data.signals import Signal
|
||||||
@ -36,17 +37,30 @@ class FitResultCreator:
|
|||||||
else:
|
else:
|
||||||
resid = kwargs['y'] - y_orig
|
resid = kwargs['y'] - y_orig
|
||||||
|
|
||||||
stats = FitResultCreator.calc_statistics(resid, _y)
|
stats = calc_statistics(resid, _y)
|
||||||
|
|
||||||
return FitResult(kwargs['x'], kwargs['y'], x_orig, y_orig, params, dict(kwargs['choice']), resid, 0, 0,
|
return FitResult(
|
||||||
kwargs['name'], stats, idx)
|
x=kwargs['x'],
|
||||||
|
y=kwargs['y'],
|
||||||
|
x_data=x_orig,
|
||||||
|
y_data=y_orig,
|
||||||
|
params=params,
|
||||||
|
fun_kwargs=dict(kwargs['choice']),
|
||||||
|
resid=resid,
|
||||||
|
nobs=0,
|
||||||
|
nvar=0,
|
||||||
|
we='',
|
||||||
|
name=kwargs['name'],
|
||||||
|
stats=stats,
|
||||||
|
idx=idx,
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def make_with_model(
|
def make_with_model(
|
||||||
model: 'Model',
|
model: 'Model',
|
||||||
x_orig: np.ndarray,
|
x_orig: np.ndarray,
|
||||||
y_orig: np.ndarray,
|
y_orig: np.ndarray,
|
||||||
p: 'Parameters',
|
p: list,
|
||||||
fun_kwargs: dict,
|
fun_kwargs: dict,
|
||||||
we: str,
|
we: str,
|
||||||
idx: str | None,
|
idx: str | None,
|
||||||
@ -54,6 +68,7 @@ class FitResultCreator:
|
|||||||
nvar: int,
|
nvar: int,
|
||||||
corr: np.ndarray,
|
corr: np.ndarray,
|
||||||
pcorr: np.ndarray,
|
pcorr: np.ndarray,
|
||||||
|
data_mode: int,
|
||||||
) -> FitResult:
|
) -> FitResult:
|
||||||
if np.all(x_orig > 0) and (np.max(x_orig) > 100 * np.min(x_orig)):
|
if np.all(x_orig > 0) and (np.max(x_orig) > 100 * np.min(x_orig)):
|
||||||
islog = True
|
islog = True
|
||||||
@ -83,17 +98,11 @@ class FitResultCreator:
|
|||||||
actual_mode = fun_kwargs['complex_mode']
|
actual_mode = fun_kwargs['complex_mode']
|
||||||
fun_kwargs['complex_mode'] = 0
|
fun_kwargs['complex_mode'] = 0
|
||||||
|
|
||||||
_y = model.func(p_final, _x, **fun_kwargs)
|
_y = check_complex(model.func(p_final, _x, **fun_kwargs), actual_mode, data_mode)
|
||||||
|
|
||||||
if not actual_mode < 0:
|
|
||||||
if actual_mode == 1:
|
|
||||||
_y.imag = 0
|
|
||||||
elif actual_mode == 2:
|
|
||||||
_y.real = 0
|
|
||||||
|
|
||||||
fun_kwargs['complex_mode'] = actual_mode
|
fun_kwargs['complex_mode'] = actual_mode
|
||||||
|
|
||||||
stats = FitResultCreator.calc_statistics(_y, resid, nobs, nvar)
|
stats = calc_statistics(_y, resid, nobs, nvar)
|
||||||
varied = [p.var for p in parameters.values()]
|
varied = [p.var for p in parameters.values()]
|
||||||
|
|
||||||
if corr is None:
|
if corr is None:
|
||||||
@ -134,41 +143,9 @@ class FitResultCreator:
|
|||||||
pcorr=partial_correlation,
|
pcorr=partial_correlation,
|
||||||
islog=islog,
|
islog=islog,
|
||||||
func=model,
|
func=model,
|
||||||
|
data_complex=data_mode,
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def calc_statistics(y, residual, nobs=None, nvar=None):
|
|
||||||
chi = (residual**2).sum()
|
|
||||||
try:
|
|
||||||
r = 1 - chi/((y-np.mean(y))**2).sum()
|
|
||||||
except RuntimeWarning:
|
|
||||||
r = -9999
|
|
||||||
|
|
||||||
if nobs is None:
|
|
||||||
nobs = 1
|
|
||||||
|
|
||||||
if nvar is None:
|
|
||||||
nvar = 0
|
|
||||||
|
|
||||||
dof = nobs - nvar
|
|
||||||
loglikehood = nobs * np.log(chi / nobs)
|
|
||||||
|
|
||||||
stats = {
|
|
||||||
'chi^2': chi,
|
|
||||||
'R^2': r,
|
|
||||||
'AIC': loglikehood + 2 * nvar,
|
|
||||||
'BIC': loglikehood + np.log(nobs) * nvar
|
|
||||||
}
|
|
||||||
|
|
||||||
if dof != 0:
|
|
||||||
stats['adj. R^2'] = 1 - (nobs-1)/dof * (1-r)
|
|
||||||
stats['red. chi^2'] = chi / dof if dof != 0 else 0
|
|
||||||
|
|
||||||
if dof != 1:
|
|
||||||
stats['AICc'] = stats['AIC'] + 2*(nvar+1)*nvar / (dof-1)
|
|
||||||
|
|
||||||
return stats
|
|
||||||
|
|
||||||
|
|
||||||
class FitResult(Points):
|
class FitResult(Points):
|
||||||
|
|
||||||
@ -191,7 +168,8 @@ class FitResult(Points):
|
|||||||
pcorr: np.ndarray = None,
|
pcorr: np.ndarray = None,
|
||||||
islog: bool = False,
|
islog: bool = False,
|
||||||
func=None,
|
func=None,
|
||||||
**kwargs
|
data_complex: int = 1,
|
||||||
|
**kwargs,
|
||||||
):
|
):
|
||||||
|
|
||||||
self.parameter, name = self._prepare_names(params, name)
|
self.parameter, name = self._prepare_names(params, name)
|
||||||
@ -213,6 +191,7 @@ class FitResult(Points):
|
|||||||
self.y_data = y_data
|
self.y_data = y_data
|
||||||
self._model_name = name
|
self._model_name = name
|
||||||
self._func = func
|
self._func = func
|
||||||
|
self._data_complex = data_complex
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _prepare_names(parameter: dict, modelname: str):
|
def _prepare_names(parameter: dict, modelname: str):
|
||||||
@ -393,8 +372,7 @@ class FitResult(Points):
|
|||||||
def get_state(self):
|
def get_state(self):
|
||||||
state = super().get_state()
|
state = super().get_state()
|
||||||
|
|
||||||
for attr in ['idx', 'fun_kwargs', 'nobs', 'nvar',
|
for attr in ['idx', 'fun_kwargs', 'nobs', 'nvar', 'we', 'islog', 'iscomplex', 'x_data', 'y_data']:
|
||||||
'islog', 'iscomplex', 'x_data', 'y_data']:
|
|
||||||
state[attr] = getattr(self, attr)
|
state[attr] = getattr(self, attr)
|
||||||
|
|
||||||
state['name'] = self._model_name
|
state['name'] = self._model_name
|
||||||
@ -412,6 +390,8 @@ class FitResult(Points):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def set_state(state, **kwargs):
|
def set_state(state, **kwargs):
|
||||||
state['params'] = {k: Parameter.set_state(v) for k, v in state.pop('params').items()}
|
state['params'] = {k: Parameter.set_state(v) for k, v in state.pop('params').items()}
|
||||||
|
if 'we' not in state:
|
||||||
|
state['we'] = '?'
|
||||||
data = FitResult(**state)
|
data = FitResult(**state)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
@ -420,41 +400,32 @@ class FitResult(Points):
|
|||||||
if self.func is None:
|
if self.func is None:
|
||||||
raise ValueError('no fit function available to calculate new y values')
|
raise ValueError('no fit function available to calculate new y values')
|
||||||
|
|
||||||
actual_mode = -1
|
|
||||||
if 'complex_mode' in self.fun_kwargs:
|
|
||||||
actual_mode = self.fun_kwargs['complex_mode']
|
|
||||||
self.fun_kwargs['complex_mode'] = 0
|
|
||||||
|
|
||||||
new_fit = self.copy()
|
new_fit = self.copy()
|
||||||
y_values = self.func.func(self.p_final, x_values, **self.fun_kwargs)
|
fun_kwargs = {k: v for k, v in self.fun_kwargs.items()}
|
||||||
if not actual_mode < 0:
|
if self.fun_kwargs.get('complex_mode', -1) == -1:
|
||||||
if actual_mode == 1:
|
fun_kwargs.pop('complex_mode', None)
|
||||||
y_values.imag = 0
|
y_values = self.func.func(self.p_final, x_values, **fun_kwargs)
|
||||||
elif actual_mode == 2:
|
y_values = check_complex(y_values, self.fun_kwargs.get('complex_mode', -1), self._data_complex)
|
||||||
y_values.real = 0
|
|
||||||
|
|
||||||
self.fun_kwargs['complex_mode'] = actual_mode
|
|
||||||
|
|
||||||
new_fit.set_data(x_values, y_values, y_err=0.0)
|
new_fit.set_data(x_values, y_values, y_err=0.0)
|
||||||
|
|
||||||
return new_fit
|
return new_fit
|
||||||
|
|
||||||
def sub(self, x_values):
|
def sub(self, x_values):
|
||||||
|
if self.func is None:
|
||||||
|
raise ValueError('no fit function available to calculate new y values')
|
||||||
|
|
||||||
part_functions = []
|
part_functions = []
|
||||||
actual_mode = -1
|
actual_mode = self.fun_kwargs.get('complex_mode', -1)
|
||||||
if 'complex_mode' in self.fun_kwargs:
|
fun_kwargs = {k: v for k, v in self.fun_kwargs.items()}
|
||||||
actual_mode = self.fun_kwargs['complex_mode']
|
if self.fun_kwargs.get('complex_mode', -1) == -1:
|
||||||
self.fun_kwargs['complex_mode'] = 0
|
fun_kwargs.pop('complex_mode', None)
|
||||||
|
|
||||||
for sub_name, sub_y in zip(self.func.sub_name(), self.func.sub(self.p_final, x_values, **self.fun_kwargs)):
|
for sub_name, sub_y in zip(self.func.sub_name(), self.func.sub(self.p_final, x_values, **self.fun_kwargs)):
|
||||||
if not actual_mode < 0:
|
sub_y = check_complex(sub_y, actual_mode, self._data_complex)
|
||||||
if actual_mode == 1:
|
|
||||||
sub_y.imag = 0
|
|
||||||
elif actual_mode == 2:
|
|
||||||
sub_y.real = 0
|
|
||||||
|
|
||||||
|
if np.iscomplexobj(sub_y):
|
||||||
part_functions.append(Signal(x_values, sub_y, name=sub_name))
|
part_functions.append(Signal(x_values, sub_y, name=sub_name))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
part_functions.append(Points(x_values, sub_y, name=sub_name))
|
part_functions.append(Points(x_values, sub_y, name=sub_name))
|
||||||
|
|
||||||
@ -462,3 +433,49 @@ class FitResult(Points):
|
|||||||
self.fun_kwargs['complex_mode'] = actual_mode
|
self.fun_kwargs['complex_mode'] = actual_mode
|
||||||
|
|
||||||
return part_functions
|
return part_functions
|
||||||
|
|
||||||
|
|
||||||
|
def check_complex(y, model_complex, data_complex):
|
||||||
|
if not np.iscomplexobj(y):
|
||||||
|
return y
|
||||||
|
|
||||||
|
if model_complex == 1:
|
||||||
|
y.imag = 0
|
||||||
|
if data_complex == 1:
|
||||||
|
y = y.real
|
||||||
|
elif model_complex == 2:
|
||||||
|
y.real = 0
|
||||||
|
if data_complex == 1:
|
||||||
|
y = y.imag
|
||||||
|
|
||||||
|
return y
|
||||||
|
|
||||||
|
|
||||||
|
def calc_statistics(y, residual, nobs=None, nvar=None):
|
||||||
|
chi = (residual**2).sum()
|
||||||
|
try:
|
||||||
|
r = 1 - chi/((y-np.mean(y))**2).sum()
|
||||||
|
except RuntimeWarning:
|
||||||
|
r = -9999
|
||||||
|
|
||||||
|
if nobs is None:
|
||||||
|
nobs = 1
|
||||||
|
|
||||||
|
if nvar is None:
|
||||||
|
nvar = 0
|
||||||
|
|
||||||
|
dof = nobs - nvar
|
||||||
|
loglikehood = nobs * np.log(chi / nobs)
|
||||||
|
|
||||||
|
stats = {
|
||||||
|
'chi^2': chi,
|
||||||
|
'R^2': r,
|
||||||
|
'AIC': loglikehood + 2 * nvar,
|
||||||
|
'BIC': loglikehood + np.log(nobs) * nvar,
|
||||||
|
'adj. R^2': 1 - (nobs-1) / (dof+1e-13) * (1-r),
|
||||||
|
'red. chi^2': chi / (dof + 1e-13),
|
||||||
|
}
|
||||||
|
|
||||||
|
stats['AICc'] = stats['AIC'] + 2*(nvar+1)*nvar / (dof - 1 + 1e-13)
|
||||||
|
|
||||||
|
return stats
|
||||||
|
@ -49,7 +49,7 @@ class AsciiReader:
|
|||||||
with self.fname.open('r') as f:
|
with self.fname.open('r') as f:
|
||||||
for i, line in enumerate(islice(f, len(self.header)+len(self.lines), num_lines)):
|
for i, line in enumerate(islice(f, len(self.header)+len(self.lines), num_lines)):
|
||||||
line = line.strip('\n\t\r, ')
|
line = line.strip('\n\t\r, ')
|
||||||
line = re.sub(r'[\t ;,] *', ';', line)
|
line = re.sub(r'[\t ;,]+', ';', line)
|
||||||
line = line.split(';')
|
line = line.split(';')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -121,6 +121,9 @@ class AsciiReader:
|
|||||||
if y is None:
|
if y is None:
|
||||||
y = list(range(int(len(x) != 0), max(self.width)))
|
y = list(range(int(len(x) != 0), max(self.width)))
|
||||||
|
|
||||||
|
if col_names is not None:
|
||||||
|
col_names = [col_names[y_i] for y_i in y]
|
||||||
|
|
||||||
cols = x + y + yerr
|
cols = x + y + yerr
|
||||||
with self.fname.open('rb') as fh:
|
with self.fname.open('rb') as fh:
|
||||||
tmp_ = re.sub(b'[;,]', b' ', fh.read())
|
tmp_ = re.sub(b'[;,]', b' ', fh.read())
|
||||||
@ -180,7 +183,13 @@ class AsciiReader:
|
|||||||
single_len = 2
|
single_len = 2
|
||||||
stepsize = 2
|
stepsize = 2
|
||||||
|
|
||||||
cls = {'points': Points, 'fid': FID, 'spectrum': Spectrum, 'bds': BDS, 'dsc': DSC}[mode]
|
cls = {
|
||||||
|
'points': Points,
|
||||||
|
'fid': FID,
|
||||||
|
'spectrum': Spectrum,
|
||||||
|
'bds': BDS,
|
||||||
|
'dsc': DSC,
|
||||||
|
}[mode]
|
||||||
|
|
||||||
for j in range(1, num_y+1, stepsize):
|
for j in range(1, num_y+1, stepsize):
|
||||||
if col_names is not None:
|
if col_names is not None:
|
||||||
@ -188,7 +197,7 @@ class AsciiReader:
|
|||||||
kwargs['name'] = col_names[j-1]
|
kwargs['name'] = col_names[j-1]
|
||||||
elif num_y > single_len:
|
elif num_y > single_len:
|
||||||
# more than one axis, append column number
|
# more than one axis, append column number
|
||||||
kwargs['name'] = filename + '_' + str(y[j-1])
|
kwargs['name'] = f'{filename}_{y[j-1]+1}'
|
||||||
|
|
||||||
if j+num_y < raw_data.shape[2]:
|
if j+num_y < raw_data.shape[2]:
|
||||||
kwargs['y_err'] = raw_data[i, :, j+num_y]
|
kwargs['y_err'] = raw_data[i, :, j+num_y]
|
||||||
|
@ -11,7 +11,8 @@ try:
|
|||||||
from scipy.integrate import simpson
|
from scipy.integrate import simpson
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from scipy.integrate import simps as simpson
|
from scipy.integrate import simps as simpson
|
||||||
from scipy.interpolate import interp1d
|
from scipy.interpolate import CubicSpline
|
||||||
|
|
||||||
|
|
||||||
ReferenceValue = namedtuple('Reference', ['name', 'transitions'])
|
ReferenceValue = namedtuple('Reference', ['name', 'transitions'])
|
||||||
Cyclohexane = ReferenceValue('Cyclohexane', [(-87.06+273.15, 79.58), (6.54+273.15, None)])
|
Cyclohexane = ReferenceValue('Cyclohexane', [(-87.06+273.15, 79.58), (6.54+273.15, None)])
|
||||||
@ -38,7 +39,7 @@ class DSCSample:
|
|||||||
def read_file(self, fname: str | Path) -> None:
|
def read_file(self, fname: str | Path) -> None:
|
||||||
fname = Path(fname)
|
fname = Path(fname)
|
||||||
|
|
||||||
# file contains weird deg C character in stupiod ISO encoding
|
# file contains weird deg C character in stupid ISO encoding
|
||||||
with fname.open('r', encoding='iso-8859-15') as f:
|
with fname.open('r', encoding='iso-8859-15') as f:
|
||||||
ii = 1
|
ii = 1
|
||||||
for line in f:
|
for line in f:
|
||||||
@ -144,9 +145,12 @@ class DSCCalibrator:
|
|||||||
self.reference = []
|
self.reference = []
|
||||||
self.ref_list = []
|
self.ref_list = []
|
||||||
|
|
||||||
def set_measurement(self,
|
def set_measurement(
|
||||||
fname: str | Path | DSCSample, mode: str = 'sample',
|
self: DSCCalibrator,
|
||||||
reference: ReferenceValue = Cyclohexane):
|
fname: str | Path | DSCSample,
|
||||||
|
mode: str = 'sample',
|
||||||
|
reference: ReferenceValue = Cyclohexane
|
||||||
|
):
|
||||||
if mode not in ['sample', 'empty', 'reference']:
|
if mode not in ['sample', 'empty', 'reference']:
|
||||||
raise ValueError(f'Unknown mode {mode}, not "sample", "empty", "reference"')
|
raise ValueError(f'Unknown mode {mode}, not "sample", "empty", "reference"')
|
||||||
if mode == 'reference' and not isinstance(reference, ReferenceValue):
|
if mode == 'reference' and not isinstance(reference, ReferenceValue):
|
||||||
@ -266,7 +270,12 @@ class DSCCalibrator:
|
|||||||
|
|
||||||
return sol
|
return sol
|
||||||
|
|
||||||
def get_data(self, idx: int, slope: str = 'iso', limits: tuple[float, float] = None):
|
def get_data(
|
||||||
|
self: DSCCalibrator,
|
||||||
|
idx: int,
|
||||||
|
slope: str = 'iso',
|
||||||
|
limits: tuple[float, float] = None
|
||||||
|
) -> tuple[np.ndarray, np.ndarray, np.ndarray,np.ndarray | None, np.ndarray]:
|
||||||
if self.sample.steps[idx][0] == 'i':
|
if self.sample.steps[idx][0] == 'i':
|
||||||
raise ValueError('baseline correction is not implemented for isotherms')
|
raise ValueError('baseline correction is not implemented for isotherms')
|
||||||
|
|
||||||
@ -292,7 +301,7 @@ class DSCCalibrator:
|
|||||||
empty_y = empty_data[1]
|
empty_y = empty_data[1]
|
||||||
if self.sample.length(idx) != self.empty.length(idx_empty):
|
if self.sample.length(idx) != self.empty.length(idx_empty):
|
||||||
with np.errstate(all='ignore'):
|
with np.errstate(all='ignore'):
|
||||||
empty_y = interp1d(empty_data[2]-empty_data[2, 0], empty_data[1], fill_value='extrapolate')(sample_data[2, 0])
|
empty_y = CubicSpline(empty_data[2]-empty_data[2, 0], empty_data[1], extrapolate=True)(sample_data[2] - sample_data[2, 0])
|
||||||
|
|
||||||
sample_data[1] -= empty_y
|
sample_data[1] -= empty_y
|
||||||
drift_value = sample_data.copy()[(2, 1), :]
|
drift_value = sample_data.copy()[(2, 1), :]
|
||||||
@ -346,9 +355,10 @@ class DSCCalibrator:
|
|||||||
|
|
||||||
offset = region[0, 0]
|
offset = region[0, 0]
|
||||||
sample_data[1] -= m * (sample_data[2] - region[1, 0]) + offset
|
sample_data[1] -= m * (sample_data[2] - region[1, 0]) + offset
|
||||||
line = np.array([[sample_data[2, 0], sample_data[2, -1]],
|
line = np.array([
|
||||||
[m * (sample_data[2, 0] - region[1, 0]) + offset,
|
[sample_data[2, 0], sample_data[2, -1]],
|
||||||
m * (sample_data[2, -1] - region[1, 0]) + offset]])
|
[m * (sample_data[2, 0] - region[1, 0]) + offset, m * (sample_data[2, -1] - region[1, 0]) + offset]
|
||||||
|
])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
line = np.array([[sample_data[2, 0], sample_data[2, -1]], [0, 0]])
|
line = np.array([[sample_data[2, 0], sample_data[2, -1]], [0, 0]])
|
||||||
|
@ -48,7 +48,7 @@ class FCReader:
|
|||||||
found_temperature = filename.stem
|
found_temperature = filename.stem
|
||||||
|
|
||||||
if filename.is_file():
|
if filename.is_file():
|
||||||
if region is None:
|
if (region is None) or (region == (None, None)):
|
||||||
_temp = self._read_from_hdf(filename)
|
_temp = self._read_from_hdf(filename)
|
||||||
else:
|
else:
|
||||||
_temp = self._read_signals(filename, region)
|
_temp = self._read_signals(filename, region)
|
||||||
|
@ -115,6 +115,7 @@ class GraceEditor:
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
def parse(self, filename: str | pathlib.Path):
|
def parse(self, filename: str | pathlib.Path):
|
||||||
|
self.clear()
|
||||||
self.file = pathlib.Path(filename)
|
self.file = pathlib.Path(filename)
|
||||||
|
|
||||||
# we start always with the header
|
# we start always with the header
|
||||||
@ -215,9 +216,8 @@ class GraceEditor:
|
|||||||
def _make_graph(self, line: str):
|
def _make_graph(self, line: str):
|
||||||
m = self._RE_GRAPH_START.match(line)
|
m = self._RE_GRAPH_START.match(line)
|
||||||
g_idx = int(m.group(1))
|
g_idx = int(m.group(1))
|
||||||
if g_idx < len(self.graphs):
|
while g_idx < len(self.graphs):
|
||||||
# this assumes that graphs are ordered in agr file even if missing, e.g. we read gß, g1, g3, ...
|
# this assumes that graphs are ordered in agr file even if missing, e.g. we read gß, g1, g3, ...
|
||||||
while g_idx != len(self.graphs):
|
|
||||||
self.graphs.append(GraceGraph(len(self.graphs)))
|
self.graphs.append(GraceGraph(len(self.graphs)))
|
||||||
|
|
||||||
self.graphs.append(GraceGraph(g_idx))
|
self.graphs.append(GraceGraph(g_idx))
|
||||||
@ -354,8 +354,8 @@ class GraceHeader(list):
|
|||||||
class GraceProperties(list):
|
class GraceProperties(list):
|
||||||
_RE_ENTRY = re.compile(r'(?!.*(on|off)$)' # ignore lines that end with on or off
|
_RE_ENTRY = re.compile(r'(?!.*(on|off)$)' # ignore lines that end with on or off
|
||||||
r'@\s*(?P<graph>[gs]\d+)?\s*' # @ maybe followed by g0 or s12
|
r'@\s*(?P<graph>[gs]\d+)?\s*' # @ maybe followed by g0 or s12
|
||||||
r'(?P<key>[\w\s]*)\s+' # key: stops at last space unless comma-separated values
|
r'(?P<key>[\w\s]*\w)*\s+' # key: stops at last space unless comma-separated values
|
||||||
r'(?P<val>(?:\s*[\d\w.+-]+\s*,)*\s*[\\{}\"\w.+\- ]+)', # one value, maybe more with commas
|
r'(?P<val>(?<!^)(?:\s*[\d\w.+-]+\s*,)*\s*[\S ]+)', # one value, maybe more with commas
|
||||||
re.IGNORECASE | re.VERBOSE)
|
re.IGNORECASE | re.VERBOSE)
|
||||||
_RE_ONOFF = re.compile(r'@\s(?P<graph>[gs]\d+)*\s*(?P<val>[\w\s]*)\s+(on|off)')
|
_RE_ONOFF = re.compile(r'@\s(?P<graph>[gs]\d+)*\s*(?P<val>[\w\s]*)\s+(on|off)')
|
||||||
|
|
||||||
@ -730,7 +730,11 @@ class GraceRegion(list):
|
|||||||
|
|
||||||
|
|
||||||
def _convert_to_value(parse_string):
|
def _convert_to_value(parse_string):
|
||||||
|
if re.match(r'\".*\"', parse_string):
|
||||||
|
tuples = [parse_string]
|
||||||
|
else:
|
||||||
tuples = parse_string.split(',')
|
tuples = parse_string.split(',')
|
||||||
|
|
||||||
for i, v in enumerate(tuples):
|
for i, v in enumerate(tuples):
|
||||||
v = v.strip()
|
v = v.strip()
|
||||||
|
|
||||||
|
@ -3,14 +3,21 @@ import numpy.polynomial.polynomial as poly
|
|||||||
from scipy import signal as signal
|
from scipy import signal as signal
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['smooth', 'loess', 'savgol',
|
__all__ = [
|
||||||
'running_max', 'running_min',
|
'smooth',
|
||||||
'running_var', 'running_std',
|
'loess',
|
||||||
'running_median', 'running_mean',
|
'savgol',
|
||||||
'running_sum']
|
'running_max',
|
||||||
|
'running_min',
|
||||||
|
'running_var',
|
||||||
|
'running_std',
|
||||||
|
'running_median',
|
||||||
|
'running_mean',
|
||||||
|
'running_sum',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def loess(x, y, window_size, it=0, deg=2):
|
def loess(x, y, window_size: int, it: int = 0, deg: int = 2):
|
||||||
# ULTRA LANGSAM !!!
|
# ULTRA LANGSAM !!!
|
||||||
it = max(it, 0)
|
it = max(it, 0)
|
||||||
|
|
||||||
@ -81,19 +88,19 @@ def savgol(x, y, window_size: int, deg: int = 2, mode: str = 'mirror'):
|
|||||||
return new_y
|
return new_y
|
||||||
|
|
||||||
|
|
||||||
def running_mean(x, y, window_size):
|
def running_mean(x, y, window_size: int):
|
||||||
return _running_func(np.nanmean, x, y, window_size)
|
return _running_func(np.nanmean, x, y, window_size)
|
||||||
|
|
||||||
|
|
||||||
def running_median(x, y, window_size):
|
def running_median(x, y, window_size: int):
|
||||||
return _running_func(np.nanmedian, x, y, window_size)
|
return _running_func(np.nanmedian, x, y, window_size)
|
||||||
|
|
||||||
|
|
||||||
def running_std(x, y, window_size):
|
def running_std(x, y, window_size: int):
|
||||||
return _running_func(np.nanstd, x, y, window_size)
|
return _running_func(np.nanstd, x, y, window_size)
|
||||||
|
|
||||||
|
|
||||||
def running_var(x, y, window_size):
|
def running_var(x, y, window_size: int):
|
||||||
return _running_func(np.nanvar, x, y, window_size)
|
return _running_func(np.nanvar, x, y, window_size)
|
||||||
|
|
||||||
|
|
||||||
@ -132,11 +139,27 @@ def _moving_window(arr, nn):
|
|||||||
return np.lib.stride_tricks.as_strided(arr, shapes, strides)
|
return np.lib.stride_tricks.as_strided(arr, shapes, strides)
|
||||||
|
|
||||||
|
|
||||||
_funcs = {'loess': loess, 'savgol': savgol, 'mean': running_mean, 'median': running_median,
|
_funcs = {
|
||||||
'std': running_std, 'var': running_var, 'max': running_max, 'min': running_min, 'sum': running_sum}
|
'loess': loess,
|
||||||
|
'savgol': savgol,
|
||||||
|
'mean': running_mean,
|
||||||
|
'median': running_median,
|
||||||
|
'std': running_std,
|
||||||
|
'var': running_var,
|
||||||
|
'max': running_max,
|
||||||
|
'min': running_min,
|
||||||
|
'sum': running_sum,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def smooth(data, window_size, mode='mean', logx=False, logy=False, **kwargs):
|
def smooth(
|
||||||
|
data: 'Data',
|
||||||
|
window_size: int,
|
||||||
|
mode: str = 'mean',
|
||||||
|
logx: bool = False,
|
||||||
|
logy: bool = False,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
func = _funcs[mode]
|
func = _funcs[mode]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -162,6 +185,6 @@ def smooth(data, window_size, mode='mean', logx=False, logy=False, **kwargs):
|
|||||||
new_y = 10**new_y
|
new_y = 10**new_y
|
||||||
|
|
||||||
new_data = data.copy()
|
new_data = data.copy()
|
||||||
new_data.set_data(x=new_x, y=new_y, y_err=None)
|
new_data.set_data(x=new_x, y=new_y, y_err=np.zeros_like(new_y))
|
||||||
|
|
||||||
return new_data
|
return new_data
|
||||||
|
@ -191,6 +191,18 @@ class PowerLawCross:
|
|||||||
return ret_val
|
return ret_val
|
||||||
|
|
||||||
|
|
||||||
|
class Sinc:
|
||||||
|
type = 'Basic'
|
||||||
|
name = 'Sinc'
|
||||||
|
equation = 'C * sinc((x-x_{0})/w)'
|
||||||
|
params = ['C', 'x_{0}', 'w']
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def func(x, c: float, x0: float, w: float):
|
||||||
|
# numpy sinc is defined as sin(pi*x)/(pi*x)
|
||||||
|
return c * np.sinc(((x-x0)/w)/np.pi)
|
||||||
|
|
||||||
|
|
||||||
class Sine:
|
class Sine:
|
||||||
"""
|
"""
|
||||||
Wavy sine function
|
Wavy sine function
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
from . import PowerLaw
|
||||||
from ..distributions import Debye, ColeCole, ColeDavidson, KWW, HavriliakNegami
|
from ..distributions import Debye, ColeCole, ColeDavidson, KWW, HavriliakNegami
|
||||||
from ..utils.constants import epsilon0
|
from ..utils.constants import epsilon0
|
||||||
|
|
||||||
@ -232,8 +233,8 @@ class DCCondBDS:
|
|||||||
|
|
||||||
|
|
||||||
class DerivativeHavriliakNegami:
|
class DerivativeHavriliakNegami:
|
||||||
name = 'Derivative HN'
|
name = 'Havriliak-Negami (der.)'
|
||||||
type = 'Dielectric Spectroscopy'
|
type = 'Dielectric Spectroscopy (derivative)'
|
||||||
params = [r'\Delta\epsilon', r'\tau', r'\alpha', r'\gamma']
|
params = [r'\Delta\epsilon', r'\tau', r'\alpha', r'\gamma']
|
||||||
choices = [
|
choices = [
|
||||||
('x axis', 'xaxis', {'Frequency': 'freq', 'Omega': 'omega'})
|
('x axis', 'xaxis', {'Frequency': 'freq', 'Omega': 'omega'})
|
||||||
@ -254,8 +255,8 @@ class DerivativeHavriliakNegami:
|
|||||||
|
|
||||||
|
|
||||||
class DerivativeColeCole:
|
class DerivativeColeCole:
|
||||||
name = 'Derivative CC'
|
name = 'Cole-Cole (der.)'
|
||||||
type = 'Dielectric Spectroscopy'
|
type = 'Dielectric Spectroscopy (derivative)'
|
||||||
params = [r'\Delta\epsilon', r'\tau', r'\alpha']
|
params = [r'\Delta\epsilon', r'\tau', r'\alpha']
|
||||||
bounds = [(0, None), (0, None), (0, 1)]
|
bounds = [(0, None), (0, None), (0, 1)]
|
||||||
choices = [
|
choices = [
|
||||||
@ -276,8 +277,8 @@ class DerivativeColeCole:
|
|||||||
|
|
||||||
|
|
||||||
class DerivativeColeDavidson:
|
class DerivativeColeDavidson:
|
||||||
name = 'Derivative CD'
|
name = 'Cole-Davidson (der.)'
|
||||||
type = 'Dielectric Spectroscopy'
|
type = 'Dielectric Spectroscopy (derivative)'
|
||||||
params = [r'\Delta\epsilon', r'\tau', r'\gamma']
|
params = [r'\Delta\epsilon', r'\tau', r'\gamma']
|
||||||
bounds = [(0, None), (0, None), (0, 1)]
|
bounds = [(0, None), (0, None), (0, 1)]
|
||||||
choices = [
|
choices = [
|
||||||
@ -295,8 +296,8 @@ class DerivativeColeDavidson:
|
|||||||
|
|
||||||
|
|
||||||
class _DerivativeHNWithHF:
|
class _DerivativeHNWithHF:
|
||||||
name = 'Derivative (HN + HF wing)'
|
name = 'HN + HF wing (der.)'
|
||||||
type = 'Dielectric Spectroscopy'
|
type = 'Dielectric Spectroscopy (derivative)'
|
||||||
params = [r'\Delta\epsilon', r'\tau', r'\alpha', r'\gamma', r'\tau_{c}', r'\delta']
|
params = [r'\Delta\epsilon', r'\tau', r'\alpha', r'\gamma', r'\tau_{c}', r'\delta']
|
||||||
bounds = [(0, None), (0, None), (0, 1), (0, 1), (0, None), (0, 1)]
|
bounds = [(0, None), (0, None), (0, 1), (0, 1), (0, None), (0, 1)]
|
||||||
choices = [
|
choices = [
|
||||||
@ -325,8 +326,8 @@ class _DerivativeHNWithHF:
|
|||||||
|
|
||||||
|
|
||||||
class DerivativeCCWithHF:
|
class DerivativeCCWithHF:
|
||||||
name = 'Derivative (CC + HF wing)'
|
name = 'CC + HF wing (der.)'
|
||||||
type = 'Dielectric Spectroscopy'
|
type = 'Dielectric Spectroscopy (derivative)'
|
||||||
params = [r'\Delta\epsilon', r'\tau', r'\alpha', r'\tau_{c}', r'\delta']
|
params = [r'\Delta\epsilon', r'\tau', r'\alpha', r'\tau_{c}', r'\delta']
|
||||||
bounds = [(0, None), (0, None), (0, 1), (0, None), (0, 1)]
|
bounds = [(0, None), (0, None), (0, 1), (0, None), (0, 1)]
|
||||||
choices = [
|
choices = [
|
||||||
@ -339,8 +340,8 @@ class DerivativeCCWithHF:
|
|||||||
|
|
||||||
|
|
||||||
class DerivativeCDWithHF:
|
class DerivativeCDWithHF:
|
||||||
name = 'Derivative (CD + HF wing)'
|
name = 'CD + HF wing (der.)'
|
||||||
type = 'Dielectric Spectroscopy'
|
type = 'Dielectric Spectroscopy (derivative)'
|
||||||
params = [r'\Delta\epsilon', r'\tau', r'\gamma', r'\tau_{c}', r'\delta']
|
params = [r'\Delta\epsilon', r'\tau', r'\gamma', r'\tau_{c}', r'\delta']
|
||||||
bounds = [(0, None), (0, None), (0, 1), (0, None), (0, 1)]
|
bounds = [(0, None), (0, None), (0, 1), (0, None), (0, 1)]
|
||||||
choices = [
|
choices = [
|
||||||
@ -352,6 +353,22 @@ class DerivativeCDWithHF:
|
|||||||
return _DerivativeHNWithHF.func(x, deps, tau, 1, gamma, tauc, delta, xaxis=xaxis)
|
return _DerivativeHNWithHF.func(x, deps, tau, 1, gamma, tauc, delta, xaxis=xaxis)
|
||||||
|
|
||||||
|
|
||||||
|
class PowerLawBDSDer:
|
||||||
|
name = 'Power Law'
|
||||||
|
type = 'Dielectric Spectroscopy (derivative)'
|
||||||
|
equation = r'A * \omega^{n}'
|
||||||
|
params = ['A', 'n']
|
||||||
|
bounds = [(None, None), (None, None)]
|
||||||
|
choices = [
|
||||||
|
('x axis', 'xaxis', {'Frequency': 'freq', 'Omega': 'omega'})
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def func(x, a, n, xaxis: str = 'freq'):
|
||||||
|
_w = _convert_x_to_omega(x, xaxis=xaxis)
|
||||||
|
return a * _w ** n
|
||||||
|
|
||||||
|
|
||||||
def _convert_x_to_omega(x, xaxis: str = 'freq'):
|
def _convert_x_to_omega(x, xaxis: str = 'freq'):
|
||||||
if xaxis not in ['freq', 'omega']:
|
if xaxis not in ['freq', 'omega']:
|
||||||
raise ValueError(f'Argument `xaxis` is `freq` or `omega`, given is {xaxis!r}')
|
raise ValueError(f'Argument `xaxis` is `freq` or `omega`, given is {xaxis!r}')
|
||||||
|
@ -2,6 +2,7 @@ import numpy as np
|
|||||||
|
|
||||||
from ..distributions import *
|
from ..distributions import *
|
||||||
from ..distributions.energy import EnergyBarriers
|
from ..distributions.energy import EnergyBarriers
|
||||||
|
from ..distributions.gengamma import GGAlpha
|
||||||
from ..distributions.intermolecular import FFHS
|
from ..distributions.intermolecular import FFHS
|
||||||
from ..nmr.relaxation import Relaxation
|
from ..nmr.relaxation import Relaxation
|
||||||
from ..utils.constants import gamma
|
from ..utils.constants import gamma
|
||||||
@ -82,6 +83,13 @@ class FFHSFC(_AbstractFC):
|
|||||||
relax = Relaxation(distribution=FFHS)
|
relax = Relaxation(distribution=FFHS)
|
||||||
|
|
||||||
|
|
||||||
|
class GGAFC(_AbstractFC):
|
||||||
|
name = 'GG(alpha)'
|
||||||
|
params = _AbstractFC.params + [r'\alpha', r'\beta']
|
||||||
|
bounds = _AbstractFC.bounds + [(None, None), (None, None)]
|
||||||
|
relax = Relaxation(distribution=GGAlpha)
|
||||||
|
|
||||||
|
|
||||||
class EnergyFC(_AbstractFC):
|
class EnergyFC(_AbstractFC):
|
||||||
name = 'Energy distribution'
|
name = 'Energy distribution'
|
||||||
params = ['C', 'T'] + EnergyBarriers.parameter
|
params = ['C', 'T'] + EnergyBarriers.parameter
|
||||||
|
@ -1,19 +1,31 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy import special as special
|
from scipy import special as special
|
||||||
|
|
||||||
from ..utils import kB
|
from ..utils import kB
|
||||||
|
|
||||||
|
|
||||||
class Weight2Phase:
|
class Weight:
|
||||||
type = 'Line shape'
|
type = 'Line shape'
|
||||||
name = 'Weighting factor'
|
name = 'Weighting factor'
|
||||||
equation = r'A*[0.5 + 0.5 erf[(x-T_{0})/\DeltaT]] + A_{0}'
|
equation = r'A * [0.5 \pm 0.5 erf[(x-T_{0})/\DeltaT]] + A_{0}'
|
||||||
params = ['T_{0}', r'\DeltaT', 'A', 'A_{0}']
|
params = ['T_{0}', r'\DeltaT', 'A', 'A_{0}']
|
||||||
|
choices = [('Direction', 'sign', {'increase': '+', 'decrease': '-'})]
|
||||||
bounds = [(0, None), (0, None), (None, None), (None, None)]
|
bounds = [(0, None), (0, None), (None, None), (None, None)]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def func(x, t0, dt, amp, off):
|
def func(x: np.ndarray | float, t0: float, dt: float, amp: float, off: float, sign: str = '+') -> np.ndarray | float:
|
||||||
return amp*(0.5 + 0.5*special.erf((x-t0)/dt)) + off
|
if sign not in '+-':
|
||||||
|
raise ValueError(f"`value` is `+` or `-`, not {sign}")
|
||||||
|
|
||||||
|
error_func = 1
|
||||||
|
if sign == '+':
|
||||||
|
error_func += special.erf((x-t0)/dt)
|
||||||
|
else:
|
||||||
|
error_func -= special.erf((x - t0) / dt)
|
||||||
|
|
||||||
|
return amp * error_func / 2. + off
|
||||||
|
|
||||||
|
|
||||||
class HendricksonBray:
|
class HendricksonBray:
|
||||||
@ -24,5 +36,5 @@ class HendricksonBray:
|
|||||||
bounds = [(0, None)] * 4
|
bounds = [(0, None)] * 4
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def func(x, a, b, e, w0):
|
def func(x: np.ndarray | float, a: float, b: float, e: float, w0: float) -> np.ndarray | float:
|
||||||
return a*b / (b + (a-b)*np.exp(-e/kB/x)) + w0
|
return a*b / (b + (a-b)*np.exp(-e/kB/x)) + w0
|
||||||
|
@ -525,7 +525,7 @@ class RelaxationEvaluation(Relaxation):
|
|||||||
dist_parameter: tuple | list = None,
|
dist_parameter: tuple | list = None,
|
||||||
prefactor: tuple | list | float = None,
|
prefactor: tuple | list | float = None,
|
||||||
coupling_kwargs: dict = None,
|
coupling_kwargs: dict = None,
|
||||||
) -> None:
|
) -> tuple[float, float] :
|
||||||
"""
|
"""
|
||||||
Determine a single parameter from a T1 minimum.
|
Determine a single parameter from a T1 minimum.
|
||||||
It replaces the previously set value.
|
It replaces the previously set value.
|
||||||
|
@ -5,3 +5,10 @@ from .constants import *
|
|||||||
|
|
||||||
NUMBER_RE = re.compile(r'[-+]?\d*[+p.]?\d+([eE][-+]?\d+)?', re.MULTILINE)
|
NUMBER_RE = re.compile(r'[-+]?\d*[+p.]?\d+([eE][-+]?\d+)?', re.MULTILINE)
|
||||||
UNSIGNED_NUMBER_RE = re.compile(r'[-+]?\d*[+p.]?\d+([eE][-+]?\d+)?', re.MULTILINE)
|
UNSIGNED_NUMBER_RE = re.compile(r'[-+]?\d*[+p.]?\d+([eE][-+]?\d+)?', re.MULTILINE)
|
||||||
|
|
||||||
|
|
||||||
|
def numbers_from_string(any_string: str) -> list[float]:
|
||||||
|
matches = []
|
||||||
|
for m in NUMBER_RE.finditer(any_string):
|
||||||
|
matches.append(float(m.group().replace('p', '.')))
|
||||||
|
return matches
|
||||||
|
@ -33,9 +33,9 @@ big_greek = [
|
|||||||
special_chars = [
|
special_chars = [
|
||||||
r'\infty \int \sum \langle \rangle \pm \perp \para \leftarrow \rightarrow \leftrightarrow \cdot \hbar \n',
|
r'\infty \int \sum \langle \rangle \pm \perp \para \leftarrow \rightarrow \leftrightarrow \cdot \hbar \n',
|
||||||
'\u221e \u222b \u2211 \u27e8 \u27e9 \u00b1 \u27c2 \u2225 \u21d0 \u21d2 \u21d4 \u00b7 \u0127 <br>',
|
'\u221e \u222b \u2211 \u27e8 \u27e9 \u00b1 \u27c2 \u2225 \u21d0 \u21d2 \u21d4 \u00b7 \u0127 <br>',
|
||||||
r'\f{Symbol}¥\f{} \f{Symbol}ò\f{} \f{Symbol}å\f{} \f{Symbol}á\f{} \f{Symbol}ñ\f{} \f{Symbol}±\f{} \n'
|
r'\f{Symbol}¥\f{} \f{Symbol}ò\f{} \f{Symbol}å\f{} \f{Symbol}á\f{} \f{Symbol}ñ\f{} \f{Symbol}±\f{} '
|
||||||
r'\f{Symbol}^\f{} \f{Symbol}||\f{} \f{Symbol}¬\f{} \f{Symbol}®\f{} \f{Symbol}«\f{} \f{Symbol}×\f{Symbol} '
|
r'\f{Symbol}^\f{} \f{Symbol}||\f{} \f{Symbol}¬\f{} \f{Symbol}®\f{} \f{Symbol}«\f{} \f{Symbol}×\f{Symbol} '
|
||||||
r'h\h{-0.6}\v{0.3}-\v{-0.3}\h{0.3}',
|
r'h\h{-0.6}\v{0.3}-\v{-0.3}\h{0.3} \n',
|
||||||
r'infty int sum < > \+- perp para <- -> <-> \* hbar \s',
|
r'infty int sum < > \+- perp para <- -> <-> \* hbar \s',
|
||||||
]
|
]
|
||||||
funcs = [
|
funcs = [
|
||||||
|
@ -336,7 +336,7 @@
|
|||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Token:<br/>[abc]: Matches any of a, b, or c<br/>[a-z]: Matches any digit in the range a-z<br/>\d: Matches any digit in the range 0-9 (equal to [0-9}</p><p>Quantifiers:<br/>a*: 0 or more of a<br/>a*: 1 or more of a<br/>a?: 0 or 1 of a</p></body></html></string>
|
<string><html><head/><body><p>Token:<br/>[abc]: Matches any of a, b, or c<br/>[a-z]: Matches any digit in the range a-z<br/>\d: Matches any digit in the range 0-9 (equal to [0-9}</p><p>Quantifiers:<br/>a+: 0 or more of a<br/>a*: 1 or more of a<br/>a?: 0 or 1 of a</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -172,6 +172,14 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>&Data</string>
|
<string>&Data</string>
|
||||||
</property>
|
</property>
|
||||||
|
<widget class="QMenu" name="menuCut_to_visible_range">
|
||||||
|
<property name="title">
|
||||||
|
<string>Cut to visible range</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="separator"/>
|
||||||
|
<addaction name="action_cut_xaxis"/>
|
||||||
|
<addaction name="action_cut_yaxis"/>
|
||||||
|
</widget>
|
||||||
<addaction name="action_new_set"/>
|
<addaction name="action_new_set"/>
|
||||||
<addaction name="action_delete_sets"/>
|
<addaction name="action_delete_sets"/>
|
||||||
<addaction name="actionMove_between_plots"/>
|
<addaction name="actionMove_between_plots"/>
|
||||||
@ -181,9 +189,10 @@
|
|||||||
<addaction name="action_sort_pts"/>
|
<addaction name="action_sort_pts"/>
|
||||||
<addaction name="actionSkip_points"/>
|
<addaction name="actionSkip_points"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="action_cut"/>
|
<addaction name="menuCut_to_visible_range"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="actionChange_datatypes"/>
|
<addaction name="actionChange_datatypes"/>
|
||||||
|
<addaction name="actionUse_script"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuHelp">
|
<widget class="QMenu" name="menuHelp">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
@ -247,6 +256,7 @@
|
|||||||
<addaction name="action_no_range"/>
|
<addaction name="action_no_range"/>
|
||||||
<addaction name="action_x_range"/>
|
<addaction name="action_x_range"/>
|
||||||
<addaction name="action_custom_range"/>
|
<addaction name="action_custom_range"/>
|
||||||
|
<addaction name="actionExclude_region"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="action_FitWidget"/>
|
<addaction name="action_FitWidget"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
@ -437,30 +447,6 @@
|
|||||||
<addaction name="t1action"/>
|
<addaction name="t1action"/>
|
||||||
<addaction name="actionCalculateT1"/>
|
<addaction name="actionCalculateT1"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QToolBar" name="toolBar_fit">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Fit</string>
|
|
||||||
</property>
|
|
||||||
<property name="iconSize">
|
|
||||||
<size>
|
|
||||||
<width>24</width>
|
|
||||||
<height>24</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<attribute name="toolBarArea">
|
|
||||||
<enum>TopToolBarArea</enum>
|
|
||||||
</attribute>
|
|
||||||
<attribute name="toolBarBreak">
|
|
||||||
<bool>false</bool>
|
|
||||||
</attribute>
|
|
||||||
<addaction name="action_FitWidget"/>
|
|
||||||
</widget>
|
|
||||||
<widget class="QToolBar" name="toolBar_spectrum">
|
<widget class="QToolBar" name="toolBar_spectrum">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
@ -885,11 +871,6 @@
|
|||||||
<string>Integration...</string>
|
<string>Integration...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_cut">
|
|
||||||
<property name="text">
|
|
||||||
<string>Cut to visible range</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="actionMove_between_plots">
|
<action name="actionMove_between_plots">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Move sets...</string>
|
<string>Move sets...</string>
|
||||||
@ -1045,6 +1026,35 @@
|
|||||||
<string>TNMH...</string>
|
<string>TNMH...</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionExclude_region">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Exclude region</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_cut_xaxis">
|
||||||
|
<property name="text">
|
||||||
|
<string>x axis</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Remove data points outside visible x range.</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="action_cut_yaxis">
|
||||||
|
<property name="text">
|
||||||
|
<string>y axis</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Remove data points outside visible y range. Uses real part of points.</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionUse_script">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use script...</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
|
@ -106,6 +106,19 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="pokemon_toolbutton">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="toolButtonStyle">
|
||||||
|
<enum>Qt::ToolButtonTextOnly</enum>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -96,11 +96,14 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="region_box">
|
<widget class="QGroupBox" name="region_box">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Evaluate region (empty values default to start/end)</string>
|
<string>Evaluate region (empty values default to values of the script)</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
@ -311,7 +314,11 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1">
|
<item row="3" column="1">
|
||||||
<widget class="QComboBox" name="graph_comboBox"/>
|
<widget class="QComboBox" name="graph_comboBox">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0">
|
<item row="3" column="0">
|
||||||
<widget class="QCheckBox" name="graph_checkbox">
|
<widget class="QCheckBox" name="graph_checkbox">
|
||||||
|
@ -86,11 +86,7 @@
|
|||||||
<layout class="QVBoxLayout" name="verticalLayout_6"/>
|
<layout class="QVBoxLayout" name="verticalLayout_6"/>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="CodeEditor" name="plainTextEdit">
|
<widget class="EditorWidget" name="editor" native="true"/>
|
||||||
<property name="enabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -107,9 +103,10 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>CodeEditor</class>
|
<class>EditorWidget</class>
|
||||||
<extends>QPlainTextEdit</extends>
|
<extends>QWidget</extends>
|
||||||
<header>..lib.codeeditor</header>
|
<header>..lib.codeeditor</header>
|
||||||
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
@ -67,6 +67,12 @@
|
|||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>160</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Initial values</string>
|
<string>Initial values</string>
|
||||||
</property>
|
</property>
|
||||||
@ -92,6 +98,13 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="reset_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use global</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -151,6 +164,12 @@
|
|||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Lower bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html></string>
|
<string><html><head/><body><p>Lower bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
@ -195,6 +214,12 @@
|
|||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Upper bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html></string>
|
<string><html><head/><body><p>Upper bound. Same bound is used for all data. Leave empty for no boundary condition.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -31,13 +31,13 @@
|
|||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
<layout class="QGridLayout" name="gridLayout_3">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>3</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>3</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
@ -45,27 +45,104 @@
|
|||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="2" column="1">
|
<item row="2" column="3">
|
||||||
<widget class="QCheckBox" name="logy_box">
|
<spacer name="horizontalSpacer_2">
|
||||||
<property name="layoutDirection">
|
<property name="orientation">
|
||||||
<enum>Qt::RightToLeft</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="4">
|
||||||
|
<widget class="QToolButton" name="autoscale_box">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Auto-scale graph for all sets</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>logarithmic y axis</string>
|
<string>Autoscale all sets</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QGroupBox" name="verticalGroupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>Logarithmic axes</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="logx_box">
|
||||||
|
<property name="layoutDirection">
|
||||||
|
<enum>Qt::LeftToRight</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>x axis</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="logy_box">
|
||||||
|
<property name="layoutDirection">
|
||||||
|
<enum>Qt::LeftToRight</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>y axis</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="2" column="0">
|
<item row="2" column="0">
|
||||||
<widget class="QCheckBox" name="logx_box">
|
<widget class="QGroupBox" name="verticalGroupBox">
|
||||||
<property name="layoutDirection">
|
<property name="title">
|
||||||
<enum>Qt::RightToLeft</enum>
|
<string>Residuals</string>
|
||||||
</property>
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QRadioButton" name="rel_dev_button">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>logarithmic x axis</string>
|
<string>relative deviation</string>
|
||||||
</property>
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">buttonGroup</string>
|
||||||
|
</attribute>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" colspan="2">
|
<item>
|
||||||
|
<widget class="QRadioButton" name="abs_dev_button">
|
||||||
|
<property name="text">
|
||||||
|
<string>absolute deviation</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="buttonGroup">
|
||||||
|
<string notr="true">buttonGroup</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" colspan="5">
|
||||||
<widget class="GraphicsLayoutWidget" name="graphicsView"/>
|
<widget class="GraphicsLayoutWidget" name="graphicsView"/>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -175,13 +252,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="0" colspan="2">
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Retry</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
<item row="1" column="0">
|
||||||
<widget class="QTableWidget" name="param_tableWidget">
|
<widget class="QTableWidget" name="param_tableWidget">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -231,152 +301,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0" colspan="2">
|
|
||||||
<widget class="QGroupBox" name="groupBox">
|
|
||||||
<property name="title">
|
|
||||||
<string>Output</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_2">
|
|
||||||
<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>
|
|
||||||
<property name="spacing">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<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">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<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="QLineEdit" name="maxx_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 highest point</string>
|
|
||||||
</property>
|
|
||||||
<property name="placeholderText">
|
|
||||||
<string>max x</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<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="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>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="ElideComboBox" name="sets_comboBox">
|
<widget class="ElideComboBox" name="sets_comboBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -409,6 +333,193 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="7" column="0" colspan="2">
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Output</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_2">
|
||||||
|
<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>
|
||||||
|
<property name="spacing">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<item row="1" column="7">
|
||||||
|
<widget class="QComboBox" name="graph_comboBox">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</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="Maximum" 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="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="1" column="3">
|
||||||
|
<widget class="QLineEdit" name="numx_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="placeholderText">
|
||||||
|
<string># pts</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="6">
|
||||||
|
<widget class="QCheckBox" name="graph_checkBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>New graph for parameter</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QLineEdit" name="maxx_line">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<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="0" column="5" rowspan="2">
|
||||||
|
<widget class="Line" name="line_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="4">
|
||||||
|
<widget class="QCheckBox" name="newx_log_checkbox">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>log-spaced?</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0" colspan="5">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="curve_checkbox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<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="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Plot partial functions</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="6" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="parameter_checkbox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Plot parameter</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0" colspan="2">
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Retry</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
@ -425,4 +536,7 @@
|
|||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
<buttongroups>
|
||||||
|
<buttongroup name="buttonGroup"/>
|
||||||
|
</buttongroups>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -449,7 +449,11 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="title_lineedit"/>
|
<widget class="QLineEdit" name="title_lineedit">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Uses simple latex syntax, does not support italic/math environment. Sub-/superscripts need curly brackets.<br/></p><p>Example: \alpha^{123}</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_3">
|
<spacer name="horizontalSpacer_3">
|
||||||
@ -475,7 +479,11 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="xaxis_linedit"/>
|
<widget class="QLineEdit" name="xaxis_linedit">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Uses simple latex syntax, does not support italic/math environment. Sub-/superscripts need curly brackets.<br/></p><p>Example: \alpha^{123}</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_4">
|
<spacer name="horizontalSpacer_4">
|
||||||
@ -501,7 +509,11 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLineEdit" name="yaxis_linedit"/>
|
<widget class="QLineEdit" name="yaxis_linedit">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p>Uses simple latex syntax, does not support italic/math environment. Sub-/superscripts need curly brackets.<br/></p><p>Example: \alpha^{123}</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -119,7 +119,7 @@
|
|||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="standardButtons">
|
<property name="standardButtons">
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -300,38 +300,5 @@
|
|||||||
<tabstop>dest_combobox</tabstop>
|
<tabstop>dest_combobox</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections/>
|
||||||
<connection>
|
|
||||||
<sender>buttonBox</sender>
|
|
||||||
<signal>accepted()</signal>
|
|
||||||
<receiver>Dialog</receiver>
|
|
||||||
<slot>accept()</slot>
|
|
||||||
<hints>
|
|
||||||
<hint type="sourcelabel">
|
|
||||||
<x>251</x>
|
|
||||||
<y>490</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>319</x>
|
|
||||||
<y>490</y>
|
|
||||||
</hint>
|
|
||||||
<hint type="destinationlabel">
|
|
||||||
<x>286</x>
|
|
||||||
<y>274</y>
|
|
||||||
</hint>
|
|
||||||
</hints>
|
|
||||||
</connection>
|
|
||||||
</connections>
|
|
||||||
</ui>
|
</ui>
|
||||||
|
460
src/resources/_ui/pokeentry.ui
Normal file
460
src/resources/_ui/pokeentry.ui
Normal file
@ -0,0 +1,460 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Form</class>
|
||||||
|
<widget class="QWidget" name="Form">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>640</width>
|
||||||
|
<height>642</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="artwork_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<property name="verticalSpacing">
|
||||||
|
<number>12</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 row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>National No.</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLabel" name="nationaldex_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_1">
|
||||||
|
<property name="text">
|
||||||
|
<string>Species</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLabel" name="species_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>Type</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="type1_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="type2_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Abilities</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="ability1_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="ability2_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="ability3_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Height</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLabel" name="height_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>0.0 m</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Weight</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLabel" name="weight_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>0.0 kg</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="gender_label">
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Stats</string>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout_4">
|
||||||
|
<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 row="0" column="3">
|
||||||
|
<widget class="QProgressBar" name="spec_attack_bar">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QProgressBar{
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #009cda;
|
||||||
|
border-radius: 3px;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>194</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>24</number>
|
||||||
|
</property>
|
||||||
|
<property name="format">
|
||||||
|
<string>%v</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>Special Attack</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="3">
|
||||||
|
<widget class="QProgressBar" name="spec_defense_bar">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QProgressBar{
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #009cda;
|
||||||
|
border-radius: 3px;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>250</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>24</number>
|
||||||
|
</property>
|
||||||
|
<property name="format">
|
||||||
|
<string>%v</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Plain</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>HP</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QProgressBar" name="hp_bar">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QProgressBar{
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #009cda;
|
||||||
|
border-radius: 3px;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>255</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>24</number>
|
||||||
|
</property>
|
||||||
|
<property name="format">
|
||||||
|
<string>%v</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="3">
|
||||||
|
<widget class="QProgressBar" name="speed_bar">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QProgressBar{
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #009cda;
|
||||||
|
border-radius: 3px;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>200</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>24</number>
|
||||||
|
</property>
|
||||||
|
<property name="format">
|
||||||
|
<string>%v</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="2">
|
||||||
|
<widget class="QLabel" name="label_11">
|
||||||
|
<property name="text">
|
||||||
|
<string>Speed</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="2">
|
||||||
|
<widget class="QLabel" name="label_10">
|
||||||
|
<property name="text">
|
||||||
|
<string>Special Defense</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QProgressBar" name="defense_bar">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QProgressBar{
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #009cda;
|
||||||
|
border-radius: 3px;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>250</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>24</number>
|
||||||
|
</property>
|
||||||
|
<property name="format">
|
||||||
|
<string>%v</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QProgressBar" name="attack_bar">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">QProgressBar{
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
QProgressBar::chunk {
|
||||||
|
background-color: #009cda;
|
||||||
|
border-radius: 3px;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>190</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>24</number>
|
||||||
|
</property>
|
||||||
|
<property name="format">
|
||||||
|
<string>%v</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_7">
|
||||||
|
<property name="text">
|
||||||
|
<string>Attack</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="label_9">
|
||||||
|
<property name="text">
|
||||||
|
<string>Defense</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="groupBox_2">
|
||||||
|
<property name="title">
|
||||||
|
<string>Evolution chain</string>
|
||||||
|
</property>
|
||||||
|
<property name="flat">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<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="QTableWidget" name="tableWidget">
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background-color: transparent;</string>
|
||||||
|
</property>
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="showGrid">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="gridStyle">
|
||||||
|
<enum>Qt::NoPen</enum>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -1,194 +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>400</width>
|
|
||||||
<height>359</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Random Pokémon</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QFormLayout" name="formLayout">
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>National-Dex</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="1">
|
|
||||||
<widget class="QLabel" name="pokedex_nr">
|
|
||||||
<property name="text">
|
|
||||||
<string>TextLabel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Name</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>name</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QComboBox" name="name"/>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Kategorie</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="1">
|
|
||||||
<widget class="QLabel" name="category">
|
|
||||||
<property name="text">
|
|
||||||
<string>TextLabel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>Typ</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLabel" name="poketype">
|
|
||||||
<property name="text">
|
|
||||||
<string>TextLabel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="text">
|
|
||||||
<string>Größe</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QLabel" name="height">
|
|
||||||
<property name="text">
|
|
||||||
<string>TextLabel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="text">
|
|
||||||
<string>Gewicht</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="QLabel" name="weight">
|
|
||||||
<property name="text">
|
|
||||||
<string>TextLabel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="0">
|
|
||||||
<widget class="QLabel" name="label_7">
|
|
||||||
<property name="text">
|
|
||||||
<string>Farbe</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="6" column="1">
|
|
||||||
<widget class="QLabel" name="color">
|
|
||||||
<property name="text">
|
|
||||||
<string>TextLabel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="0">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="text">
|
|
||||||
<string>Mehr...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="1">
|
|
||||||
<widget class="QLabel" name="info">
|
|
||||||
<property name="text">
|
|
||||||
<string>TextLabel</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="prev_button">
|
|
||||||
<property name="text">
|
|
||||||
<string>Prev.</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QToolButton" name="next_button">
|
|
||||||
<property name="text">
|
|
||||||
<string>Next</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Close|QDialogButtonBox::Retry</set>
|
|
||||||
</property>
|
|
||||||
<property name="centerButtons">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections>
|
|
||||||
<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>
|
|
219
src/resources/_ui/pokewindow.ui
Normal file
219
src/resources/_ui/pokewindow.ui
Normal file
@ -0,0 +1,219 @@
|
|||||||
|
<?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>1687</width>
|
||||||
|
<height>991</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Gotta catch 'em all!</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QPushButton" name="pushButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Random</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QComboBox" name="comboBox_2"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="comboBox"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Close</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="5">
|
||||||
|
<widget class="QSplitter" name="splitter">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QTableWidget" name="tableWidget_2">
|
||||||
|
<property name="editTriggers">
|
||||||
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
|
</property>
|
||||||
|
<property name="alternatingRowColors">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="selectionMode">
|
||||||
|
<enum>QAbstractItemView::SingleSelection</enum>
|
||||||
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectRows</enum>
|
||||||
|
</property>
|
||||||
|
<property name="showGrid">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="gridStyle">
|
||||||
|
<enum>Qt::NoPen</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<attribute name="horizontalHeaderDefaultSectionSize">
|
||||||
|
<number>80</number>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="horizontalHeaderStretchLastSection">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<attribute name="verticalHeaderVisible">
|
||||||
|
<bool>false</bool>
|
||||||
|
</attribute>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>#</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pokemon</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Type</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Total</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>HP</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Hit Points; Kraftpunkte</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Attack</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Attacke</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Defense</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Verteidigung</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Sp. Attack</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Special Attack; Spezial-Attacke</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Sp. Defense</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Special Defense; Spezial-Verteidigung</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Speed</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Initiative</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Height</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Größe</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>Weight</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Gewicht</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
<column>
|
||||||
|
<property name="text">
|
||||||
|
<string>BMI</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Body-Mass-Index</string>
|
||||||
|
</property>
|
||||||
|
</column>
|
||||||
|
</widget>
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>418</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>-1</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>Dialog</receiver>
|
||||||
|
<slot>close()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>762</x>
|
||||||
|
<y>969</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>762</x>
|
||||||
|
<y>495</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
@ -6,27 +6,25 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>316</width>
|
<width>417</width>
|
||||||
<height>747</height>
|
<height>746</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<property name="leftMargin">
|
<item row="0" column="0" colspan="2">
|
||||||
<number>3</number>
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Selected points and regions</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="topMargin">
|
<property name="buddy">
|
||||||
<number>3</number>
|
<cstring>peaktable</cstring>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
</widget>
|
||||||
<number>3</number>
|
</item>
|
||||||
</property>
|
<item row="1" column="0" colspan="2">
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QListWidget" name="peaktable">
|
<widget class="QListWidget" name="peaktable">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Edit by entering new value:
|
<string>Edit by entering new value:
|
||||||
@ -39,110 +37,18 @@ Changing between regions and points is NOT possible</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="3" column="0">
|
||||||
<widget class="QGroupBox" name="groupBox">
|
<widget class="QCheckBox" name="special_checkbox">
|
||||||
<property name="title">
|
|
||||||
<string>Average</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<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="QSpinBox" name="left_pt">
|
|
||||||
<property name="suffix">
|
|
||||||
<string> pts</string>
|
|
||||||
</property>
|
|
||||||
<property name="prefix">
|
|
||||||
<string>- </string>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>999</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSpinBox" name="right_pt">
|
|
||||||
<property name="suffix">
|
|
||||||
<string> pts</string>
|
|
||||||
</property>
|
|
||||||
<property name="prefix">
|
|
||||||
<string>+ </string>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>999</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="average_combobox">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Mean</string>
|
<string>Use special value</string>
|
||||||
</property>
|
</property>
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Sum</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Integral</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item row="3" column="1">
|
||||||
</widget>
|
<widget class="QComboBox" name="special_comboBox">
|
||||||
</item>
|
<property name="enabled">
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="groupBox_2">
|
|
||||||
<property name="title">
|
|
||||||
<string>Special value</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>2</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="QComboBox" name="special_comboBox">
|
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Automatic selection of respective points</string>
|
<string>Automatic selection of respective points</string>
|
||||||
</property>
|
</property>
|
||||||
@ -168,38 +74,113 @@ Changing between regions and points is NOT possible</string>
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item row="4" column="0">
|
||||||
|
<spacer name="verticalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Preferred</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Region around points</string>
|
||||||
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox_3">
|
<widget class="QLineEdit" name="left_limit"/>
|
||||||
<property name="title">
|
</item>
|
||||||
<string>Result</string>
|
<item>
|
||||||
|
<widget class="QLineEdit" name="right_limit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="limit_combobox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>points</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
</item>
|
||||||
<property name="leftMargin">
|
<item>
|
||||||
<number>3</number>
|
<property name="text">
|
||||||
|
<string>range</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="topMargin">
|
</item>
|
||||||
<number>3</number>
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>Aggregation</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="buddy">
|
||||||
<number>3</number>
|
<cstring>average_combobox</cstring>
|
||||||
</property>
|
</property>
|
||||||
<property name="bottomMargin">
|
</widget>
|
||||||
<number>3</number>
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QComboBox" name="average_combobox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="spacing">
|
<item>
|
||||||
<number>3</number>
|
<property name="text">
|
||||||
|
<string>Mean</string>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Sum</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Integral</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Std. deviation</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="0">
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>New set based on</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>xbutton</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
<widget class="QCheckBox" name="xbutton">
|
<widget class="QCheckBox" name="xbutton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>x</string>
|
<string>x</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item>
|
||||||
<widget class="QCheckBox" name="ybutton">
|
<widget class="QCheckBox" name="ybutton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>y</string>
|
<string>y</string>
|
||||||
@ -209,7 +190,49 @@ Changing between regions and points is NOT possible</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Group by</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>group_box</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<widget class="QComboBox" name="group_box">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>"Group" value</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>x value</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="9" column="0">
|
||||||
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Preferred</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="10" column="0">
|
||||||
<widget class="QCheckBox" name="graph_checkbox">
|
<widget class="QCheckBox" name="graph_checkbox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>New graph?</string>
|
<string>New graph?</string>
|
||||||
@ -219,25 +242,30 @@ Changing between regions and points is NOT possible</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="10" column="1">
|
||||||
<widget class="QComboBox" name="graph_combobox">
|
<widget class="QComboBox" name="graph_combobox">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item row="12" column="0">
|
||||||
</widget>
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Expanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="11" column="0" colspan="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>2</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="okButton">
|
<widget class="QPushButton" name="okButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Apply</string>
|
<string>Apply</string>
|
||||||
@ -248,10 +276,10 @@ Changing between regions and points is NOT possible</string>
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item row="2" column="0" colspan="2">
|
||||||
<widget class="QPushButton" name="deleteButton">
|
<widget class="QPushButton" name="deleteButton">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Delete selected</string>
|
<string>Delete selection</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset theme="dialog-cancel">
|
<iconset theme="dialog-cancel">
|
||||||
@ -260,9 +288,17 @@ Changing between regions and points is NOT possible</string>
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>peaktable</tabstop>
|
||||||
|
<tabstop>limit_combobox</tabstop>
|
||||||
|
<tabstop>average_combobox</tabstop>
|
||||||
|
<tabstop>xbutton</tabstop>
|
||||||
|
<tabstop>ybutton</tabstop>
|
||||||
|
<tabstop>group_box</tabstop>
|
||||||
|
<tabstop>graph_checkbox</tabstop>
|
||||||
|
<tabstop>graph_combobox</tabstop>
|
||||||
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
@ -17,7 +17,20 @@
|
|||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="1" column="0">
|
<item row="7" column="0">
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="frac_label">
|
<widget class="QLabel" name="frac_label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Window length</string>
|
<string>Window length</string>
|
||||||
@ -27,68 +40,14 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0" colspan="2">
|
<item row="5" column="0" colspan="2">
|
||||||
<widget class="QWidget" name="widget_2" native="true">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
|
||||||
<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="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Iterations</string>
|
|
||||||
</property>
|
|
||||||
<property name="buddy">
|
|
||||||
<cstring>iter_spinBox</cstring>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSpinBox" name="iter_spinBox">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>3</number>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0" colspan="2">
|
|
||||||
<widget class="Line" name="line">
|
<widget class="Line" name="line">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0" colspan="2">
|
<item row="3" column="0" colspan="2">
|
||||||
<widget class="QDialogButtonBox" name="buttonBox">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="standardButtons">
|
|
||||||
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0" colspan="2">
|
|
||||||
<widget class="QWidget" name="widget" native="true">
|
<widget class="QWidget" name="widget" native="true">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
@ -132,7 +91,65 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="6" column="1">
|
||||||
|
<widget class="QCheckBox" name="y_checkBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>y log-spaced?</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QCheckBox" name="x_checkBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>x log-spaced?</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0" colspan="2">
|
||||||
|
<widget class="QWidget" name="widget_2" native="true">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<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="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Iterations</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>iter_spinBox</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="iter_spinBox">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
<widget class="QSpinBox" name="frac_spinBox">
|
<widget class="QSpinBox" name="frac_spinBox">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string><html><head/><body><p>Number of data points used as smoothing window.</p></body></html></string>
|
<string><html><head/><body><p>Number of data points used as smoothing window.</p></body></html></string>
|
||||||
@ -145,7 +162,17 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0" colspan="2">
|
<item row="8" column="0" colspan="2">
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="2">
|
||||||
<widget class="QComboBox" name="comboBox">
|
<widget class="QComboBox" name="comboBox">
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@ -194,30 +221,13 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="0" column="0" colspan="2">
|
||||||
<spacer name="verticalSpacer">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="5" column="1">
|
|
||||||
<widget class="QCheckBox" name="y_checkBox">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>y log-spaced?</string>
|
<string><html><head/><body><p><span style=" font-weight:600;">Note:</span> Sets must be sorted for correct results</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<property name="margin">
|
||||||
</item>
|
<number>3</number>
|
||||||
<item row="5" column="0">
|
|
||||||
<widget class="QCheckBox" name="x_checkBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>x log-spaced?</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -31,13 +31,7 @@
|
|||||||
<number>3</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="CodeEditor" name="edit_field">
|
<widget class="EditorWidget" name="widget" native="true"/>
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>10</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
@ -47,7 +41,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>800</width>
|
<width>800</width>
|
||||||
<height>30</height>
|
<height>20</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menuFile">
|
<widget class="QMenu" name="menuFile">
|
||||||
@ -85,9 +79,10 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>CodeEditor</class>
|
<class>EditorWidget</class>
|
||||||
<extends>QPlainTextEdit</extends>
|
<extends>QWidget</extends>
|
||||||
<header>..lib.codeeditor</header>
|
<header>..lib.codeeditor</header>
|
||||||
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
BIN
src/resources/pokemon.sqlite
Normal file
BIN
src/resources/pokemon.sqlite
Normal file
Binary file not shown.
@ -5,4 +5,5 @@ else
|
|||||||
wget https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/$BUILDER
|
wget https://github.com/AppImageCrafters/appimage-builder/releases/download/v1.1.0/$BUILDER
|
||||||
fi
|
fi
|
||||||
chmod +x appimage-builder-1.1.0-x86_64.AppImage
|
chmod +x appimage-builder-1.1.0-x86_64.AppImage
|
||||||
./appimage-builder-1.1.0-x86_64.AppImage --skip-tests --recipe AppImageBuilder${GO_PIPELINE_LABEL:-}.yml
|
./appimage-builder-1.1.0-x86_64.AppImage --appimage-extract
|
||||||
|
./squashfs-root/AppRun --skip-tests --recipe AppImageBuilder${GO_PIPELINE_LABEL:-}.yml
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user