forked from IPKM/nmreval
Compare commits
370 Commits
csv_broken
...
master
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 | ||
|
8fb17b22fd | ||
|
f04cadf780 | ||
|
ae45ff2e55 | ||
|
735896e68d | ||
|
aff9cd31a7 | ||
8772fa9e7a | |||
|
9c5d91918f | ||
|
dbb35cdba4 | ||
|
070509c691 | ||
|
5ea1ed6d0a | ||
|
a1691f11a6 | ||
|
f956c111c2 | ||
|
cb2bc78a2a | ||
|
9e9751cd9d | ||
|
5a8ef8c9c7 | ||
45f5eb9bef | |||
|
5116622e42 | ||
|
661ab81d7e | ||
|
185dd160f1 | ||
|
7fe564a61e | ||
|
6339bdc2cc | ||
|
37a6d789bb | ||
|
cde794cb0d | ||
|
2a69147ed4 | ||
|
902a35b71a | ||
|
6f76349932 | ||
|
f9bb466cb3 | ||
|
a97c31325f | ||
|
207ee5bffd | ||
|
0046d04683 | ||
|
9463ed1e6c | ||
|
ea62a05bd3 | ||
|
c5706084bf | ||
|
04037d6b4d | ||
|
dedb130163 | ||
|
6ecc4a4126 | ||
|
067857eda2 | ||
|
41d90bb15f | ||
|
8d994bb9b4 | ||
|
2cbc7e8d75 | ||
|
1d22f22901 | ||
|
bd1a227e4c | ||
|
03d172bade | ||
|
e51a02d277 | ||
|
3af5cb0301 | ||
|
22f317da8d | ||
|
24b56cbd2a | ||
5fd52a1a44 | |||
|
d8e5de6b7a | ||
|
869901596b | ||
|
e4dbaf2b91 | ||
|
dee1271fe1 | ||
|
b8bab2af7b | ||
|
a406908a69 | ||
|
5e55f06723 | ||
|
e2e52cebde | ||
|
53c58b2bbb | ||
4e865cd0c6 | |||
|
311157a01a | ||
|
f0ee2073ad | ||
|
d2e63a5ee3 | ||
|
5a153585ee | ||
|
d17d0f251e | ||
|
0b8f4932b2 | ||
|
5d43ccb05d | ||
|
88a32ea7fd | ||
|
7febe55929 | ||
|
783fe505ba | ||
|
2fed4bb0bf | ||
|
ec8fafcc9c | ||
|
7762758958 | ||
|
258922772e | ||
|
e612c607e2 | ||
|
b27d9b55ff | ||
|
3475650899 | ||
|
0eca306ebe | ||
d7eaff5f0b | |||
|
a5216b1eed | ||
cf1565f7d3 | |||
|
c601e77cec | ||
|
63f4f82228 | ||
|
bae7ee2db6 | ||
|
dde7b7006d | ||
|
141e9f810a | ||
|
b6136bc8ce | ||
|
7762e299e4 | ||
|
ca130eaa14 | ||
|
2b2c6e932d | ||
|
402994e09b | ||
|
7a50028202 | ||
|
becc1a15a9 | ||
13e6112c99 | |||
|
1ff462c4b1 | ||
0cf5d7eef9 | |||
|
609f135855 | ||
|
5db6a9f2c5 | ||
|
3149a3f958 | ||
|
3321d85203 | ||
|
76cd4acfb0 | ||
|
33afc2ca94 | ||
|
ac039c1b6d | ||
|
ef21d7c7f2 | ||
|
3ed7368bb0 | ||
|
fbf4246c7e | ||
|
91afe8224f | ||
|
ead9751541 | ||
|
1d9b641f0a | ||
|
46ca50845b | ||
|
a310a78fb9 | ||
|
9756bf958b | ||
|
8de4a0cbd3 | ||
|
bc946e1027 | ||
|
1d9bf600ba | ||
|
4a04502012 | ||
|
6bcf42d6a8 | ||
|
8a96e0472d | ||
567fcfe37e | |||
|
058551cc72 | ||
|
6fd3053964 | ||
|
3ee95a1990 | ||
|
1a2f178f58 | ||
|
c39ffb8a51 | ||
a26595695c | |||
|
c9ea32629d | ||
|
032ffb72b1 | ||
|
354d5cbc99 | ||
|
22f8bc80ed | ||
|
84d588cf80 | ||
|
5b146433f3 | ||
|
1a225b2cd2 | ||
|
89c640e591 | ||
|
1703b8d514 | ||
|
7732544f69 | ||
|
988d2ccbda | ||
|
4268bdc5ae | ||
|
775b5e7e8a | ||
|
30e148de14 | ||
|
2499aac7a1 | ||
|
f934104587 | ||
|
6e976e1404 | ||
|
92c29bec2a | ||
|
9f6d4e0d0c | ||
|
90bd33a680 | ||
|
26fea8f69f | ||
|
25f7ff5616 | ||
|
bec789318d | ||
|
edc6af2762 | ||
|
eb1e657dab | ||
|
79a424c4bd | ||
|
f74dd982ba | ||
|
a5a9561b54 | ||
|
c8287c2dbf | ||
|
a8a7e75501 | ||
|
30750cc4ed | ||
|
af14793286 | ||
|
2906c17472 | ||
5590b5cd16 | |||
|
09e415babf | ||
4e2938b2a2 | |||
|
685b9d2316 | ||
|
b91fbf7621 | ||
|
8d55430246 | ||
|
8d06240205 | ||
|
65034d4518 | ||
|
2adf15104f | ||
|
cd9c85c12b | ||
|
84d136dd4c | ||
|
f60e125487 | ||
|
1e9a390ae2 | ||
|
8673e5acdb | ||
|
66a0e40a23 | ||
|
a1ab6335c5 | ||
|
09a2b61160 | ||
|
681b49a22f | ||
|
3dcd44c3ee | ||
|
6e9dd4d45f | ||
|
888d86d9fe | ||
|
67d60949b5 | ||
|
fcaf43b3eb | ||
|
49101565a3 | ||
255d7c7862 | |||
|
12dacb73b3 | ||
|
b127cc15e2 | ||
|
bc215ce32b | ||
|
996b0b2ae2 | ||
|
753cd06dd1 | ||
|
45d319834b | ||
|
11ed3c16eb | ||
|
edf858da29 | ||
|
e10b85b904 | ||
|
267554b252 | ||
|
233cdd9f80 | ||
|
15c959fd71 | ||
|
1378cf6ac7 | ||
|
a964e02612 | ||
|
a72e4ba833 | ||
|
75ec462efd | ||
|
adcd98fc31 | ||
d8cc99cea4 | |||
|
7671a56b6f | ||
|
8086dd5276 | ||
|
9479364a64 | ||
def2a99ed8 | |||
|
ac4a4d3b8e | ||
|
dd1c26e285 | ||
|
eba7869c4d | ||
|
efd5b34b13 | ||
|
2d472bd44e | ||
|
2042148d0f | ||
|
4a9d50e8a4 | ||
|
56b588293d | ||
59625c1581 | |||
|
bb3d5ac58b | ||
|
48861c3f80 | ||
|
8e2ebfc765 | ||
|
924b58beda | ||
|
bd8a4f16ea | ||
|
e41c42d573 | ||
|
c94231f9d9 | ||
|
99bb196e5c | ||
|
e5563d55d5 | ||
|
abe6ca42c7 | ||
|
40961a89df | ||
|
29518b9ea0 | ||
|
3793f67951 | ||
|
0251dea563 | ||
|
bc034cf4f4 | ||
|
3e513a1231 | ||
|
ead30d127a | ||
|
3b79c571fb | ||
|
ee8ea4f2c5 | ||
|
2c0cdfbd68 | ||
|
767fa5f6fb | ||
02f8a3bb31 | |||
|
ffecc9c873 | ||
0ec0021727 | |||
6b71de8265 | |||
43285b4bd5 | |||
2fbaa94109 | |||
ebf3e9635d | |||
79befb50f1 | |||
0adb530dc2 | |||
|
d7fd8395e5 | ||
|
75f9bc84f8 | ||
1c98676bee | |||
|
8a35a5e6cb | ||
df9b302f9d |
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 }}
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ AppDir
|
||||
NMReval*.zsync
|
||||
.idea
|
||||
*.zs-old
|
||||
docs
|
||||
|
@ -12,7 +12,9 @@ script:
|
||||
# Copy the python application code into the AppDir
|
||||
- cp bin/evaluate.py $TARGET_APPDIR/usr/bin/
|
||||
- cp -r src/* $TARGET_APPDIR/usr/src/
|
||||
- cp src/pkm.vogel.nmreval.desktop $TARGET_APPDIR/usr/share/applications
|
||||
- cp src/resources/pkm.vogel.nmreval.desktop $TARGET_APPDIR/usr/share/applications
|
||||
# set current date as version info
|
||||
- sed -i "s/CURRENT_DATE/$(date +'%Y-%m-%d')/" $TARGET_APPDIR/usr/src/nmreval/version.py
|
||||
|
||||
|
||||
AppDir:
|
||||
@ -30,35 +32,50 @@ AppDir:
|
||||
arch: amd64
|
||||
allow_unauthenticated: true
|
||||
sources:
|
||||
- sourceline: 'deb [arch=amd64] http://mirror.infra.pkm/ bullseye main contrib non-free'
|
||||
- sourceline: 'deb [arch=amd64] http://ftp.uni-mainz.de/debian bullseye main contrib non-free'
|
||||
|
||||
include:
|
||||
# for /usr/bin/env
|
||||
- coreutils
|
||||
- dash
|
||||
- zsync
|
||||
- hicolor-icon-theme
|
||||
# - coreutils
|
||||
# - dash
|
||||
# - zsync
|
||||
# - hicolor-icon-theme
|
||||
- libatlas3-base
|
||||
- python3.9-minimal
|
||||
- gnuplot-nox
|
||||
- python3-minimal
|
||||
- python3-numpy
|
||||
- python3-scipy
|
||||
# - python3-matplotlib
|
||||
# - python-matplotlib-data
|
||||
- python3-bsddb3
|
||||
- python3-h5py
|
||||
- python3-pyqt5
|
||||
- python3-pyqtgraph
|
||||
- python3-requests
|
||||
- python3-urllib3
|
||||
# - python3-tk
|
||||
exclude:
|
||||
# lots of qt stuff we do not use
|
||||
- libqt5designer5
|
||||
- libqt5help5
|
||||
- libqt5network5
|
||||
- libqt5sql5
|
||||
- libqt5test5
|
||||
- libqt5xml5
|
||||
- qtbase5-dev-tools
|
||||
- pyqt5-dev-tools
|
||||
- libavahi-client3
|
||||
- libavahi-common-data
|
||||
- libavahi-common3
|
||||
after_bundle: |
|
||||
echo "MONSTER SED FOLLOWING...(uncomment if needed for mpl-data)"
|
||||
#sed -i s,\'/usr/share/matplotlib/mpl-data\',"f\"\{os.environ.get\('APPDIR'\,'/'\)\}/usr/share/matplotlib/mpl-data\"", ${TARGET_APPDIR}/usr/lib/python3/dist-packages/matplotlib/__init__.py
|
||||
- libwacom2
|
||||
- libwacom-common
|
||||
|
||||
files:
|
||||
exclude:
|
||||
- usr/share/man
|
||||
- usr/share/doc/*/README.*
|
||||
- usr/share/doc/*/changelog.*
|
||||
- usr/share/doc/*/NEWS.*
|
||||
- usr/share/doc/*/TODO.*
|
||||
runtime:
|
||||
# if needed, apparently replaces hardcoded location with APPDIR location
|
||||
# path_mappings:
|
||||
# - /usr/share/matplotlib/mpl-data:$APPDIR/usr/share/matplotlib/mpl-data
|
||||
version: "continuous"
|
||||
env:
|
||||
PATH: '${APPDIR}/usr/bin:${PATH}'
|
||||
|
24
Makefile
24
Makefile
@ -5,30 +5,36 @@ PYUIC = pyuic5
|
||||
PYRCC = pyrcc5
|
||||
|
||||
#Directory with ui files
|
||||
RESOURCE_DIR = resources/_ui
|
||||
RESOURCE_DIR = src/resources/_ui
|
||||
|
||||
#Directory for compiled resources
|
||||
COMPILED_DIR = nmreval/gui_qt/_py
|
||||
PYQT_DIR = src/gui_qt/_py
|
||||
|
||||
#UI files to compile, uses every *.ui found in RESOURCE_DIR
|
||||
UI_FILES = $(foreach dir, $(RESOURCE_DIR), $(notdir $(wildcard $(dir)/*.ui)))
|
||||
COMPILED_UI = $(UI_FILES:%.ui=$(COMPILED_DIR)/%.py)
|
||||
PYQT_UI = $(UI_FILES:%.ui=$(PYQT_DIR)/%.py)
|
||||
|
||||
SVG_FILES = $(foreach dir, $(RCC_DIR), $(notdir $(wildcard $(dir)/*.svg)))
|
||||
PNG_FILES = $(SVG_FILES:%.svg=$(RCC_DIR)/%.png)
|
||||
|
||||
all : ui
|
||||
CC = gcc
|
||||
CFLAGS = -O2 -fPIC
|
||||
LDFLAGS = -shared
|
||||
|
||||
ui : $(COMPILED_UI)
|
||||
C_DIR = src/nmreval/clib
|
||||
|
||||
rcc: $(PNG_FILES)
|
||||
all : ui compile
|
||||
|
||||
ui : $(PYQT_UI)
|
||||
|
||||
rcc : $(PNG_FILES)
|
||||
|
||||
# only one C file at the moment
|
||||
compile : $(C_DIR)/integrate.c
|
||||
$(CC) $(LDFLAGS) $(CFLAGS) -o $(C_DIR)/integrate.so $<
|
||||
|
||||
$(COMPILED_DIR)/%.py : $(RESOURCE_DIR)/%.ui
|
||||
$(PYUIC) $< -o $@
|
||||
# replace import of ressource to correct path
|
||||
# @sed -i s/images_rc/nmrevalqt.$(COMPILED_DIR).images_rc/g $@
|
||||
# @sed -i /images_rc/d $@
|
||||
|
||||
$(RCC_DIR)/%.png : $(RCC_DIR)/%.svg
|
||||
convert -background none $< $@
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
import sys
|
||||
import pathlib
|
||||
import os
|
||||
sys.path.append(str(pathlib.Path(__file__).absolute().parent.parent / 'src'))
|
||||
|
||||
from nmreval.configs import check_for_config
|
||||
@ -16,12 +17,45 @@ from nmreval.lib.logger import handle_exception
|
||||
sys.excepthook = handle_exception
|
||||
|
||||
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.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()
|
||||
|
||||
sys.exit(app.exec())
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '_ui/apod_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/apod_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# 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
|
||||
@ -13,62 +14,223 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
class Ui_ApodEdit(object):
|
||||
def setupUi(self, ApodEdit):
|
||||
ApodEdit.setObjectName("ApodEdit")
|
||||
ApodEdit.resize(784, 484)
|
||||
ApodEdit.resize(1144, 655)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(ApodEdit.sizePolicy().hasHeightForWidth())
|
||||
ApodEdit.setSizePolicy(sizePolicy)
|
||||
self.gridLayout = QtWidgets.QGridLayout(ApodEdit)
|
||||
self.gridLayout.setContentsMargins(3, 3, 3, 3)
|
||||
self.gridLayout.setContentsMargins(9, 9, 9, 9)
|
||||
self.gridLayout.setSpacing(3)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.graphicsView = PlotWidget(ApodEdit)
|
||||
self.freq_graph = NMRPlotWidget(ApodEdit)
|
||||
self.freq_graph.setObjectName("freq_graph")
|
||||
self.gridLayout.addWidget(self.freq_graph, 2, 2, 1, 1)
|
||||
self.time_graph = NMRPlotWidget(ApodEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.graphicsView.sizePolicy().hasHeightForWidth())
|
||||
self.graphicsView.setSizePolicy(sizePolicy)
|
||||
self.graphicsView.setObjectName("graphicsView")
|
||||
self.gridLayout.addWidget(self.graphicsView, 2, 0, 1, 1)
|
||||
self.graphicsView_2 = PlotWidget(ApodEdit)
|
||||
self.graphicsView_2.setObjectName("graphicsView_2")
|
||||
self.gridLayout.addWidget(self.graphicsView_2, 2, 1, 1, 1)
|
||||
self.apodcombobox = QtWidgets.QComboBox(ApodEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHeightForWidth(self.time_graph.sizePolicy().hasHeightForWidth())
|
||||
self.time_graph.setSizePolicy(sizePolicy)
|
||||
self.time_graph.setObjectName("time_graph")
|
||||
self.gridLayout.addWidget(self.time_graph, 2, 1, 1, 1)
|
||||
self.widget = QtWidgets.QWidget(ApodEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.apodcombobox.sizePolicy().hasHeightForWidth())
|
||||
self.apodcombobox.setSizePolicy(sizePolicy)
|
||||
sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth())
|
||||
self.widget.setSizePolicy(sizePolicy)
|
||||
self.widget.setObjectName("widget")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.baseline_box = QtWidgets.QCheckBox(self.widget)
|
||||
self.baseline_box.setObjectName("baseline_box")
|
||||
self.verticalLayout.addWidget(self.baseline_box)
|
||||
self.shift_box = QtWidgets.QGroupBox(self.widget)
|
||||
self.shift_box.setFlat(True)
|
||||
self.shift_box.setCheckable(True)
|
||||
self.shift_box.setChecked(False)
|
||||
self.shift_box.setObjectName("shift_box")
|
||||
self.gridLayout_4 = QtWidgets.QGridLayout(self.shift_box)
|
||||
self.gridLayout_4.setContentsMargins(3, 3, 3, 3)
|
||||
self.gridLayout_4.setSpacing(3)
|
||||
self.gridLayout_4.setObjectName("gridLayout_4")
|
||||
self.ls_lineedit = QtWidgets.QLineEdit(self.shift_box)
|
||||
self.ls_lineedit.setObjectName("ls_lineedit")
|
||||
self.gridLayout_4.addWidget(self.ls_lineedit, 1, 1, 1, 1)
|
||||
self.ls_spinbox = QtWidgets.QSpinBox(self.shift_box)
|
||||
self.ls_spinbox.setMaximum(999999)
|
||||
self.ls_spinbox.setObjectName("ls_spinbox")
|
||||
self.gridLayout_4.addWidget(self.ls_spinbox, 0, 1, 1, 1)
|
||||
self.ls_combobox = QtWidgets.QComboBox(self.shift_box)
|
||||
self.ls_combobox.setObjectName("ls_combobox")
|
||||
self.ls_combobox.addItem("")
|
||||
self.ls_combobox.addItem("")
|
||||
self.gridLayout_4.addWidget(self.ls_combobox, 0, 0, 2, 1)
|
||||
self.verticalLayout.addWidget(self.shift_box)
|
||||
self.apod_box = QtWidgets.QGroupBox(self.widget)
|
||||
self.apod_box.setFlat(True)
|
||||
self.apod_box.setCheckable(True)
|
||||
self.apod_box.setChecked(False)
|
||||
self.apod_box.setObjectName("apod_box")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.apod_box)
|
||||
self.verticalLayout_2.setContentsMargins(3, 3, 3, 3)
|
||||
self.verticalLayout_2.setSpacing(3)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.apodcombobox = QtWidgets.QComboBox(self.apod_box)
|
||||
self.apodcombobox.setObjectName("apodcombobox")
|
||||
self.gridLayout.addWidget(self.apodcombobox, 0, 0, 1, 1)
|
||||
self.verticalLayout_2.addWidget(self.apodcombobox)
|
||||
self.eqn_label = QtWidgets.QLabel(self.apod_box)
|
||||
self.eqn_label.setIndent(3)
|
||||
self.eqn_label.setObjectName("eqn_label")
|
||||
self.verticalLayout_2.addWidget(self.eqn_label)
|
||||
self.widget_layout = QtWidgets.QHBoxLayout()
|
||||
self.widget_layout.setContentsMargins(-1, 6, -1, -1)
|
||||
self.widget_layout.setSpacing(20)
|
||||
self.widget_layout.setObjectName("widget_layout")
|
||||
self.gridLayout.addLayout(self.widget_layout, 1, 0, 1, 2)
|
||||
self.verticalLayout_2.addLayout(self.widget_layout)
|
||||
self.verticalLayout.addWidget(self.apod_box)
|
||||
self.zerofill_box = QtWidgets.QGroupBox(self.widget)
|
||||
self.zerofill_box.setFlat(True)
|
||||
self.zerofill_box.setCheckable(True)
|
||||
self.zerofill_box.setChecked(False)
|
||||
self.zerofill_box.setObjectName("zerofill_box")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.zerofill_box)
|
||||
self.horizontalLayout.setContentsMargins(3, 3, 3, 3)
|
||||
self.horizontalLayout.setSpacing(3)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.label = QtWidgets.QLabel(self.zerofill_box)
|
||||
self.label.setObjectName("label")
|
||||
self.horizontalLayout.addWidget(self.label)
|
||||
self.zf_spinbox = QtWidgets.QSpinBox(self.zerofill_box)
|
||||
self.zf_spinbox.setMinimum(1)
|
||||
self.zf_spinbox.setMaximum(3)
|
||||
self.zf_spinbox.setObjectName("zf_spinbox")
|
||||
self.horizontalLayout.addWidget(self.zf_spinbox)
|
||||
self.verticalLayout.addWidget(self.zerofill_box)
|
||||
self.phase_box = QtWidgets.QGroupBox(self.widget)
|
||||
self.phase_box.setFlat(True)
|
||||
self.phase_box.setCheckable(True)
|
||||
self.phase_box.setChecked(False)
|
||||
self.phase_box.setObjectName("phase_box")
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(self.phase_box)
|
||||
self.gridLayout_2.setContentsMargins(3, 3, 3, 3)
|
||||
self.gridLayout_2.setSpacing(3)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.label_3 = QtWidgets.QLabel(self.phase_box)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.gridLayout_2.addWidget(self.label_3, 1, 0, 1, 1)
|
||||
self.label_4 = QtWidgets.QLabel(self.phase_box)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.gridLayout_2.addWidget(self.label_4, 2, 0, 1, 1)
|
||||
self.ph0_spinbox = QtWidgets.QDoubleSpinBox(self.phase_box)
|
||||
self.ph0_spinbox.setWrapping(True)
|
||||
self.ph0_spinbox.setDecimals(1)
|
||||
self.ph0_spinbox.setMinimum(-180.0)
|
||||
self.ph0_spinbox.setMaximum(180.0)
|
||||
self.ph0_spinbox.setSingleStep(0.5)
|
||||
self.ph0_spinbox.setObjectName("ph0_spinbox")
|
||||
self.gridLayout_2.addWidget(self.ph0_spinbox, 0, 1, 1, 1)
|
||||
self.pivot_lineedit = QtWidgets.QLineEdit(self.phase_box)
|
||||
self.pivot_lineedit.setObjectName("pivot_lineedit")
|
||||
self.gridLayout_2.addWidget(self.pivot_lineedit, 2, 1, 1, 1)
|
||||
self.label_2 = QtWidgets.QLabel(self.phase_box)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 1)
|
||||
self.ph1_spinbox = QtWidgets.QDoubleSpinBox(self.phase_box)
|
||||
self.ph1_spinbox.setWrapping(True)
|
||||
self.ph1_spinbox.setDecimals(2)
|
||||
self.ph1_spinbox.setMinimum(-720.0)
|
||||
self.ph1_spinbox.setMaximum(720.0)
|
||||
self.ph1_spinbox.setSingleStep(0.05)
|
||||
self.ph1_spinbox.setObjectName("ph1_spinbox")
|
||||
self.gridLayout_2.addWidget(self.ph1_spinbox, 1, 1, 1, 1)
|
||||
self.verticalLayout.addWidget(self.phase_box)
|
||||
self.ft_box = QtWidgets.QGroupBox(self.widget)
|
||||
self.ft_box.setCheckable(True)
|
||||
self.ft_box.setChecked(False)
|
||||
self.ft_box.setObjectName("ft_box")
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.ft_box)
|
||||
self.verticalLayout_3.setContentsMargins(3, 3, 3, 3)
|
||||
self.verticalLayout_3.setSpacing(3)
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.phase_before_button = QtWidgets.QRadioButton(self.ft_box)
|
||||
self.phase_before_button.setChecked(True)
|
||||
self.phase_before_button.setObjectName("phase_before_button")
|
||||
self.buttonGroup = QtWidgets.QButtonGroup(ApodEdit)
|
||||
self.buttonGroup.setObjectName("buttonGroup")
|
||||
self.buttonGroup.addButton(self.phase_before_button)
|
||||
self.verticalLayout_3.addWidget(self.phase_before_button)
|
||||
self.phase_after_button = QtWidgets.QRadioButton(self.ft_box)
|
||||
self.phase_after_button.setObjectName("phase_after_button")
|
||||
self.buttonGroup.addButton(self.phase_after_button)
|
||||
self.verticalLayout_3.addWidget(self.phase_after_button)
|
||||
self.verticalLayout.addWidget(self.ft_box)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout.addItem(spacerItem)
|
||||
self.gridLayout.addWidget(self.widget, 2, 0, 1, 1)
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(ApodEdit)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.gridLayout.addWidget(self.buttonBox, 4, 0, 1, 2)
|
||||
self.eqn_label = QtWidgets.QLabel(ApodEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.eqn_label.sizePolicy().hasHeightForWidth())
|
||||
self.eqn_label.setSizePolicy(sizePolicy)
|
||||
self.eqn_label.setIndent(3)
|
||||
self.eqn_label.setObjectName("eqn_label")
|
||||
self.gridLayout.addWidget(self.eqn_label, 0, 1, 1, 1)
|
||||
self.gridLayout.addWidget(self.buttonBox, 4, 1, 1, 2)
|
||||
self.log_freq_widget = QtWidgets.QWidget(ApodEdit)
|
||||
self.log_freq_widget.setObjectName("log_freq_widget")
|
||||
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.log_freq_widget)
|
||||
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
||||
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout_3.addItem(spacerItem1)
|
||||
self.logx_freq = QtWidgets.QCheckBox(self.log_freq_widget)
|
||||
self.logx_freq.setObjectName("logx_freq")
|
||||
self.horizontalLayout_3.addWidget(self.logx_freq)
|
||||
self.logy_freq = QtWidgets.QCheckBox(self.log_freq_widget)
|
||||
self.logy_freq.setObjectName("logy_freq")
|
||||
self.horizontalLayout_3.addWidget(self.logy_freq)
|
||||
self.gridLayout.addWidget(self.log_freq_widget, 3, 2, 1, 1)
|
||||
self.logtime_widget = QtWidgets.QWidget(ApodEdit)
|
||||
self.logtime_widget.setObjectName("logtime_widget")
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.logtime_widget)
|
||||
self.horizontalLayout_2.setContentsMargins(-1, 1, -1, -1)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout_2.addItem(spacerItem2)
|
||||
self.logx_time = QtWidgets.QCheckBox(self.logtime_widget)
|
||||
self.logx_time.setObjectName("logx_time")
|
||||
self.horizontalLayout_2.addWidget(self.logx_time)
|
||||
self.logy_time = QtWidgets.QCheckBox(self.logtime_widget)
|
||||
self.logy_time.setObjectName("logy_time")
|
||||
self.horizontalLayout_2.addWidget(self.logy_time)
|
||||
self.gridLayout.addWidget(self.logtime_widget, 3, 1, 1, 1)
|
||||
|
||||
self.retranslateUi(ApodEdit)
|
||||
self.buttonBox.accepted.connect(ApodEdit.accept)
|
||||
self.buttonBox.rejected.connect(ApodEdit.close)
|
||||
self.buttonBox.accepted.connect(ApodEdit.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(ApodEdit.close) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(ApodEdit)
|
||||
|
||||
def retranslateUi(self, ApodEdit):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
ApodEdit.setWindowTitle(_translate("ApodEdit", "Apodization"))
|
||||
self.baseline_box.setText(_translate("ApodEdit", "Baseline"))
|
||||
self.shift_box.setTitle(_translate("ApodEdit", "Shift"))
|
||||
self.ls_lineedit.setText(_translate("ApodEdit", "0"))
|
||||
self.ls_combobox.setItemText(0, _translate("ApodEdit", "Points"))
|
||||
self.ls_combobox.setItemText(1, _translate("ApodEdit", "Seconds"))
|
||||
self.apod_box.setTitle(_translate("ApodEdit", "Apodization"))
|
||||
self.eqn_label.setText(_translate("ApodEdit", "TextLabel"))
|
||||
from pyqtgraph import PlotWidget
|
||||
self.zerofill_box.setTitle(_translate("ApodEdit", "Zero fill"))
|
||||
self.label.setText(_translate("ApodEdit", "Double length"))
|
||||
self.zf_spinbox.setSuffix(_translate("ApodEdit", "x"))
|
||||
self.phase_box.setTitle(_translate("ApodEdit", "Phase correction"))
|
||||
self.label_3.setText(_translate("ApodEdit", "Phase 1"))
|
||||
self.label_4.setText(_translate("ApodEdit", "Pivot"))
|
||||
self.pivot_lineedit.setText(_translate("ApodEdit", "0"))
|
||||
self.label_2.setText(_translate("ApodEdit", "Phase 0"))
|
||||
self.ft_box.setTitle(_translate("ApodEdit", "Fourier transform"))
|
||||
self.phase_before_button.setText(_translate("ApodEdit", "before phase correction"))
|
||||
self.phase_after_button.setText(_translate("ApodEdit", "after phase correction"))
|
||||
self.logx_freq.setText(_translate("ApodEdit", "Log X"))
|
||||
self.logy_freq.setText(_translate("ApodEdit", "Log Y"))
|
||||
self.logx_time.setText(_translate("ApodEdit", "Log X"))
|
||||
self.logy_time.setText(_translate("ApodEdit", "Log Y"))
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/asciidialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.7
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
|
||||
# run again. Do not edit this file unless you know what you are doing.
|
||||
@ -14,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
class Ui_ascii_reader(object):
|
||||
def setupUi(self, ascii_reader):
|
||||
ascii_reader.setObjectName("ascii_reader")
|
||||
ascii_reader.resize(627, 703)
|
||||
ascii_reader.resize(665, 904)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(ascii_reader)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.tabWidget = QtWidgets.QTabWidget(ascii_reader)
|
||||
@ -28,92 +28,25 @@ class Ui_ascii_reader(object):
|
||||
self.header_widget.setObjectName("header_widget")
|
||||
self.verticalLayout_3.addWidget(self.header_widget)
|
||||
self.groupBox = QtWidgets.QGroupBox(self.tabWidgetPage1)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.groupBox.sizePolicy().hasHeightForWidth())
|
||||
self.groupBox.setSizePolicy(sizePolicy)
|
||||
self.groupBox.setObjectName("groupBox")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.groupBox)
|
||||
self.gridLayout.setContentsMargins(3, 3, 3, 3)
|
||||
self.gridLayout.setHorizontalSpacing(9)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.FID_radioButton = QtWidgets.QRadioButton(self.groupBox)
|
||||
self.FID_radioButton.setAutoExclusive(True)
|
||||
self.FID_radioButton.setObjectName("FID_radioButton")
|
||||
self.buttonGroup = QtWidgets.QButtonGroup(ascii_reader)
|
||||
self.buttonGroup.setObjectName("buttonGroup")
|
||||
self.buttonGroup.addButton(self.FID_radioButton)
|
||||
self.gridLayout.addWidget(self.FID_radioButton, 2, 1, 1, 1)
|
||||
self.x_lineedit = QtWidgets.QLineEdit(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.x_lineedit.sizePolicy().hasHeightForWidth())
|
||||
self.x_lineedit.setSizePolicy(sizePolicy)
|
||||
self.x_lineedit.setInputMethodHints(QtCore.Qt.ImhFormattedNumbersOnly|QtCore.Qt.ImhPreferNumbers)
|
||||
self.x_lineedit.setObjectName("x_lineedit")
|
||||
self.gridLayout.addWidget(self.x_lineedit, 1, 3, 1, 1)
|
||||
self.y_label = QtWidgets.QLabel(self.groupBox)
|
||||
self.y_label.setObjectName("y_label")
|
||||
self.gridLayout.addWidget(self.y_label, 2, 2, 1, 1)
|
||||
self.pts_radioButton = QtWidgets.QRadioButton(self.groupBox)
|
||||
self.pts_radioButton.setChecked(True)
|
||||
self.pts_radioButton.setAutoExclusive(True)
|
||||
self.pts_radioButton.setObjectName("pts_radioButton")
|
||||
self.buttonGroup.addButton(self.pts_radioButton)
|
||||
self.gridLayout.addWidget(self.pts_radioButton, 1, 1, 1, 1)
|
||||
self.deltay_lineEdit = QtWidgets.QLineEdit(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.deltay_lineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.deltay_lineEdit.setSizePolicy(sizePolicy)
|
||||
self.deltay_lineEdit.setObjectName("deltay_lineEdit")
|
||||
self.gridLayout.addWidget(self.deltay_lineEdit, 3, 3, 1, 1)
|
||||
self.label_5 = QtWidgets.QLabel(self.groupBox)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.gridLayout.addWidget(self.label_5, 3, 2, 1, 1)
|
||||
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.groupBox)
|
||||
self.horizontalLayout_4.setContentsMargins(3, 3, 3, 3)
|
||||
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
|
||||
self.verticalLayout_6 = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
||||
self.column_checkBox = QtWidgets.QCheckBox(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.column_checkBox.sizePolicy().hasHeightForWidth())
|
||||
self.column_checkBox.setSizePolicy(sizePolicy)
|
||||
self.column_checkBox.setObjectName("column_checkBox")
|
||||
self.gridLayout.addWidget(self.column_checkBox, 0, 0, 1, 1)
|
||||
self.label = QtWidgets.QLabel(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
|
||||
self.label.setSizePolicy(sizePolicy)
|
||||
self.label.setObjectName("label")
|
||||
self.gridLayout.addWidget(self.label, 0, 1, 1, 1)
|
||||
self.label_7 = QtWidgets.QLabel(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.label_7.sizePolicy().hasHeightForWidth())
|
||||
self.label_7.setSizePolicy(sizePolicy)
|
||||
self.label_7.setObjectName("label_7")
|
||||
self.gridLayout.addWidget(self.label_7, 0, 2, 1, 2)
|
||||
self.y_lineedit = QtWidgets.QLineEdit(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.y_lineedit.sizePolicy().hasHeightForWidth())
|
||||
self.y_lineedit.setSizePolicy(sizePolicy)
|
||||
self.y_lineedit.setInputMethodHints(QtCore.Qt.ImhFormattedNumbersOnly|QtCore.Qt.ImhPreferNumbers)
|
||||
self.y_lineedit.setObjectName("y_lineedit")
|
||||
self.gridLayout.addWidget(self.y_lineedit, 2, 3, 1, 1)
|
||||
self.spectrum_radioButton = QtWidgets.QRadioButton(self.groupBox)
|
||||
self.spectrum_radioButton.setObjectName("spectrum_radioButton")
|
||||
self.buttonGroup.addButton(self.spectrum_radioButton)
|
||||
self.gridLayout.addWidget(self.spectrum_radioButton, 3, 1, 1, 1)
|
||||
self.x_label = QtWidgets.QLabel(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.x_label.sizePolicy().hasHeightForWidth())
|
||||
self.x_label.setSizePolicy(sizePolicy)
|
||||
self.x_label.setObjectName("x_label")
|
||||
self.gridLayout.addWidget(self.x_label, 1, 2, 1, 1)
|
||||
self.verticalLayout_6.addWidget(self.column_checkBox)
|
||||
self.line_spinBox = QtWidgets.QSpinBox(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
@ -122,17 +55,158 @@ class Ui_ascii_reader(object):
|
||||
self.line_spinBox.setSizePolicy(sizePolicy)
|
||||
self.line_spinBox.setMinimum(1)
|
||||
self.line_spinBox.setObjectName("line_spinBox")
|
||||
self.gridLayout.addWidget(self.line_spinBox, 1, 0, 1, 1)
|
||||
self.verticalLayout_6.addWidget(self.line_spinBox)
|
||||
self.label_6 = QtWidgets.QLabel(self.groupBox)
|
||||
self.label_6.setObjectName("label_6")
|
||||
self.verticalLayout_6.addWidget(self.label_6)
|
||||
self.preview_spinBox = QtWidgets.QSpinBox(self.groupBox)
|
||||
self.preview_spinBox.setMinimum(1)
|
||||
self.preview_spinBox.setProperty("value", 10)
|
||||
self.preview_spinBox.setObjectName("preview_spinBox")
|
||||
self.gridLayout.addWidget(self.preview_spinBox, 3, 0, 1, 1)
|
||||
self.label_6 = QtWidgets.QLabel(self.groupBox)
|
||||
self.label_6.setObjectName("label_6")
|
||||
self.gridLayout.addWidget(self.label_6, 2, 0, 1, 1)
|
||||
self.verticalLayout_6.addWidget(self.preview_spinBox)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_6.addItem(spacerItem)
|
||||
self.horizontalLayout_4.addLayout(self.verticalLayout_6)
|
||||
self.verticalLayout_5 = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout_5.setObjectName("verticalLayout_5")
|
||||
self.label = QtWidgets.QLabel(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
|
||||
self.label.setSizePolicy(sizePolicy)
|
||||
self.label.setObjectName("label")
|
||||
self.verticalLayout_5.addWidget(self.label)
|
||||
self.pts_radioButton = QtWidgets.QRadioButton(self.groupBox)
|
||||
self.pts_radioButton.setChecked(True)
|
||||
self.pts_radioButton.setAutoExclusive(True)
|
||||
self.pts_radioButton.setObjectName("pts_radioButton")
|
||||
self.buttonGroup = QtWidgets.QButtonGroup(ascii_reader)
|
||||
self.buttonGroup.setObjectName("buttonGroup")
|
||||
self.buttonGroup.addButton(self.pts_radioButton)
|
||||
self.verticalLayout_5.addWidget(self.pts_radioButton)
|
||||
self.dsc_radioButton = QtWidgets.QRadioButton(self.groupBox)
|
||||
self.dsc_radioButton.setObjectName("dsc_radioButton")
|
||||
self.buttonGroup.addButton(self.dsc_radioButton)
|
||||
self.verticalLayout_5.addWidget(self.dsc_radioButton)
|
||||
self.FID_radioButton = QtWidgets.QRadioButton(self.groupBox)
|
||||
self.FID_radioButton.setAutoExclusive(True)
|
||||
self.FID_radioButton.setObjectName("FID_radioButton")
|
||||
self.buttonGroup.addButton(self.FID_radioButton)
|
||||
self.verticalLayout_5.addWidget(self.FID_radioButton)
|
||||
self.spectrum_radioButton = QtWidgets.QRadioButton(self.groupBox)
|
||||
self.spectrum_radioButton.setObjectName("spectrum_radioButton")
|
||||
self.buttonGroup.addButton(self.spectrum_radioButton)
|
||||
self.verticalLayout_5.addWidget(self.spectrum_radioButton)
|
||||
self.bds_radioButton = QtWidgets.QRadioButton(self.groupBox)
|
||||
self.bds_radioButton.setObjectName("bds_radioButton")
|
||||
self.buttonGroup.addButton(self.bds_radioButton)
|
||||
self.verticalLayout_5.addWidget(self.bds_radioButton)
|
||||
self.horizontalLayout_4.addLayout(self.verticalLayout_5)
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout()
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.deltay_lineEdit = QtWidgets.QLineEdit(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.deltay_lineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.deltay_lineEdit.setSizePolicy(sizePolicy)
|
||||
self.deltay_lineEdit.setObjectName("deltay_lineEdit")
|
||||
self.gridLayout_2.addWidget(self.deltay_lineEdit, 3, 1, 1, 1)
|
||||
self.label_7 = QtWidgets.QLabel(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.label_7.sizePolicy().hasHeightForWidth())
|
||||
self.label_7.setSizePolicy(sizePolicy)
|
||||
self.label_7.setObjectName("label_7")
|
||||
self.gridLayout_2.addWidget(self.label_7, 0, 0, 1, 2)
|
||||
self.y_lineedit = QtWidgets.QLineEdit(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.y_lineedit.sizePolicy().hasHeightForWidth())
|
||||
self.y_lineedit.setSizePolicy(sizePolicy)
|
||||
self.y_lineedit.setInputMethodHints(QtCore.Qt.ImhFormattedNumbersOnly|QtCore.Qt.ImhPreferNumbers)
|
||||
self.y_lineedit.setObjectName("y_lineedit")
|
||||
self.gridLayout_2.addWidget(self.y_lineedit, 2, 1, 1, 1)
|
||||
self.y_label = QtWidgets.QLabel(self.groupBox)
|
||||
self.y_label.setObjectName("y_label")
|
||||
self.gridLayout_2.addWidget(self.y_label, 2, 0, 1, 1)
|
||||
self.x_lineedit = QtWidgets.QLineEdit(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.x_lineedit.sizePolicy().hasHeightForWidth())
|
||||
self.x_lineedit.setSizePolicy(sizePolicy)
|
||||
self.x_lineedit.setInputMethodHints(QtCore.Qt.ImhFormattedNumbersOnly|QtCore.Qt.ImhPreferNumbers)
|
||||
self.x_lineedit.setObjectName("x_lineedit")
|
||||
self.gridLayout_2.addWidget(self.x_lineedit, 1, 1, 1, 1)
|
||||
self.label_5 = QtWidgets.QLabel(self.groupBox)
|
||||
self.label_5.setObjectName("label_5")
|
||||
self.gridLayout_2.addWidget(self.label_5, 3, 0, 1, 1)
|
||||
self.x_label = QtWidgets.QLabel(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.x_label.sizePolicy().hasHeightForWidth())
|
||||
self.x_label.setSizePolicy(sizePolicy)
|
||||
self.x_label.setObjectName("x_label")
|
||||
self.gridLayout_2.addWidget(self.x_label, 1, 0, 1, 1)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_2.addItem(spacerItem1, 4, 1, 1, 1)
|
||||
self.horizontalLayout_4.addLayout(self.gridLayout_2)
|
||||
self.verticalLayout_3.addWidget(self.groupBox)
|
||||
self.dsdfsf = QtWidgets.QLabel(self.tabWidgetPage1)
|
||||
self.dsdfsf.setObjectName("dsdfsf")
|
||||
self.verticalLayout_3.addWidget(self.dsdfsf)
|
||||
self.gridLayout = QtWidgets.QGridLayout()
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.re_match_index = QtWidgets.QSpinBox(self.tabWidgetPage1)
|
||||
self.re_match_index.setMinimum(1)
|
||||
self.re_match_index.setObjectName("re_match_index")
|
||||
self.gridLayout.addWidget(self.re_match_index, 1, 3, 1, 1)
|
||||
self.label_9 = QtWidgets.QLabel(self.tabWidgetPage1)
|
||||
self.label_9.setObjectName("label_9")
|
||||
self.gridLayout.addWidget(self.label_9, 1, 2, 1, 1)
|
||||
self.regex_input = QtWidgets.QLineEdit(self.tabWidgetPage1)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.regex_input.sizePolicy().hasHeightForWidth())
|
||||
self.regex_input.setSizePolicy(sizePolicy)
|
||||
self.regex_input.setObjectName("regex_input")
|
||||
self.gridLayout.addWidget(self.regex_input, 1, 1, 1, 1)
|
||||
self.re_button = QtWidgets.QRadioButton(self.tabWidgetPage1)
|
||||
self.re_button.setChecked(True)
|
||||
self.re_button.setObjectName("re_button")
|
||||
self.buttonGroup_2 = QtWidgets.QButtonGroup(ascii_reader)
|
||||
self.buttonGroup_2.setObjectName("buttonGroup_2")
|
||||
self.buttonGroup_2.addButton(self.re_button)
|
||||
self.gridLayout.addWidget(self.re_button, 1, 0, 1, 1)
|
||||
self.custom_input = QtWidgets.QLineEdit(self.tabWidgetPage1)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.custom_input.sizePolicy().hasHeightForWidth())
|
||||
self.custom_input.setSizePolicy(sizePolicy)
|
||||
self.custom_input.setObjectName("custom_input")
|
||||
self.gridLayout.addWidget(self.custom_input, 2, 1, 1, 1)
|
||||
self.custom_button = QtWidgets.QRadioButton(self.tabWidgetPage1)
|
||||
self.custom_button.setObjectName("custom_button")
|
||||
self.buttonGroup_2.addButton(self.custom_button)
|
||||
self.gridLayout.addWidget(self.custom_button, 2, 0, 1, 1)
|
||||
self.label_8 = QtWidgets.QLabel(self.tabWidgetPage1)
|
||||
self.label_8.setWordWrap(True)
|
||||
self.label_8.setObjectName("label_8")
|
||||
self.gridLayout.addWidget(self.label_8, 0, 0, 1, 4)
|
||||
self.verticalLayout_3.addLayout(self.gridLayout)
|
||||
self.groupBox_2 = QtWidgets.QGroupBox(self.tabWidgetPage1)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.groupBox_2.sizePolicy().hasHeightForWidth())
|
||||
self.groupBox_2.setSizePolicy(sizePolicy)
|
||||
self.groupBox_2.setObjectName("groupBox_2")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox_2)
|
||||
self.verticalLayout_2.setContentsMargins(3, 3, 3, 3)
|
||||
@ -215,24 +289,19 @@ class Ui_ascii_reader(object):
|
||||
self.pushButton.setSizePolicy(sizePolicy)
|
||||
self.pushButton.setObjectName("pushButton")
|
||||
self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.pushButton)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.formLayout.setItem(6, QtWidgets.QFormLayout.FieldRole, spacerItem)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.formLayout.setItem(6, QtWidgets.QFormLayout.FieldRole, spacerItem2)
|
||||
self.horizontalLayout_3.addLayout(self.formLayout)
|
||||
self.tabWidget.addTab(self.tabWidgetPage2, "")
|
||||
self.verticalLayout.addWidget(self.tabWidget)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem1)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setContentsMargins(-1, 0, -1, -1)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout_2.addItem(spacerItem3)
|
||||
self.skippy_checkbox = QtWidgets.QCheckBox(ascii_reader)
|
||||
self.skippy_checkbox.setObjectName("skippy_checkbox")
|
||||
self.horizontalLayout_2.addWidget(self.skippy_checkbox)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout_2.addItem(spacerItem2)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
||||
self.buttonbox = QtWidgets.QDialogButtonBox(ascii_reader)
|
||||
self.buttonbox.setStandardButtons(QtWidgets.QDialogButtonBox.Apply|QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
@ -247,14 +316,20 @@ class Ui_ascii_reader(object):
|
||||
ascii_reader.setTabOrder(self.column_checkBox, self.line_spinBox)
|
||||
ascii_reader.setTabOrder(self.line_spinBox, self.preview_spinBox)
|
||||
ascii_reader.setTabOrder(self.preview_spinBox, self.pts_radioButton)
|
||||
ascii_reader.setTabOrder(self.pts_radioButton, self.FID_radioButton)
|
||||
ascii_reader.setTabOrder(self.pts_radioButton, self.dsc_radioButton)
|
||||
ascii_reader.setTabOrder(self.dsc_radioButton, self.FID_radioButton)
|
||||
ascii_reader.setTabOrder(self.FID_radioButton, self.spectrum_radioButton)
|
||||
ascii_reader.setTabOrder(self.spectrum_radioButton, self.x_lineedit)
|
||||
ascii_reader.setTabOrder(self.spectrum_radioButton, self.bds_radioButton)
|
||||
ascii_reader.setTabOrder(self.bds_radioButton, self.x_lineedit)
|
||||
ascii_reader.setTabOrder(self.x_lineedit, self.y_lineedit)
|
||||
ascii_reader.setTabOrder(self.y_lineedit, self.deltay_lineEdit)
|
||||
ascii_reader.setTabOrder(self.deltay_lineEdit, self.ascii_table)
|
||||
ascii_reader.setTabOrder(self.ascii_table, self.skippy_checkbox)
|
||||
ascii_reader.setTabOrder(self.skippy_checkbox, self.delay_textfield)
|
||||
ascii_reader.setTabOrder(self.deltay_lineEdit, self.re_button)
|
||||
ascii_reader.setTabOrder(self.re_button, self.regex_input)
|
||||
ascii_reader.setTabOrder(self.regex_input, self.re_match_index)
|
||||
ascii_reader.setTabOrder(self.re_match_index, self.custom_button)
|
||||
ascii_reader.setTabOrder(self.custom_button, self.custom_input)
|
||||
ascii_reader.setTabOrder(self.custom_input, self.ascii_table)
|
||||
ascii_reader.setTabOrder(self.ascii_table, self.delay_textfield)
|
||||
ascii_reader.setTabOrder(self.delay_textfield, self.delay_lineedit)
|
||||
ascii_reader.setTabOrder(self.delay_lineedit, self.start_lineedit)
|
||||
ascii_reader.setTabOrder(self.start_lineedit, self.end_lineedit)
|
||||
@ -262,24 +337,33 @@ class Ui_ascii_reader(object):
|
||||
ascii_reader.setTabOrder(self.log_checkBox, self.staggered_checkBox)
|
||||
ascii_reader.setTabOrder(self.staggered_checkBox, self.stag_lineEdit)
|
||||
ascii_reader.setTabOrder(self.stag_lineEdit, self.pushButton)
|
||||
ascii_reader.setTabOrder(self.pushButton, self.skippy_checkbox)
|
||||
|
||||
def retranslateUi(self, ascii_reader):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
ascii_reader.setWindowTitle(_translate("ascii_reader", "Read text file"))
|
||||
self.groupBox.setTitle(_translate("ascii_reader", "Options"))
|
||||
self.FID_radioButton.setText(_translate("ascii_reader", "FID"))
|
||||
self.x_lineedit.setToolTip(_translate("ascii_reader", "<html><head/><body><p>Specify which column is used as x-value.</p></body></html>"))
|
||||
self.y_label.setText(_translate("ascii_reader", "y"))
|
||||
self.pts_radioButton.setText(_translate("ascii_reader", "Points"))
|
||||
self.label_5.setText(_translate("ascii_reader", "<html><head/><body><p>Δy</p></body></html>"))
|
||||
self.column_checkBox.setText(_translate("ascii_reader", "Column name"))
|
||||
self.label.setText(_translate("ascii_reader", "Import as"))
|
||||
self.label_7.setText(_translate("ascii_reader", "Use columns as"))
|
||||
self.y_lineedit.setToolTip(_translate("ascii_reader", "<html><head/><body><p>Specify which columns are read for y-values. (\'Points\': Every number creates a new data set;\'FID\'/\'Spectrum\': Numbers at even positions are used for real parts, at odd positions for imaginary parts.)</p></body></html>"))
|
||||
self.spectrum_radioButton.setText(_translate("ascii_reader", "Spectrum"))
|
||||
self.x_label.setText(_translate("ascii_reader", "x"))
|
||||
self.line_spinBox.setPrefix(_translate("ascii_reader", "header line "))
|
||||
self.label_6.setText(_translate("ascii_reader", "Preview length"))
|
||||
self.label.setText(_translate("ascii_reader", "Import as"))
|
||||
self.pts_radioButton.setText(_translate("ascii_reader", "Points"))
|
||||
self.dsc_radioButton.setText(_translate("ascii_reader", "DSC"))
|
||||
self.FID_radioButton.setText(_translate("ascii_reader", "FID"))
|
||||
self.spectrum_radioButton.setText(_translate("ascii_reader", "Spectrum"))
|
||||
self.bds_radioButton.setText(_translate("ascii_reader", "BDS"))
|
||||
self.label_7.setText(_translate("ascii_reader", "Use columns as"))
|
||||
self.y_lineedit.setToolTip(_translate("ascii_reader", "<html><head/><body><p>Specify which columns are used for y values.</p><p>- \'Points\': Every number creates a new data set;<br/>- \'FID\'/\'Spectrum\': Numbers at even positions are used for real parts, at odd positions for imaginary parts.</p></body></html>"))
|
||||
self.y_label.setText(_translate("ascii_reader", "y"))
|
||||
self.x_lineedit.setToolTip(_translate("ascii_reader", "<html><head/><body><p>Specify which column is used for x values, write <span style=\" font-style:italic;\">index</span> to use row numbers (starting with 0). </p></body></html>"))
|
||||
self.label_5.setText(_translate("ascii_reader", "<html><head/><body><p>Δy</p></body></html>"))
|
||||
self.x_label.setText(_translate("ascii_reader", "x"))
|
||||
self.dsdfsf.setText(_translate("ascii_reader", "Numerical value"))
|
||||
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.re_button.setText(_translate("ascii_reader", "Regex"))
|
||||
self.custom_button.setText(_translate("ascii_reader", "Custom value"))
|
||||
self.label_8.setText(_translate("ascii_reader", "Filename"))
|
||||
self.groupBox_2.setTitle(_translate("ascii_reader", "Preview"))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tabWidgetPage1), _translate("ascii_reader", "Data"))
|
||||
self.label_2.setText(_translate("ascii_reader", "Number of delays"))
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '_ui/baseline_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/baseline_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# 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
|
||||
@ -44,7 +45,7 @@ class Ui_SignalEdit(object):
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 3)
|
||||
self.graphicsView = PlotWidget(SignalEdit)
|
||||
self.graphicsView = NMRPlotWidget(SignalEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -54,11 +55,11 @@ class Ui_SignalEdit(object):
|
||||
self.gridLayout.addWidget(self.graphicsView, 0, 2, 1, 1)
|
||||
|
||||
self.retranslateUi(SignalEdit)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept)
|
||||
self.buttonBox.rejected.connect(SignalEdit.close)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(SignalEdit.close) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(SignalEdit)
|
||||
|
||||
def retranslateUi(self, SignalEdit):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
SignalEdit.setWindowTitle(_translate("SignalEdit", "Dialog"))
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
@ -1,8 +1,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.7
|
||||
# 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.
|
||||
@ -70,7 +70,7 @@ class Ui_BaseWindow(object):
|
||||
self.integralwidget = IntegralWidget()
|
||||
self.integralwidget.setObjectName("integralwidget")
|
||||
self.tabWidget.addTab(self.integralwidget, "")
|
||||
self.area = QtWidgets.QMdiArea(self.splitter)
|
||||
self.area = MdiAreaTile(self.splitter)
|
||||
self.area.setObjectName("area")
|
||||
self.horizontalLayout.addWidget(self.splitter)
|
||||
BaseWindow.setCentralWidget(self.centralwidget)
|
||||
@ -87,6 +87,8 @@ class Ui_BaseWindow(object):
|
||||
self.menuSave.setObjectName("menuSave")
|
||||
self.menuData = QtWidgets.QMenu(self.menubar)
|
||||
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.setObjectName("menuHelp")
|
||||
self.menuExtra = QtWidgets.QMenu(self.menubar)
|
||||
@ -117,6 +119,8 @@ class Ui_BaseWindow(object):
|
||||
self.menuStuff = QtWidgets.QMenu(self.menubar)
|
||||
self.menuStuff.setTitle("")
|
||||
self.menuStuff.setObjectName("menuStuff")
|
||||
self.menuDSC = QtWidgets.QMenu(self.menubar)
|
||||
self.menuDSC.setObjectName("menuDSC")
|
||||
BaseWindow.setMenuBar(self.menubar)
|
||||
self.toolBar = QtWidgets.QToolBar(BaseWindow)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
@ -151,15 +155,6 @@ class Ui_BaseWindow(object):
|
||||
self.toolBar_nmr.setIconSize(QtCore.QSize(24, 24))
|
||||
self.toolBar_nmr.setObjectName("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)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
@ -261,6 +256,10 @@ class Ui_BaseWindow(object):
|
||||
self.actionMaximize.setObjectName("actionMaximize")
|
||||
self.actionTile = QtWidgets.QAction(BaseWindow)
|
||||
self.actionTile.setObjectName("actionTile")
|
||||
self.actionTileVertical = QtWidgets.QAction(BaseWindow)
|
||||
self.actionTileVertical.setObjectName("actionTileVertical")
|
||||
self.actionTileHorizontal = QtWidgets.QAction(BaseWindow)
|
||||
self.actionTileHorizontal.setObjectName("actionTileHorizontal")
|
||||
self.actionMinimize = QtWidgets.QAction(BaseWindow)
|
||||
self.actionMinimize.setCheckable(True)
|
||||
self.actionMinimize.setVisible(False)
|
||||
@ -307,8 +306,6 @@ class Ui_BaseWindow(object):
|
||||
self.actionDerivation.setObjectName("actionDerivation")
|
||||
self.actionIntegration = QtWidgets.QAction(BaseWindow)
|
||||
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.setObjectName("actionMove_between_plots")
|
||||
self.actionBaseline = QtWidgets.QAction(BaseWindow)
|
||||
@ -358,6 +355,25 @@ class Ui_BaseWindow(object):
|
||||
self.actionBugs.setObjectName("actionBugs")
|
||||
self.actionShow_error_log = QtWidgets.QAction(BaseWindow)
|
||||
self.actionShow_error_log.setObjectName("actionShow_error_log")
|
||||
self.actionCreate_starter = QtWidgets.QAction(BaseWindow)
|
||||
self.actionCreate_starter.setObjectName("actionCreate_starter")
|
||||
self.actionAbout = QtWidgets.QAction(BaseWindow)
|
||||
self.actionAbout.setObjectName("actionAbout")
|
||||
self.actionTNMH_model = QtWidgets.QAction(BaseWindow)
|
||||
self.actionTNMH_model.setObjectName("actionTNMH_model")
|
||||
self.actionBinning = QtWidgets.QAction(BaseWindow)
|
||||
self.actionBinning.setObjectName("actionBinning")
|
||||
self.actionTNMH = QtWidgets.QAction(BaseWindow)
|
||||
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.actionExportGraphic)
|
||||
self.menuSave.addAction(self.action_save_fit_parameter)
|
||||
@ -370,6 +386,9 @@ class Ui_BaseWindow(object):
|
||||
self.menuFile.addSeparator()
|
||||
self.menuFile.addAction(self.action_close)
|
||||
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_delete_sets)
|
||||
self.menuData.addAction(self.actionMove_between_plots)
|
||||
@ -379,13 +398,14 @@ class Ui_BaseWindow(object):
|
||||
self.menuData.addAction(self.action_sort_pts)
|
||||
self.menuData.addAction(self.actionSkip_points)
|
||||
self.menuData.addSeparator()
|
||||
self.menuData.addAction(self.action_cut)
|
||||
self.menuData.addAction(self.menuCut_to_visible_range.menuAction())
|
||||
self.menuData.addSeparator()
|
||||
self.menuData.addAction(self.actionChange_datatypes)
|
||||
self.menuData.addAction(self.actionUse_script)
|
||||
self.menuHelp.addAction(self.actionShow_error_log)
|
||||
self.menuHelp.addAction(self.actionDocumentation)
|
||||
self.menuHelp.addAction(self.actionUpdate)
|
||||
self.menuHelp.addAction(self.actionBugs)
|
||||
self.menuHelp.addAction(self.actionAbout)
|
||||
self.menuNormalize.addAction(self.action_norm_max)
|
||||
self.menuNormalize.addAction(self.action_norm_max_abs)
|
||||
self.menuNormalize.addSeparator()
|
||||
@ -401,6 +421,7 @@ class Ui_BaseWindow(object):
|
||||
self.menuExtra.addSeparator()
|
||||
self.menuExtra.addAction(self.menuNormalize.menuAction())
|
||||
self.menuExtra.addAction(self.actionInterpolation)
|
||||
self.menuExtra.addAction(self.actionBinning)
|
||||
self.menuExtra.addAction(self.actionRunning_values)
|
||||
self.menuExtra.addAction(self.actionShift)
|
||||
self.menuExtra.addSeparator()
|
||||
@ -411,6 +432,7 @@ class Ui_BaseWindow(object):
|
||||
self.menuLimits.addAction(self.action_no_range)
|
||||
self.menuLimits.addAction(self.action_x_range)
|
||||
self.menuLimits.addAction(self.action_custom_range)
|
||||
self.menuLimits.addAction(self.actionExclude_region)
|
||||
self.menuFit.addAction(self.action_FitWidget)
|
||||
self.menuFit.addSeparator()
|
||||
self.menuFit.addAction(self.action_create_fit_function)
|
||||
@ -422,7 +444,10 @@ class Ui_BaseWindow(object):
|
||||
self.menuOptions.addSeparator()
|
||||
self.menuOptions.addAction(self.action_colorcycle)
|
||||
self.menuOptions.addAction(self.actionConfiguration)
|
||||
self.menuOptions.addAction(self.actionCreate_starter)
|
||||
self.menuView.addAction(self.actionTile)
|
||||
self.menuView.addAction(self.actionTileVertical)
|
||||
self.menuView.addAction(self.actionTileHorizontal)
|
||||
self.menuView.addAction(self.actionCascade_windows)
|
||||
self.menuWindow.addAction(self.actionNew_window)
|
||||
self.menuWindow.addAction(self.actionDelete_window)
|
||||
@ -451,6 +476,7 @@ class Ui_BaseWindow(object):
|
||||
self.menuStuff.addAction(self.actionLife)
|
||||
self.menuStuff.addAction(self.actionTetris)
|
||||
self.menuStuff.addAction(self.actionMine)
|
||||
self.menuDSC.addAction(self.actionTNMH_model)
|
||||
self.menubar.addAction(self.menuFile.menuAction())
|
||||
self.menubar.addAction(self.menuWindow.menuAction())
|
||||
self.menubar.addAction(self.menuData.menuAction())
|
||||
@ -459,6 +485,7 @@ class Ui_BaseWindow(object):
|
||||
self.menubar.addAction(self.menuFit.menuAction())
|
||||
self.menubar.addAction(self.menuNMR.menuAction())
|
||||
self.menubar.addAction(self.menuBDS.menuAction())
|
||||
self.menubar.addAction(self.menuDSC.menuAction())
|
||||
self.menubar.addAction(self.menuOptions.menuAction())
|
||||
self.menubar.addAction(self.menuHelp.menuAction())
|
||||
self.menubar.addAction(self.menuStuff.menuAction())
|
||||
@ -474,7 +501,6 @@ class Ui_BaseWindow(object):
|
||||
self.toolbar_edit.addAction(self.actionShift)
|
||||
self.toolBar_nmr.addAction(self.t1action)
|
||||
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.actionPick_position)
|
||||
self.toolBar_data.addAction(self.actionConcatenate_sets)
|
||||
@ -499,6 +525,7 @@ class Ui_BaseWindow(object):
|
||||
self.menuFile.setTitle(_translate("BaseWindow", "&File"))
|
||||
self.menuSave.setTitle(_translate("BaseWindow", "&Save..."))
|
||||
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.menuExtra.setTitle(_translate("BaseWindow", "Math"))
|
||||
self.menuNormalize.setTitle(_translate("BaseWindow", "&Normalize"))
|
||||
@ -511,10 +538,10 @@ class Ui_BaseWindow(object):
|
||||
self.menuNMR.setTitle(_translate("BaseWindow", "NMR"))
|
||||
self.menuBDS.setTitle(_translate("BaseWindow", "BDS"))
|
||||
self.menuSpectrum.setTitle(_translate("BaseWindow", "Spectrum"))
|
||||
self.menuDSC.setTitle(_translate("BaseWindow", "DSC"))
|
||||
self.toolBar.setWindowTitle(_translate("BaseWindow", "Main"))
|
||||
self.toolbar_edit.setWindowTitle(_translate("BaseWindow", "Math"))
|
||||
self.toolBar_nmr.setWindowTitle(_translate("BaseWindow", "NMR"))
|
||||
self.toolBar_fit.setWindowTitle(_translate("BaseWindow", "Fit"))
|
||||
self.toolBar_spectrum.setWindowTitle(_translate("BaseWindow", "Spectrum"))
|
||||
self.toolBar_data.setWindowTitle(_translate("BaseWindow", "Data"))
|
||||
self.action_close.setText(_translate("BaseWindow", "&Quit"))
|
||||
@ -566,6 +593,8 @@ class Ui_BaseWindow(object):
|
||||
self.actionGuide_lines.setText(_translate("BaseWindow", "Draw lines..."))
|
||||
self.actionMaximize.setText(_translate("BaseWindow", "Maximize"))
|
||||
self.actionTile.setText(_translate("BaseWindow", "Tile windows"))
|
||||
self.actionTileVertical.setText(_translate("BaseWindow", "Tile windows vertically"))
|
||||
self.actionTileHorizontal.setText(_translate("BaseWindow", "Tile windows horizontally"))
|
||||
self.actionMinimize.setText(_translate("BaseWindow", "Minimize"))
|
||||
self.actionNew_window.setText(_translate("BaseWindow", "New graph"))
|
||||
self.actionDelete_window.setText(_translate("BaseWindow", "Delete graph"))
|
||||
@ -590,7 +619,6 @@ class Ui_BaseWindow(object):
|
||||
self.actionIntegrate.setText(_translate("BaseWindow", "Integrate"))
|
||||
self.actionDerivation.setText(_translate("BaseWindow", "Differentiation..."))
|
||||
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.actionBaseline.setText(_translate("BaseWindow", "Baseline..."))
|
||||
self.actionCalculateT1.setText(_translate("BaseWindow", "Calculate relaxation..."))
|
||||
@ -612,6 +640,17 @@ class Ui_BaseWindow(object):
|
||||
self.action_draw_object.setText(_translate("BaseWindow", "Draw objects..."))
|
||||
self.actionBugs.setText(_translate("BaseWindow", "Bugs! Problems! Wishes!"))
|
||||
self.actionShow_error_log.setText(_translate("BaseWindow", "Show error log"))
|
||||
self.actionCreate_starter.setText(_translate("BaseWindow", "Create starter.."))
|
||||
self.actionAbout.setText(_translate("BaseWindow", "About..."))
|
||||
self.actionTNMH_model.setText(_translate("BaseWindow", "Tg , Hodge, TNMH,,,"))
|
||||
self.actionBinning.setText(_translate("BaseWindow", "Binning..."))
|
||||
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.integral_widget import IntegralWidget
|
||||
from ..data.point_select import PointSelectWidget
|
||||
@ -619,4 +658,5 @@ from ..data.signaledit.editsignalwidget import EditSignalWidget
|
||||
from ..data.valueeditwidget import ValueEditWidget
|
||||
from ..fit.fitwindow import QFitDialog
|
||||
from ..graphs.drawings import DrawingsWidget
|
||||
from ..lib.mdiarea import MdiAreaTile
|
||||
from ..nmr.t1widget import QT1Widget
|
||||
|
@ -1,13 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/bdsdialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/bdsdialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.9.2
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# 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
|
||||
|
||||
|
||||
class Ui_Dialog(object):
|
||||
def setupUi(self, Dialog):
|
||||
Dialog.setObjectName("Dialog")
|
||||
@ -16,12 +19,13 @@ class Ui_Dialog(object):
|
||||
self.gridLayout.setContentsMargins(3, 3, 3, 3)
|
||||
self.gridLayout.setSpacing(3)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.listWidget = QtWidgets.QListWidget(Dialog)
|
||||
self.listWidget = QListWidgetSelect(Dialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth())
|
||||
self.listWidget.setSizePolicy(sizePolicy)
|
||||
self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
self.listWidget.setObjectName("listWidget")
|
||||
self.gridLayout.addWidget(self.listWidget, 1, 0, 2, 1)
|
||||
self.groupBox_2 = QtWidgets.QGroupBox(Dialog)
|
||||
@ -93,8 +97,8 @@ class Ui_Dialog(object):
|
||||
self.gridLayout.addWidget(self.label, 0, 0, 1, 2)
|
||||
|
||||
self.retranslateUi(Dialog)
|
||||
self.buttonBox.accepted.connect(Dialog.accept)
|
||||
self.buttonBox.rejected.connect(Dialog.reject)
|
||||
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||
Dialog.setTabOrder(self.freq_button, self.temp_button)
|
||||
Dialog.setTabOrder(self.temp_button, self.eps_checkBox)
|
||||
@ -117,4 +121,4 @@ class Ui_Dialog(object):
|
||||
self.temp_checkBox.setText(_translate("Dialog", "Meas. temperature"))
|
||||
self.time_checkBox.setText(_translate("Dialog", "Meas. time"))
|
||||
self.label.setText(_translate("Dialog", "Found entries"))
|
||||
|
||||
from ..lib.listwidget import QListWidgetSelect
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- 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
|
||||
@ -49,6 +50,12 @@ class Ui_DataWidget(object):
|
||||
self.horizontalLayout.addWidget(self.func_toolButton)
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
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.retranslateUi(DataWidget)
|
||||
|
@ -1,29 +1,113 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/dscfile_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/dscfile_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.9.2
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# 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
|
||||
|
||||
|
||||
class Ui_Dialog(object):
|
||||
def setupUi(self, Dialog):
|
||||
Dialog.setObjectName("Dialog")
|
||||
Dialog.resize(962, 662)
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(Dialog)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Apply|QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Save)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.gridLayout_2.addWidget(self.buttonBox, 1, 1, 1, 1)
|
||||
self.gridLayout_4 = QtWidgets.QGridLayout()
|
||||
self.gridLayout_4.setContentsMargins(-1, 0, 0, -1)
|
||||
self.gridLayout_4.setSpacing(3)
|
||||
self.gridLayout_4.setObjectName("gridLayout_4")
|
||||
self.cp_checkBox = QtWidgets.QCheckBox(Dialog)
|
||||
Dialog.resize(1341, 799)
|
||||
self.verticalLayout_5 = QtWidgets.QVBoxLayout(Dialog)
|
||||
self.verticalLayout_5.setObjectName("verticalLayout_5")
|
||||
self.splitter = QtWidgets.QSplitter(Dialog)
|
||||
self.splitter.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.splitter.setObjectName("splitter")
|
||||
self.verticalLayoutWidget = QtWidgets.QWidget(self.splitter)
|
||||
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
|
||||
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
|
||||
self.verticalLayout_4.setContentsMargins(6, 6, 6, 6)
|
||||
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||
self.groupBox = QtWidgets.QGroupBox(self.verticalLayoutWidget)
|
||||
self.groupBox.setFlat(False)
|
||||
self.groupBox.setObjectName("groupBox")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox)
|
||||
self.verticalLayout.setContentsMargins(6, 6, 6, 6)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.step_listWidget = QtWidgets.QListWidget(self.groupBox)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.step_listWidget.sizePolicy().hasHeightForWidth())
|
||||
self.step_listWidget.setSizePolicy(sizePolicy)
|
||||
self.step_listWidget.setMinimumSize(QtCore.QSize(0, 0))
|
||||
self.step_listWidget.setObjectName("step_listWidget")
|
||||
self.verticalLayout.addWidget(self.step_listWidget)
|
||||
self.verticalLayout_4.addWidget(self.groupBox)
|
||||
self.groupBox_2 = QtWidgets.QGroupBox(self.verticalLayoutWidget)
|
||||
self.groupBox_2.setObjectName("groupBox_2")
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.groupBox_2)
|
||||
self.verticalLayout_2.setContentsMargins(6, 6, 6, 6)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.groupBox_4 = QtWidgets.QGroupBox(self.groupBox_2)
|
||||
self.groupBox_4.setObjectName("groupBox_4")
|
||||
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.groupBox_4)
|
||||
self.verticalLayout_6.setContentsMargins(6, 6, 6, 6)
|
||||
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
||||
self.empty_label = QtWidgets.QLabel(self.groupBox_4)
|
||||
self.empty_label.setObjectName("empty_label")
|
||||
self.verticalLayout_6.addWidget(self.empty_label)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setSpacing(3)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.loadempty_button = QtWidgets.QPushButton(self.groupBox_4)
|
||||
self.loadempty_button.setObjectName("loadempty_button")
|
||||
self.horizontalLayout_2.addWidget(self.loadempty_button)
|
||||
self.delempty_button = QtWidgets.QPushButton(self.groupBox_4)
|
||||
self.delempty_button.setObjectName("delempty_button")
|
||||
self.horizontalLayout_2.addWidget(self.delempty_button)
|
||||
self.verticalLayout_6.addLayout(self.horizontalLayout_2)
|
||||
self.verticalLayout_2.addWidget(self.groupBox_4)
|
||||
self.groupBox_5 = QtWidgets.QGroupBox(self.groupBox_2)
|
||||
self.groupBox_5.setObjectName("groupBox_5")
|
||||
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.groupBox_5)
|
||||
self.verticalLayout_7.setContentsMargins(6, 6, 6, 6)
|
||||
self.verticalLayout_7.setSpacing(3)
|
||||
self.verticalLayout_7.setObjectName("verticalLayout_7")
|
||||
self.none_radioButton = QtWidgets.QRadioButton(self.groupBox_5)
|
||||
self.none_radioButton.setObjectName("none_radioButton")
|
||||
self.buttonGroup = QtWidgets.QButtonGroup(Dialog)
|
||||
self.buttonGroup.setObjectName("buttonGroup")
|
||||
self.buttonGroup.addButton(self.none_radioButton)
|
||||
self.verticalLayout_7.addWidget(self.none_radioButton)
|
||||
self.isotherm_radioButton = QtWidgets.QRadioButton(self.groupBox_5)
|
||||
self.isotherm_radioButton.setChecked(True)
|
||||
self.isotherm_radioButton.setObjectName("isotherm_radioButton")
|
||||
self.buttonGroup.addButton(self.isotherm_radioButton)
|
||||
self.verticalLayout_7.addWidget(self.isotherm_radioButton)
|
||||
self.slope_radioButton = QtWidgets.QRadioButton(self.groupBox_5)
|
||||
self.slope_radioButton.setObjectName("slope_radioButton")
|
||||
self.buttonGroup.addButton(self.slope_radioButton)
|
||||
self.verticalLayout_7.addWidget(self.slope_radioButton)
|
||||
self.widget = QtWidgets.QWidget(self.groupBox_5)
|
||||
self.widget.setMinimumSize(QtCore.QSize(0, 33))
|
||||
self.widget.setObjectName("widget")
|
||||
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widget)
|
||||
self.horizontalLayout_3.setContentsMargins(3, 3, 3, 3)
|
||||
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
||||
self.limit1_lineedit = QtWidgets.QLineEdit(self.widget)
|
||||
self.limit1_lineedit.setObjectName("limit1_lineedit")
|
||||
self.horizontalLayout_3.addWidget(self.limit1_lineedit)
|
||||
self.limit2_lineedit = QtWidgets.QLineEdit(self.widget)
|
||||
self.limit2_lineedit.setText("")
|
||||
self.limit2_lineedit.setObjectName("limit2_lineedit")
|
||||
self.horizontalLayout_3.addWidget(self.limit2_lineedit)
|
||||
self.verticalLayout_7.addWidget(self.widget)
|
||||
self.verticalLayout_2.addWidget(self.groupBox_5)
|
||||
self.verticalLayout_4.addWidget(self.groupBox_2)
|
||||
self.groupBox_3 = QtWidgets.QGroupBox(self.verticalLayoutWidget)
|
||||
self.groupBox_3.setObjectName("groupBox_3")
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.groupBox_3)
|
||||
self.verticalLayout_3.setContentsMargins(6, 6, 6, 6)
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.cp_checkBox = QtWidgets.QCheckBox(self.groupBox_3)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -31,36 +115,8 @@ class Ui_Dialog(object):
|
||||
self.cp_checkBox.setSizePolicy(sizePolicy)
|
||||
self.cp_checkBox.setChecked(True)
|
||||
self.cp_checkBox.setObjectName("cp_checkBox")
|
||||
self.gridLayout_4.addWidget(self.cp_checkBox, 11, 0, 1, 4)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setSpacing(3)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.loadempty_button = QtWidgets.QPushButton(Dialog)
|
||||
self.loadempty_button.setObjectName("loadempty_button")
|
||||
self.horizontalLayout_2.addWidget(self.loadempty_button)
|
||||
self.delempty_button = QtWidgets.QPushButton(Dialog)
|
||||
self.delempty_button.setObjectName("delempty_button")
|
||||
self.horizontalLayout_2.addWidget(self.delempty_button)
|
||||
self.gridLayout_4.addLayout(self.horizontalLayout_2, 5, 0, 1, 4)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_4.addItem(spacerItem, 12, 0, 1, 1)
|
||||
self.isotherm_radioButton = QtWidgets.QRadioButton(Dialog)
|
||||
self.isotherm_radioButton.setChecked(True)
|
||||
self.isotherm_radioButton.setObjectName("isotherm_radioButton")
|
||||
self.buttonGroup = QtWidgets.QButtonGroup(Dialog)
|
||||
self.buttonGroup.setObjectName("buttonGroup")
|
||||
self.buttonGroup.addButton(self.isotherm_radioButton)
|
||||
self.gridLayout_4.addWidget(self.isotherm_radioButton, 6, 1, 1, 1)
|
||||
self.label_4 = QtWidgets.QLabel(Dialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.label_4.sizePolicy().hasHeightForWidth())
|
||||
self.label_4.setSizePolicy(sizePolicy)
|
||||
self.label_4.setStyleSheet("font-weight: bold")
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.gridLayout_4.addWidget(self.label_4, 0, 0, 1, 4)
|
||||
self.reference_tableWidget = QtWidgets.QTableWidget(Dialog)
|
||||
self.verticalLayout_3.addWidget(self.cp_checkBox)
|
||||
self.reference_tableWidget = QtWidgets.QTableWidget(self.groupBox_3)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -75,57 +131,11 @@ class Ui_Dialog(object):
|
||||
self.reference_tableWidget.horizontalHeader().setVisible(False)
|
||||
self.reference_tableWidget.horizontalHeader().setStretchLastSection(True)
|
||||
self.reference_tableWidget.verticalHeader().setVisible(False)
|
||||
self.gridLayout_4.addWidget(self.reference_tableWidget, 9, 0, 1, 4)
|
||||
self.step_listWidget = QtWidgets.QListWidget(Dialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Minimum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.step_listWidget.sizePolicy().hasHeightForWidth())
|
||||
self.step_listWidget.setSizePolicy(sizePolicy)
|
||||
self.step_listWidget.setMinimumSize(QtCore.QSize(0, 0))
|
||||
self.step_listWidget.setObjectName("step_listWidget")
|
||||
self.gridLayout_4.addWidget(self.step_listWidget, 1, 0, 1, 4)
|
||||
self.label = QtWidgets.QLabel(Dialog)
|
||||
self.label.setObjectName("label")
|
||||
self.gridLayout_4.addWidget(self.label, 6, 0, 1, 1)
|
||||
self.slope_radioButton = QtWidgets.QRadioButton(Dialog)
|
||||
self.slope_radioButton.setObjectName("slope_radioButton")
|
||||
self.buttonGroup.addButton(self.slope_radioButton)
|
||||
self.gridLayout_4.addWidget(self.slope_radioButton, 6, 2, 1, 1)
|
||||
self.empty_label = QtWidgets.QLabel(Dialog)
|
||||
self.empty_label.setObjectName("empty_label")
|
||||
self.gridLayout_4.addWidget(self.empty_label, 4, 0, 1, 4)
|
||||
self.label_3 = QtWidgets.QLabel(Dialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.label_3.sizePolicy().hasHeightForWidth())
|
||||
self.label_3.setSizePolicy(sizePolicy)
|
||||
self.label_3.setStyleSheet("font-weight: bold")
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.gridLayout_4.addWidget(self.label_3, 8, 0, 1, 4)
|
||||
self.label_2 = QtWidgets.QLabel(Dialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth())
|
||||
self.label_2.setSizePolicy(sizePolicy)
|
||||
self.label_2.setStyleSheet("font-weight: bold")
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout_4.addWidget(self.label_2, 3, 0, 1, 4)
|
||||
self.line = QtWidgets.QFrame(Dialog)
|
||||
self.line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
self.line.setObjectName("line")
|
||||
self.gridLayout_4.addWidget(self.line, 7, 0, 1, 4)
|
||||
self.none_radioButton = QtWidgets.QRadioButton(Dialog)
|
||||
self.none_radioButton.setObjectName("none_radioButton")
|
||||
self.buttonGroup.addButton(self.none_radioButton)
|
||||
self.gridLayout_4.addWidget(self.none_radioButton, 6, 3, 1, 1)
|
||||
self.verticalLayout_3.addWidget(self.reference_tableWidget)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setSpacing(3)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.ref_add_pushButton = QtWidgets.QPushButton(Dialog)
|
||||
self.ref_add_pushButton = QtWidgets.QPushButton(self.groupBox_3)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -133,7 +143,7 @@ class Ui_Dialog(object):
|
||||
self.ref_add_pushButton.setSizePolicy(sizePolicy)
|
||||
self.ref_add_pushButton.setObjectName("ref_add_pushButton")
|
||||
self.horizontalLayout.addWidget(self.ref_add_pushButton)
|
||||
self.ref_remove_pushButton = QtWidgets.QPushButton(Dialog)
|
||||
self.ref_remove_pushButton = QtWidgets.QPushButton(self.groupBox_3)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Maximum)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -141,16 +151,22 @@ class Ui_Dialog(object):
|
||||
self.ref_remove_pushButton.setSizePolicy(sizePolicy)
|
||||
self.ref_remove_pushButton.setObjectName("ref_remove_pushButton")
|
||||
self.horizontalLayout.addWidget(self.ref_remove_pushButton)
|
||||
self.gridLayout_4.addLayout(self.horizontalLayout, 10, 0, 1, 4)
|
||||
self.line_2 = QtWidgets.QFrame(Dialog)
|
||||
self.line_2.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
self.line_2.setObjectName("line_2")
|
||||
self.gridLayout_4.addWidget(self.line_2, 2, 0, 1, 4)
|
||||
self.gridLayout_2.addLayout(self.gridLayout_4, 0, 0, 1, 1)
|
||||
self.gridLayout = QtWidgets.QGridLayout()
|
||||
self.verticalLayout_3.addLayout(self.horizontalLayout)
|
||||
self.verticalLayout_4.addWidget(self.groupBox_3)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.verticalLayout_4.addItem(spacerItem)
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(self.verticalLayoutWidget)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Apply|QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Save)
|
||||
self.buttonBox.setCenterButtons(True)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.verticalLayout_4.addWidget(self.buttonBox)
|
||||
self.layoutWidget = QtWidgets.QWidget(self.splitter)
|
||||
self.layoutWidget.setObjectName("layoutWidget")
|
||||
self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
|
||||
self.gridLayout.setContentsMargins(0, 0, 0, 0)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.raw_graph = PlotWidget(Dialog)
|
||||
self.raw_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -159,7 +175,7 @@ class Ui_Dialog(object):
|
||||
self.raw_graph.setMinimumSize(QtCore.QSize(300, 200))
|
||||
self.raw_graph.setObjectName("raw_graph")
|
||||
self.gridLayout.addWidget(self.raw_graph, 0, 0, 1, 1)
|
||||
self.calib_graph = PlotWidget(Dialog)
|
||||
self.calib_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -168,7 +184,7 @@ class Ui_Dialog(object):
|
||||
self.calib_graph.setMinimumSize(QtCore.QSize(300, 200))
|
||||
self.calib_graph.setObjectName("calib_graph")
|
||||
self.gridLayout.addWidget(self.calib_graph, 1, 0, 1, 1)
|
||||
self.baseline_graph = PlotWidget(Dialog)
|
||||
self.baseline_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -177,7 +193,7 @@ class Ui_Dialog(object):
|
||||
self.baseline_graph.setMinimumSize(QtCore.QSize(300, 200))
|
||||
self.baseline_graph.setObjectName("baseline_graph")
|
||||
self.gridLayout.addWidget(self.baseline_graph, 0, 1, 1, 1)
|
||||
self.end_graph = PlotWidget(Dialog)
|
||||
self.end_graph = NMRPlotWidget(self.layoutWidget)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -186,28 +202,30 @@ class Ui_Dialog(object):
|
||||
self.end_graph.setMinimumSize(QtCore.QSize(0, 0))
|
||||
self.end_graph.setObjectName("end_graph")
|
||||
self.gridLayout.addWidget(self.end_graph, 1, 1, 1, 1)
|
||||
self.gridLayout_2.addLayout(self.gridLayout, 0, 1, 1, 1)
|
||||
self.verticalLayout_5.addWidget(self.splitter)
|
||||
|
||||
self.retranslateUi(Dialog)
|
||||
self.buttonBox.accepted.connect(Dialog.accept)
|
||||
self.buttonBox.rejected.connect(Dialog.reject)
|
||||
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||
|
||||
def retranslateUi(self, Dialog):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
Dialog.setWindowTitle(_translate("Dialog", "Read DSC file"))
|
||||
self.cp_checkBox.setText(_translate("Dialog", "Convert to heat capacity"))
|
||||
self.groupBox.setTitle(_translate("Dialog", "Detected steps"))
|
||||
self.groupBox_2.setTitle(_translate("Dialog", "Baseline corrections"))
|
||||
self.groupBox_4.setTitle(_translate("Dialog", "Empty measurement"))
|
||||
self.empty_label.setText(_translate("Dialog", "No emtpy measurement"))
|
||||
self.loadempty_button.setText(_translate("Dialog", "Load empty"))
|
||||
self.delempty_button.setText(_translate("Dialog", "Remove empty"))
|
||||
self.isotherm_radioButton.setText(_translate("Dialog", "Isotherms"))
|
||||
self.label_4.setText(_translate("Dialog", "Detected steps"))
|
||||
self.label.setText(_translate("Dialog", "Slope"))
|
||||
self.slope_radioButton.setText(_translate("Dialog", "Initial slope"))
|
||||
self.empty_label.setText(_translate("Dialog", "Empty measurement"))
|
||||
self.label_3.setText(_translate("Dialog", "Calibration"))
|
||||
self.label_2.setText(_translate("Dialog", "Baseline"))
|
||||
self.groupBox_5.setTitle(_translate("Dialog", "Slope correction"))
|
||||
self.none_radioButton.setText(_translate("Dialog", "None"))
|
||||
self.isotherm_radioButton.setText(_translate("Dialog", "Isotherms"))
|
||||
self.slope_radioButton.setText(_translate("Dialog", "Curve slope"))
|
||||
self.limit1_lineedit.setPlaceholderText(_translate("Dialog", "start (in min)"))
|
||||
self.limit2_lineedit.setPlaceholderText(_translate("Dialog", "stop (in min)"))
|
||||
self.groupBox_3.setTitle(_translate("Dialog", "References"))
|
||||
self.cp_checkBox.setText(_translate("Dialog", "Use reference to convert to heat capacity"))
|
||||
self.ref_add_pushButton.setText(_translate("Dialog", "Add reference"))
|
||||
self.ref_remove_pushButton.setText(_translate("Dialog", "Remove reference"))
|
||||
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/eval_expr_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/eval_expr_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.2
|
||||
#
|
||||
# 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
|
||||
@ -36,14 +37,14 @@ class Ui_CalcDialog(object):
|
||||
self.label_2 = QtWidgets.QLabel(self.page)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.verticalLayout_2.addWidget(self.label_2)
|
||||
self.listWidget = QtWidgets.QListWidget(self.page)
|
||||
self.listWidget = QListWidgetSelect(self.page)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth())
|
||||
self.listWidget.setSizePolicy(sizePolicy)
|
||||
self.listWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
|
||||
self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
self.listWidget.setObjectName("listWidget")
|
||||
self.verticalLayout_2.addWidget(self.listWidget)
|
||||
self.overwrite_checkbox = QtWidgets.QCheckBox(self.page)
|
||||
@ -202,7 +203,7 @@ class Ui_CalcDialog(object):
|
||||
self.label_8.setBuddy(self.line_doubleSpinBox)
|
||||
|
||||
self.retranslateUi(CalcDialog)
|
||||
self.stackedWidget.setCurrentIndex(2)
|
||||
self.stackedWidget.setCurrentIndex(0)
|
||||
QtCore.QMetaObject.connectSlotsByName(CalcDialog)
|
||||
CalcDialog.setTabOrder(self.calc_edit, self.listWidget)
|
||||
CalcDialog.setTabOrder(self.listWidget, self.overwrite_checkbox)
|
||||
@ -237,4 +238,5 @@ class Ui_CalcDialog(object):
|
||||
self.label_11.setText(_translate("CalcDialog", "Style"))
|
||||
self.label.setText(_translate("CalcDialog", "Expressions are evaluated line by line and change previous values"))
|
||||
from ..lib.delegates import ColorListEditor, LineStyleEditor, SymbolStyleEditor
|
||||
from ..lib.listwidget import QListWidgetSelect
|
||||
from ..lib.namespace import QNamespaceWidget
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- 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
|
||||
@ -47,6 +48,7 @@ class Ui_FCEval_dialog(object):
|
||||
self.verticalLayout.addWidget(self.input_box)
|
||||
self.region_box = QtWidgets.QGroupBox(FCEval_dialog)
|
||||
self.region_box.setCheckable(True)
|
||||
self.region_box.setChecked(False)
|
||||
self.region_box.setObjectName("region_box")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.region_box)
|
||||
self.horizontalLayout.setContentsMargins(3, 3, 3, 3)
|
||||
@ -139,6 +141,7 @@ class Ui_FCEval_dialog(object):
|
||||
self.line.setObjectName("line")
|
||||
self.gridLayout.addWidget(self.line, 2, 0, 1, 2)
|
||||
self.graph_comboBox = QtWidgets.QComboBox(self.out_box)
|
||||
self.graph_comboBox.setEnabled(False)
|
||||
self.graph_comboBox.setObjectName("graph_comboBox")
|
||||
self.gridLayout.addWidget(self.graph_comboBox, 3, 1, 1, 1)
|
||||
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.retranslateUi(FCEval_dialog)
|
||||
self.buttonBox.accepted.connect(FCEval_dialog.accept)
|
||||
self.buttonBox.rejected.connect(FCEval_dialog.reject)
|
||||
self.buttonBox.accepted.connect(FCEval_dialog.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(FCEval_dialog.reject) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(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.dir_pushbutton.setText(_translate("FCEval_dialog", "Add directory..."))
|
||||
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.stop_lineedit.setPlaceholderText(_translate("FCEval_dialog", "end pos in µs"))
|
||||
self.fit_box.setTitle(_translate("FCEval_dialog", "Fit equation"))
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# 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
|
||||
# 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.setObjectName("verticalLayout_6")
|
||||
self.tabWidget.addTab(self.namespace_box, "")
|
||||
self.plainTextEdit = CodeEditor(self.splitter)
|
||||
self.plainTextEdit.setEnabled(True)
|
||||
self.plainTextEdit.setObjectName("plainTextEdit")
|
||||
self.editor = EditorWidget(self.splitter)
|
||||
self.editor.setObjectName("editor")
|
||||
self.verticalLayout.addWidget(self.splitter)
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||
@ -63,8 +62,8 @@ class Ui_Dialog(object):
|
||||
|
||||
self.retranslateUi(Dialog)
|
||||
self.tabWidget.setCurrentIndex(0)
|
||||
self.buttonBox.accepted.connect(Dialog.accept)
|
||||
self.buttonBox.rejected.connect(Dialog.reject)
|
||||
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(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.kwargs_box), _translate("Dialog", "Multiple choice"))
|
||||
self.tabWidget.setTabText(self.tabWidget.indexOf(self.namespace_box), _translate("Dialog", "Available Functions"))
|
||||
from ..lib.codeeditor import CodeEditor
|
||||
from ..lib.codeeditor import EditorWidget
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/fitdialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/fitdialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.2
|
||||
#
|
||||
# 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
|
||||
@ -37,7 +38,6 @@ class Ui_FitDialog(object):
|
||||
self.weight_combobox.addItem("")
|
||||
self.weight_combobox.addItem("")
|
||||
self.weight_combobox.addItem("")
|
||||
self.weight_combobox.addItem("")
|
||||
self.gridLayout_2.addWidget(self.weight_combobox, 6, 1, 1, 1)
|
||||
self.newmodel_button = QtWidgets.QPushButton(self.scrollAreaWidgetContents_2)
|
||||
self.newmodel_button.setEnabled(False)
|
||||
@ -143,7 +143,6 @@ class Ui_FitDialog(object):
|
||||
self.weight_combobox.setItemText(1, _translate("FitDialog", "y"))
|
||||
self.weight_combobox.setItemText(2, _translate("FitDialog", "y²"))
|
||||
self.weight_combobox.setItemText(3, _translate("FitDialog", "Δy"))
|
||||
self.weight_combobox.setItemText(4, _translate("FitDialog", "log(y)"))
|
||||
self.newmodel_button.setText(_translate("FitDialog", "New model"))
|
||||
self.deletemodel_button.setText(_translate("FitDialog", "Delete model"))
|
||||
self.label_3.setText(_translate("FitDialog", "Weight"))
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/fitmodelwidget.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/fitmodelwidget.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
|
||||
@ -13,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
class Ui_FitParameter(object):
|
||||
def setupUi(self, FitParameter):
|
||||
FitParameter.setObjectName("FitParameter")
|
||||
FitParameter.resize(365, 78)
|
||||
FitParameter.resize(365, 66)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -36,28 +37,24 @@ class Ui_FitParameter(object):
|
||||
self.parametername.setObjectName("parametername")
|
||||
self.horizontalLayout_2.addWidget(self.parametername)
|
||||
self.parameter_line = LineEdit(FitParameter)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.parameter_line.sizePolicy().hasHeightForWidth())
|
||||
self.parameter_line.setSizePolicy(sizePolicy)
|
||||
self.parameter_line.setMaximumSize(QtCore.QSize(160, 16777215))
|
||||
self.parameter_line.setText("")
|
||||
self.parameter_line.setObjectName("parameter_line")
|
||||
self.horizontalLayout_2.addWidget(self.parameter_line)
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout_2.addItem(spacerItem)
|
||||
self.fixed_check = QtWidgets.QCheckBox(FitParameter)
|
||||
self.fixed_check.setObjectName("fixed_check")
|
||||
self.horizontalLayout_2.addWidget(self.fixed_check)
|
||||
self.global_checkbox = QtWidgets.QCheckBox(FitParameter)
|
||||
self.global_checkbox.setObjectName("global_checkbox")
|
||||
self.horizontalLayout_2.addWidget(self.global_checkbox)
|
||||
self.toolButton = QtWidgets.QToolButton(FitParameter)
|
||||
self.toolButton.setText("")
|
||||
self.toolButton.setPopupMode(QtWidgets.QToolButton.InstantPopup)
|
||||
self.toolButton.setArrowType(QtCore.Qt.RightArrow)
|
||||
self.toolButton.setObjectName("toolButton")
|
||||
self.horizontalLayout_2.addWidget(self.toolButton)
|
||||
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.frame = QtWidgets.QFrame(FitParameter)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)
|
||||
@ -89,6 +86,7 @@ class Ui_FitParameter(object):
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.lineEdit.sizePolicy().hasHeightForWidth())
|
||||
self.lineEdit.setSizePolicy(sizePolicy)
|
||||
self.lineEdit.setMaximumSize(QtCore.QSize(100, 16777215))
|
||||
self.lineEdit.setText("")
|
||||
self.lineEdit.setFrame(True)
|
||||
self.lineEdit.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
|
||||
@ -107,6 +105,7 @@ class Ui_FitParameter(object):
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.lineEdit_2.sizePolicy().hasHeightForWidth())
|
||||
self.lineEdit_2.setSizePolicy(sizePolicy)
|
||||
self.lineEdit_2.setMaximumSize(QtCore.QSize(100, 16777215))
|
||||
self.lineEdit_2.setText("")
|
||||
self.lineEdit_2.setFrame(True)
|
||||
self.lineEdit_2.setObjectName("lineEdit_2")
|
||||
@ -129,6 +128,7 @@ class Ui_FitParameter(object):
|
||||
self.parameter_line.setPlaceholderText(_translate("FitParameter", "0"))
|
||||
self.fixed_check.setText(_translate("FitParameter", "Fix"))
|
||||
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.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>"))
|
||||
|
@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/autohome/dominik/nmreval-gitea/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.7
|
||||
# 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.
|
||||
@ -14,120 +14,9 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
class Ui_Dialog(object):
|
||||
def setupUi(self, Dialog):
|
||||
Dialog.setObjectName("Dialog")
|
||||
Dialog.resize(864, 649)
|
||||
Dialog.resize(969, 974)
|
||||
self.gridLayout = QtWidgets.QGridLayout(Dialog)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.sets_comboBox = ElideComboBox(Dialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.sets_comboBox.sizePolicy().hasHeightForWidth())
|
||||
self.sets_comboBox.setSizePolicy(sizePolicy)
|
||||
self.sets_comboBox.setMaximumSize(QtCore.QSize(400, 16777215))
|
||||
self.sets_comboBox.setBaseSize(QtCore.QSize(200, 0))
|
||||
self.sets_comboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength)
|
||||
self.sets_comboBox.setObjectName("sets_comboBox")
|
||||
self.gridLayout.addWidget(self.sets_comboBox, 0, 0, 1, 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, 6, 0, 1, 2)
|
||||
self.param_tableWidget = QtWidgets.QTableWidget(Dialog)
|
||||
self.param_tableWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
|
||||
self.param_tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored)
|
||||
self.param_tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
self.param_tableWidget.setAlternatingRowColors(True)
|
||||
self.param_tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
|
||||
self.param_tableWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectColumns)
|
||||
self.param_tableWidget.setShowGrid(False)
|
||||
self.param_tableWidget.setColumnCount(0)
|
||||
self.param_tableWidget.setObjectName("param_tableWidget")
|
||||
self.param_tableWidget.setRowCount(0)
|
||||
self.param_tableWidget.horizontalHeader().setStretchLastSection(False)
|
||||
self.gridLayout.addWidget(self.param_tableWidget, 1, 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.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, 5, 0, 1, 2)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setSpacing(3)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.reject_fit_checkBox = QtWidgets.QCheckBox(Dialog)
|
||||
self.reject_fit_checkBox.setObjectName("reject_fit_checkBox")
|
||||
self.horizontalLayout_2.addWidget(self.reject_fit_checkBox)
|
||||
self.del_prev_checkBox = QtWidgets.QCheckBox(Dialog)
|
||||
self.del_prev_checkBox.setObjectName("del_prev_checkBox")
|
||||
self.horizontalLayout_2.addWidget(self.del_prev_checkBox)
|
||||
self.gridLayout.addLayout(self.horizontalLayout_2, 2, 0, 1, 1)
|
||||
self.line = QtWidgets.QFrame(Dialog)
|
||||
self.line.setFrameShape(QtWidgets.QFrame.HLine)
|
||||
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
||||
self.line.setObjectName("line")
|
||||
self.gridLayout.addWidget(self.line, 3, 0, 1, 2)
|
||||
self.stack = QtWidgets.QTabWidget(Dialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
@ -138,20 +27,48 @@ class Ui_Dialog(object):
|
||||
self.stackPage1 = QtWidgets.QWidget()
|
||||
self.stackPage1.setObjectName("stackPage1")
|
||||
self.gridLayout_3 = QtWidgets.QGridLayout(self.stackPage1)
|
||||
self.gridLayout_3.setContentsMargins(3, 3, 3, 3)
|
||||
self.gridLayout_3.setContentsMargins(6, 3, 6, 3)
|
||||
self.gridLayout_3.setSpacing(3)
|
||||
self.gridLayout_3.setObjectName("gridLayout_3")
|
||||
self.logy_box = QtWidgets.QCheckBox(self.stackPage1)
|
||||
self.logy_box.setLayoutDirection(QtCore.Qt.RightToLeft)
|
||||
self.logy_box.setObjectName("logy_box")
|
||||
self.gridLayout_3.addWidget(self.logy_box, 2, 1, 1, 1)
|
||||
self.logx_box = QtWidgets.QCheckBox(self.stackPage1)
|
||||
self.logx_box.setLayoutDirection(QtCore.Qt.RightToLeft)
|
||||
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.gridLayout_3.addItem(spacerItem, 2, 3, 1, 1)
|
||||
self.autoscale_box = QtWidgets.QToolButton(self.stackPage1)
|
||||
self.autoscale_box.setObjectName("autoscale_box")
|
||||
self.gridLayout_3.addWidget(self.autoscale_box, 2, 4, 1, 1)
|
||||
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.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.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.stackPage2 = QtWidgets.QWidget()
|
||||
self.stackPage2.setObjectName("stackPage2")
|
||||
@ -194,7 +111,142 @@ class Ui_Dialog(object):
|
||||
self.corr_tableWidget.verticalHeader().setVisible(False)
|
||||
self.verticalLayout_3.addWidget(self.corr_tableWidget)
|
||||
self.stack.addTab(self.stackPage3, "")
|
||||
self.gridLayout.addWidget(self.stack, 0, 1, 3, 1)
|
||||
self.gridLayout.addWidget(self.stack, 0, 1, 5, 1)
|
||||
self.param_tableWidget = QtWidgets.QTableWidget(Dialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.param_tableWidget.sizePolicy().hasHeightForWidth())
|
||||
self.param_tableWidget.setSizePolicy(sizePolicy)
|
||||
self.param_tableWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
|
||||
self.param_tableWidget.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored)
|
||||
self.param_tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
self.param_tableWidget.setAlternatingRowColors(True)
|
||||
self.param_tableWidget.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
|
||||
self.param_tableWidget.setColumnCount(1)
|
||||
self.param_tableWidget.setObjectName("param_tableWidget")
|
||||
self.param_tableWidget.setRowCount(0)
|
||||
self.param_tableWidget.horizontalHeader().setVisible(False)
|
||||
self.param_tableWidget.horizontalHeader().setStretchLastSection(True)
|
||||
self.gridLayout.addWidget(self.param_tableWidget, 1, 0, 1, 1)
|
||||
self.del_prev_checkBox = QtWidgets.QCheckBox(Dialog)
|
||||
self.del_prev_checkBox.setObjectName("del_prev_checkBox")
|
||||
self.gridLayout.addWidget(self.del_prev_checkBox, 3, 0, 1, 1)
|
||||
self.line = QtWidgets.QFrame(Dialog)
|
||||
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.sets_comboBox = ElideComboBox(Dialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.sets_comboBox.sizePolicy().hasHeightForWidth())
|
||||
self.sets_comboBox.setSizePolicy(sizePolicy)
|
||||
self.sets_comboBox.setMaximumSize(QtCore.QSize(400, 16777215))
|
||||
self.sets_comboBox.setBaseSize(QtCore.QSize(200, 0))
|
||||
self.sets_comboBox.setSizeAdjustPolicy(QtWidgets.QComboBox.AdjustToMinimumContentsLength)
|
||||
self.sets_comboBox.setObjectName("sets_comboBox")
|
||||
self.gridLayout.addWidget(self.sets_comboBox, 0, 0, 1, 1)
|
||||
self.reject_fit_checkBox = QtWidgets.QCheckBox(Dialog)
|
||||
self.reject_fit_checkBox.setObjectName("reject_fit_checkBox")
|
||||
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.stack.setCurrentIndex(0)
|
||||
@ -203,22 +255,14 @@ class Ui_Dialog(object):
|
||||
def retranslateUi(self, Dialog):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
Dialog.setWindowTitle(_translate("Dialog", "Fit results"))
|
||||
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.setPlaceholderText(_translate("Dialog", "min x"))
|
||||
self.maxx_line.setToolTip(_translate("Dialog", "Leave empty to start at highest point"))
|
||||
self.maxx_line.setPlaceholderText(_translate("Dialog", "max x"))
|
||||
self.numx_line.setPlaceholderText(_translate("Dialog", "# pts"))
|
||||
self.curve_checkbox.setText(_translate("Dialog", "Plot fit curve"))
|
||||
self.partial_checkBox.setText(_translate("Dialog", "Plot partial functions"))
|
||||
self.reject_fit_checkBox.setText(_translate("Dialog", "Reject this fit"))
|
||||
self.del_prev_checkBox.setText(_translate("Dialog", "Delete previous fits"))
|
||||
self.logy_box.setText(_translate("Dialog", "logarithmic y axis"))
|
||||
self.logx_box.setText(_translate("Dialog", "logarithmic x axis"))
|
||||
self.autoscale_box.setToolTip(_translate("Dialog", "Auto-scale graph for all sets"))
|
||||
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.stackPage2), _translate("Dialog", "Statistics"))
|
||||
item = self.corr_tableWidget.horizontalHeaderItem(0)
|
||||
@ -230,5 +274,20 @@ class Ui_Dialog(object):
|
||||
item = self.corr_tableWidget.horizontalHeaderItem(3)
|
||||
item.setText(_translate("Dialog", "Partial Corr."))
|
||||
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.reject_fit_checkBox.setText(_translate("Dialog", "Reject this fit"))
|
||||
self.groupBox.setTitle(_translate("Dialog", "Output"))
|
||||
self.minx_line.setToolTip(_translate("Dialog", "Leave empty to start at lowest point"))
|
||||
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.setPlaceholderText(_translate("Dialog", "max x"))
|
||||
self.newx_log_checkbox.setText(_translate("Dialog", "log-spaced?"))
|
||||
self.curve_checkbox.setText(_translate("Dialog", "Plot fit curve"))
|
||||
self.partial_checkBox.setText(_translate("Dialog", "Plot partial functions"))
|
||||
self.parameter_checkbox.setText(_translate("Dialog", "Plot parameter"))
|
||||
from ..lib.forms import ElideComboBox
|
||||
from pyqtgraph import GraphicsLayoutWidget
|
||||
|
@ -2,9 +2,10 @@
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/graph.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
|
||||
@ -196,19 +197,20 @@ class Ui_GraphWindow(object):
|
||||
self.gridLayout.setHorizontalSpacing(3)
|
||||
self.gridLayout.setVerticalSpacing(0)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.listWidget = QtWidgets.QListWidget(GraphWindow)
|
||||
self.listWidget = QListWidgetSelect(GraphWindow)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth())
|
||||
self.listWidget.setSizePolicy(sizePolicy)
|
||||
self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
self.listWidget.setObjectName("listWidget")
|
||||
self.gridLayout.addWidget(self.listWidget, 1, 1, 1, 1)
|
||||
self.checkBox = QtWidgets.QCheckBox(GraphWindow)
|
||||
self.checkBox.setChecked(True)
|
||||
self.checkBox.setObjectName("checkBox")
|
||||
self.gridLayout.addWidget(self.checkBox, 0, 1, 1, 1)
|
||||
self.graphic = PlotWidget(GraphWindow)
|
||||
self.graphic = NMRPlotWidget(GraphWindow)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -269,7 +271,11 @@ class Ui_GraphWindow(object):
|
||||
self.label_4.setText(_translate("GraphWindow", "---"))
|
||||
self.apply_button.setText(_translate("GraphWindow", "Apply"))
|
||||
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.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.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"))
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
from ..lib.listwidget import QListWidgetSelect
|
||||
|
@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '/autohome/dominik/nmreval/src/resources/_ui/integral_widget.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/integral_widget.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.4
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# 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.
|
||||
@ -26,7 +26,6 @@ class Ui_Form(object):
|
||||
self.set_combobox.setObjectName("set_combobox")
|
||||
self.verticalLayout.addWidget(self.set_combobox)
|
||||
self.treeWidget = QtWidgets.QTreeWidget(Form)
|
||||
self.treeWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
|
||||
self.treeWidget.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
|
||||
self.treeWidget.setHeaderHidden(True)
|
||||
self.treeWidget.setObjectName("treeWidget")
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/integratederive_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/integratederive_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# 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
|
||||
@ -13,7 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
class Ui_Dialog(object):
|
||||
def setupUi(self, Dialog):
|
||||
Dialog.setObjectName("Dialog")
|
||||
Dialog.resize(400, 308)
|
||||
Dialog.resize(400, 375)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(Dialog)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.listWidget = QtWidgets.QListWidget(Dialog)
|
||||
@ -49,6 +50,9 @@ class Ui_Dialog(object):
|
||||
self.log_checkbox = QtWidgets.QCheckBox(Dialog)
|
||||
self.log_checkbox.setObjectName("log_checkbox")
|
||||
self.verticalLayout.addWidget(self.log_checkbox)
|
||||
self.freq_box = QtWidgets.QCheckBox(Dialog)
|
||||
self.freq_box.setObjectName("freq_box")
|
||||
self.verticalLayout.addWidget(self.freq_box)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setContentsMargins(-1, 0, -1, -1)
|
||||
self.horizontalLayout_2.setSpacing(3)
|
||||
@ -67,8 +71,8 @@ class Ui_Dialog(object):
|
||||
self.verticalLayout.addWidget(self.buttonBox)
|
||||
|
||||
self.retranslateUi(Dialog)
|
||||
self.buttonBox.accepted.connect(Dialog.accept)
|
||||
self.buttonBox.rejected.connect(Dialog.reject)
|
||||
self.buttonBox.accepted.connect(Dialog.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(Dialog.reject) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||
|
||||
def retranslateUi(self, Dialog):
|
||||
@ -80,4 +84,5 @@ class Ui_Dialog(object):
|
||||
self.ft_comboBox.setItemText(1, _translate("Dialog", "Imag"))
|
||||
self.ft_comboBox.setItemText(2, _translate("Dialog", "Complex"))
|
||||
self.log_checkbox.setText(_translate("Dialog", "use logarithmic x axis"))
|
||||
self.freq_box.setText(_translate("Dialog", "return x axis as f, not omega"))
|
||||
self.newgraph_checkbox.setText(_translate("Dialog", "New graph"))
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file '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.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
|
||||
@ -54,7 +55,7 @@ class Ui_Dialog(object):
|
||||
self.gridLayout.addWidget(self.interp_comboBox, 4, 1, 1, 1)
|
||||
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
||||
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.gridLayout.addWidget(self.buttonBox, 12, 0, 1, 2)
|
||||
self.line = QtWidgets.QFrame(Dialog)
|
||||
@ -65,12 +66,13 @@ class Ui_Dialog(object):
|
||||
self.label_2 = QtWidgets.QLabel(Dialog)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout.addWidget(self.label_2, 6, 0, 1, 1)
|
||||
self.listWidget = QtWidgets.QListWidget(Dialog)
|
||||
self.listWidget = QListWidgetSelect(Dialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth())
|
||||
self.listWidget.setSizePolicy(sizePolicy)
|
||||
self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.MultiSelection)
|
||||
self.listWidget.setObjectName("listWidget")
|
||||
self.gridLayout.addWidget(self.listWidget, 1, 0, 1, 2)
|
||||
self.sampling_widget = QtWidgets.QWidget(Dialog)
|
||||
@ -130,8 +132,6 @@ class Ui_Dialog(object):
|
||||
self.label_8.setBuddy(self.dest_combobox)
|
||||
|
||||
self.retranslateUi(Dialog)
|
||||
self.buttonBox.accepted.connect(Dialog.accept)
|
||||
self.buttonBox.rejected.connect(Dialog.reject)
|
||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||
Dialog.setTabOrder(self.listWidget, self.ylog_checkBox)
|
||||
Dialog.setTabOrder(self.ylog_checkBox, self.interp_comboBox)
|
||||
@ -164,3 +164,4 @@ class Ui_Dialog(object):
|
||||
self.xaxis_comboBox.setItemText(1, _translate("Dialog", "from data"))
|
||||
self.label_8.setText(_translate("Dialog", "Add interpolated data to"))
|
||||
self.xlog_checkBox.setText(_translate("Dialog", "use log(x)"))
|
||||
from ..lib.listwidget import QListWidgetSelect
|
||||
|
@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/phase_corr_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/phase_corr_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.4
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# 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.
|
||||
@ -24,7 +24,7 @@ class Ui_SignalEdit(object):
|
||||
self.gridLayout.setContentsMargins(6, 6, 6, 6)
|
||||
self.gridLayout.setSpacing(3)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.graphicsView = PlotWidget(SignalEdit)
|
||||
self.graphicsView = NMRPlotWidget(SignalEdit)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -83,8 +83,8 @@ class Ui_SignalEdit(object):
|
||||
self.gridLayout.addItem(spacerItem1, 1, 5, 1, 1)
|
||||
|
||||
self.retranslateUi(SignalEdit)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept)
|
||||
self.buttonBox.rejected.connect(SignalEdit.close)
|
||||
self.buttonBox.accepted.connect(SignalEdit.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(SignalEdit.close) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(SignalEdit)
|
||||
|
||||
def retranslateUi(self, SignalEdit):
|
||||
@ -94,4 +94,4 @@ class Ui_SignalEdit(object):
|
||||
self.label_8.setText(_translate("SignalEdit", "Pivot"))
|
||||
self.label_6.setText(_translate("SignalEdit", "Phase 1"))
|
||||
self.label.setText(_translate("SignalEdit", "Phase 0"))
|
||||
from pyqtgraph import PlotWidget
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
|
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 -*-
|
||||
|
||||
# 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
|
||||
@ -13,29 +14,50 @@ from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
class Ui_Form(object):
|
||||
def setupUi(self, Form):
|
||||
Form.setObjectName("Form")
|
||||
Form.resize(316, 747)
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout(Form)
|
||||
self.verticalLayout.setContentsMargins(3, 3, 3, 3)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
Form.resize(417, 746)
|
||||
self.gridLayout = QtWidgets.QGridLayout(Form)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
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.setEditTriggers(QtWidgets.QAbstractItemView.DoubleClicked|QtWidgets.QAbstractItemView.EditKeyPressed)
|
||||
self.peaktable.setObjectName("peaktable")
|
||||
self.verticalLayout.addWidget(self.peaktable)
|
||||
self.groupBox = QtWidgets.QGroupBox(Form)
|
||||
self.groupBox.setObjectName("groupBox")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox)
|
||||
self.horizontalLayout.setContentsMargins(3, 3, 3, 3)
|
||||
self.horizontalLayout.setSpacing(3)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.left_pt = QtWidgets.QSpinBox(self.groupBox)
|
||||
self.left_pt.setMaximum(999)
|
||||
self.left_pt.setObjectName("left_pt")
|
||||
self.horizontalLayout.addWidget(self.left_pt)
|
||||
self.right_pt = QtWidgets.QSpinBox(self.groupBox)
|
||||
self.right_pt.setMaximum(999)
|
||||
self.right_pt.setObjectName("right_pt")
|
||||
self.horizontalLayout.addWidget(self.right_pt)
|
||||
self.average_combobox = QtWidgets.QComboBox(self.groupBox)
|
||||
self.gridLayout.addWidget(self.peaktable, 1, 0, 1, 2)
|
||||
self.special_checkbox = QtWidgets.QCheckBox(Form)
|
||||
self.special_checkbox.setObjectName("special_checkbox")
|
||||
self.gridLayout.addWidget(self.special_checkbox, 3, 0, 1, 1)
|
||||
self.special_comboBox = QtWidgets.QComboBox(Form)
|
||||
self.special_comboBox.setEnabled(False)
|
||||
self.special_comboBox.setObjectName("special_comboBox")
|
||||
self.special_comboBox.addItem("")
|
||||
self.special_comboBox.addItem("")
|
||||
self.special_comboBox.addItem("")
|
||||
self.special_comboBox.addItem("")
|
||||
self.gridLayout.addWidget(self.special_comboBox, 3, 1, 1, 1)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 30, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
|
||||
self.gridLayout.addItem(spacerItem, 4, 0, 1, 1)
|
||||
self.label_3 = QtWidgets.QLabel(Form)
|
||||
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.setHorizontalStretch(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.horizontalLayout.addWidget(self.average_combobox)
|
||||
self.verticalLayout.addWidget(self.groupBox)
|
||||
self.groupBox_2 = QtWidgets.QGroupBox(Form)
|
||||
self.groupBox_2.setCheckable(True)
|
||||
self.groupBox_2.setChecked(False)
|
||||
self.groupBox_2.setObjectName("groupBox_2")
|
||||
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.groupBox_2)
|
||||
self.horizontalLayout_5.setContentsMargins(3, 3, 3, 3)
|
||||
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.average_combobox.addItem("")
|
||||
self.gridLayout.addWidget(self.average_combobox, 6, 1, 1, 1)
|
||||
self.label_4 = QtWidgets.QLabel(Form)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.gridLayout.addWidget(self.label_4, 7, 0, 1, 1)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.xbutton = QtWidgets.QCheckBox(Form)
|
||||
self.xbutton.setObjectName("xbutton")
|
||||
self.gridLayout.addWidget(self.xbutton, 0, 0, 1, 1)
|
||||
self.ybutton = QtWidgets.QCheckBox(self.groupBox_3)
|
||||
self.horizontalLayout.addWidget(self.xbutton)
|
||||
self.ybutton = QtWidgets.QCheckBox(Form)
|
||||
self.ybutton.setChecked(True)
|
||||
self.ybutton.setObjectName("ybutton")
|
||||
self.gridLayout.addWidget(self.ybutton, 0, 1, 1, 1)
|
||||
self.graph_checkbox = QtWidgets.QCheckBox(self.groupBox_3)
|
||||
self.horizontalLayout.addWidget(self.ybutton)
|
||||
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.setObjectName("graph_checkbox")
|
||||
self.gridLayout.addWidget(self.graph_checkbox, 1, 0, 1, 1)
|
||||
self.graph_combobox = QtWidgets.QComboBox(self.groupBox_3)
|
||||
self.gridLayout.addWidget(self.graph_checkbox, 10, 0, 1, 1)
|
||||
self.graph_combobox = QtWidgets.QComboBox(Form)
|
||||
self.graph_combobox.setEnabled(False)
|
||||
self.graph_combobox.setObjectName("graph_combobox")
|
||||
self.gridLayout.addWidget(self.graph_combobox, 1, 1, 1, 1)
|
||||
self.verticalLayout.addWidget(self.groupBox_3)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setContentsMargins(-1, 0, -1, -1)
|
||||
self.horizontalLayout_2.setSpacing(2)
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.gridLayout.addWidget(self.graph_combobox, 10, 1, 1, 1)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout.addItem(spacerItem2, 12, 0, 1, 1)
|
||||
self.okButton = QtWidgets.QPushButton(Form)
|
||||
icon = QtGui.QIcon.fromTheme("dialog-ok")
|
||||
self.okButton.setIcon(icon)
|
||||
self.okButton.setObjectName("okButton")
|
||||
self.horizontalLayout_2.addWidget(self.okButton)
|
||||
self.gridLayout.addWidget(self.okButton, 11, 0, 1, 2)
|
||||
self.deleteButton = QtWidgets.QPushButton(Form)
|
||||
icon = QtGui.QIcon.fromTheme("dialog-cancel")
|
||||
self.deleteButton.setIcon(icon)
|
||||
self.deleteButton.setObjectName("deleteButton")
|
||||
self.horizontalLayout_2.addWidget(self.deleteButton)
|
||||
self.verticalLayout.addLayout(self.horizontalLayout_2)
|
||||
self.gridLayout.addWidget(self.deleteButton, 2, 0, 1, 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)
|
||||
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):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
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"
|
||||
"Single number for points (e.g. 1e-6); \n"
|
||||
"two numbers separated by space for regions (e.g. 1e-6 5e-6). \n"
|
||||
"Changing between regions and points is NOT possible"))
|
||||
self.groupBox.setTitle(_translate("Form", "Average"))
|
||||
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_checkbox.setText(_translate("Form", "Use special value"))
|
||||
self.special_comboBox.setToolTip(_translate("Form", "Automatic selection of respective points"))
|
||||
self.special_comboBox.setItemText(0, _translate("Form", "max(y)"))
|
||||
self.special_comboBox.setItemText(1, _translate("Form", "max(abs(y))"))
|
||||
self.special_comboBox.setItemText(2, _translate("Form", "min(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.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.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 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/shift_scale_dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/shift_scale_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# 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
|
||||
@ -162,7 +163,7 @@ class Ui_shift_dialog(object):
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalFrame_2)
|
||||
self.verticalLayout_2.setSpacing(3)
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.graphicsView = PlotWidget(self.verticalFrame_2)
|
||||
self.graphicsView = NMRPlotWidget(self.verticalFrame_2)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
@ -267,8 +268,8 @@ class Ui_shift_dialog(object):
|
||||
|
||||
self.retranslateUi(shift_dialog)
|
||||
self.tabWidget.setCurrentIndex(0)
|
||||
self.buttonBox.accepted.connect(shift_dialog.accept)
|
||||
self.buttonBox.rejected.connect(shift_dialog.reject)
|
||||
self.buttonBox.accepted.connect(shift_dialog.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(shift_dialog.reject) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(shift_dialog)
|
||||
shift_dialog.setTabOrder(self.tabWidget, self.shift_table)
|
||||
shift_dialog.setTabOrder(self.shift_table, self.x_shift_spinbox)
|
||||
@ -310,5 +311,5 @@ class Ui_shift_dialog(object):
|
||||
self.overwrite_checkbox.setText(_translate("shift_dialog", "Overwrite data"))
|
||||
self.data_newgraph.setText(_translate("shift_dialog", "New graph"))
|
||||
self.values_newgraph.setText(_translate("shift_dialog", "New graph"))
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
from ..lib.spinboxes import SciSpinBox
|
||||
from pyqtgraph import PlotWidget
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- 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
|
||||
@ -17,9 +18,37 @@ class Ui_SmoothDialog(object):
|
||||
self.gridLayout = QtWidgets.QGridLayout(SmoothDialog)
|
||||
self.gridLayout.setSpacing(3)
|
||||
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.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.setObjectName("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.setObjectName("iter_spinBox")
|
||||
self.horizontalLayout_3.addWidget(self.iter_spinBox)
|
||||
self.gridLayout.addWidget(self.widget_2, 3, 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.gridLayout.addWidget(self.widget_2, 4, 0, 1, 2)
|
||||
self.frac_spinBox = QtWidgets.QSpinBox(SmoothDialog)
|
||||
self.frac_spinBox.setMinimum(1)
|
||||
self.frac_spinBox.setMaximum(999)
|
||||
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.setObjectName("comboBox")
|
||||
self.comboBox.addItem("")
|
||||
@ -77,22 +86,17 @@ class Ui_SmoothDialog(object):
|
||||
self.comboBox.addItem("")
|
||||
self.comboBox.addItem("")
|
||||
self.comboBox.addItem("")
|
||||
self.gridLayout.addWidget(self.comboBox, 0, 0, 1, 2)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout.addItem(spacerItem, 6, 0, 1, 1)
|
||||
self.y_checkBox = QtWidgets.QCheckBox(SmoothDialog)
|
||||
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.gridLayout.addWidget(self.comboBox, 1, 0, 1, 2)
|
||||
self.label_2 = QtWidgets.QLabel(SmoothDialog)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.gridLayout.addWidget(self.label_2, 0, 0, 1, 2)
|
||||
self.frac_label.setBuddy(self.frac_spinBox)
|
||||
self.label_3.setBuddy(self.iter_spinBox)
|
||||
self.label.setBuddy(self.polynom_spinBox)
|
||||
self.label_3.setBuddy(self.iter_spinBox)
|
||||
|
||||
self.retranslateUi(SmoothDialog)
|
||||
self.buttonBox.accepted.connect(SmoothDialog.accept)
|
||||
self.buttonBox.rejected.connect(SmoothDialog.reject)
|
||||
self.buttonBox.accepted.connect(SmoothDialog.accept) # type: ignore
|
||||
self.buttonBox.rejected.connect(SmoothDialog.reject) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(SmoothDialog)
|
||||
SmoothDialog.setTabOrder(self.comboBox, self.frac_spinBox)
|
||||
SmoothDialog.setTabOrder(self.frac_spinBox, self.polynom_spinBox)
|
||||
@ -104,9 +108,11 @@ class Ui_SmoothDialog(object):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
SmoothDialog.setWindowTitle(_translate("SmoothDialog", "1D smoothing filter"))
|
||||
self.frac_label.setText(_translate("SmoothDialog", "Window length"))
|
||||
self.label_3.setText(_translate("SmoothDialog", "Iterations"))
|
||||
self.label.setText(_translate("SmoothDialog", "Polynomial degree"))
|
||||
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.comboBox.setItemText(0, _translate("SmoothDialog", "Moving mean"))
|
||||
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(7, _translate("SmoothDialog", "Moving minimum"))
|
||||
self.comboBox.setItemText(8, _translate("SmoothDialog", "Moving sum"))
|
||||
self.y_checkBox.setText(_translate("SmoothDialog", "y log-spaced?"))
|
||||
self.x_checkBox.setText(_translate("SmoothDialog", "x 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>"))
|
||||
|
@ -1,10 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/t1dialog.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/t1dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.12.3
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# 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
|
||||
@ -160,6 +161,7 @@ class Ui_t1dialog(object):
|
||||
self.tau_combox.addItem("")
|
||||
self.gridLayout_4.addWidget(self.tau_combox, 1, 0, 1, 2)
|
||||
self.checkBox_interpol = QtWidgets.QCheckBox(self.groupBox_3)
|
||||
self.checkBox_interpol.setEnabled(False)
|
||||
self.checkBox_interpol.setObjectName("checkBox_interpol")
|
||||
self.gridLayout_4.addWidget(self.checkBox_interpol, 2, 0, 1, 2)
|
||||
self.graph_checkbox = QtWidgets.QCheckBox(self.groupBox_3)
|
||||
|
253
src/gui_qt/_py/tnmh_dialog.py
Normal file
253
src/gui_qt/_py/tnmh_dialog.py
Normal file
@ -0,0 +1,253 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/tnmh_dialog.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# 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_DSCEvalDialog(object):
|
||||
def setupUi(self, DSCEvalDialog):
|
||||
DSCEvalDialog.setObjectName("DSCEvalDialog")
|
||||
DSCEvalDialog.resize(996, 712)
|
||||
self.gridLayout = QtWidgets.QGridLayout(DSCEvalDialog)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.listWidget = QListWidgetSelect(DSCEvalDialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Expanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.listWidget.sizePolicy().hasHeightForWidth())
|
||||
self.listWidget.setSizePolicy(sizePolicy)
|
||||
self.listWidget.setSelectionMode(QtWidgets.QAbstractItemView.ExtendedSelection)
|
||||
self.listWidget.setObjectName("listWidget")
|
||||
self.gridLayout.addWidget(self.listWidget, 0, 0, 1, 1)
|
||||
self.stackedWidget = QtWidgets.QStackedWidget(DSCEvalDialog)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.stackedWidget.sizePolicy().hasHeightForWidth())
|
||||
self.stackedWidget.setSizePolicy(sizePolicy)
|
||||
self.stackedWidget.setFrameShape(QtWidgets.QFrame.Box)
|
||||
self.stackedWidget.setObjectName("stackedWidget")
|
||||
self.page = QtWidgets.QWidget()
|
||||
self.page.setObjectName("page")
|
||||
self.gridLayout_2 = QtWidgets.QGridLayout(self.page)
|
||||
self.gridLayout_2.setObjectName("gridLayout_2")
|
||||
self.gridLayout_9 = QtWidgets.QGridLayout()
|
||||
self.gridLayout_9.setObjectName("gridLayout_9")
|
||||
self.tg_export_check = QtWidgets.QCheckBox(self.page)
|
||||
self.tg_export_check.setChecked(True)
|
||||
self.tg_export_check.setObjectName("tg_export_check")
|
||||
self.gridLayout_9.addWidget(self.tg_export_check, 0, 0, 1, 1)
|
||||
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_9.addItem(spacerItem, 3, 0, 1, 1)
|
||||
self.tglines_export_check = QtWidgets.QCheckBox(self.page)
|
||||
self.tglines_export_check.setChecked(True)
|
||||
self.tglines_export_check.setObjectName("tglines_export_check")
|
||||
self.gridLayout_9.addWidget(self.tglines_export_check, 0, 1, 1, 1)
|
||||
self.tg_export_button = QtWidgets.QPushButton(self.page)
|
||||
self.tg_export_button.setObjectName("tg_export_button")
|
||||
self.gridLayout_9.addWidget(self.tg_export_button, 2, 0, 1, 2)
|
||||
self.gridLayout_2.addLayout(self.gridLayout_9, 2, 1, 1, 1)
|
||||
self.tg_tree = QtWidgets.QTreeWidget(self.page)
|
||||
self.tg_tree.setObjectName("tg_tree")
|
||||
self.tg_tree.headerItem().setText(0, "1")
|
||||
self.tg_tree.header().setVisible(False)
|
||||
self.gridLayout_2.addWidget(self.tg_tree, 2, 0, 1, 1)
|
||||
self.dsc_plot = NMRPlotWidget(self.page)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.dsc_plot.sizePolicy().hasHeightForWidth())
|
||||
self.dsc_plot.setSizePolicy(sizePolicy)
|
||||
self.dsc_plot.setObjectName("dsc_plot")
|
||||
self.gridLayout_2.addWidget(self.dsc_plot, 1, 0, 1, 2)
|
||||
self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
|
||||
self.label = QtWidgets.QLabel(self.page)
|
||||
self.label.setObjectName("label")
|
||||
self.horizontalLayout_4.addWidget(self.label)
|
||||
self.calctg_button = QtWidgets.QPushButton(self.page)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.calctg_button.sizePolicy().hasHeightForWidth())
|
||||
self.calctg_button.setSizePolicy(sizePolicy)
|
||||
self.calctg_button.setObjectName("calctg_button")
|
||||
self.horizontalLayout_4.addWidget(self.calctg_button)
|
||||
self.gridLayout_2.addLayout(self.horizontalLayout_4, 0, 0, 1, 2)
|
||||
self.stackedWidget.addWidget(self.page)
|
||||
self.page_2 = QtWidgets.QWidget()
|
||||
self.page_2.setObjectName("page_2")
|
||||
self.gridLayout_3 = QtWidgets.QGridLayout(self.page_2)
|
||||
self.gridLayout_3.setObjectName("gridLayout_3")
|
||||
self.label_4 = QtWidgets.QLabel(self.page_2)
|
||||
self.label_4.setObjectName("label_4")
|
||||
self.gridLayout_3.addWidget(self.label_4, 2, 0, 1, 1)
|
||||
self.tghodge_graph = NMRPlotWidget(self.page_2)
|
||||
self.tghodge_graph.setObjectName("tghodge_graph")
|
||||
self.gridLayout_3.addWidget(self.tghodge_graph, 1, 0, 1, 1)
|
||||
self.tau_plot = NMRPlotWidget(self.page_2)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.MinimumExpanding)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.tau_plot.sizePolicy().hasHeightForWidth())
|
||||
self.tau_plot.setSizePolicy(sizePolicy)
|
||||
self.tau_plot.setObjectName("tau_plot")
|
||||
self.gridLayout_3.addWidget(self.tau_plot, 1, 1, 1, 1)
|
||||
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
|
||||
self.label_2 = QtWidgets.QLabel(self.page_2)
|
||||
self.label_2.setObjectName("label_2")
|
||||
self.horizontalLayout_3.addWidget(self.label_2)
|
||||
self.hodge_button = QtWidgets.QPushButton(self.page_2)
|
||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
|
||||
sizePolicy.setHorizontalStretch(0)
|
||||
sizePolicy.setVerticalStretch(0)
|
||||
sizePolicy.setHeightForWidth(self.hodge_button.sizePolicy().hasHeightForWidth())
|
||||
self.hodge_button.setSizePolicy(sizePolicy)
|
||||
self.hodge_button.setObjectName("hodge_button")
|
||||
self.horizontalLayout_3.addWidget(self.hodge_button)
|
||||
self.gridLayout_3.addLayout(self.horizontalLayout_3, 0, 0, 1, 2)
|
||||
self.export_hodge_button = QtWidgets.QPushButton(self.page_2)
|
||||
self.export_hodge_button.setObjectName("export_hodge_button")
|
||||
self.gridLayout_3.addWidget(self.export_hodge_button, 5, 1, 1, 1)
|
||||
self.hodge_graph_combo = QtWidgets.QComboBox(self.page_2)
|
||||
self.hodge_graph_combo.setEnabled(False)
|
||||
self.hodge_graph_combo.setObjectName("hodge_graph_combo")
|
||||
self.gridLayout_3.addWidget(self.hodge_graph_combo, 4, 1, 1, 1)
|
||||
self.hodge_graph_check = QtWidgets.QCheckBox(self.page_2)
|
||||
self.hodge_graph_check.setChecked(True)
|
||||
self.hodge_graph_check.setObjectName("hodge_graph_check")
|
||||
self.gridLayout_3.addWidget(self.hodge_graph_check, 4, 0, 1, 1)
|
||||
self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
|
||||
self.onset_check = QtWidgets.QCheckBox(self.page_2)
|
||||
self.onset_check.setChecked(True)
|
||||
self.onset_check.setObjectName("onset_check")
|
||||
self.horizontalLayout_5.addWidget(self.onset_check)
|
||||
self.mid_check = QtWidgets.QCheckBox(self.page_2)
|
||||
self.mid_check.setChecked(True)
|
||||
self.mid_check.setObjectName("mid_check")
|
||||
self.horizontalLayout_5.addWidget(self.mid_check)
|
||||
self.end_check = QtWidgets.QCheckBox(self.page_2)
|
||||
self.end_check.setChecked(True)
|
||||
self.end_check.setObjectName("end_check")
|
||||
self.horizontalLayout_5.addWidget(self.end_check)
|
||||
self.inflection_check = QtWidgets.QCheckBox(self.page_2)
|
||||
self.inflection_check.setChecked(True)
|
||||
self.inflection_check.setObjectName("inflection_check")
|
||||
self.horizontalLayout_5.addWidget(self.inflection_check)
|
||||
self.fictive_check = QtWidgets.QCheckBox(self.page_2)
|
||||
self.fictive_check.setChecked(True)
|
||||
self.fictive_check.setObjectName("fictive_check")
|
||||
self.horizontalLayout_5.addWidget(self.fictive_check)
|
||||
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout_5.addItem(spacerItem1)
|
||||
self.gridLayout_3.addLayout(self.horizontalLayout_5, 3, 0, 1, 2)
|
||||
self.stackedWidget.addWidget(self.page_2)
|
||||
self.page_3 = QtWidgets.QWidget()
|
||||
self.page_3.setObjectName("page_3")
|
||||
self.gridLayout_6 = QtWidgets.QGridLayout(self.page_3)
|
||||
self.gridLayout_6.setObjectName("gridLayout_6")
|
||||
self.tnmh_graphics = NMRPlotWidget(self.page_3)
|
||||
self.tnmh_graphics.setObjectName("tnmh_graphics")
|
||||
self.gridLayout_6.addWidget(self.tnmh_graphics, 1, 0, 1, 2)
|
||||
self.tnmh_tree = QtWidgets.QTreeWidget(self.page_3)
|
||||
self.tnmh_tree.setObjectName("tnmh_tree")
|
||||
self.tnmh_tree.headerItem().setText(0, "1")
|
||||
self.tnmh_tree.header().setVisible(False)
|
||||
self.gridLayout_6.addWidget(self.tnmh_tree, 2, 0, 1, 1)
|
||||
self.gridLayout_5 = QtWidgets.QGridLayout()
|
||||
self.gridLayout_5.setObjectName("gridLayout_5")
|
||||
self.tnmh_graph_check = QtWidgets.QCheckBox(self.page_3)
|
||||
self.tnmh_graph_check.setChecked(True)
|
||||
self.tnmh_graph_check.setObjectName("tnmh_graph_check")
|
||||
self.gridLayout_5.addWidget(self.tnmh_graph_check, 1, 0, 1, 1)
|
||||
self.tnmhfit_export_check = QtWidgets.QCheckBox(self.page_3)
|
||||
self.tnmhfit_export_check.setChecked(True)
|
||||
self.tnmhfit_export_check.setObjectName("tnmhfit_export_check")
|
||||
self.gridLayout_5.addWidget(self.tnmhfit_export_check, 0, 0, 1, 1)
|
||||
self.tnmh_export_button = QtWidgets.QPushButton(self.page_3)
|
||||
self.tnmh_export_button.setObjectName("tnmh_export_button")
|
||||
self.gridLayout_5.addWidget(self.tnmh_export_button, 2, 0, 1, 2)
|
||||
self.fictive_export_check = QtWidgets.QCheckBox(self.page_3)
|
||||
self.fictive_export_check.setChecked(True)
|
||||
self.fictive_export_check.setObjectName("fictive_export_check")
|
||||
self.gridLayout_5.addWidget(self.fictive_export_check, 0, 1, 1, 1)
|
||||
self.tnmh_graph_combo = QtWidgets.QComboBox(self.page_3)
|
||||
self.tnmh_graph_combo.setEnabled(False)
|
||||
self.tnmh_graph_combo.setObjectName("tnmh_graph_combo")
|
||||
self.gridLayout_5.addWidget(self.tnmh_graph_combo, 1, 1, 1, 1)
|
||||
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
|
||||
self.gridLayout_5.addItem(spacerItem2, 3, 0, 1, 1)
|
||||
self.gridLayout_6.addLayout(self.gridLayout_5, 2, 1, 1, 1)
|
||||
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||
self.label_3 = QtWidgets.QLabel(self.page_3)
|
||||
self.label_3.setObjectName("label_3")
|
||||
self.horizontalLayout_2.addWidget(self.label_3)
|
||||
self.tnhm_fitbutton = QtWidgets.QPushButton(self.page_3)
|
||||
self.tnhm_fitbutton.setObjectName("tnhm_fitbutton")
|
||||
self.horizontalLayout_2.addWidget(self.tnhm_fitbutton)
|
||||
self.gridLayout_6.addLayout(self.horizontalLayout_2, 0, 0, 1, 2)
|
||||
self.stackedWidget.addWidget(self.page_3)
|
||||
self.gridLayout.addWidget(self.stackedWidget, 0, 1, 1, 1)
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
spacerItem3 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
|
||||
self.horizontalLayout.addItem(spacerItem3)
|
||||
self.back_button = QtWidgets.QToolButton(DSCEvalDialog)
|
||||
self.back_button.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
|
||||
self.back_button.setArrowType(QtCore.Qt.LeftArrow)
|
||||
self.back_button.setObjectName("back_button")
|
||||
self.horizontalLayout.addWidget(self.back_button)
|
||||
self.next_button = QtWidgets.QToolButton(DSCEvalDialog)
|
||||
self.next_button.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
|
||||
self.next_button.setArrowType(QtCore.Qt.RightArrow)
|
||||
self.next_button.setObjectName("next_button")
|
||||
self.horizontalLayout.addWidget(self.next_button)
|
||||
self.close_button = QtWidgets.QPushButton(DSCEvalDialog)
|
||||
self.close_button.setObjectName("close_button")
|
||||
self.horizontalLayout.addWidget(self.close_button)
|
||||
self.gridLayout.addLayout(self.horizontalLayout, 1, 0, 1, 2)
|
||||
|
||||
self.retranslateUi(DSCEvalDialog)
|
||||
self.stackedWidget.setCurrentIndex(0)
|
||||
self.close_button.clicked.connect(DSCEvalDialog.close) # type: ignore
|
||||
QtCore.QMetaObject.connectSlotsByName(DSCEvalDialog)
|
||||
|
||||
def retranslateUi(self, DSCEvalDialog):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
DSCEvalDialog.setWindowTitle(_translate("DSCEvalDialog", "To boldly go where no man has gone before"))
|
||||
self.tg_export_check.setText(_translate("DSCEvalDialog", "Export Tg"))
|
||||
self.tglines_export_check.setText(_translate("DSCEvalDialog", "Export lines"))
|
||||
self.tg_export_button.setText(_translate("DSCEvalDialog", "Export"))
|
||||
self.label.setText(_translate("DSCEvalDialog", "<html><head/><body><p><span style=\" font-weight:600;\">Glass transition</span></p></body></html>"))
|
||||
self.calctg_button.setText(_translate("DSCEvalDialog", "Calculate Tg"))
|
||||
self.label_4.setText(_translate("DSCEvalDialog", "Export tau:"))
|
||||
self.label_2.setText(_translate("DSCEvalDialog", "<html><head/><body><p><span style=\" font-weight:600;\">Hodge tau</span></p></body></html>"))
|
||||
self.hodge_button.setText(_translate("DSCEvalDialog", "Make it so."))
|
||||
self.export_hodge_button.setText(_translate("DSCEvalDialog", "Export"))
|
||||
self.hodge_graph_check.setText(_translate("DSCEvalDialog", "New graph"))
|
||||
self.onset_check.setText(_translate("DSCEvalDialog", "Onset"))
|
||||
self.mid_check.setText(_translate("DSCEvalDialog", "Midpoint"))
|
||||
self.end_check.setText(_translate("DSCEvalDialog", "End"))
|
||||
self.inflection_check.setText(_translate("DSCEvalDialog", "Inflection"))
|
||||
self.fictive_check.setText(_translate("DSCEvalDialog", "Fictive"))
|
||||
self.tnmh_graph_check.setText(_translate("DSCEvalDialog", "New graph"))
|
||||
self.tnmhfit_export_check.setText(_translate("DSCEvalDialog", "Export fit"))
|
||||
self.tnmh_export_button.setText(_translate("DSCEvalDialog", "Export"))
|
||||
self.fictive_export_check.setText(_translate("DSCEvalDialog", "Export dTf / dT"))
|
||||
self.label_3.setText(_translate("DSCEvalDialog", "<html><head/><body><p><span style=\" font-weight:600;\">dTf/dT and TNMH </span></p></body></html>"))
|
||||
self.tnhm_fitbutton.setText(_translate("DSCEvalDialog", "Engage!"))
|
||||
self.back_button.setText(_translate("DSCEvalDialog", "Back"))
|
||||
self.next_button.setText(_translate("DSCEvalDialog", "Next"))
|
||||
self.close_button.setText(_translate("DSCEvalDialog", "Close"))
|
||||
from ..lib.graph_items import NMRPlotWidget
|
||||
from ..lib.listwidget import QListWidgetSelect
|
@ -2,9 +2,10 @@
|
||||
|
||||
# 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
|
||||
@ -20,15 +21,12 @@ class Ui_MainWindow(object):
|
||||
self.verticalLayout.setContentsMargins(3, 3, 3, 3)
|
||||
self.verticalLayout.setSpacing(3)
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.edit_field = CodeEditor(self.centralwidget)
|
||||
font = QtGui.QFont()
|
||||
font.setPointSize(10)
|
||||
self.edit_field.setFont(font)
|
||||
self.edit_field.setObjectName("edit_field")
|
||||
self.verticalLayout.addWidget(self.edit_field)
|
||||
self.widget = EditorWidget(self.centralwidget)
|
||||
self.widget.setObjectName("widget")
|
||||
self.verticalLayout.addWidget(self.widget)
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
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.menuFile = QtWidgets.QMenu(self.menubar)
|
||||
self.menuFile.setObjectName("menuFile")
|
||||
@ -61,4 +59,4 @@ class Ui_MainWindow(object):
|
||||
self.actionSave.setText(_translate("MainWindow", "Save"))
|
||||
self.actionSave_as.setText(_translate("MainWindow", "Save as..."))
|
||||
self.actionClose.setText(_translate("MainWindow", "Close"))
|
||||
from ..lib.codeeditor import CodeEditor
|
||||
from ..lib.codeeditor import EditorWidget
|
||||
|
@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'resources/_ui/valueeditor.ui'
|
||||
# Form implementation generated from reading ui file 'src/resources/_ui/valueeditor.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.15.4
|
||||
# Created by: PyQt5 UI code generator 5.15.9
|
||||
#
|
||||
# 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.
|
||||
|
@ -8,8 +8,10 @@ from pyqtgraph import mkPen
|
||||
|
||||
from nmreval.data.points import Points
|
||||
from nmreval.data.signals import Signal
|
||||
from nmreval.lib.logger import logger
|
||||
from nmreval.utils.text import convert
|
||||
from nmreval.data.bds import BDS
|
||||
from nmreval.data.dsc import DSC
|
||||
from nmreval.lib.colors import BaseColor, TUColors
|
||||
from nmreval.lib.lines import LineStyle
|
||||
from nmreval.lib.symbols import SymbolStyle, symbolcycle
|
||||
@ -32,6 +34,7 @@ class ExperimentContainer(QtCore.QObject):
|
||||
self.id = str(identifier)
|
||||
|
||||
self._fits = []
|
||||
self._relations = kwargs.get('relations', {})
|
||||
self._data = data
|
||||
self._manager = kwargs.get('manager')
|
||||
self.graph = ''
|
||||
@ -44,6 +47,7 @@ class ExperimentContainer(QtCore.QObject):
|
||||
self.actions = {}
|
||||
self._update_actions()
|
||||
|
||||
@plot_update
|
||||
def _init_plot(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@ -226,6 +230,8 @@ class ExperimentContainer(QtCore.QObject):
|
||||
return self.plot_real, self.plot_imag, self.plot_error
|
||||
|
||||
def get_state(self):
|
||||
# TODO preserve relationships
|
||||
|
||||
ret_dic = {
|
||||
'id': self.id,
|
||||
'data': self._data.get_state(),
|
||||
@ -267,11 +273,39 @@ class ExperimentContainer(QtCore.QObject):
|
||||
else:
|
||||
self._fits.extend(value)
|
||||
|
||||
def has_relation(self, relation_type):
|
||||
return relation_type in self._relations
|
||||
|
||||
def get_relation(self, relation_type: int):
|
||||
return self._relations.get(relation_type, [])
|
||||
|
||||
def add_relation(self, relation_type: int, value: str):
|
||||
if relation_type not in self._relations:
|
||||
self._relations[relation_type] = []
|
||||
|
||||
self._relations[relation_type].append(value)
|
||||
|
||||
def remove_relation(self, relation_type: int, value: str):
|
||||
if relation_type not in self._relations:
|
||||
raise ValueError(f'Relationship {relation_type!r} with id {value!r} doe not exist for {self.name}')
|
||||
|
||||
related_id_value = self._relations[relation_type]
|
||||
|
||||
idx = related_id_value.index(value)
|
||||
if idx == -1:
|
||||
raise ValueError(f'Relationship {relation_type!r} with id {value!r} doe not exist for {self.name}')
|
||||
|
||||
related_id_value.pop(idx)
|
||||
if len(related_id_value) == 0:
|
||||
self._relations.pop(relation_type)
|
||||
|
||||
def _update_actions(self):
|
||||
self.actions.update({'sort': self._data.sort,
|
||||
self.actions.update({
|
||||
'sort': self._data.sort,
|
||||
'cut': self._data.cut,
|
||||
'norm': self._data.normalize,
|
||||
'center': self.center})
|
||||
'center': self.center,
|
||||
})
|
||||
|
||||
@plot_update
|
||||
def update(self, opts: dict):
|
||||
@ -279,9 +313,11 @@ class ExperimentContainer(QtCore.QObject):
|
||||
|
||||
def get_properties(self) -> dict:
|
||||
props = OrderedDict()
|
||||
props['General'] = OrderedDict([('Name', self.name),
|
||||
props['General'] = OrderedDict([
|
||||
('Name', self.name),
|
||||
('Value', str(self.value)),
|
||||
('Group', str(self.group))])
|
||||
('Group', str(self.group)),
|
||||
])
|
||||
props['Symbol'] = OrderedDict()
|
||||
props['Line'] = OrderedDict()
|
||||
|
||||
@ -312,12 +348,10 @@ class ExperimentContainer(QtCore.QObject):
|
||||
err_pen.setColor(QtGui.QColor(*self.plot_real.symbolcolor.rgb()))
|
||||
self.plot_error.setData(pen=err_pen)
|
||||
|
||||
elif mode == 'imag' and self.plot_imag is not None:
|
||||
if mode in ['imag', 'all'] and self.plot_imag is not None:
|
||||
self.plot_imag.set_color(color, symbol=symbol, line=line)
|
||||
else:
|
||||
print('Updating color failed for ' + str(self.id))
|
||||
|
||||
def setSymbol(self, symbol=None, color=None, size=None, mode='real'):
|
||||
def setSymbol(self, *, symbol=None, color=None, size=None, mode='real'):
|
||||
if mode in ['real', 'all']:
|
||||
self.plot_real.set_symbol(symbol=symbol, size=size, color=color)
|
||||
if color is not None and self.plot_error is not None and self.plot_real.symbol != SymbolStyle.No:
|
||||
@ -327,9 +361,9 @@ class ExperimentContainer(QtCore.QObject):
|
||||
elif mode in ['imag', 'all'] and self.plot_imag is not None:
|
||||
self.plot_imag.set_symbol(symbol=symbol, size=size, color=color)
|
||||
else:
|
||||
print('Updating symbol failed for ' + str(self.id))
|
||||
logger.warning(f'Updating symbol failed for {self.id}')
|
||||
|
||||
def setLine(self, width=None, style=None, color=None, mode='real'):
|
||||
def setLine(self, *, width=None, style=None, color=None, mode='real'):
|
||||
if mode in ['real', 'all']:
|
||||
self.plot_real.set_line(width=width, style=style, color=color)
|
||||
if color is not None and self.plot_error is not None and self.plot_real.symbol == SymbolStyle.No:
|
||||
@ -339,7 +373,7 @@ class ExperimentContainer(QtCore.QObject):
|
||||
elif mode in ['imag', 'all'] and self.plot_imag is not None:
|
||||
self.plot_imag.set_line(width=width, style=style, color=color)
|
||||
else:
|
||||
print('Updating line failed for ' + str(self.id))
|
||||
logger.warning(f'Updating line failed for {self.id}')
|
||||
|
||||
def update_property(self, key1: str, key2: str, value: Any):
|
||||
keykey = key2.split()
|
||||
@ -434,16 +468,28 @@ class ExperimentContainer(QtCore.QObject):
|
||||
|
||||
return offset
|
||||
|
||||
@plot_update
|
||||
def shift_scale(self, shift_factor: tuple[float, float], scaling_factor: tuple[float, float]):
|
||||
scale_x, scale_y = scaling_factor
|
||||
shift_x, shift_y = shift_factor
|
||||
self.data.x = self.data.x * scale_x + shift_x
|
||||
self.data.y = self.data.y * scale_y + shift_y
|
||||
self.data.y_err = self.data.y_err * scale_y
|
||||
|
||||
self.update({'shift': scaling_factor, 'scale': shift_factor})
|
||||
|
||||
def get_namespace(self, i: int = None, j: int = None) -> dict:
|
||||
if (i is None) and (j is None):
|
||||
prefix = ''
|
||||
else:
|
||||
prefix = 'g[%i].s[%i].' % (i, 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_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:
|
||||
namespace.update({
|
||||
@ -459,27 +505,50 @@ class ExperimentContainer(QtCore.QObject):
|
||||
|
||||
return namespace
|
||||
|
||||
def eval_expression(self, cmds, namespace):
|
||||
namespace.update({'x': self.x, 'y': self.y, 'y_err': self.y_err, 'value': self.value})
|
||||
def eval_expression(self, cmds, namespace, i=None, j=None):
|
||||
if i is not None:
|
||||
namespace['i'] = i
|
||||
|
||||
if len(self._fits) == 1:
|
||||
namespace.update({"fit['%s']" % (convert(pname, old='tex', new='str')): pvalue.value
|
||||
for (pname, pvalue) in self._manager[self._fits[0]].parameter.items()})
|
||||
if j is not None:
|
||||
namespace['j'] = j
|
||||
|
||||
namespace.update({'x': self._data.x, 'y': self._data.y, 'y_err': self._data.y_err, 'value': self.value})
|
||||
namespace['fit'] = {}
|
||||
|
||||
if isinstance(self, FitContainer):
|
||||
namespace['fit'].update({
|
||||
'%s' % convert(pname, old='latex', new='plain'): pvalue.value
|
||||
for (pname, pvalue) in self._data.parameter.items()
|
||||
})
|
||||
|
||||
elif len(self._fits) == 1:
|
||||
namespace['fit'].update({
|
||||
'%s' % convert(pname, old='tex', new='str'): pvalue.value
|
||||
for (pname, pvalue) in self._manager[self._fits[0]].parameter.items()
|
||||
})
|
||||
else:
|
||||
for k, f in enumerate(self._fits):
|
||||
namespace.update({"fit['%s_%i']" % (convert(pname, old='tex', new='str'), k): pvalue.value
|
||||
for (pname, pvalue) in self._manager[f].parameter.items()})
|
||||
namespace['fit'].update({
|
||||
"%s_%i" % (convert(pname, old='tex', new='str'), k): pvalue.value
|
||||
for (pname, pvalue) in self._manager[f].parameter.items()
|
||||
})
|
||||
|
||||
new_data = self.copy()
|
||||
for c in cmds:
|
||||
if c:
|
||||
exec(c, globals(), namespace)
|
||||
|
||||
new_data.set_data(x=namespace['x'], y=namespace['y'], y_err=namespace['y_err'])
|
||||
new_data.set_data(x=namespace['x'], y=namespace['y'], y_err=namespace['y_err'], replace_mask=False)
|
||||
new_data.value = namespace['value']
|
||||
|
||||
return new_data
|
||||
|
||||
def binning(self, digits: float):
|
||||
new_data = self.copy(full=True)
|
||||
new_data.data = self._data.binning(value=digits)
|
||||
|
||||
return new_data
|
||||
|
||||
|
||||
class PointContainer(ExperimentContainer):
|
||||
symbols = symbolcycle()
|
||||
@ -490,6 +559,9 @@ class PointContainer(ExperimentContainer):
|
||||
self.mode = 'pts'
|
||||
self._init_plot(**kwargs)
|
||||
|
||||
if isinstance(self._data, DSC):
|
||||
self.mode = 'dsc'
|
||||
|
||||
def _init_plot(self, **kwargs):
|
||||
self.plot_imag = None
|
||||
|
||||
@ -526,17 +598,17 @@ class PointContainer(ExperimentContainer):
|
||||
line_kwargs['style'] = LineStyle.No
|
||||
sym_kwargs['symbol'] = next(PointContainer.symbols)
|
||||
|
||||
self.plot_real = PlotItem(x=self._data.x, y=self._data.y, name=self.name,
|
||||
self.plot_real = PlotItem(x=self.x, y=self.y, name=self.name,
|
||||
symbol=None, pen=None, connect='finite')
|
||||
|
||||
self.setSymbol(mode='real', **sym_kwargs)
|
||||
self.setLine(mode='real', **line_kwargs)
|
||||
|
||||
if sym_kwargs['symbol'] != SymbolStyle.No:
|
||||
self.plot_error = ErrorBars(x=self._data.x, y=self._data.y, top=self._data.y_err, bottom=self._data.y_err,
|
||||
self.plot_error = ErrorBars(x=self.x, y=self.y, top=self.y_err, bottom=self.y_err,
|
||||
pen=mkPen({'color': self.plot_real.symbolcolor.rgb()}))
|
||||
else:
|
||||
self.plot_error = ErrorBars(x=self._data.x, y=self._data.y, top=self._data.y_err, bottom=self._data.y_err,
|
||||
self.plot_error = ErrorBars(x=self.x, y=self.y, top=self.y_err, bottom=self.y_err,
|
||||
pen=mkPen({'color': self.plot_real.linecolor.rgb()}))
|
||||
|
||||
|
||||
@ -559,12 +631,12 @@ class FitContainer(ExperimentContainer):
|
||||
if isinstance(color, BaseColor):
|
||||
color = color.rgb()
|
||||
|
||||
self.plot_real = PlotItem(x=self._data.x, y=self._data.y.real, name=self.name,
|
||||
self.plot_real = PlotItem(x=self.x, y=self.y.real, name=self.name,
|
||||
pen=mkPen({'color': color}),
|
||||
connect='finite', symbol=None)
|
||||
|
||||
if np.iscomplexobj(self._data.y):
|
||||
self.plot_imag = PlotItem(x=self._data.x, y=self._data.y.imag, name=self.name,
|
||||
self.plot_imag = PlotItem(x=self.x, y=self.y.imag, name=self.name,
|
||||
pen=mkPen({'color': color}),
|
||||
connect='finite', symbol=None)
|
||||
|
||||
@ -597,9 +669,9 @@ class SignalContainer(ExperimentContainer):
|
||||
self._init_plot(symbol=symbol, **kwargs)
|
||||
|
||||
def _init_plot(self, **kwargs):
|
||||
self.plot_real = PlotItem(x=self._data.x, y=self._data.y.real, name=self.name,
|
||||
self.plot_real = PlotItem(x=self.x, y=self.y.real, name=self.name,
|
||||
symbol=None, pen=None, connect='finite')
|
||||
self.plot_imag = PlotItem(x=self._data.x, y=self._data.y.imag, name=self.name,
|
||||
self.plot_imag = PlotItem(x=self.x, y=self.y.imag, name=self.name,
|
||||
symbol=None, pen=None, connect='finite')
|
||||
|
||||
color = kwargs.get('color', None)
|
||||
@ -683,3 +755,46 @@ class SignalContainer(ExperimentContainer):
|
||||
self._update_actions()
|
||||
|
||||
return self
|
||||
|
||||
@plot_update
|
||||
def edit_signal(
|
||||
self: SignalContainer,
|
||||
baseline: tuple[None | bool],
|
||||
leftshift: tuple[None | float, str],
|
||||
zerofill: tuple[None, int],
|
||||
apod: tuple[None, list[float], type[object]],
|
||||
phase: tuple[None | float, float, float],
|
||||
fourier: tuple[None | bool]
|
||||
):
|
||||
"""
|
||||
Function for EditUndoCommand to call if a timesignal or spectra must be worked on.
|
||||
This avoids to update the plot for every action we do and makes it slightly faster.
|
||||
"""
|
||||
|
||||
if baseline[0] is not None:
|
||||
self._data.baseline()
|
||||
|
||||
if leftshift[0] is not None:
|
||||
self._data.shift(*leftshift)
|
||||
|
||||
if zerofill[0] is not None:
|
||||
self._data.zerofill(*zerofill)
|
||||
|
||||
if apod[0] is not None:
|
||||
self._data.apod(*apod)
|
||||
|
||||
# ft with three options: None, True, False
|
||||
if fourier[0] is None:
|
||||
# ft None -> only phase correct
|
||||
if phase[0] is not None:
|
||||
self._data.manual_phase(*phase)
|
||||
elif fourier[0] == True:
|
||||
# ft True -> first phase correct then fft
|
||||
if phase[0] is not None:
|
||||
self._data.manual_phase(*phase)
|
||||
self.fourier()
|
||||
else:
|
||||
# ft False -> first fft then phase correct
|
||||
self.fourier()
|
||||
if phase[0] is not None:
|
||||
self._data.manual_phase(*phase)
|
@ -5,7 +5,7 @@ from nmreval.lib.colors import available_cycles
|
||||
from .properties import PropWidget
|
||||
from ...Qt import QtWidgets, QtGui, QtCore
|
||||
from ..._py.datawidget import Ui_DataWidget
|
||||
from ...lib import make_action_icons
|
||||
from ...lib.iconloading import make_action_icons
|
||||
from ...lib.delegates import HeaderDelegate
|
||||
|
||||
|
||||
@ -17,8 +17,9 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
moveItem = QtCore.pyqtSignal(list, str, str, int) # items, from, to, new row
|
||||
copyItem = QtCore.pyqtSignal(list, str)
|
||||
saveFits = QtCore.pyqtSignal(list)
|
||||
extendFits = QtCore.pyqtSignal(list)
|
||||
extendFits = QtCore.pyqtSignal(list, bool)
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
@ -48,11 +49,16 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
|
||||
def add_graph(self, idd: str, name: str):
|
||||
item = QtWidgets.QTreeWidgetItem()
|
||||
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDropEnabled | QtCore.Qt.ItemIsEditable |
|
||||
QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable)
|
||||
item.setFlags(
|
||||
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.setData(0, QtCore.Qt.UserRole, idd)
|
||||
item.setCheckState(0, QtCore.Qt.Checked)
|
||||
item.setData(0, QtCore.Qt.ItemDataRole.UserRole, idd)
|
||||
item.setCheckState(0, QtCore.Qt.CheckState.Checked)
|
||||
|
||||
self.addTopLevelItem(item)
|
||||
self._checked_graphs.add(idd)
|
||||
@ -60,31 +66,37 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
|
||||
self.update_indexes()
|
||||
|
||||
def add_item(self, items: (tuple | list[tuple]), gid: str):
|
||||
def add_item(self, items: (tuple | list[tuple]), gid: str, update: bool = True):
|
||||
if isinstance(items, tuple):
|
||||
items = [items]
|
||||
|
||||
for row in range(self.invisibleRootItem().childCount()):
|
||||
graph = self.invisibleRootItem().child(row)
|
||||
if graph.data(0, QtCore.Qt.UserRole) == gid:
|
||||
for (idd, name) in items:
|
||||
if graph.data(0, QtCore.Qt.ItemDataRole.UserRole) == gid:
|
||||
for (idd, name, value) in items:
|
||||
item = QtWidgets.QTreeWidgetItem([name])
|
||||
item.setData(0, QtCore.Qt.UserRole, idd)
|
||||
item.setCheckState(0, QtCore.Qt.Checked)
|
||||
item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsEditable |
|
||||
QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable)
|
||||
item.setToolTip(0, f'Value: {value}')
|
||||
item.setData(0, QtCore.Qt.ItemDataRole.UserRole, idd)
|
||||
item.setCheckState(0, QtCore.Qt.CheckState.Checked)
|
||||
item.setFlags(
|
||||
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||
QtCore.Qt.ItemFlag.ItemIsDragEnabled |
|
||||
QtCore.Qt.ItemFlag.ItemIsEditable |
|
||||
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||
)
|
||||
graph.addChild(item)
|
||||
self._checked_sets.add(idd)
|
||||
|
||||
self.resizeColumnToContents(0)
|
||||
break
|
||||
|
||||
if update:
|
||||
self.update_indexes()
|
||||
|
||||
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem)
|
||||
def data_change(self, item: QtWidgets.QTreeWidgetItem) -> tuple[set, set]:
|
||||
idd = item.data(0, QtCore.Qt.UserRole)
|
||||
is_selected = item.checkState(0) == QtCore.Qt.Checked
|
||||
def data_change(self, item: QtWidgets.QTreeWidgetItem, emit: bool = True) -> tuple[set, set]:
|
||||
idd = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||
is_selected = item.checkState(0) == QtCore.Qt.CheckState.Checked
|
||||
to_be_hidden = set()
|
||||
to_be_shown = set()
|
||||
|
||||
@ -102,9 +114,9 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
self.blockSignals(True)
|
||||
for i in range(item.childCount()):
|
||||
child = item.child(i)
|
||||
child.setCheckState(0, QtCore.Qt.Checked)
|
||||
to_be_shown.add(child.data(0, QtCore.Qt.UserRole))
|
||||
self._checked_sets.add(child.data(0, QtCore.Qt.UserRole))
|
||||
child.setCheckState(0, QtCore.Qt.CheckState.Checked)
|
||||
to_be_shown.add(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||
self._checked_sets.add(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||
self.blockSignals(False)
|
||||
|
||||
# check state change to unchecked
|
||||
@ -113,10 +125,10 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
self.blockSignals(True)
|
||||
for i in range(item.childCount()):
|
||||
child = item.child(i)
|
||||
child.setCheckState(0, QtCore.Qt.Unchecked)
|
||||
to_be_hidden.add(child.data(0, QtCore.Qt.UserRole))
|
||||
child.setCheckState(0, QtCore.Qt.CheckState.Unchecked)
|
||||
to_be_hidden.add(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||
try:
|
||||
self._checked_sets.remove(child.data(0, QtCore.Qt.UserRole))
|
||||
self._checked_sets.remove(child.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||
except KeyError:
|
||||
pass
|
||||
self.blockSignals(False)
|
||||
@ -140,9 +152,10 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
pass
|
||||
|
||||
else:
|
||||
if emit:
|
||||
self.keyChanged.emit(idd, item.text(0))
|
||||
|
||||
if to_be_shown or to_be_hidden:
|
||||
if (to_be_shown or to_be_hidden) and emit:
|
||||
self.stateChanged.emit(list(to_be_shown), list(to_be_hidden))
|
||||
|
||||
return to_be_shown, to_be_hidden
|
||||
@ -150,7 +163,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
@QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem)
|
||||
def new_selection(self, item: QtWidgets.QTreeWidgetItem):
|
||||
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):
|
||||
dropped_index = self.indexAt(evt.pos())
|
||||
@ -176,7 +189,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
|
||||
from_parent.removeChild(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)
|
||||
if self.dropIndicatorPosition() == QtWidgets.QAbstractItemView.BelowItem:
|
||||
@ -188,8 +201,8 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
else:
|
||||
to_parent.insertChildren(row, tobemoved)
|
||||
|
||||
self.management.move_sets([it.data(0, QtCore.Qt.UserRole) for it in tobemoved],
|
||||
to_parent.data(0, QtCore.Qt.UserRole), take_from,
|
||||
self.management.move_sets([it.data(0, QtCore.Qt.ItemDataRole.UserRole) for it in tobemoved],
|
||||
to_parent.data(0, QtCore.Qt.ItemDataRole.UserRole), take_from,
|
||||
pos=-1 if append else row)
|
||||
|
||||
self.update_indexes()
|
||||
@ -204,7 +217,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
while iterator.value():
|
||||
item = iterator.value()
|
||||
if item is not None:
|
||||
data = item.data(0, QtCore.Qt.UserRole)
|
||||
data = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||
if data == gid_out:
|
||||
from_parent = item
|
||||
|
||||
@ -228,7 +241,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
self.blockSignals(False)
|
||||
|
||||
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 = [el[0] for el in sorted(sets.items(), key=lambda x: x[1])]
|
||||
|
||||
@ -240,18 +253,18 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
|
||||
for s in sets:
|
||||
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)
|
||||
|
||||
self.update_indexes()
|
||||
|
||||
self.blockSignals(False)
|
||||
|
||||
|
||||
def update_indexes(self):
|
||||
graph_cnt = -1
|
||||
set_cnt = 0
|
||||
iterator = QtWidgets.QTreeWidgetItemIterator(self)
|
||||
self.blockSignals(True)
|
||||
while iterator.value():
|
||||
item = iterator.value()
|
||||
if item is not None:
|
||||
@ -266,13 +279,14 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
iterator += 1
|
||||
|
||||
self.resizeColumnToContents(1)
|
||||
self.blockSignals(False)
|
||||
|
||||
def set_name(self, sid, name):
|
||||
iterator = QtWidgets.QTreeWidgetItemIterator(self)
|
||||
while iterator.value():
|
||||
item = iterator.value()
|
||||
if item is not None:
|
||||
data = item.data(0, QtCore.Qt.UserRole)
|
||||
data = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||
if data == sid:
|
||||
if name != item.text(0):
|
||||
item.setText(0, name)
|
||||
@ -281,24 +295,31 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
iterator += 1
|
||||
|
||||
def keyPressEvent(self, evt: QtGui.QKeyEvent):
|
||||
if evt.key() == QtCore.Qt.Key_Delete:
|
||||
if evt.key() == QtCore.Qt.Key.Key_Delete:
|
||||
rm_sets = []
|
||||
rm_graphs = []
|
||||
for idx in self.selectedIndexes():
|
||||
if idx.column() == 1:
|
||||
continue
|
||||
|
||||
item = self.itemFromIndex(idx)
|
||||
if item.parent() is None:
|
||||
for c_i in range(item.childCount()):
|
||||
rm_sets.append(item.child(c_i).data(0, QtCore.Qt.UserRole))
|
||||
rm_graphs.append(item.data(0, QtCore.Qt.UserRole))
|
||||
# add sets inside graph to removal
|
||||
child_data = item.child(c_i).data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||
if child_data not in rm_sets:
|
||||
rm_sets.append(child_data)
|
||||
rm_graphs.append(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||
|
||||
else:
|
||||
rm_sets.append(item.data(0, QtCore.Qt.UserRole))
|
||||
item_data = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||
if item_data not in rm_sets:
|
||||
rm_sets.append(item_data)
|
||||
|
||||
# self.deleteItem.emit(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 = []
|
||||
from_parent = []
|
||||
|
||||
@ -306,26 +327,24 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
if idx.column() != 0:
|
||||
continue
|
||||
item = self.itemFromIndex(idx)
|
||||
|
||||
if item.parent() is None:
|
||||
is_selected = item.checkState(0)
|
||||
self.blockSignals(True)
|
||||
for i in range(item.childCount()):
|
||||
child = item.child(i)
|
||||
from_parent.append(child)
|
||||
self.blockSignals(False)
|
||||
if is_selected == QtCore.Qt.Checked:
|
||||
item.setCheckState(0, QtCore.Qt.Unchecked)
|
||||
else:
|
||||
item.setCheckState(0, QtCore.Qt.Checked)
|
||||
|
||||
else:
|
||||
sets.append(item)
|
||||
|
||||
to_be_hidden = set()
|
||||
to_be_shown = set()
|
||||
self.blockSignals(True)
|
||||
for it in sets:
|
||||
if it in from_parent:
|
||||
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)
|
||||
to_be_hidden |= s2
|
||||
to_be_shown |= s1
|
||||
self.blockSignals(False)
|
||||
self.stateChanged.emit(list(to_be_shown), list(to_be_hidden))
|
||||
else:
|
||||
super().keyPressEvent(evt)
|
||||
|
||||
@ -335,27 +354,47 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
self.setDragEnabled(idx.column() == 0)
|
||||
super().mousePressEvent(evt)
|
||||
|
||||
def remove_item(self, ids: list):
|
||||
def remove_item(self, ids: list[str]):
|
||||
iterator = QtWidgets.QTreeWidgetItemIterator(self)
|
||||
|
||||
toberemoved = []
|
||||
graph_removal = []
|
||||
|
||||
# find all items that have to be removed
|
||||
while iterator.value():
|
||||
item = iterator.value()
|
||||
_id = item.data(0, QtCore.Qt.UserRole)
|
||||
_id = item.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||
if _id in ids:
|
||||
try:
|
||||
if item.parent() is None:
|
||||
item_parent = item.parent()
|
||||
if item_parent is None:
|
||||
raise AttributeError
|
||||
|
||||
idx = item.parent().indexOfChild(item)
|
||||
item.parent().takeChild(idx)
|
||||
idx = item_parent.indexOfChild(item)
|
||||
# item.parent().takeChild(idx)
|
||||
|
||||
toberemoved.append((item_parent, idx))
|
||||
|
||||
if _id in self._checked_sets:
|
||||
self._checked_sets.remove(_id)
|
||||
|
||||
except AttributeError:
|
||||
idx = self.invisibleRootItem().indexOfChild(item)
|
||||
self.invisibleRootItem().takeChild(idx)
|
||||
# self.invisibleRootItem().takeChild(idx)
|
||||
|
||||
graph_removal.append(idx)
|
||||
|
||||
if _id in self._checked_graphs:
|
||||
self._checked_graphs.remove(_id)
|
||||
|
||||
iterator += 1
|
||||
|
||||
for (item, set_idx) in sorted(toberemoved, key=lambda x: x[1], reverse=True):
|
||||
item.takeChild(set_idx)
|
||||
|
||||
for graph_idx in sorted(graph_removal, reverse=True):
|
||||
self.invisibleRootItem().takeChild(graph_idx)
|
||||
|
||||
self.update_indexes()
|
||||
|
||||
def contextMenuEvent(self, evt):
|
||||
@ -381,6 +420,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
self.ctx_sets(evt, menu)
|
||||
|
||||
def ctx_graphs(self, evt, menu):
|
||||
copy_action = menu.addAction('Replicate graph!')
|
||||
del_action = menu.addAction('Exterminate graph!')
|
||||
|
||||
sort_menu = menu.addMenu('Sort sets')
|
||||
@ -401,12 +441,16 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
if i.column() == 0:
|
||||
continue
|
||||
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:
|
||||
for gid in graphs:
|
||||
self.management.delete_graph(gid)
|
||||
|
||||
elif action == copy_action:
|
||||
for gid in graphs:
|
||||
self.management.copy_graph(gid)
|
||||
|
||||
elif action.parent() == col_menu:
|
||||
for gid in graphs:
|
||||
self.management.set_cycle(self.management.graphs[gid].sets, action.text())
|
||||
@ -421,7 +465,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
del_action = menu.addAction('Exterminate sets')
|
||||
cp_action = menu.addAction('Replicate sets')
|
||||
cat_action = menu.addAction('Join us!')
|
||||
plt_action = save_action = extend_action = None
|
||||
plt_action = save_action = extend_action = subfit_action = None
|
||||
menu.addSeparator()
|
||||
col_menu = menu.addMenu('Color cycle')
|
||||
for c in available_cycles.keys():
|
||||
@ -439,12 +483,12 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
continue
|
||||
|
||||
else:
|
||||
graph_id = parent.data(0, QtCore.Qt.UserRole)
|
||||
graph_id = parent.data(0, QtCore.Qt.ItemDataRole.UserRole)
|
||||
if graph_id not in idx:
|
||||
idx[graph_id] = []
|
||||
# collect sets in their graph
|
||||
idx[graph_id].append(item.data(0, QtCore.Qt.UserRole))
|
||||
data = self.management[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.ItemDataRole.UserRole)]
|
||||
if data.mode == 'fit':
|
||||
has_fits = True
|
||||
|
||||
@ -453,6 +497,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
plt_action = menu.addAction('Plot fit parameter')
|
||||
save_action = menu.addAction('Save fit parameter')
|
||||
extend_action = menu.addAction('Extrapolate fit')
|
||||
subfit_action = menu.addAction('Plot partial functions')
|
||||
|
||||
action = menu.exec(evt.globalPos())
|
||||
|
||||
@ -460,6 +505,9 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
for gid, sets in idx.items():
|
||||
s.extend(sets)
|
||||
|
||||
if action is None:
|
||||
return
|
||||
|
||||
if action == del_action:
|
||||
self.management.delete_sets(s)
|
||||
|
||||
@ -477,7 +525,10 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
self.saveFits.emit(s)
|
||||
|
||||
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:
|
||||
self.management.set_cycle(s, action.text())
|
||||
@ -489,7 +540,7 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
while iterator.value():
|
||||
item = iterator.value()
|
||||
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')))
|
||||
else:
|
||||
item.setBackground(0, QtGui.QBrush())
|
||||
@ -498,11 +549,14 @@ class DataTree(QtWidgets.QTreeWidget):
|
||||
def uncheck_sets(self, sets: list[str]):
|
||||
self.blockSignals(True)
|
||||
iterator = QtWidgets.QTreeWidgetItemIterator(self)
|
||||
self._checked_sets = set()
|
||||
while iterator.value():
|
||||
item = iterator.value()
|
||||
if item is not None:
|
||||
if item.data(0, QtCore.Qt.UserRole) in sets:
|
||||
item.setCheckState(0, QtCore.Qt.Unchecked)
|
||||
if item.data(0, QtCore.Qt.ItemDataRole.UserRole) in sets:
|
||||
item.setCheckState(0, QtCore.Qt.CheckState.Unchecked)
|
||||
else:
|
||||
self._checked_sets.add(item.data(0, QtCore.Qt.ItemDataRole.UserRole))
|
||||
iterator += 1
|
||||
self.blockSignals(False)
|
||||
|
||||
@ -519,6 +573,7 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
||||
self.setupUi(self)
|
||||
self.tree = DataTree(self)
|
||||
self.verticalLayout.addWidget(self.tree)
|
||||
# noinspection PyUnresolvedReferences
|
||||
self.tree.selectionModel().selectionChanged.connect(lambda x, y: self.show_property(x))
|
||||
|
||||
self.tree.keyChanged.connect(lambda x, y: self.keyChanged.emit(x, y))
|
||||
@ -529,6 +584,8 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
||||
self.propwidget.expansionChanged.connect(self.show_property)
|
||||
self.proptable.propertyChanged.connect(self.change_property)
|
||||
|
||||
self.pokemon_toolbutton.clicked.connect(self.catchthemall)
|
||||
|
||||
make_action_icons(self)
|
||||
|
||||
def add_graph(self, idd: str, name: str):
|
||||
@ -536,9 +593,9 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
||||
self.tree.add_graph(idd, name)
|
||||
self.tree.blockSignals(False)
|
||||
|
||||
def add_item(self, idd: str, name: str, gid: str):
|
||||
def add_item(self, idd: str, name: str, value: str, gid: str, update: bool= True):
|
||||
self.tree.blockSignals(True)
|
||||
self.tree.add_item((idd, name), gid)
|
||||
self.tree.add_item((idd, name, value), gid, update=update)
|
||||
self.tree.blockSignals(False)
|
||||
|
||||
def add_item_list(self, loi: list, gid: str):
|
||||
@ -546,7 +603,7 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
||||
self.tree.add_item(loi, gid)
|
||||
self.tree.blockSignals(False)
|
||||
|
||||
def remove_item(self, key):
|
||||
def remove_item(self, key: list[str]):
|
||||
self.tree.remove_item(key)
|
||||
|
||||
def show_property(self, _: QtCore.QModelIndex = None):
|
||||
@ -556,7 +613,7 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
||||
sid = []
|
||||
for i in self.tree.selectedIndexes():
|
||||
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)
|
||||
|
||||
@ -565,15 +622,23 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
||||
self.proptable.populate(props)
|
||||
|
||||
def change_property(self, key1, key2, value):
|
||||
ids = [item.data(0, QtCore.Qt.UserRole) for item in self.tree.selectedItems()]
|
||||
if key2 == 'Value':
|
||||
try:
|
||||
value = float(value)
|
||||
except ValueError:
|
||||
QtWidgets.QMessageBox.warning(self, 'Invalid entry',
|
||||
'Value %r is not a valid number for `value`.' % value)
|
||||
QtWidgets.QMessageBox.warning(
|
||||
self,
|
||||
'Invalid entry',
|
||||
f'Value {value!r} is not a valid number for `value`.')
|
||||
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)
|
||||
|
||||
def uncheck_sets(self, sets: list[str]):
|
||||
@ -582,6 +647,12 @@ class DataWidget(QtWidgets.QWidget, Ui_DataWidget):
|
||||
def set_name(self, 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
|
||||
def management(self):
|
||||
return self.tree.management
|
||||
|
@ -41,7 +41,7 @@ class PropWidget(QtWidgets.QWidget):
|
||||
idx = table.indexFromItem(item)
|
||||
self.propertyChanged.emit(self.tab.tabText(tab_idx),
|
||||
table.item(idx.row(), idx.column()-1).text(),
|
||||
item.data(QtCore.Qt.DisplayRole))
|
||||
item.data(QtCore.Qt.ItemDataRole.DisplayRole))
|
||||
|
||||
@QtCore.pyqtSlot(int)
|
||||
def tab_change(self, idx: int):
|
||||
@ -66,10 +66,10 @@ class PropTable(QtWidgets.QTableWidget):
|
||||
self.blockSignals(True)
|
||||
for k, v in prop.items():
|
||||
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.setFlags(QtCore.Qt.NoItemFlags)
|
||||
key_item.setFlags(QtCore.Qt.ItemFlag.NoItemFlags)
|
||||
key_item.setForeground(QtGui.QBrush(QtGui.QColor(0, 0, 0)))
|
||||
|
||||
self.setRowCount(self.rowCount()+1)
|
||||
|
@ -42,6 +42,8 @@ class IntegralWidget(QtWidgets.QWidget, Ui_Form):
|
||||
self.max_y = inf
|
||||
self.min_y = -inf
|
||||
|
||||
self.treeWidget.itemChanged.connect(self._update_by_tree)
|
||||
|
||||
def __call__(self, graph_name, items):
|
||||
self.label_2.setText(f'Connected to {graph_name}\nChanging tab will remove all integration limits.')
|
||||
|
||||
@ -77,7 +79,6 @@ class IntegralWidget(QtWidgets.QWidget, Ui_Form):
|
||||
for idx, rnge in enumerate(self.ranges):
|
||||
self._update_values(idx, rnge)
|
||||
|
||||
|
||||
def add(self, pos):
|
||||
x = pos[0]
|
||||
self.ranges.append((x, x*1.1))
|
||||
@ -108,6 +109,9 @@ class IntegralWidget(QtWidgets.QWidget, Ui_Form):
|
||||
item_list = []
|
||||
for text, val in [('Start', pts_i[0]), ('Stop', pts_i[1]), ('Areas', 0), ('Ratio', 1.)]:
|
||||
child = QtWidgets.QTreeWidgetItem()
|
||||
if text.startswith('S'):
|
||||
child.setFlags(child.flags() | QtCore.Qt.ItemIsEditable)
|
||||
else:
|
||||
child.setFlags(QtCore.Qt.NoItemFlags)
|
||||
child.setText(0, f'{text}: {val:.5g}')
|
||||
child.setForeground(0, QtGui.QBrush(QtGui.QColor('black')))
|
||||
@ -121,8 +125,27 @@ class IntegralWidget(QtWidgets.QWidget, Ui_Form):
|
||||
|
||||
self._update_values(len(self.ranges) - 1, pts_i)
|
||||
|
||||
def _update_by_tree(self, item: QtWidgets.QTreeWidgetItem) -> None:
|
||||
parent_item = item.parent()
|
||||
idx = self.treeWidget.invisibleRootItem().indexOfChild(parent_item)
|
||||
|
||||
is_left_border = parent_item.indexOfChild(item) == 0
|
||||
current_region = self.lines[idx][0]
|
||||
current_limits = current_region.getRegion()
|
||||
|
||||
new_value = item.text(0)
|
||||
try:
|
||||
new_value = float(new_value)
|
||||
if is_left_border:
|
||||
current_region.setRegion((new_value, current_limits[1]))
|
||||
else:
|
||||
current_region.setRegion((current_limits[0], new_value))
|
||||
except ValueError:
|
||||
self._update_values(idx, current_limits)
|
||||
|
||||
def _update_integral(self):
|
||||
idx = None
|
||||
reg = None
|
||||
sender = self.sender()
|
||||
for i, (reg, _) in enumerate(self.lines):
|
||||
if sender == reg:
|
||||
@ -132,19 +155,20 @@ class IntegralWidget(QtWidgets.QWidget, Ui_Form):
|
||||
if idx is None:
|
||||
return
|
||||
|
||||
self._update_values(idx, sender.getRegion())
|
||||
self._update_values(idx, reg.getRegion())
|
||||
|
||||
def _update_values(self, idx, new_range):
|
||||
self.ranges[idx] = new_range
|
||||
|
||||
area = self.make_integral(idx, *new_range)
|
||||
|
||||
self.treeWidget.blockSignals(True)
|
||||
|
||||
item = self.treeWidget.topLevelItem(idx)
|
||||
item.child(0).setText(0, f'Start: {new_range[0]:.5g}')
|
||||
item.child(1).setText(0, f'Stop: {new_range[1]:.5g}')
|
||||
|
||||
if area is not None:
|
||||
self.areas[idx] = area
|
||||
item.child(2).setText(0, f'Area: {area:.5g}')
|
||||
if self.max_area > 0:
|
||||
self._set_ratios(idx, self.max_area)
|
||||
@ -157,9 +181,12 @@ class IntegralWidget(QtWidgets.QWidget, Ui_Form):
|
||||
self._set_ratios(i, curr_max)
|
||||
self.max_area = curr_max
|
||||
|
||||
self.treeWidget.blockSignals(False)
|
||||
|
||||
def _set_ratios(self, idx, max_value):
|
||||
item = self.treeWidget.invisibleRootItem().child(idx)
|
||||
area_i = self.areas[idx]
|
||||
|
||||
item.child(3).setText(0, f'Ratio: {area_i / max_value:.3g}')
|
||||
|
||||
integral_line = self.lines[idx][1]
|
||||
@ -178,6 +205,8 @@ class IntegralWidget(QtWidgets.QWidget, Ui_Form):
|
||||
scale = (self.max_y-self.min_y) / area
|
||||
self.lines[idx][1].setData(x=integral[:, 0], y=integral[:, 1]*scale + self.min_y)
|
||||
|
||||
self.areas[idx] = area
|
||||
|
||||
return area
|
||||
|
||||
else:
|
||||
|
@ -1,6 +1,6 @@
|
||||
import re
|
||||
|
||||
from ..Qt import QtCore, QtWidgets
|
||||
from ..Qt import QtCore, QtWidgets, QtGui
|
||||
from .._py.ptstab import Ui_Form
|
||||
from ..lib.pg_objects import LogInfiniteLine, RegionItem
|
||||
|
||||
@ -27,15 +27,23 @@ class PointSelectWidget(QtWidgets.QWidget, Ui_Form):
|
||||
self._last_item = None
|
||||
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.deleteButton.clicked.connect(self.remove_points)
|
||||
|
||||
self.peaktable.itemChanged.connect(self.editing_finished)
|
||||
self.peaktable.itemDoubleClicked.connect(self.editing_started)
|
||||
|
||||
self.left_limit.setValidator(QtGui.QDoubleValidator())
|
||||
self.right_limit.setValidator(QtGui.QDoubleValidator())
|
||||
|
||||
def keyPressEvent(self, e):
|
||||
if e.key() == QtCore.Qt.Key_Delete:
|
||||
if e.key() == QtCore.Qt.Key.Key_Delete:
|
||||
self.remove_points()
|
||||
elif e.key() == QtCore.Qt.Key_F2:
|
||||
elif e.key() == QtCore.Qt.Key.Key_F2:
|
||||
self.editing_started()
|
||||
else:
|
||||
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}')
|
||||
else:
|
||||
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.addItem(item)
|
||||
self.peaktable.blockSignals(False)
|
||||
@ -102,21 +110,22 @@ class PointSelectWidget(QtWidgets.QWidget, Ui_Form):
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def apply(self) -> dict:
|
||||
ret_dic = {'avg_range': [self.left_pt.value(), self.right_pt.value()],
|
||||
'avg_mode': {0: 'mean', 1: 'sum', 2: 'integral'}[self.average_combobox.currentIndex()],
|
||||
'special': None, 'idx': None,
|
||||
'xy': (self.xbutton.isChecked(), self.ybutton.isChecked())}
|
||||
ret_dic = {
|
||||
'avg_range': self.get_limits(),
|
||||
'avg_mode': self._avg_modes[self.average_combobox.currentIndex()],
|
||||
'special': None,
|
||||
'idx': None,
|
||||
'xy': (self.xbutton.isChecked(), self.ybutton.isChecked()),
|
||||
'groupby': self._group_modes[self.group_box.currentIndex()],
|
||||
}
|
||||
|
||||
if self.groupBox_2.isChecked():
|
||||
ret_dic['special'] = {0: 'max', 1: 'absmax', 2: 'min', 3: 'absmin'}[self.special_comboBox.currentIndex()]
|
||||
if self.special_checkbox.isChecked():
|
||||
ret_dic['special'] = self._special_values[self.special_comboBox.currentIndex()]
|
||||
|
||||
if len(self.pts) != 0:
|
||||
ret_dic['idx'] = self.pts
|
||||
|
||||
if self.graph_checkbox.isChecked():
|
||||
gid = ''
|
||||
else:
|
||||
gid = self.graph_combobox.currentData()
|
||||
gid = self.graph_combobox.currentData() if not self.graph_checkbox.isChecked() else ''
|
||||
|
||||
self.points_selected.emit(ret_dic, gid)
|
||||
|
||||
@ -177,7 +186,7 @@ class PointSelectWidget(QtWidgets.QWidget, Ui_Form):
|
||||
it.setText(f'{pos[0]:.5g} - {pos[1]:.5g}')
|
||||
self.peaktable.blockSignals(False)
|
||||
it_pts.blockSignals(True)
|
||||
it_pts.setRegion(pos)
|
||||
it_pts.setRegion(pos, use_log=True)
|
||||
it_pts.blockSignals(False)
|
||||
undo = False
|
||||
|
||||
@ -187,10 +196,34 @@ class PointSelectWidget(QtWidgets.QWidget, Ui_Form):
|
||||
self.peaktable.blockSignals(False)
|
||||
|
||||
def set_graphs(self, graphs: list):
|
||||
last_graph = self.graph_combobox.currentData()
|
||||
self.graph_combobox.clear()
|
||||
for g in graphs:
|
||||
idx = 0
|
||||
for i, g in enumerate(graphs):
|
||||
self.graph_combobox.addItem(g[1], userData=g[0])
|
||||
if g[0] == last_graph:
|
||||
idx = i
|
||||
|
||||
self.graph_combobox.setCurrentIndex(idx)
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_graph_checkbox_stateChanged')
|
||||
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()
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import numpy as np
|
||||
from itertools import cycle
|
||||
|
||||
from pyqtgraph import mkColor, mkPen
|
||||
from pyqtgraph import mkColor, mkPen, mkBrush
|
||||
|
||||
from nmreval.lib.colors import Tab10
|
||||
|
||||
@ -42,11 +42,17 @@ class QShift(QtWidgets.QDialog, Ui_shift_dialog):
|
||||
|
||||
def add_item(self, idx, name, x, y):
|
||||
color = mkColor(next(self._colors).rgb())
|
||||
if np.iscomplexobj(y):
|
||||
pl = [PlotItem(x=x, y=y.real, name=name, pen=mkPen(color=color)),
|
||||
PlotItem(x=x, y=y.imag, name=name, pen=mkPen(color=color))]
|
||||
|
||||
if len(y) == 1:
|
||||
sym_kwds = {'symbol': 'o', 'symbolBrush': mkBrush(color=color), 'symbolPen': mkPen(color=color)}
|
||||
else:
|
||||
pl = [PlotItem(x=x, y=y, name=name, pen=mkPen(color=color))]
|
||||
sym_kwds = {'symbol': None, 'symbolBrush': mkBrush(color=color), 'symbolPen': mkPen(color=color)}
|
||||
|
||||
if np.iscomplexobj(y):
|
||||
pl = [PlotItem(x=x, y=y.real, name=name, pen=mkPen(color=color), **sym_kwds),
|
||||
PlotItem(x=x, y=y.imag, name=name, pen=mkPen(color=color), **sym_kwds)]
|
||||
else:
|
||||
pl = [PlotItem(x=x, y=y, name=name, pen=mkPen(color=color), **sym_kwds)]
|
||||
|
||||
self.data[idx] = (pl, x, y)
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
from .phase_dialog import QApodDialog, QPhasedialog
|
||||
from .phase_dialog import QPreviewDialog
|
||||
from .baseline_dialog import QBaselineDialog
|
||||
|
@ -1,3 +1,4 @@
|
||||
from nmreval.lib.logger import logger
|
||||
from nmreval.math import apodization
|
||||
from nmreval.lib.importer import find_models
|
||||
from nmreval.utils.text import convert
|
||||
@ -46,7 +47,7 @@ class EditSignalWidget(QtWidgets.QWidget, Ui_Form):
|
||||
stype = 'pts'
|
||||
else:
|
||||
try:
|
||||
_nop = float(self.lineEdit.text())
|
||||
_nop = float(self.ls_lineEdit.text())
|
||||
except ValueError:
|
||||
_nop = 0.0
|
||||
stype = 'time'
|
||||
@ -67,7 +68,7 @@ class EditSignalWidget(QtWidgets.QWidget, Ui_Form):
|
||||
self.do_something.emit(sender, (ph0, ph1, pvt))
|
||||
|
||||
else:
|
||||
print('You should never reach this by accident.')
|
||||
logger.warning(f'You should never reach this by accident, invalid sender {sender!r}')
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_apodcombobox_currentIndexChanged')
|
||||
def change_apodization(self, index):
|
||||
|
@ -1,119 +1,43 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
from pyqtgraph import mkPen
|
||||
from numpy import inf, linspace
|
||||
from numpy.fft import fft, fftfreq, fftshift
|
||||
import numpy as np
|
||||
from numpy import pi
|
||||
from numpy.fft import fft, fftshift, fftfreq
|
||||
|
||||
from nmreval.data import FID, Spectrum
|
||||
from ...lib.pg_objects import PlotItem, LogInfiniteLine
|
||||
from nmreval.lib.importer import find_models
|
||||
from nmreval.math import apodization as apodization
|
||||
from nmreval.utils.text import convert
|
||||
|
||||
from ...Qt import QtCore, QtWidgets
|
||||
from ...Qt import QtCore, QtWidgets, QtGui
|
||||
from ..._py.apod_dialog import Ui_ApodEdit
|
||||
from ..._py.phase_corr_dialog import Ui_SignalEdit
|
||||
from ...lib.forms import FormWidget
|
||||
|
||||
|
||||
class QPreviewDialogs(QtWidgets.QDialog):
|
||||
class QPreviewDialog(QtWidgets.QDialog, Ui_ApodEdit):
|
||||
finished = QtCore.pyqtSignal(str, tuple)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
self.data = []
|
||||
self.graphs = []
|
||||
|
||||
self.mode = ''
|
||||
|
||||
def setRange(self, xlim: list, ylim: list, logmode: list[bool]):
|
||||
self.graphicsView.getPlotItem().setLogMode(x=logmode[0], y=logmode[1])
|
||||
if logmode[0]:
|
||||
xlim = [np.log10(x) for x in xlim]
|
||||
if logmode[1]:
|
||||
ylim = [np.log10(y) for y in ylim]
|
||||
|
||||
self.graphicsView.setRange(xRange=xlim, yRange=ylim, padding=0, disableAutoRange=True)
|
||||
|
||||
def add_data(self, x, y):
|
||||
self.data.append((x, y))
|
||||
real_plt = PlotItem(x=x, y=y.real, pen=mkPen('b'), )
|
||||
imag_plt = PlotItem(x=x, y=y.imag, pen=mkPen('r'))
|
||||
self.graphs.append((real_plt, imag_plt))
|
||||
self.graphicsView.addItem(real_plt)
|
||||
self.graphicsView.addItem(imag_plt)
|
||||
|
||||
def done(self, val):
|
||||
self.cleanup()
|
||||
super().done(val)
|
||||
|
||||
def close(self):
|
||||
self.cleanup()
|
||||
super().close()
|
||||
|
||||
def accept(self):
|
||||
self.finished.emit(self.mode, self.get_value())
|
||||
super().accept()
|
||||
|
||||
def get_value(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def cleanup(self):
|
||||
self.blockSignals(True)
|
||||
|
||||
for line in self.graphs:
|
||||
for g in line:
|
||||
self.graphicsView.removeItem(g)
|
||||
del g
|
||||
|
||||
self.graphicsView.clear()
|
||||
|
||||
self.data = []
|
||||
self.graphs = []
|
||||
|
||||
self.blockSignals(False)
|
||||
|
||||
|
||||
class QPhasedialog(QPreviewDialogs, Ui_SignalEdit):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.mode = 'ph'
|
||||
self.data = []
|
||||
self.graphs = []
|
||||
self._tmp_data_bl = []
|
||||
self._tmp_data_zf = []
|
||||
self._tmp_data_ls = []
|
||||
self._tmp_data_ap = []
|
||||
self._tmp_data_ph = []
|
||||
|
||||
self.pvt_line = LogInfiniteLine(pos=0, movable=True)
|
||||
self.graphicsView.addItem(self.pvt_line)
|
||||
self.freq_graph.addItem(self.pvt_line)
|
||||
self.pvt_line.sigPositionChanged.connect(self.move_line)
|
||||
|
||||
@QtCore.pyqtSlot(float, name='on_ph1slider_valueChanged')
|
||||
@QtCore.pyqtSlot(float, name='on_ph0slider_valueChanged')
|
||||
def _temp_phase(self, *args):
|
||||
ph0, ph1, pvt = self.get_value()
|
||||
self.pvt_line.setValue(pvt)
|
||||
self.ls_lineedit.hide()
|
||||
|
||||
for i, (x, y) in enumerate(self.data):
|
||||
phasecorr = np.exp(-1j * (ph0 + ph1*(x-pvt)/np.max(x))*np.pi/180.)
|
||||
_y = y * phasecorr
|
||||
|
||||
self.graphs[i][0].setData(x=x, y=_y.real)
|
||||
self.graphs[i][1].setData(x=x, y=_y.imag)
|
||||
|
||||
def get_value(self):
|
||||
return float(self.ph0slider.text()), float(self.ph1slider.text()), float(self.pivot_lineedit.text())
|
||||
|
||||
def move_line(self, evt):
|
||||
self.pivot_lineedit.setText(f'{evt.value():.5g}')
|
||||
|
||||
|
||||
class QApodDialog(QPreviewDialogs, Ui_ApodEdit):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self._limits = (-inf, inf), -inf
|
||||
|
||||
self.apods = []
|
||||
self.apods = find_models(apodization)
|
||||
|
||||
self.apodcombobox.blockSignals(True)
|
||||
@ -122,72 +46,288 @@ class QApodDialog(QPreviewDialogs, Ui_ApodEdit):
|
||||
self.apodcombobox.blockSignals(False)
|
||||
|
||||
self.apod_graph = PlotItem(x=[], y=[])
|
||||
self.graphicsView.addItem(self.apod_graph)
|
||||
self.time_graph.addItem(self.apod_graph)
|
||||
|
||||
self.mode = 'ap'
|
||||
for g in [self.freq_graph, self.time_graph]:
|
||||
pl = g.getPlotItem()
|
||||
pl.hideButtons()
|
||||
pl.setMenuEnabled(False)
|
||||
|
||||
self._all_time = None
|
||||
self._all_freq = None
|
||||
|
||||
self.change_apodization(0)
|
||||
|
||||
def add_data(self, x, y):
|
||||
real_plt = PlotItem(x=x, y=y.real, pen=mkPen('b'))
|
||||
# imag_plt = (x=x, y=y.imag, pen=pg.mkPen('r'))
|
||||
self.graphicsView.addItem(real_plt)
|
||||
# self.graphicsView.addItem(imag_plt)
|
||||
self.shift_box.clicked.connect(self._update_shift)
|
||||
self.ls_spinbox.valueChanged.connect(self._update_shift)
|
||||
self.ls_lineedit.setValidator(QtGui.QDoubleValidator())
|
||||
self.ls_lineedit.textChanged.connect(self._update_shift)
|
||||
|
||||
self.zerofill_box.clicked.connect(self._update_zf)
|
||||
self.zf_spinbox.valueChanged.connect(self._update_zf)
|
||||
|
||||
self.apod_box.clicked.connect(self._update_apod)
|
||||
|
||||
self.phase_box.clicked.connect(self._update_phase)
|
||||
self.ph0_spinbox.valueChanged.connect(self._update_phase)
|
||||
self.ph1_spinbox.valueChanged.connect(self._update_phase)
|
||||
self.pivot_lineedit.setValidator(QtGui.QDoubleValidator())
|
||||
self.pivot_lineedit.textChanged.connect(self._update_phase)
|
||||
self.pivot_lineedit.textEdited.connect(lambda x: self.pvt_line.setValue(float(x)))
|
||||
|
||||
def add_data(self: QPreviewDialog, data: FID | Spectrum) -> bool:
|
||||
if isinstance(data, FID):
|
||||
valid, (real_plt, imag_plt, real_plt_fft, imag_plt_fft) = self._prep_time(data)
|
||||
|
||||
elif isinstance(data, Spectrum):
|
||||
valid, (real_plt, imag_plt, real_plt_fft, imag_plt_fft) = self._prep_freq(data)
|
||||
|
||||
else:
|
||||
return False
|
||||
|
||||
if not valid:
|
||||
return False
|
||||
|
||||
x_len = data.x.size
|
||||
self.zf_spinbox.setMaximum(min(2**17//x_len, 3))
|
||||
|
||||
self.time_graph.addItem(imag_plt)
|
||||
self.time_graph.addItem(real_plt)
|
||||
|
||||
self.freq_graph.addItem(imag_plt_fft)
|
||||
self.freq_graph.addItem(real_plt_fft)
|
||||
|
||||
self.data.append(data)
|
||||
for p in [self._tmp_data_bl, self._tmp_data_ls]:
|
||||
p.append(data.y.copy())
|
||||
|
||||
for p in [self._tmp_data_zf, self._tmp_data_ap]:
|
||||
p.append((data.x, data.y.copy()))
|
||||
|
||||
self.graphs.append((real_plt, imag_plt, real_plt_fft, imag_plt_fft))
|
||||
|
||||
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')
|
||||
def _update_bl(self):
|
||||
if self.baseline_box.isChecked():
|
||||
for y in self._tmp_data_bl:
|
||||
self._temp_baseline(y)
|
||||
else:
|
||||
for i, d in enumerate(self.data):
|
||||
self._tmp_data_bl[i] = d.y.copy()
|
||||
|
||||
self._update_shift()
|
||||
|
||||
def _update_shift(self):
|
||||
if self.shift_box.isChecked():
|
||||
if self.ls_combobox.currentIndex() == 0:
|
||||
num_points = self.ls_spinbox.value()
|
||||
is_time = False
|
||||
else:
|
||||
num_points = float(self.ls_lineedit.text())
|
||||
is_time = True
|
||||
|
||||
for i, y in enumerate(self._tmp_data_bl):
|
||||
self._tmp_data_ls[i] = self._temp_leftshift(self.data[i].dx, y, num_points, is_time)
|
||||
|
||||
else:
|
||||
for i, y in enumerate(self._tmp_data_bl):
|
||||
self._tmp_data_ls[i] = y
|
||||
|
||||
self._update_zf()
|
||||
|
||||
def _update_zf(self):
|
||||
zf_padding = self.zf_spinbox.value()
|
||||
|
||||
if self.zerofill_box.isChecked():
|
||||
for i, y in enumerate(self._tmp_data_ls):
|
||||
self._tmp_data_zf[i] = self._temp_zerofill(self.data[i].x, y, zf_padding)
|
||||
|
||||
else:
|
||||
for i, y in enumerate(self._tmp_data_ls):
|
||||
self._tmp_data_zf[i] = self.data[i].x, y
|
||||
|
||||
self._update_apod()
|
||||
|
||||
def _update_apod(self):
|
||||
if self.apod_box.isChecked():
|
||||
model = self.apods[self.apodcombobox.currentIndex()]
|
||||
p = self._get_parameter()
|
||||
|
||||
x_limit = np.inf, -np.inf
|
||||
y_limit = -np.inf
|
||||
|
||||
for i, (x, y) in enumerate(self._tmp_data_zf):
|
||||
self._tmp_data_ap[i] = x, y * model.apod(x, *p)
|
||||
y_limit = max(y.real.max(), y_limit)
|
||||
x_limit = min(x_limit[0], x.min()), max(x_limit[1], x.max())
|
||||
|
||||
_x_apod = np.linspace(*x_limit, num=150)
|
||||
_y_apod = model.apod(_x_apod, *p)
|
||||
self.apod_graph.setData(x=_x_apod, y=y_limit * _y_apod)
|
||||
self.apod_graph.show()
|
||||
|
||||
else:
|
||||
for i, (x, y) in enumerate(self._tmp_data_zf):
|
||||
self._tmp_data_ap[i] = x, y
|
||||
|
||||
self.apod_graph.hide()
|
||||
|
||||
self._update_phase()
|
||||
|
||||
def _update_phase(self):
|
||||
if self.phase_box.isChecked():
|
||||
pvt = float(self.pivot_lineedit.text())
|
||||
self.pvt_line.show()
|
||||
ph0 = self.ph0_spinbox.value()
|
||||
ph1 = self.ph1_spinbox.value()
|
||||
|
||||
for i, (x, y) in enumerate(self._tmp_data_ap):
|
||||
x_fft, y_fft = self._temp_fft(x, y, self.baseline_box.isChecked())
|
||||
|
||||
if ph0 != 0:
|
||||
y = self._temp_phase(x, y, ph0, 0, 0)
|
||||
y_fft = self._temp_phase(x, y_fft, ph0, ph1, pvt)
|
||||
elif ph1 != 0:
|
||||
y_fft = self._temp_phase(x, y_fft, ph0, ph1, pvt)
|
||||
|
||||
self._tmp_data_ph[i] = x, y, x_fft, y_fft
|
||||
|
||||
else:
|
||||
self.pvt_line.hide()
|
||||
for i, (x, y) in enumerate(self._tmp_data_ap):
|
||||
self._tmp_data_ph[i] = x, y, *self._temp_fft(x, y, self.baseline_box.isChecked())
|
||||
|
||||
self._update_plots()
|
||||
|
||||
def _update_plots(self):
|
||||
for i, (x, y, xf, yf) in enumerate(self._tmp_data_ph):
|
||||
self.graphs[i][0].setData(x=x, y=y.real)
|
||||
self.graphs[i][1].setData(x=x, y=y.imag)
|
||||
|
||||
self.graphs[i][2].setData(x=xf, y=yf.real)
|
||||
self.graphs[i][3].setData(x=xf, y=yf.imag)
|
||||
|
||||
@staticmethod
|
||||
def _temp_baseline_time(y):
|
||||
y -= y[int(-0.12 * y.size):].mean()
|
||||
|
||||
@staticmethod
|
||||
def _temp_baseline_freq(y):
|
||||
region = int(0.12 * y.size)
|
||||
y -= np.mean([y[-region:], y[:region]])
|
||||
|
||||
@staticmethod
|
||||
def _temp_phase(x: np.ndarray, y: np.ndarray, ph0: float, ph1: float, pvt: float) -> np.ndarray:
|
||||
phase_correction = np.exp(-1j * (ph0 + ph1 * (x - pvt) / x.max()) * pi / 180.)
|
||||
_y = y * phase_correction
|
||||
|
||||
return _y
|
||||
|
||||
@staticmethod
|
||||
def _temp_zerofill(x: np.ndarray, y: np.ndarray, num_padding: int) -> tuple[np.ndarray, np.ndarray]:
|
||||
length = x.size
|
||||
factor = 2**num_padding
|
||||
|
||||
_y = np.r_[y, np.zeros((factor-1) * length)]
|
||||
|
||||
_temp_x = np.arange(1, (factor-1) * length+1) * (x[1]-x[0]) + np.max(x)
|
||||
_x = np.r_[x, _temp_x]
|
||||
|
||||
return _x, _y
|
||||
|
||||
@staticmethod
|
||||
def _temp_leftshift(dx: np.ndarray, y: np.ndarray, points: float | int, is_time: bool) -> np.ndarray:
|
||||
if is_time:
|
||||
points = int(points//dx)
|
||||
_y = np.roll(y, -points)
|
||||
_y[-points-1:] = 0
|
||||
|
||||
return _y
|
||||
|
||||
@staticmethod
|
||||
def _temp_fft_time(x: np.ndarray, y: np.ndarray, baseline: bool = False) -> tuple[np.ndarray, np.ndarray]:
|
||||
y_fft = fftshift(fft(y))
|
||||
x_fft = fftshift(fftfreq(len(x), d=x[1]-x[0]))
|
||||
real_plt_fft = PlotItem(x=x_fft, y=y_fft.real, pen=mkPen('b'))
|
||||
# imag_plt_fft = pg.PlotDataItem(x=x_fft, y=y_fft.imag, pen=pg.mkPen('b'))
|
||||
self.graphicsView_2.addItem(real_plt_fft)
|
||||
# self.graphicsView_2.addItem(imag_plt_fft)
|
||||
|
||||
self.graphs.append((real_plt, real_plt_fft))
|
||||
self.data.append((x, y, x_fft))
|
||||
if baseline:
|
||||
QPreviewDialog._temp_baseline_freq(y_fft)
|
||||
|
||||
xlimits = (max(x.min(), self._limits[0][0]), min(x.max(), self._limits[0][1]))
|
||||
ylimit = max(self._limits[1], y.real.max())
|
||||
self._limits = xlimits, ylimit
|
||||
return x_fft, y_fft
|
||||
|
||||
@staticmethod
|
||||
def _temp_fft_freq(x: np.ndarray, y: np.ndarray, _=None):
|
||||
return x, y
|
||||
|
||||
def move_line(self, evt):
|
||||
self.pivot_lineedit.setText(f'{evt.value():.5g}')
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_apodcombobox_currentIndexChanged')
|
||||
def change_apodization(self, index):
|
||||
def change_apodization(self, index: int) -> None:
|
||||
# delete old widgets
|
||||
self.eqn_label.setText(convert(self.apods[index].equation))
|
||||
while self.widget_layout.count():
|
||||
item = self.widget_layout.takeAt(0)
|
||||
if isinstance(item, FormWidget):
|
||||
item.disconnect()
|
||||
|
||||
try:
|
||||
item.widget().deleteLater()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# set up parameter widgets for new model
|
||||
for k, v in enumerate(self.apods[index]().params):
|
||||
widgt = FormWidget(name=v)
|
||||
widgt.valueChanged.connect(self._temp_apod)
|
||||
self.widget_layout.addWidget(widgt)
|
||||
for k, v in enumerate(self.apods[index].params):
|
||||
widget = FormWidget(name=v)
|
||||
widget.value = 1
|
||||
widget.valueChanged.connect(self._update_apod)
|
||||
self.widget_layout.addWidget(widget)
|
||||
|
||||
self.widget_layout.addStretch()
|
||||
self._temp_apod()
|
||||
|
||||
def _temp_apod(self):
|
||||
apodmodel = self.apods[self.apodcombobox.currentIndex()]
|
||||
p = self._get_parameter()
|
||||
|
||||
if self.data:
|
||||
for i, (x, y, x_fft) in enumerate(self.data):
|
||||
y2 = apodmodel.apod(x, *p)
|
||||
_y = y2 * y
|
||||
self.graphs[i][0].setData(x=x, y=_y.real)
|
||||
# self.graphs[i][1].setData(y=_y.imag)
|
||||
y_fft = fftshift(fft(_y))
|
||||
self.graphs[i][1].setData(x=x_fft, y=y_fft.real)
|
||||
# self.graphs[i][3].setData(y=y_fft.imag)
|
||||
|
||||
_x_apod = linspace(self._limits[0][0], self._limits[0][1])
|
||||
try:
|
||||
_y_apod = apodmodel.apod(_x_apod, *p)
|
||||
self.apod_graph.setData(x=_x_apod, y=self._limits[1]*_y_apod)
|
||||
except IndexError:
|
||||
pass
|
||||
self._update_apod()
|
||||
|
||||
def _get_parameter(self):
|
||||
p = []
|
||||
@ -201,8 +341,104 @@ class QApodDialog(QPreviewDialogs, Ui_ApodEdit):
|
||||
|
||||
return p
|
||||
|
||||
def get_value(self):
|
||||
apodmodel = self.apods[self.apodcombobox.currentIndex()]
|
||||
p = self._get_parameter()
|
||||
@QtCore.pyqtSlot(int, name='on_ls_combobox_currentIndexChanged')
|
||||
def change_ls(self, idx: int) -> None:
|
||||
self.ls_lineedit.setVisible(bool(idx))
|
||||
self.ls_spinbox.setVisible(not bool(idx))
|
||||
|
||||
@QtCore.pyqtSlot(bool, name='on_ft_checkbox_stateChanged')
|
||||
def change_ft(self, state: bool):
|
||||
self.ph1_spinbox.setEnabled(state)
|
||||
self.pivot_lineedit.setEnabled(state)
|
||||
|
||||
def cleanup(self):
|
||||
self.blockSignals(True)
|
||||
|
||||
for line in self.graphs:
|
||||
for g in line:
|
||||
self.time_graph.removeItem(g)
|
||||
self.freq_graph.removeItem(g)
|
||||
del g
|
||||
|
||||
self.time_graph.clear()
|
||||
self.freq_graph.clear()
|
||||
|
||||
self._tmp_data_ap = []
|
||||
self._tmp_data_bl = []
|
||||
self._tmp_data_ls = []
|
||||
self._tmp_data_ph = []
|
||||
self._tmp_data_zf = []
|
||||
|
||||
self.data = []
|
||||
self.graphs = []
|
||||
self.freq_graph.removeItem(self.pvt_line)
|
||||
|
||||
self.blockSignals(False)
|
||||
|
||||
def get_value(self):
|
||||
edits = [(None,), (None,), (None,), (None,), (None,), (None,)]
|
||||
|
||||
if self.baseline_box.isChecked():
|
||||
edits[0] = (True,)
|
||||
|
||||
if self.zerofill_box.isChecked():
|
||||
edits[2] = (self.zf_spinbox.value(),)
|
||||
|
||||
if self.shift_box.isChecked():
|
||||
if self.ls_combobox.currentIndex() == 0:
|
||||
edits[1] = (self.ls_spinbox.value(), 'pts')
|
||||
else:
|
||||
edits[1] = (float(self.ls_lineedit.text()), 'time')
|
||||
|
||||
if self.apod_box.isChecked():
|
||||
edits[3] = (self._get_parameter(), self.apods[self.apodcombobox.currentIndex()])
|
||||
|
||||
if self.phase_box.isChecked():
|
||||
edits[4] = (self.ph0_spinbox.value(), self.ph1_spinbox.value(), float(self.pivot_lineedit.text()))
|
||||
|
||||
if self.ft_box.isChecked():
|
||||
edits[5] = (self.phase_before_button.isChecked(),)
|
||||
|
||||
return edits
|
||||
|
||||
def exec(self):
|
||||
self._prepare_ui()
|
||||
return super().exec()
|
||||
|
||||
def _prepare_ui(self):
|
||||
"""Stuff we have to do before showing the window but after all the data was added"""
|
||||
|
||||
vb = self.freq_graph.getPlotItem().getViewBox()
|
||||
vb.disableAutoRange(axis=vb.YAxis)
|
||||
|
||||
vb = self.time_graph.getPlotItem().getViewBox()
|
||||
vb.disableAutoRange(axis=vb.YAxis)
|
||||
if self._all_time is not None:
|
||||
self.zerofill_box.setVisible(self._all_time)
|
||||
self.apod_box.setVisible(self._all_time)
|
||||
self.shift_box.setVisible(self._all_time)
|
||||
self.time_graph.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_logy_time_stateChanged')
|
||||
@QtCore.pyqtSlot(int, name='on_logx_freq_stateChanged')
|
||||
@QtCore.pyqtSlot(int, name='on_logy_freq_stateChanged')
|
||||
def set_log(self, state: int):
|
||||
switch = {
|
||||
self.logx_time: lambda _x: self.time_graph.setLogMode(x=_x),
|
||||
self.logy_time: lambda _x: self.time_graph.setLogMode(y=_x),
|
||||
self.logx_freq: lambda _x: self.freq_graph.setLogMode(x=_x),
|
||||
self.logy_freq: lambda _x: self.freq_graph.setLogMode(y=_x),
|
||||
}[self.sender()]
|
||||
switch(state == QtCore.Qt.Checked)
|
||||
|
||||
vb = self.freq_graph.getPlotItem().getViewBox()
|
||||
vb.disableAutoRange(axis=vb.YAxis)
|
||||
|
||||
vb = self.time_graph.getPlotItem().getViewBox()
|
||||
vb.disableAutoRange(axis=vb.YAxis)
|
||||
|
||||
return p, apodmodel
|
||||
|
@ -3,10 +3,10 @@ from __future__ import annotations
|
||||
from typing import Any
|
||||
|
||||
from numpy import ndarray, iscomplexobj, asarray
|
||||
from pyqtgraph import PlotDataItem
|
||||
|
||||
from ..Qt import QtGui, QtCore, QtWidgets
|
||||
from .._py.valueeditor import Ui_MaskDialog
|
||||
from ..lib.pg_objects import PlotItem
|
||||
|
||||
|
||||
class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
||||
@ -35,12 +35,12 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
||||
|
||||
self.tableView.setModel(self.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.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')
|
||||
self.selection_imag = PlotDataItem(x=[], y=[], symbolSize=25, symbol='+',
|
||||
self.selection_imag = PlotItem(x=[], y=[], symbolSize=25, symbol='+',
|
||||
pen=None, symbolPen='#dcdcdc', symbolBrush='#dcdcdc')
|
||||
|
||||
def __call__(self, items: dict):
|
||||
@ -133,7 +133,7 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
||||
def keyPressEvent(self, evt):
|
||||
if evt.matches(QtGui.QKeySequence.Copy):
|
||||
self.copy_selection()
|
||||
elif evt.key() == QtCore.Qt.Key_Delete:
|
||||
elif evt.key() == QtCore.Qt.Key.Key_Delete:
|
||||
self.delete_item()
|
||||
else:
|
||||
super().keyPressEvent(evt)
|
||||
@ -188,7 +188,15 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
||||
new_value = complex(val)
|
||||
new_value = new_value.real if new_value.imag == 0 else new_value
|
||||
|
||||
# table view loses focus when itemChanged is emitted
|
||||
# if edit of item is cause of change resume editing at next item
|
||||
prev_state = self.tableView.state()
|
||||
idx = self.tableView.currentIndex()
|
||||
idx = idx.sibling((col+1)//3+row, (col+1) % 3)
|
||||
self.itemChanged.emit(sid, (col, row), new_value)
|
||||
if prev_state == self.tableView.State.EditingState:
|
||||
self.tableView.setCurrentIndex(idx)
|
||||
self.tableView.edit(idx)
|
||||
|
||||
@QtCore.pyqtSlot(QtCore.QItemSelection, QtCore.QItemSelection)
|
||||
def show_position(self, *_):
|
||||
@ -221,7 +229,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
||||
"""
|
||||
itemChanged = QtCore.pyqtSignal(int, int, str)
|
||||
load_number = 20
|
||||
maskRole = QtCore.Qt.UserRole+321
|
||||
maskRole = QtCore.Qt.ItemDataRole.UserRole+321
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
@ -232,7 +240,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
||||
self.mask = None
|
||||
self.headers = ['x', 'y', '\u0394y']
|
||||
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:
|
||||
return self.total_rows
|
||||
@ -250,28 +258,28 @@ class ValueModel(QtCore.QAbstractTableModel):
|
||||
self.mask = mask.tolist()
|
||||
|
||||
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():
|
||||
return
|
||||
|
||||
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()]
|
||||
if isinstance(val, complex):
|
||||
return f'{val.real:.8g}{val.imag:+.8g}j'
|
||||
else:
|
||||
return f'{val:.8g}'
|
||||
return self.as_string(val)
|
||||
|
||||
elif role == QtCore.Qt.BackgroundRole:
|
||||
elif role == QtCore.Qt.ItemDataRole.BackgroundRole:
|
||||
pal = QtGui.QGuiApplication.palette()
|
||||
if not self.mask[row]:
|
||||
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Base)
|
||||
else:
|
||||
return pal.color(QtGui.QPalette.Base)
|
||||
|
||||
elif role == QtCore.Qt.ForegroundRole:
|
||||
elif role == QtCore.Qt.ItemDataRole.ForegroundRole:
|
||||
pal = QtGui.QGuiApplication.palette()
|
||||
if not self.mask[row]:
|
||||
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Text)
|
||||
@ -284,7 +292,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
||||
else:
|
||||
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()
|
||||
|
||||
if role == ValueModel.maskRole:
|
||||
@ -294,12 +302,17 @@ class ValueModel(QtCore.QAbstractTableModel):
|
||||
return True
|
||||
|
||||
if value:
|
||||
if role == QtCore.Qt.EditRole:
|
||||
if role == QtCore.Qt.ItemDataRole.EditRole:
|
||||
if value == self.as_string(self._data[row][col]):
|
||||
return True
|
||||
|
||||
try:
|
||||
value = complex(value)
|
||||
except ValueError:
|
||||
# not a number
|
||||
return False
|
||||
|
||||
value = value.real if value.imag == 0 else value
|
||||
self._data[row][col] = value.real if value.imag == 0 else value
|
||||
self.itemChanged.emit(col, row, str(value))
|
||||
self.dataChanged.emit(self.index(0, 0), self.index(0, 1), [role])
|
||||
@ -312,9 +325,9 @@ class ValueModel(QtCore.QAbstractTableModel):
|
||||
else:
|
||||
return False
|
||||
|
||||
def headerData(self, section: int, orientation, role=QtCore.Qt.DisplayRole) -> Any:
|
||||
if role == QtCore.Qt.DisplayRole:
|
||||
if orientation == QtCore.Qt.Horizontal:
|
||||
def headerData(self, section: int, orientation, role=QtCore.Qt.ItemDataRole.DisplayRole) -> Any:
|
||||
if role == QtCore.Qt.ItemDataRole.DisplayRole:
|
||||
if orientation == QtCore.Qt.Orientation.Horizontal:
|
||||
return self.headers[section]
|
||||
else:
|
||||
return str(section+1)
|
||||
@ -336,7 +349,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
||||
self.endInsertRows()
|
||||
|
||||
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:
|
||||
self.beginRemoveRows(parent, pos, pos+rows-1)
|
||||
@ -368,3 +381,10 @@ class ValueModel(QtCore.QAbstractTableModel):
|
||||
def unmask(self):
|
||||
self.mask = [True] * self.total_rows
|
||||
self.dataChanged.emit(self.index(0, 0), self.index(0, 1), [ValueModel.maskRole])
|
||||
|
||||
@staticmethod
|
||||
def as_string(value) -> str:
|
||||
if isinstance(value, complex):
|
||||
return f'{value.real:.13g}{value.imag:+.13g}j'
|
||||
else:
|
||||
return f'{value:.13g}'
|
||||
|
0
src/gui_qt/dsc/__init__.py
Normal file
0
src/gui_qt/dsc/__init__.py
Normal file
375
src/gui_qt/dsc/glass_dialog.py
Normal file
375
src/gui_qt/dsc/glass_dialog.py
Normal file
@ -0,0 +1,375 @@
|
||||
from itertools import cycle
|
||||
|
||||
from numpy import array, nan, isnan
|
||||
from pyqtgraph import mkPen, mkBrush
|
||||
|
||||
from nmreval.dsc.hodge import tau_hodge
|
||||
from nmreval.lib.colors import Tab10
|
||||
from ..Qt import QtWidgets, QtCore
|
||||
from .._py.tnmh_dialog import Ui_DSCEvalDialog
|
||||
from ..lib.pg_objects import PlotItem, RegionItem
|
||||
|
||||
from nmreval.data import DSC, Points
|
||||
|
||||
|
||||
class TgCalculator(QtWidgets.QWizard, Ui_DSCEvalDialog):
|
||||
newData = QtCore.pyqtSignal(dict, str)
|
||||
|
||||
def __init__(self, management, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
self.setupUi(self)
|
||||
|
||||
self._management = management
|
||||
self._colors = cycle(Tab10)
|
||||
|
||||
self._dsc = {}
|
||||
self._plots = {}
|
||||
self._tg_value = {}
|
||||
self._fit = {}
|
||||
self._hodge = {
|
||||
'onset': (
|
||||
PlotItem(x=[], y=[], pen=None, symbol='o', symbolBrush=Tab10.TabBlue.rgb(), name='Onset'),
|
||||
None,
|
||||
(PlotItem(x=[], y=[], pen=mkPen({'color': Tab10.TabBlue.rgb()})),
|
||||
PlotItem(x=[], y=[], pen=None, symbol='o', symbolBrush=Tab10.TabBlue.rgb())),
|
||||
None,
|
||||
),
|
||||
'midpoint': (
|
||||
PlotItem(x=[], y=[], pen=None, symbol='s', symbolBrush=Tab10.TabOrange.rgb(), name='Midpoint'),
|
||||
None,
|
||||
(PlotItem(x=[], y=[], pen=mkPen({'color': Tab10.TabOrange.rgb()})),
|
||||
PlotItem(x=[], y=[], pen=None, symbol='s', symbolBrush=Tab10.TabOrange.rgb())),
|
||||
None,
|
||||
),
|
||||
'end': (
|
||||
PlotItem(x=[], y=[], pen=None, symbol='t', symbolBrush=Tab10.TabGreen.rgb(), name='End'),
|
||||
None,
|
||||
(PlotItem(x=[], y=[], pen=mkPen({'color': Tab10.TabGreen.rgb()})),
|
||||
PlotItem(x=[], y=[], pen=None, symbol='t', symbolBrush=Tab10.TabGreen.rgb())),
|
||||
None,
|
||||
),
|
||||
'inflection': (
|
||||
PlotItem(x=[], y=[], pen=None, symbol='d', symbolBrush=Tab10.TabRed.rgb(), name='Inflection'),
|
||||
None,
|
||||
(PlotItem(x=[], y=[], pen=mkPen({'color': Tab10.TabRed.rgb()})),
|
||||
PlotItem(x=[], y=[], pen=None, symbol='d', symbolBrush=Tab10.TabRed.rgb())),
|
||||
None,
|
||||
),
|
||||
'fictive': (
|
||||
PlotItem(x=[], y=[], pen=None, symbol='t1', symbolBrush=Tab10.TabPurple.rgb(), name='Fictive'),
|
||||
None,
|
||||
(PlotItem(x=[], y=[], pen=mkPen({'color': Tab10.TabPurple.rgb()})),
|
||||
PlotItem(x=[], y=[], pen=None, symbol='t1', symbolBrush=Tab10.TabPurple.rgb())),
|
||||
None,
|
||||
),
|
||||
}
|
||||
self._lines = {}
|
||||
self.tau_plot.getPlotItem().addLegend()
|
||||
for plt, _, fitplt, _ in self._hodge.values():
|
||||
self.tau_plot.addItem(plt)
|
||||
self.tghodge_graph.addItem(fitplt[0])
|
||||
self.tghodge_graph.addItem(fitplt[1])
|
||||
self.tau_plot.setLogMode(y=True)
|
||||
self.tghodge_graph.setLogMode(y=True)
|
||||
|
||||
self.limits = RegionItem(), RegionItem()
|
||||
for lim in self.limits:
|
||||
self.dsc_plot.addItem(lim)
|
||||
self._limitless = True
|
||||
|
||||
self.add_sets()
|
||||
|
||||
self.tnmh_graph_check.stateChanged.connect(lambda state: self.tnmh_graph_combo.setEnabled(not bool(state)))
|
||||
self.hodge_graph_check.stateChanged.connect(lambda state: self.hodge_graph_combo.setEnabled(not bool(state)))
|
||||
|
||||
self.next_button.clicked.connect(lambda: self.stackedWidget.setCurrentIndex((self.stackedWidget.currentIndex() + 1) % 3))
|
||||
self.back_button.clicked.connect(lambda: self.stackedWidget.setCurrentIndex((self.stackedWidget.currentIndex() + 2) % 3))
|
||||
|
||||
self.listWidget.itemChanged.connect(self.change_visibility)
|
||||
|
||||
def __call__(self):
|
||||
self.clear()
|
||||
self._colors = cycle(Tab10)
|
||||
self.add_sets()
|
||||
|
||||
return self
|
||||
|
||||
def clear(self):
|
||||
self.listWidget.clear()
|
||||
self.tg_tree.clear()
|
||||
self.tnmh_tree.clear()
|
||||
|
||||
for plots in self._plots.values():
|
||||
for val in plots:
|
||||
self.dsc_plot.removeItem(val)
|
||||
self.tnmh_graphics.removeItem(val)
|
||||
|
||||
for key, plt in self._hodge.items():
|
||||
plt[0].setData(x=[], y=[])
|
||||
plt[2][0].setData(x=[], y=[])
|
||||
plt[2][1].setData(x=[], y=[])
|
||||
self._hodge[key] = (plt[0], None, plt[2], None)
|
||||
|
||||
self._dsc = {}
|
||||
self._plots = {}
|
||||
self._tg_value = {}
|
||||
self._lines = {}
|
||||
self._fit = {}
|
||||
|
||||
self.stackedWidget.setCurrentIndex(0)
|
||||
|
||||
def add_sets(self):
|
||||
for w in (self.tnmh_graph_combo, self.hodge_graph_combo):
|
||||
w.clear()
|
||||
for graphs in self._management.graphs.list():
|
||||
w.addItem(graphs[1], userData=graphs[0])
|
||||
|
||||
min_x = 10_000_000
|
||||
max_x = -10_000_000
|
||||
for (key, name), c in zip(self._management.active_sets, self._colors):
|
||||
data = self._management[key].data
|
||||
if not isinstance(data, DSC):
|
||||
continue
|
||||
|
||||
min_x = min(min_x, data.x.min())
|
||||
max_x = max(max_x, data.x.max())
|
||||
|
||||
item = QtWidgets.QListWidgetItem(name)
|
||||
item.setCheckState(QtCore.Qt.CheckState.Checked)
|
||||
item.setData(QtCore.Qt.ItemDataRole.UserRole, key)
|
||||
item.setForeground(mkBrush(c.rgb()))
|
||||
self.listWidget.addItem(item)
|
||||
|
||||
self._dsc[key] = (data, None)
|
||||
|
||||
data_plot = PlotItem(x=data.x, y=data.y, pen=mkPen(c.rgb()))
|
||||
self.dsc_plot.addItem(data_plot)
|
||||
|
||||
glass = PlotItem()
|
||||
glass.set_line(style=2, color=c)
|
||||
self.dsc_plot.addItem(glass)
|
||||
|
||||
liquid = PlotItem()
|
||||
liquid.set_line(style=2, color=c)
|
||||
self.dsc_plot.addItem(liquid)
|
||||
|
||||
tangent = PlotItem()
|
||||
tangent.set_line(style=2, color=c)
|
||||
self.dsc_plot.addItem(tangent)
|
||||
|
||||
tg_plot = PlotItem(pen=None, symbolBrush=c.rgb(), symbol='o')
|
||||
self.dsc_plot.addItem(tg_plot)
|
||||
|
||||
fictive_cp = PlotItem(pen=mkPen(c.rgb()))
|
||||
self.tnmh_graphics.addItem(fictive_cp)
|
||||
|
||||
tnmh_fit = PlotItem()
|
||||
tnmh_fit.set_line(style=2, color=c)
|
||||
self.tnmh_graphics.addItem(tnmh_fit)
|
||||
|
||||
self._plots[key] = (data_plot, tg_plot, glass, liquid, tangent, fictive_cp, tnmh_fit)
|
||||
self._tg_value[key] = {
|
||||
'onset': (nan, nan),
|
||||
'midpoint': (nan, nan),
|
||||
'end': (nan, nan),
|
||||
'inflection': (nan, nan),
|
||||
# 'fictive': (nan, nan),
|
||||
}
|
||||
|
||||
if self._limitless and max_x != -10000000 and min_x != 10000000 :
|
||||
dist = max_x - min_x
|
||||
self.limits[0].setRegion((min_x, min_x+min(0.1*dist, 5)))
|
||||
self.limits[1].setRegion((max_x-min(5, 0.1*dist), max_x))
|
||||
self._limitless = False
|
||||
|
||||
@QtCore.pyqtSlot(name='on_calctg_button_clicked')
|
||||
def calc_tg(self):
|
||||
baselines = tuple(lim.getRegion() for lim in self.limits)
|
||||
if baselines[0][0] > baselines[1][0]:
|
||||
baselines = baselines[1], baselines[0]
|
||||
|
||||
for idx in range(self.listWidget.count()):
|
||||
item = self.listWidget.item(idx)
|
||||
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||
continue
|
||||
|
||||
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||
plot = self._plots[key]
|
||||
data, _ = self._dsc[key]
|
||||
|
||||
tg_results, glass, liquid, tangent = data.glass_transition(*baselines)
|
||||
self._lines[key] = (glass, liquid, tangent)
|
||||
|
||||
for i, line in enumerate((glass, liquid, tangent)):
|
||||
plot[i+2].setData(x=line.x, y=line.y)
|
||||
|
||||
self._tg_value[key].update(tg_results)
|
||||
|
||||
self._update_tg_plots()
|
||||
|
||||
def _update_tg_plots(self):
|
||||
self.tg_tree.clear()
|
||||
for idx in range(self.listWidget.count()):
|
||||
item = self.listWidget.item(idx)
|
||||
|
||||
tree_item = QtWidgets.QTreeWidgetItem([item.text()])
|
||||
values = self._tg_value.get(item.data(QtCore.Qt.ItemDataRole.UserRole))
|
||||
|
||||
if values is not None:
|
||||
for name, pos in values.items():
|
||||
child_item = QtWidgets.QTreeWidgetItem([f'{name.capitalize()}: {pos[0]:.2f} K'])
|
||||
tree_item.addChild(child_item)
|
||||
|
||||
self.tg_tree.addTopLevelItem(tree_item)
|
||||
|
||||
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||
plot = self._plots[key]
|
||||
data, _ = self._dsc[key]
|
||||
|
||||
plot[1].setData(array(list(self._tg_value[key].values())))
|
||||
|
||||
@QtCore.pyqtSlot(name='on_tg_export_button_clicked')
|
||||
def export_tg(self):
|
||||
ret_dic = {}
|
||||
for key, tg in self._tg_value.items():
|
||||
tgx = [x for x, y in tg.values()]
|
||||
tgy = [y for x, y in tg.values()]
|
||||
if self.tg_export_check.isChecked():
|
||||
tg_pts = Points(x=tgx, y=tgy, name=self._management[key].name + ' (Tg)', value=self._management[key].value)
|
||||
else:
|
||||
tg_pts = None
|
||||
|
||||
line = []
|
||||
if self.tglines_export_check.isChecked():
|
||||
line = self._lines.get(key, [])
|
||||
|
||||
ret_dic[key] = (tg_pts, line)
|
||||
|
||||
self.newData.emit(ret_dic, 'tg')
|
||||
|
||||
@QtCore.pyqtSlot(QtWidgets.QListWidgetItem)
|
||||
def change_visibility(self, item: QtWidgets.QListWidgetItem):
|
||||
is_checked = bool(item.checkState())
|
||||
plot = self._plots[item.data(QtCore.Qt.ItemDataRole.UserRole)]
|
||||
for val in plot:
|
||||
val.setVisible(is_checked)
|
||||
|
||||
def get_fictive(self, key, baselines):
|
||||
plot = self._plots[key]
|
||||
data, _ = self._dsc[key]
|
||||
|
||||
cp, tg = data.get_fictive_cp(*baselines)
|
||||
|
||||
plot[5].setData(cp.x, cp.y)
|
||||
self._dsc[key] = (data, cp)
|
||||
|
||||
return cp
|
||||
|
||||
@QtCore.pyqtSlot(name='on_tnhm_fitbutton_clicked')
|
||||
def make_tnmh(self):
|
||||
baselines = tuple(lim.getRegion() for lim in self.limits)
|
||||
if baselines[0][0] > baselines[1][0]:
|
||||
baselines = baselines[1], baselines[0]
|
||||
|
||||
self.tnmh_tree.clear()
|
||||
for idx in range(self.listWidget.count()):
|
||||
item = self.listWidget.item(idx)
|
||||
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||
continue
|
||||
|
||||
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||
|
||||
data = self.get_fictive(key, baselines)
|
||||
|
||||
res = data.calculate_tnmh([60, 0.5, 1, 2e5], *baselines, return_fictive=False)
|
||||
self._fit[key] = res
|
||||
|
||||
plot = self._plots[key]
|
||||
plot[-1].setData(res.x, res.y)
|
||||
|
||||
for idx in range(self.listWidget.count()):
|
||||
item = self.listWidget.item(idx)
|
||||
|
||||
tree_item = QtWidgets.QTreeWidgetItem([item.text()])
|
||||
values = self._fit.get(item.data(QtCore.Qt.ItemDataRole.UserRole))
|
||||
|
||||
if values is not None:
|
||||
child_item = QtWidgets.QTreeWidgetItem([values.parameter_string()])
|
||||
tree_item.addChild(child_item)
|
||||
|
||||
self.tnmh_tree.addTopLevelItem(tree_item)
|
||||
|
||||
@QtCore.pyqtSlot(name='on_tnmh_export_button_clicked')
|
||||
def export_tnmh(self):
|
||||
ret_dic = {}
|
||||
for idx in range(self.listWidget.count()):
|
||||
item = self.listWidget.item(idx)
|
||||
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||
continue
|
||||
|
||||
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||
|
||||
cp = None
|
||||
if self.fictive_export_check.isChecked():
|
||||
_, cp = self._dsc[key]
|
||||
|
||||
line = None
|
||||
|
||||
if self.tnmhfit_export_check.isChecked():
|
||||
line = self._fit.get(key)
|
||||
|
||||
ret_dic[key] = (cp, line)
|
||||
|
||||
ret_dic['graph'] = '' if self.tnmh_graph_check.isChecked() else self.tnmh_graph_combo.currentData()
|
||||
|
||||
self.newData.emit(ret_dic, 'tnmh')
|
||||
|
||||
@QtCore.pyqtSlot(name='on_hodge_button_clicked')
|
||||
def hodge(self):
|
||||
for tg_type, (plot, data, fitplots, fit) in self._hodge.items():
|
||||
|
||||
m = []
|
||||
for idx in range(self.listWidget.count()):
|
||||
item = self.listWidget.item(idx)
|
||||
if item.checkState() == QtCore.Qt.CheckState.Unchecked:
|
||||
continue
|
||||
|
||||
key = item.data(QtCore.Qt.ItemDataRole.UserRole)
|
||||
data, _ = self._dsc[key]
|
||||
try:
|
||||
tg_value = self._tg_value[key][tg_type][0]
|
||||
if isnan(tg_value):
|
||||
continue
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
m.append([tg_value, data.value])
|
||||
|
||||
if len(m) > 1:
|
||||
data, fit = tau_hodge(*array(m).T)
|
||||
data.name = f'{data.name} ({tg_type.capitalize()})'
|
||||
plot.setData(data.x, data.y)
|
||||
fitplots[0].setData(fit.x, fit.y)
|
||||
fitplots[1].setData(fit.x_data, fit.y_data)
|
||||
|
||||
self._hodge[tg_type] = (plot, data, fitplots, fit)
|
||||
|
||||
@QtCore.pyqtSlot(name='on_export_hodge_button_clicked')
|
||||
def export_hodge(self):
|
||||
ret_dic = {}
|
||||
|
||||
for cb in (self.onset_check, self.mid_check, self.end_check, self.inflection_check, self.fictive_check):
|
||||
if cb.isChecked():
|
||||
item = cb.text().lower()
|
||||
data = self._hodge.get(item)
|
||||
if data[1] is not None:
|
||||
ret_dic[item] = data[1]
|
||||
|
||||
ret_dic['graph'] = '' if self.hodge_graph_check.isChecked() else self.hodge_graph_combo.currentData()
|
||||
|
||||
self.newData.emit(ret_dic, 'hodge')
|
||||
|
||||
def close(self) -> bool:
|
||||
self.clear()
|
||||
return super().close()
|
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
|
||||
|
||||
import typing
|
||||
from ast import parse
|
||||
|
||||
from ..Qt import QtGui, QtCore, QtWidgets
|
||||
|
||||
@ -71,7 +72,8 @@ class PythonHighlighter(QtGui.QSyntaxHighlighter):
|
||||
(r'\bdef\b\s*(\w+)', 1, STYLES['defclass']),
|
||||
# 'class' followed by an identifier
|
||||
(r'\bclass\b\s*(\w+)', 1, STYLES['defclass']),
|
||||
# @ followed by a word
|
||||
|
||||
# decorator @ followed by a word
|
||||
(r'\s*@(\w+)\s*', 0, STYLES['property']),
|
||||
|
||||
# Numeric literals
|
||||
@ -79,7 +81,6 @@ class PythonHighlighter(QtGui.QSyntaxHighlighter):
|
||||
(r'\b[+-]?0[xX][\dA-Fa-f]+[lL]?\b', 0, STYLES['numbers']),
|
||||
(r'\b[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b', 0, STYLES['numbers']),
|
||||
|
||||
|
||||
# Double-quoted string, possibly containing escape sequences
|
||||
(r'[rf]?"[^"\\]*(\\.[^"\\]*)*"', 0, STYLES['string']),
|
||||
# Single-quoted string, possibly containing escape sequences
|
||||
@ -186,10 +187,10 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
||||
self.highlight = PythonHighlighter(self.document())
|
||||
|
||||
def keyPressEvent(self, evt):
|
||||
if evt.key() == QtCore.Qt.Key_Tab:
|
||||
if evt.key() == QtCore.Qt.Key.Key_Tab:
|
||||
# use spaces instead of tab
|
||||
self.insertPlainText(' '*4)
|
||||
elif evt.key() == QtCore.Qt.Key_Insert:
|
||||
elif evt.key() == QtCore.Qt.Key.Key_Insert:
|
||||
self.setOverwriteMode(not self.overwriteMode())
|
||||
else:
|
||||
super().keyPressEvent(evt)
|
||||
@ -224,7 +225,7 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
||||
|
||||
def paintevent_linenumber(self, evt):
|
||||
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_number = block.blockNumber()
|
||||
@ -236,9 +237,9 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
||||
while block.isValid() and (top <= evt.rect().bottom()):
|
||||
if block.isVisible() and (bottom >= evt.rect().top()):
|
||||
number = str(block_number + 1)
|
||||
painter.setPen(QtCore.Qt.black)
|
||||
painter.drawText(0, top, self.current_linenumber.width() - 3, height,
|
||||
QtCore.Qt.AlignRight, number)
|
||||
painter.setPen(QtCore.Qt.GlobalColor.black)
|
||||
painter.drawText(0, int(top), self.current_linenumber.width() - 3, height,
|
||||
QtCore.Qt.AlignmentFlag.AlignRight, number)
|
||||
|
||||
block = block.next()
|
||||
top = bottom
|
||||
@ -251,7 +252,7 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
||||
if not self.isReadOnly():
|
||||
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.setProperty(QtGui.QTextFormat.FullWidthSelection, True)
|
||||
@ -260,3 +261,49 @@ class CodeEditor(QtWidgets.QPlainTextEdit):
|
||||
extra_selections.append(selection)
|
||||
|
||||
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 ..Qt import QtWidgets, QtCore, QtGui
|
||||
from ..lib.codeeditor import CodeEditor
|
||||
from .codeeditor import EditorWidget
|
||||
|
||||
|
||||
class QUsermodelEditor(QtWidgets.QMainWindow):
|
||||
@ -26,7 +26,7 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
||||
layout.setContentsMargins(3, 3, 3, 3)
|
||||
layout.setSpacing(3)
|
||||
|
||||
self.edit_field = CodeEditor(self.centralwidget)
|
||||
self.edit_field = EditorWidget(self.centralwidget)
|
||||
font = QtGui.QFont('default')
|
||||
font.setStyleHint(font.Monospace)
|
||||
font.setPointSize(10)
|
||||
@ -50,18 +50,20 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
||||
self.menuFile.addAction('Close', self.close, QtGui.QKeySequence.Quit)
|
||||
|
||||
self.resize(800, 600)
|
||||
self.setGeometry(QtWidgets.QStyle.alignedRect(
|
||||
QtCore.Qt.LeftToRight, QtCore.Qt.AlignCenter,
|
||||
self.size(), QtWidgets.qApp.desktop().availableGeometry()
|
||||
))
|
||||
self.setGeometry(
|
||||
QtWidgets.QStyle.alignedRect(
|
||||
QtCore.Qt.LayoutDirection.LeftToRight,
|
||||
QtCore.Qt.AlignmentFlag.AlignCenter,
|
||||
self.size(),
|
||||
QtWidgets.qApp.desktop().availableGeometry()
|
||||
)
|
||||
)
|
||||
|
||||
@property
|
||||
def is_modified(self):
|
||||
return self.edit_field.document().isModified()
|
||||
return self.edit_field.editor.document().isModified()
|
||||
|
||||
@is_modified.setter
|
||||
def is_modified(self, val: bool):
|
||||
self.edit_field.document().setModified(val)
|
||||
def set_modified(self, val: bool):
|
||||
self.edit_field.editor.document().setModified(val)
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def open_file(self):
|
||||
@ -75,17 +77,22 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
||||
def read_file(self, fname: str | Path):
|
||||
self.set_fname_opts(fname)
|
||||
|
||||
if self.fname is not None:
|
||||
with self.fname.open('r') as f:
|
||||
self.edit_field.setPlainText(f.read())
|
||||
|
||||
def set_fname_opts(self, fname: str | Path):
|
||||
fname = Path(fname)
|
||||
if fname.is_file():
|
||||
self.fname = Path(fname)
|
||||
self._dir = self.fname.parent
|
||||
self.setWindowTitle('Edit ' + str(fname))
|
||||
elif fname.is_dir():
|
||||
self._dir = fname
|
||||
|
||||
|
||||
@property
|
||||
def changes_saved(self) -> bool:
|
||||
if not self.is_modified:
|
||||
if not self.is_modified():
|
||||
return True
|
||||
|
||||
ret = QtWidgets.QMessageBox.question(self, 'Time to think',
|
||||
@ -97,9 +104,9 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
||||
self.save_file()
|
||||
|
||||
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()
|
||||
def save_file(self):
|
||||
@ -111,9 +118,9 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
||||
|
||||
self.set_fname_opts(outfile)
|
||||
|
||||
self.is_modified = False
|
||||
self.set_modified(False)
|
||||
|
||||
return self.is_modified
|
||||
return self.is_modified()
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def overwrite_file(self):
|
||||
@ -123,10 +130,10 @@ class QUsermodelEditor(QtWidgets.QMainWindow):
|
||||
|
||||
self.modelsChanged.emit()
|
||||
|
||||
self.is_modified = False
|
||||
self.set_modified(False)
|
||||
|
||||
def closeEvent(self, evt: QtGui.QCloseEvent):
|
||||
if not self.changes_saved:
|
||||
if not self.changes_saved():
|
||||
evt.ignore()
|
||||
else:
|
||||
super().closeEvent(evt)
|
@ -1,191 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from nmreval.utils.text import convert
|
||||
|
||||
from ..Qt import QtCore, QtWidgets, QtGui
|
||||
from .._py.fitmodelwidget import Ui_FitParameter
|
||||
from .._py.save_fitmodel_dialog import Ui_SaveDialog
|
||||
from ..lib import get_icon
|
||||
|
||||
|
||||
class FitModelWidget(QtWidgets.QWidget, Ui_FitParameter):
|
||||
value_requested = QtCore.pyqtSignal(object)
|
||||
value_changed = QtCore.pyqtSignal(str)
|
||||
state_changed = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(self, label: str = 'Fitparameter', parent=None, fixed: bool = False):
|
||||
super().__init__(parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.parametername.setText(label + ' ')
|
||||
|
||||
validator = QtGui.QDoubleValidator()
|
||||
validator.setDecimals(9)
|
||||
self.parameter_line.setValidator(validator)
|
||||
self.parameter_line.setText('1')
|
||||
self.parameter_line.setMaximumWidth(60)
|
||||
self.lineEdit.setMaximumWidth(60)
|
||||
self.lineEdit_2.setMaximumWidth(60)
|
||||
|
||||
self.label_3.setText(f'< {label} <')
|
||||
|
||||
self.checkBox.stateChanged.connect(self.enableBounds)
|
||||
self.global_checkbox.stateChanged.connect(lambda: self.state_changed.emit())
|
||||
self.parameter_line.values_requested.connect(lambda: self.value_requested.emit(self))
|
||||
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.menu = QtWidgets.QMenu(self)
|
||||
self.add_links()
|
||||
|
||||
self.is_linked = None
|
||||
self.parameter_pos = None
|
||||
self.func_idx = None
|
||||
|
||||
self._linetext = '1'
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return convert(self.parametername.text().strip(), old='html', new='str')
|
||||
|
||||
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):
|
||||
if p is None:
|
||||
# bad hack: linked parameter return (None, linked parameter)
|
||||
# if p is None -> parameter is linked to argument given by bds
|
||||
self.link_parameter(linkto=bds)
|
||||
else:
|
||||
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):
|
||||
if self.is_linked:
|
||||
try:
|
||||
p = float(self._linetext)
|
||||
except ValueError:
|
||||
p = 1.0
|
||||
else:
|
||||
try:
|
||||
p = float(self.parameter_line.text().replace(',', '.'))
|
||||
except ValueError:
|
||||
_ = QtWidgets.QMessageBox().warning(self, 'Invalid value',
|
||||
f'{self.parametername.text()} contains invalid values',
|
||||
QtWidgets.QMessageBox.Cancel)
|
||||
return None
|
||||
|
||||
if self.checkBox.isChecked():
|
||||
try:
|
||||
lb = float(self.lineEdit.text().replace(',', '.'))
|
||||
except ValueError:
|
||||
lb = None
|
||||
|
||||
try:
|
||||
rb = float(self.lineEdit_2.text().replace(',', '.'))
|
||||
except ValueError:
|
||||
rb = None
|
||||
else:
|
||||
lb = rb = None
|
||||
|
||||
bounds = (lb, rb)
|
||||
|
||||
return p, bounds, not self.fixed_check.isChecked(), self.global_checkbox.isChecked(), self.is_linked
|
||||
|
||||
@QtCore.pyqtSlot(bool)
|
||||
def set_fixed(self, state: bool):
|
||||
# self.global_checkbox.setVisible(not state)
|
||||
self.frame.setVisible(not state)
|
||||
|
||||
def add_links(self, parameter: dict = None):
|
||||
if parameter is None:
|
||||
parameter = {}
|
||||
self.menu.clear()
|
||||
|
||||
ac = QtWidgets.QAction('Link to...', self)
|
||||
ac.triggered.connect(self.link_parameter)
|
||||
self.menu.addAction(ac)
|
||||
|
||||
for model_key, model_funcs in parameter.items():
|
||||
m = QtWidgets.QMenu('Model ' + model_key, self)
|
||||
for func_name, func_params in model_funcs.items():
|
||||
m2 = QtWidgets.QMenu(func_name, m)
|
||||
for p_name, idx in func_params:
|
||||
ac = QtWidgets.QAction(p_name, m2)
|
||||
ac.setData((model_key, *idx))
|
||||
ac.triggered.connect(self.link_parameter)
|
||||
m2.addAction(ac)
|
||||
m.addMenu(m2)
|
||||
self.menu.addMenu(m)
|
||||
|
||||
self.toolButton.setMenu(self.menu)
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def link_parameter(self, linkto=None):
|
||||
if linkto is None:
|
||||
action = self.sender()
|
||||
else:
|
||||
action = False
|
||||
for m in self.menu.actions():
|
||||
if m.menu():
|
||||
for a in m.menu().actions():
|
||||
if a.data() == linkto:
|
||||
action = a
|
||||
break
|
||||
if action:
|
||||
break
|
||||
|
||||
if (self.func_idx, self.parameter_pos) == action.data():
|
||||
return
|
||||
|
||||
try:
|
||||
new_text = f'Linked to {action.parentWidget().title()}.{action.text()}'
|
||||
self._linetext = self.parameter_line.text()
|
||||
self.parameter_line.setText(new_text)
|
||||
self.parameter_line.setEnabled(False)
|
||||
self.global_checkbox.hide()
|
||||
self.global_checkbox.blockSignals(True)
|
||||
self.global_checkbox.setCheckState(QtCore.Qt.Checked)
|
||||
self.global_checkbox.blockSignals(False)
|
||||
self.frame.hide()
|
||||
self.is_linked = action.data()
|
||||
|
||||
except AttributeError:
|
||||
self.parameter_line.setText(self._linetext)
|
||||
self.parameter_line.setEnabled(True)
|
||||
if self.fixed_check.isEnabled():
|
||||
self.global_checkbox.show()
|
||||
self.frame.show()
|
||||
self.is_linked = None
|
||||
|
||||
self.state_changed.emit()
|
||||
from ..lib.iconloading import get_icon
|
||||
from ..lib.tables import TableWidget
|
||||
|
||||
|
||||
class QSaveModelDialog(QtWidgets.QDialog, Ui_SaveDialog):
|
||||
@ -227,30 +45,37 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
||||
treeChanged = QtCore.pyqtSignal()
|
||||
itemRemoved = QtCore.pyqtSignal(int)
|
||||
|
||||
counterRole = QtCore.Qt.UserRole + 1
|
||||
operatorRole = QtCore.Qt.UserRole + 2
|
||||
counterRole = QtCore.Qt.ItemDataRole.UserRole + 1
|
||||
operatorRole = QtCore.Qt.ItemDataRole.UserRole + 2
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setHeaderHidden(True)
|
||||
self.setDragEnabled(True)
|
||||
self.setDragDropMode(QtWidgets.QTreeWidget.InternalMove)
|
||||
self.setDefaultDropAction(QtCore.Qt.MoveAction)
|
||||
self.setDefaultDropAction(QtCore.Qt.DropAction.MoveAction)
|
||||
|
||||
self.itemSelectionChanged.connect(lambda: self.treeChanged.emit())
|
||||
|
||||
def keyPressEvent(self, evt):
|
||||
operators = [QtCore.Qt.Key_Plus, QtCore.Qt.Key_Asterisk,
|
||||
QtCore.Qt.Key_Minus, QtCore.Qt.Key_Slash]
|
||||
operators = [
|
||||
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():
|
||||
self.remove_function(item)
|
||||
|
||||
elif evt.key() == QtCore.Qt.Key_Space:
|
||||
for item in self.treeWidget.selectedItems():
|
||||
item.setCheckState(0, QtCore.Qt.Checked) if item.checkState(
|
||||
0) == QtCore.Qt.Unchecked else item.setCheckState(0, QtCore.Qt.Unchecked)
|
||||
elif evt.key() == QtCore.Qt.Key.Key_Space:
|
||||
for item in self.selectedItems():
|
||||
cs = item.checkState(0)
|
||||
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:
|
||||
idx = operators.index(evt.key())
|
||||
@ -280,8 +105,17 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
||||
idx = item.data(0, self.counterRole)
|
||||
self.itemRemoved.emit(idx)
|
||||
|
||||
def add_function(self, idx: int, cnt: int, op: int, name: str, color: QtGui.QColor | str | tuple,
|
||||
parent: QtWidgets.QTreeWidgetItem = None, children: list = None, active: bool = True, **kwargs):
|
||||
def add_function(self,
|
||||
idx: int,
|
||||
cnt: int,
|
||||
op: int,
|
||||
name: str,
|
||||
color: QtGui.QColor | str | tuple,
|
||||
parent: QtWidgets.QTreeWidgetItem = None,
|
||||
children: list = None,
|
||||
active: bool = True,
|
||||
param_names: list[str] = None,
|
||||
**kwargs):
|
||||
"""
|
||||
Add function to tree and dictionary of functions.
|
||||
"""
|
||||
@ -292,14 +126,18 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
||||
color = QtGui.QColor(color)
|
||||
|
||||
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.operatorRole, op)
|
||||
it.setText(0, name)
|
||||
if param_names is not None:
|
||||
it.setToolTip(0,
|
||||
'Parameter names:\n' +
|
||||
'\n'.join(f'{pn}({cnt})' for pn in param_names))
|
||||
it.setForeground(0, QtGui.QBrush(color))
|
||||
|
||||
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:
|
||||
self.addTopLevelItem(it)
|
||||
@ -319,7 +157,7 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
||||
def get_selected(self):
|
||||
try:
|
||||
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)
|
||||
|
||||
except IndexError:
|
||||
@ -342,10 +180,10 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
||||
it = parent.child(i)
|
||||
|
||||
child = {
|
||||
'idx': it.data(0, QtCore.Qt.UserRole),
|
||||
'idx': it.data(0, QtCore.Qt.ItemDataRole.UserRole),
|
||||
'op': it.data(0, self.operatorRole),
|
||||
'pos': pos,
|
||||
'active': (it.checkState(0) == QtCore.Qt.Checked),
|
||||
'active': (it.checkState(0) == QtCore.Qt.CheckState.Checked),
|
||||
'children': []
|
||||
}
|
||||
|
||||
@ -365,7 +203,7 @@ class FitModelTree(QtWidgets.QTreeWidget):
|
||||
return funcs
|
||||
|
||||
|
||||
class FitTableWidget(QtWidgets.QTableWidget):
|
||||
class FitTableWidget(TableWidget):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
@ -413,8 +251,8 @@ class FitTableWidget(QtWidgets.QTableWidget):
|
||||
|
||||
for (sid, name) in set_ids:
|
||||
item = QtWidgets.QTableWidgetItem(name)
|
||||
item.setCheckState(QtCore.Qt.Checked)
|
||||
item.setData(QtCore.Qt.UserRole+1, sid)
|
||||
item.setCheckState(QtCore.Qt.CheckState.Checked)
|
||||
item.setData(QtCore.Qt.ItemDataRole.UserRole+1, sid)
|
||||
row = self.rowCount()
|
||||
self.setRowCount(row+1)
|
||||
self.setItem(row, 0, item)
|
||||
@ -432,15 +270,15 @@ class FitTableWidget(QtWidgets.QTableWidget):
|
||||
|
||||
for i in range(self.rowCount()):
|
||||
item = self.item(i, 0)
|
||||
if item.checkState() == QtCore.Qt.Checked:
|
||||
if item.checkState() == QtCore.Qt.CheckState.Checked:
|
||||
mod = self.cellWidget(i, 1).currentData()
|
||||
if mod is None:
|
||||
mod = default
|
||||
|
||||
if include_name:
|
||||
arg = (item.data(QtCore.Qt.UserRole+1), item.text())
|
||||
arg = (item.data(QtCore.Qt.ItemDataRole.UserRole+1), item.text())
|
||||
else:
|
||||
arg = item.data(QtCore.Qt.UserRole+1)
|
||||
arg = item.data(QtCore.Qt.ItemDataRole.UserRole+1)
|
||||
|
||||
if mod not in data:
|
||||
data[mod] = []
|
||||
@ -453,8 +291,8 @@ class FitTableWidget(QtWidgets.QTableWidget):
|
||||
for i in range(self.rowCount()):
|
||||
item = self.item(i, 0)
|
||||
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:
|
||||
ret_val.append(item.data(QtCore.Qt.UserRole+1))
|
||||
ret_val.append(item.data(QtCore.Qt.ItemDataRole.UserRole+1))
|
||||
|
||||
return ret_val
|
||||
|
@ -1,22 +1,24 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from nmreval.fit.parameter import Parameter
|
||||
from nmreval.utils.text import convert
|
||||
|
||||
from ..Qt import QtWidgets, QtCore, QtGui
|
||||
from .._py.fitfuncwidget import Ui_FormFit
|
||||
from .._py.fitmodelwidget import Ui_FitParameter
|
||||
from ..lib.forms import SelectionWidget
|
||||
from .fit_forms import FitModelWidget
|
||||
|
||||
|
||||
class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
value_requested = QtCore.pyqtSignal(int)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
def __init__(self, func_id: int, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setupUi(self)
|
||||
|
||||
self.func = None
|
||||
self.func_idx = None
|
||||
self.func_id = func_id
|
||||
self.max_width = QtCore.QSize(0, 0)
|
||||
self.global_parameter = []
|
||||
self.data_parameter = []
|
||||
@ -27,16 +29,15 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
self.scrollwidget2.setLayout(QtWidgets.QVBoxLayout())
|
||||
|
||||
def eventFilter(self, src: QtCore.QObject, evt: QtCore.QEvent):
|
||||
modifiers = QtCore.Qt.KeyboardModifier.ControlModifier | QtCore.Qt.KeyboardModifier.ShiftModifier
|
||||
if isinstance(evt, QtGui.QKeyEvent):
|
||||
if (evt.key() == QtCore.Qt.Key_Right) and \
|
||||
(evt.modifiers() == QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier):
|
||||
if (evt.key() == QtCore.Qt.Key.Key_Right) and (evt.modifiers() == modifiers):
|
||||
self.change_single_parameter(src.value, sender=src)
|
||||
self.select_next_preview(1)
|
||||
|
||||
return True
|
||||
|
||||
elif (evt.key() == QtCore.Qt.Key_Left) and \
|
||||
(evt.modifiers() == QtCore.Qt.ControlModifier | QtCore.Qt.ShiftModifier):
|
||||
elif (evt.key() == QtCore.Qt.Key.Key_Left) and (evt.modifiers() == modifiers):
|
||||
self.change_single_parameter(src.value, sender=src)
|
||||
self.select_next_preview(-1)
|
||||
|
||||
@ -62,8 +63,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
self.glob_values = [1] * len(func.params)
|
||||
|
||||
for k, v in enumerate(func.params):
|
||||
name = convert(v)
|
||||
widgt = FitModelWidget(label=name, parent=self.scrollwidget)
|
||||
widgt = ParameterGlobalWidget(name=v, parent=self.scrollwidget)
|
||||
widgt.parameter_pos = k
|
||||
widgt.func_idx = idx
|
||||
try:
|
||||
@ -78,11 +78,12 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
widgt.state_changed.connect(self.make_global)
|
||||
widgt.value_requested.connect(self.look_for_value)
|
||||
widgt.value_changed.connect(self.change_global_parameter)
|
||||
widgt.replace_single_value.connect(self.delete_single_parameter)
|
||||
|
||||
self.global_parameter.append(widgt)
|
||||
self.scrollwidget.layout().addWidget(widgt)
|
||||
|
||||
widgt2 = ParameterSingleWidget(name=name, parent=self.scrollwidget2)
|
||||
widgt2 = ParameterSingleWidget(name=v, parent=self.scrollwidget2)
|
||||
widgt2.valueChanged.connect(self.change_single_parameter)
|
||||
widgt2.removeSingleValue.connect(self.change_single_parameter)
|
||||
widgt2.installEventFilter(self)
|
||||
@ -92,7 +93,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
for w1, w2 in zip(self.global_parameter, self.data_parameter):
|
||||
w1.parametername.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:
|
||||
cbox = func.choices
|
||||
@ -114,20 +115,22 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
self.scrollwidget.layout().addStretch(1)
|
||||
self.scrollwidget2.layout().addStretch(1)
|
||||
|
||||
def set_links(self, parameter):
|
||||
for w in self.global_parameter:
|
||||
if isinstance(w, FitModelWidget):
|
||||
w.add_links(parameter)
|
||||
# def set_links(self, parameter):
|
||||
# for w in self.global_parameter:
|
||||
# if isinstance(w, FitModelWidget):
|
||||
# w.add_links(parameter)
|
||||
|
||||
@QtCore.pyqtSlot(str)
|
||||
def change_global_parameter(self, value: str, idx: int = None):
|
||||
if idx is None:
|
||||
idx = self.global_parameter.index(self.sender())
|
||||
|
||||
self.glob_values[idx] = float(value)
|
||||
# self.glob_values[idx] = float(value)
|
||||
self.glob_values[idx] = value
|
||||
if self.data_values[self.comboBox.currentData()][idx] is None:
|
||||
self.data_parameter[idx].blockSignals(True)
|
||||
self.data_parameter[idx].value = float(value)
|
||||
# self.data_parameter[idx].value = float(value)
|
||||
self.data_parameter[idx].value = value
|
||||
self.data_parameter[idx].blockSignals(False)
|
||||
|
||||
@QtCore.pyqtSlot(str, object)
|
||||
@ -148,6 +151,13 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
if value is None:
|
||||
self.change_data(self.comboBox.currentIndex())
|
||||
|
||||
def delete_single_parameter(self):
|
||||
idx = self.global_parameter.index(self.sender())
|
||||
for i in range(self.comboBox.count()):
|
||||
set_id = self.comboBox.itemData(i)
|
||||
self.data_values[set_id][idx] = None
|
||||
self.change_data(self.comboBox.currentIndex())
|
||||
|
||||
def change_single_choice(self, _, value, sender=None):
|
||||
if sender is None:
|
||||
sender = self.sender()
|
||||
@ -163,7 +173,7 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
# disable single parameter if it is set global, enable if global is unset
|
||||
widget = self.sender()
|
||||
idx = self.global_parameter.index(widget)
|
||||
enable = (widget.global_checkbox.checkState() == QtCore.Qt.Unchecked) and (widget.is_linked is None)
|
||||
enable = (widget.global_checkbox.checkState() == QtCore.Qt.CheckState.Unchecked)
|
||||
self.data_parameter[idx].setEnabled(enable)
|
||||
|
||||
def select_next_preview(self, direction):
|
||||
@ -181,6 +191,11 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
for i, value in enumerate(self.data_values[sid]):
|
||||
w = self.data_parameter[i]
|
||||
w.blockSignals(True)
|
||||
try:
|
||||
w.show_as_local_parameter(value is not None)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if value is None:
|
||||
w.value = self.glob_values[i]
|
||||
else:
|
||||
@ -191,64 +206,50 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
if sid not in self.data_values:
|
||||
self.data_values[sid] = [None] * len(self.data_parameter)
|
||||
|
||||
def get_parameter(self, use_func=None):
|
||||
def get_parameter(self, use_func=None) -> tuple[dict, list]:
|
||||
bds = []
|
||||
is_global = []
|
||||
is_fixed = []
|
||||
globs = []
|
||||
is_linked = []
|
||||
param_general = []
|
||||
|
||||
for g in self.global_parameter:
|
||||
if isinstance(g, FitModelWidget):
|
||||
p_i, bds_i, fixed_i, global_i, link_i = g.get_parameter()
|
||||
if isinstance(g, ParameterGlobalWidget):
|
||||
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)
|
||||
param_general.append(parameter_i)
|
||||
|
||||
globs.append(p_i)
|
||||
bds.append(bds_i)
|
||||
is_fixed.append(fixed_i)
|
||||
is_global.append(global_i)
|
||||
is_linked.append(link_i)
|
||||
|
||||
lb, ub = list(zip(*bds))
|
||||
|
||||
data_parameter = {}
|
||||
if use_func is None:
|
||||
use_func = list(self.data_values.keys())
|
||||
|
||||
global_p = None
|
||||
for sid, parameter in self.data_values.items():
|
||||
if sid not in use_func:
|
||||
continue
|
||||
|
||||
kw_p = {}
|
||||
p = []
|
||||
if global_p is None:
|
||||
global_p = {'p': [], 'idx': [], 'var': [], 'ub': [], 'lb': []}
|
||||
|
||||
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]:
|
||||
p.append(globs[i])
|
||||
if is_global[i]:
|
||||
if i not in global_p['idx']:
|
||||
global_p['p'].append(globs[i])
|
||||
global_p['idx'].append(i)
|
||||
global_p['var'].append(is_fixed[i])
|
||||
global_p['ub'].append(ub[i])
|
||||
global_p['lb'].append(lb[i])
|
||||
# set has no oen value
|
||||
p.append(param_general[i].copy())
|
||||
else:
|
||||
p.append(p_i)
|
||||
|
||||
lb, ub = bds[i]
|
||||
try:
|
||||
if p[i] > ub[i]:
|
||||
raise ValueError(f'Parameter {g.name} is outside bounds ({lb[i]}, {ub[i]})')
|
||||
if not ((lb < p_i < ub) or (not is_fixed[i])):
|
||||
raise ValueError(f'Parameter {g.name} is outside bounds ({lb}, {ub})')
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
try:
|
||||
if p[i] < lb[i]:
|
||||
raise ValueError(f'Parameter {g.name} is outside bounds ({lb[i]}, {ub[i]})')
|
||||
except TypeError:
|
||||
pass
|
||||
# create Parameter
|
||||
p.append(
|
||||
Parameter(name=g.name, value=p_i, lb=lb, ub=ub, var=is_fixed[i])
|
||||
)
|
||||
|
||||
else:
|
||||
if p_i is None:
|
||||
@ -260,20 +261,28 @@ class QFitParameterWidget(QtWidgets.QWidget, Ui_FormFit):
|
||||
|
||||
data_parameter[sid] = (p, kw_p)
|
||||
|
||||
return data_parameter, lb, ub, is_fixed, global_p, is_linked
|
||||
global_parameter = []
|
||||
for param, global_flag in zip(param_general, is_global):
|
||||
if global_flag:
|
||||
param.is_global = True
|
||||
global_parameter.append(param)
|
||||
else:
|
||||
global_parameter.append(None)
|
||||
|
||||
return data_parameter, global_parameter
|
||||
|
||||
def set_parameter(self, set_id: str | None, parameter: list[float]) -> int:
|
||||
param_len = len(list(filter(lambda g: not isinstance(g, SelectionWidget), self.global_parameter)))
|
||||
|
||||
num_parameter = list(filter(lambda g: not isinstance(g, SelectionWidget), self.global_parameter))
|
||||
param_len = len(num_parameter)
|
||||
if set_id is None:
|
||||
for val, g in zip(parameter, self.global_parameter):
|
||||
if isinstance(g, SelectionWidget):
|
||||
continue
|
||||
for i, g in enumerate(num_parameter):
|
||||
val = parameter[i]
|
||||
g.set_parameter(val)
|
||||
self.glob_values[i] = val
|
||||
|
||||
else:
|
||||
new_param = self.data_values[set_id]
|
||||
min_len = min(param_len, len(new_param), len(new_param))
|
||||
min_len = min(param_len, len(new_param))
|
||||
for i in range(min_len):
|
||||
new_param[i] = parameter[i]
|
||||
|
||||
@ -291,10 +300,14 @@ class ParameterSingleWidget(QtWidgets.QWidget):
|
||||
|
||||
self._init_ui()
|
||||
|
||||
self._name = name
|
||||
self.label.setText(convert(name))
|
||||
self.name = name
|
||||
self.parametername.setText(convert(name))
|
||||
self.parametername.setToolTip(
|
||||
'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.reset_button.clicked.connect(lambda x: self.removeSingleValue.emit())
|
||||
|
||||
@ -303,16 +316,18 @@ class ParameterSingleWidget(QtWidgets.QWidget):
|
||||
layout.setContentsMargins(2, 2, 2, 2)
|
||||
layout.setSpacing(2)
|
||||
|
||||
self.label = QtWidgets.QLabel(self)
|
||||
layout.addWidget(self.label)
|
||||
self.parametername = QtWidgets.QLabel(self)
|
||||
layout.addWidget(self.parametername)
|
||||
|
||||
layout.addSpacerItem(QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum))
|
||||
|
||||
self.value_line = QtWidgets.QLineEdit(self)
|
||||
self.value_line.textEdited.connect(lambda x: self.show_as_local_parameter(True))
|
||||
layout.addWidget(self.value_line)
|
||||
|
||||
self.reset_button = QtWidgets.QToolButton(self)
|
||||
self.reset_button.setText('Use global')
|
||||
self.reset_button.clicked.connect(lambda: self.show_as_local_parameter(False))
|
||||
layout.addWidget(self.reset_button)
|
||||
|
||||
self.setLayout(layout)
|
||||
@ -326,4 +341,139 @@ class ParameterSingleWidget(QtWidgets.QWidget):
|
||||
|
||||
@value.setter
|
||||
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.setCursorPosition(0)
|
||||
|
||||
def show_as_local_parameter(self, is_local: bool):
|
||||
if is_local:
|
||||
self.parametername.setStyleSheet('font-weight: bold;')
|
||||
else:
|
||||
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,12 +6,14 @@ from nmreval.configs import config_paths
|
||||
from nmreval import models
|
||||
from nmreval.lib.importer import find_models
|
||||
from nmreval.lib.colors import BaseColor, Tab10
|
||||
from nmreval.lib.logger import logger
|
||||
from nmreval.utils.text import convert
|
||||
|
||||
from ..lib import get_icon
|
||||
from ..lib.iconloading import get_icon
|
||||
from .._py.fitfunctionwidget import Ui_Form
|
||||
from ..Qt import QtWidgets, QtCore, QtGui
|
||||
|
||||
|
||||
class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
|
||||
func_cnt = count()
|
||||
func_colors = cycle(Tab10)
|
||||
@ -49,8 +51,17 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
|
||||
user_defined = []
|
||||
try:
|
||||
user_defined = find_models(config_paths() / 'usermodels.py')
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
except Exception as e:
|
||||
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:
|
||||
name = model.__name__
|
||||
@ -127,7 +138,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
|
||||
|
||||
self.newFunction.emit(idx, cnt)
|
||||
|
||||
self.add_function(idx, cnt, op, name, col)
|
||||
self.add_function(idx, cnt, op, name, col, param_names=self.functions[idx].params)
|
||||
|
||||
def add_function(self, idx: int, cnt: int, op: int,
|
||||
name: str, color: str | tuple[float, float, float] | BaseColor, **kwargs):
|
||||
@ -140,6 +151,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
|
||||
qcolor = QtGui.QColor.fromRgbF(*color)
|
||||
else:
|
||||
qcolor = QtGui.QColor(color)
|
||||
|
||||
self.functree.add_function(idx, cnt, op, name, qcolor, **kwargs)
|
||||
|
||||
f = self.functions[idx]
|
||||
@ -153,7 +165,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
|
||||
self.iscomplex = False
|
||||
while 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:
|
||||
self.iscomplex = True
|
||||
break
|
||||
@ -214,7 +226,7 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
|
||||
iterator = QtWidgets.QTreeWidgetItemIterator(self.functree)
|
||||
while 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)
|
||||
all_parameters[f'{f.name}_{cnt}'] = [(convert(pp, new='str'), (cnt, i)) for i, pp in enumerate(f.params)]
|
||||
|
||||
@ -223,7 +235,19 @@ class QFunctionWidget(QtWidgets.QWidget, Ui_Form):
|
||||
return all_parameters
|
||||
|
||||
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):
|
||||
if state is not None:
|
||||
|
@ -9,10 +9,13 @@ import numpy as np
|
||||
from pyqtgraph import mkPen
|
||||
|
||||
from nmreval.fit._meta import MultiModel, ModelFactory
|
||||
from nmreval.fit.model import Model
|
||||
from nmreval.fit.parameter import Parameters
|
||||
from nmreval.fit.result import FitResult
|
||||
|
||||
from .fit_forms import FitTableWidget
|
||||
from .fit_parameter import QFitParameterWidget
|
||||
from ..lib import Relations
|
||||
from ..lib.pg_objects import PlotItem
|
||||
from ..Qt import QtGui, QtCore, QtWidgets
|
||||
from .._py.fitdialog import Ui_FitDialog
|
||||
@ -38,8 +41,8 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
self._management = mgmt
|
||||
|
||||
self._current_model = next(QFitDialog.model_cnt)
|
||||
self.show_combobox.setItemData(0, self._current_model, QtCore.Qt.UserRole)
|
||||
self.default_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.ItemDataRole.UserRole)
|
||||
|
||||
self.data_table = FitTableWidget(self.data_widget)
|
||||
self.data_widget.addWidget(self.data_table)
|
||||
@ -49,7 +52,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
self._func_list = {}
|
||||
self._complex = {}
|
||||
|
||||
self.connected_figure = ''
|
||||
self.connected_figure = None
|
||||
|
||||
self.model_frame.hide()
|
||||
self.preview_button.hide()
|
||||
@ -74,19 +77,18 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
"""
|
||||
w = self.param_widgets[idx]
|
||||
self.stackedWidget.removeWidget(w)
|
||||
w.setParent(None)
|
||||
w.deleteLater()
|
||||
del self.param_widgets[idx]
|
||||
_, func_id = self.functionwidget.get_selected()
|
||||
|
||||
if len(self.functionwidget) == 0:
|
||||
self.get_functions()
|
||||
|
||||
self._current_function = None
|
||||
if len(self.param_widgets) == 0:
|
||||
# empty model
|
||||
self.newmodel_button.setEnabled(False)
|
||||
self.deletemodel_button.setEnabled(False)
|
||||
self._current_function = None
|
||||
|
||||
else:
|
||||
f_tree = self.functionwidget.functree
|
||||
func_idx = f_tree.currentItem().data(0, f_tree.counterRole)
|
||||
self._current_function = self.functionwidget.functions[func_idx]
|
||||
|
||||
@QtCore.pyqtSlot(int)
|
||||
def show_function_parameter(self, function_id: int, function_idx: int = None):
|
||||
@ -106,7 +108,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
if function is None:
|
||||
return
|
||||
|
||||
dialog = QFitParameterWidget(self.stackedWidget)
|
||||
dialog = QFitParameterWidget(function_id, self.stackedWidget)
|
||||
data_names = self.data_table.data_list(include_name=True)
|
||||
|
||||
dialog.set_function(function, function_idx)
|
||||
@ -120,7 +122,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
|
||||
# collect parameter names etc. to allow linkage
|
||||
self._func_list[self._current_model] = self.functionwidget.get_parameter_list()
|
||||
dialog.set_links(self._func_list)
|
||||
# dialog.set_links(self._func_list)
|
||||
|
||||
# show same tab (general parameter/Data parameter)
|
||||
tab_idx = 0
|
||||
@ -148,6 +150,13 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
Add name and id of dataset to list.
|
||||
"""
|
||||
self.data_table.load(ids)
|
||||
|
||||
# deselect all fit sets
|
||||
for i in range(self.data_table.rowCount()):
|
||||
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):
|
||||
self.data_table.item(i, 0).setCheckState(QtCore.Qt.CheckState.Unchecked)
|
||||
|
||||
if self.models:
|
||||
for m in self.models.keys():
|
||||
self.data_table.add_model(m)
|
||||
@ -170,7 +179,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
|
||||
self.default_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._current_model = idx
|
||||
@ -184,7 +193,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
self.get_functions()
|
||||
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]):
|
||||
for el in self.models[self._current_model]:
|
||||
self.functionwidget.add_function(**el)
|
||||
@ -201,9 +210,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
|
||||
for m in self.models[model_id]:
|
||||
func_id = m['cnt']
|
||||
self.stackedWidget.removeWidget(self.param_widgets[func_id])
|
||||
|
||||
self.param_widgets.pop(func_id)
|
||||
self.remove_function(func_id)
|
||||
|
||||
self._complex.pop(model_id)
|
||||
self._func_list.pop(model_id)
|
||||
@ -214,59 +221,57 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
if len(self.models) == 1:
|
||||
self.model_frame.hide()
|
||||
|
||||
def _prepare(self, model: list, function_use: list = None,
|
||||
parameter: dict = None, add_idx: bool = False, cnt: int = 0) -> tuple[dict, int]:
|
||||
def _prepare(
|
||||
self,
|
||||
model: list,
|
||||
function_use: list = None,
|
||||
parameter: dict = None,
|
||||
add_idx: bool = False,
|
||||
cnt: int = 0,
|
||||
) -> tuple[dict, int]:
|
||||
|
||||
if parameter is None:
|
||||
parameter = {'parameter': {}, 'lb': (), 'ub': (), 'var': [],
|
||||
'glob': {'idx': [], 'p': [], 'var': [], 'lb': [], 'ub': []},
|
||||
'links': [], 'color': []}
|
||||
parameter = {
|
||||
'data_parameter': {},
|
||||
'global_parameter': [],
|
||||
'links': [],
|
||||
'color': [],
|
||||
}
|
||||
|
||||
for i, f in enumerate(model):
|
||||
if not f['active']:
|
||||
continue
|
||||
|
||||
try:
|
||||
p, lb, ub, var, glob, links = self.param_widgets[f['cnt']].get_parameter(function_use)
|
||||
p, glob = self.param_widgets[f['cnt']].get_parameter(function_use)
|
||||
except ValueError as e:
|
||||
_ = QtWidgets.QMessageBox().warning(self, 'Invalid value', str(e),
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return {}, -1
|
||||
|
||||
p_len = len(parameter['lb'])
|
||||
|
||||
parameter['lb'] += lb
|
||||
parameter['ub'] += ub
|
||||
parameter['var'] += var
|
||||
parameter['links'] += links
|
||||
parameter['color'] += [f['color']]
|
||||
parameter['color'].append(f['color'])
|
||||
parameter['global_parameter'].extend(glob)
|
||||
|
||||
cnt = f['cnt']
|
||||
|
||||
for p_k, v_k in p.items():
|
||||
if add_idx:
|
||||
kw_k = {f'{k}_{cnt}': v for k, v in v_k[1].items()}
|
||||
else:
|
||||
kw_k = v_k[1]
|
||||
|
||||
if p_k in parameter['parameter']:
|
||||
params, kw = parameter['parameter'][p_k]
|
||||
if p_k in parameter['data_parameter']:
|
||||
params, kw = parameter['data_parameter'][p_k]
|
||||
params += v_k[0]
|
||||
kw.update(kw_k)
|
||||
else:
|
||||
parameter['parameter'][p_k] = (v_k[0], kw_k)
|
||||
|
||||
for g_k, g_v in glob.items():
|
||||
if g_k != 'idx':
|
||||
parameter['glob'][g_k] += g_v
|
||||
else:
|
||||
parameter['glob']['idx'] += [idx_i + p_len for idx_i in g_v]
|
||||
parameter['data_parameter'][p_k] = (v_k[0], kw_k)
|
||||
|
||||
if add_idx:
|
||||
cnt += 1
|
||||
|
||||
if f['children']:
|
||||
# recurse for children
|
||||
child_parameter, 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
|
||||
|
||||
@ -277,30 +282,46 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
data = self.data_table.collect_data(default=self.default_combobox.currentData())
|
||||
|
||||
func_dict = {}
|
||||
for k, mod in self.models.items():
|
||||
func, order, param_len = ModelFactory.create_from_list(mod)
|
||||
|
||||
for model_name, model_parameter in self.models.items():
|
||||
func, order, param_len, _ = ModelFactory.create_from_list(model_parameter)
|
||||
multiple_funcs = isinstance(func, MultiModel)
|
||||
if func is None:
|
||||
continue
|
||||
|
||||
if k in data:
|
||||
parameter, _ = self._prepare(mod, function_use=data[k], add_idx=isinstance(func, MultiModel))
|
||||
if parameter is None:
|
||||
func = Model(func)
|
||||
|
||||
if model_name in data:
|
||||
parameter, _ = self._prepare(model_parameter, function_use=data[model_name], add_idx=multiple_funcs)
|
||||
|
||||
if parameter is None or not isinstance(parameter, dict):
|
||||
return
|
||||
|
||||
if ('data_parameter' not in parameter) or ('global_parameter' not in parameter):
|
||||
return
|
||||
|
||||
for (data_parameter, _) in parameter['data_parameter'].values():
|
||||
for pname, param in zip(func.params, data_parameter):
|
||||
param.name = pname
|
||||
|
||||
if self._complex[model_name] is not None:
|
||||
for p_k, p_v in parameter['data_parameter'].items():
|
||||
p_v[1].update({'complex_mode': self._complex[model_name]})
|
||||
parameter['data_parameter'][p_k] = p_v[0], p_v[1]
|
||||
|
||||
for pname, param_value in zip(func.params, parameter['global_parameter']):
|
||||
if param_value is not None:
|
||||
param_value.name = pname
|
||||
func.set_global_parameter(param_value)
|
||||
|
||||
parameter['func'] = func
|
||||
parameter['order'] = order
|
||||
parameter['len'] = param_len
|
||||
parameter['complex'] = self._complex[k]
|
||||
if self._complex[k] is not None:
|
||||
for p_k, p_v in parameter['parameter'].items():
|
||||
p_v[1].update({'complex_mode': self._complex[k]})
|
||||
parameter['parameter'][p_k] = p_v[0], p_v[1]
|
||||
parameter['complex'] = self._complex[model_name]
|
||||
|
||||
func_dict[k] = parameter
|
||||
func_dict[model_name] = parameter
|
||||
|
||||
replaceable = []
|
||||
for k, v in func_dict.items():
|
||||
for model_name, v in func_dict.items():
|
||||
for i, link_i in enumerate(v['links']):
|
||||
if link_i is None:
|
||||
continue
|
||||
@ -331,7 +352,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return
|
||||
|
||||
replaceable.append((k, i, rep_model, repl_idx))
|
||||
replaceable.append((model_name, i, rep_model, repl_idx))
|
||||
|
||||
replace_value = None
|
||||
for p_k in f['parameter'].values():
|
||||
@ -374,7 +395,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
|
||||
func_dict = {}
|
||||
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)
|
||||
|
||||
if k in data:
|
||||
@ -409,31 +430,37 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
def make_previews(self, x, models_parameters: dict):
|
||||
self.preview_lines = []
|
||||
|
||||
# needed to create namespace
|
||||
param_dict = Parameters()
|
||||
|
||||
cnt = 0
|
||||
for model in models_parameters.values():
|
||||
f = model['func']
|
||||
for parameter_list in model['data_parameter'].values():
|
||||
for i, p_value in enumerate(parameter_list[0]):
|
||||
p_value.name = f.params[i]
|
||||
param_dict.add_parameter(f'a{cnt}', p_value)
|
||||
cnt += 1
|
||||
|
||||
for k, model in models_parameters.items():
|
||||
f = model['func']
|
||||
is_complex = self._complex[k]
|
||||
|
||||
parameters = model['parameter']
|
||||
parameters = model['data_parameter']
|
||||
color = model['color']
|
||||
|
||||
seen_parameter = []
|
||||
|
||||
for p, kwargs in parameters.values():
|
||||
if (p, kwargs) in seen_parameter:
|
||||
# plot only previews with different parameter
|
||||
continue
|
||||
|
||||
seen_parameter.append((p, kwargs))
|
||||
p_value = [pp.value for pp in p]
|
||||
|
||||
if is_complex is not None:
|
||||
y = f.func(x, *p, complex_mode=is_complex, **kwargs)
|
||||
y = f.func(x, *p_value, complex_mode=is_complex, **kwargs)
|
||||
if np.iscomplexobj(y):
|
||||
self.preview_lines.append(PlotItem(x=x, y=y.real, pen=mkPen(width=3)))
|
||||
self.preview_lines.append(PlotItem(x=x, y=y.imag, pen=mkPen(width=3)))
|
||||
else:
|
||||
self.preview_lines.append(PlotItem(x=x, y=y, pen=mkPen(width=3)))
|
||||
else:
|
||||
y = f.func(x, *p, **kwargs)
|
||||
y = f.func(x, *p_value, **kwargs)
|
||||
self.preview_lines.append(PlotItem(x=x, y=y, pen=mkPen(width=3)))
|
||||
|
||||
if isinstance(f, MultiModel):
|
||||
@ -441,7 +468,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
if is_complex is not None:
|
||||
sub_kwargs.update({'complex_mode': is_complex})
|
||||
|
||||
for i, s in enumerate(f.subs(x, *p, **sub_kwargs)):
|
||||
for i, s in enumerate(f.subs(x, *p_value, **sub_kwargs)):
|
||||
pen_i = mkPen(QtGui.QColor.fromRgbF(*color[i]))
|
||||
if np.iscomplexobj(s):
|
||||
self.preview_lines.append(PlotItem(x=x, y=s.real, pen=pen_i))
|
||||
@ -449,15 +476,17 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
else:
|
||||
self.preview_lines.append(PlotItem(x=x, y=s, pen=pen_i))
|
||||
|
||||
param_dict.clear()
|
||||
|
||||
return self.preview_lines
|
||||
|
||||
def set_parameter(self, parameter: dict[str, FitResult]):
|
||||
# which data uses which model
|
||||
data = self.data_table.collect_data(default=self.default_combobox.currentData())
|
||||
|
||||
for fitted_model, fitted_data in data.items():
|
||||
glob_fit_parameter = []
|
||||
|
||||
for fitted_model, fitted_data in data.items():
|
||||
for fit_id, fit_curve in parameter.items():
|
||||
if fit_id in fitted_data:
|
||||
fit_parameter = list(fit_curve.parameter.values())
|
||||
@ -474,7 +503,7 @@ class QFitDialog(QtWidgets.QWidget, Ui_FitDialog):
|
||||
if model_p['active']:
|
||||
cnt += self.param_widgets[model_p['cnt']].set_parameter(fit_id, param[cnt:])
|
||||
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
|
||||
|
||||
|
@ -8,13 +8,13 @@ from typing import Any
|
||||
|
||||
import numpy as np
|
||||
|
||||
from gui_qt.Qt import QtCore, QtWidgets, QtGui
|
||||
from gui_qt._py.fitcreationdialog import Ui_Dialog
|
||||
from gui_qt.lib.namespace import QNamespaceWidget
|
||||
from ..Qt import QtCore, QtWidgets, QtGui
|
||||
from .._py.fitcreationdialog import Ui_Dialog
|
||||
from ..editors.namespace import QNamespaceWidget
|
||||
|
||||
__all__ = ['QUserFitCreator']
|
||||
|
||||
validator = QtGui.QRegExpValidator(QtCore.QRegExp('[A-Za-z]\S*'))
|
||||
validator = QtGui.QRegExpValidator(QtCore.QRegExp('[_A-Za-z][_A-Za-z0-9]*'))
|
||||
pattern = re.compile(r'def func\(.*\):', flags=re.MULTILINE)
|
||||
|
||||
|
||||
@ -48,13 +48,13 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
self.update_function()
|
||||
|
||||
def __call__(self, filepath: str|pathlib.Path):
|
||||
def __call__(self, filepath: str | pathlib.Path):
|
||||
self.filepath = pathlib.Path(filepath)
|
||||
|
||||
return self
|
||||
|
||||
def update_function(self):
|
||||
prev_text = self.plainTextEdit.toPlainText().split('\n')
|
||||
prev_text = self.editor.toPlainText().split('\n')
|
||||
func_body = ''
|
||||
in_body = False
|
||||
for line in prev_text:
|
||||
@ -89,9 +89,12 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
|
||||
else:
|
||||
k += f' def func(x):\n'
|
||||
|
||||
if func_body:
|
||||
k += func_body
|
||||
else:
|
||||
k += ' return x'
|
||||
|
||||
self.plainTextEdit.setPlainText(k)
|
||||
self.editor.setPlainText(k)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self, 'Failure', f'Error found: {e.args[0]}')
|
||||
|
||||
@ -145,6 +148,7 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.classCreated.emit()
|
||||
super().accept()
|
||||
|
||||
|
||||
class KwargsWidget(QtWidgets.QWidget):
|
||||
Changed = QtCore.pyqtSignal()
|
||||
|
||||
@ -209,12 +213,12 @@ class KwargsWidget(QtWidgets.QWidget):
|
||||
def get_strings(self) -> str:
|
||||
kwargs = []
|
||||
if self.use_nuclei.isChecked():
|
||||
kwargs.append("(r'\gamma', 'nucleus', gamma)")
|
||||
kwargs.append(r"(r'\gamma', 'nucleus', gamma)")
|
||||
|
||||
for i in range(self.choices.count()):
|
||||
kwargs.append(self.choices.widget(i).get_strings())
|
||||
if kwargs:
|
||||
return f" choices = {', '.join(kwargs)}\n"
|
||||
return f" choices = [{', '.join(kwargs)}]\n"
|
||||
else:
|
||||
return ''
|
||||
|
||||
@ -300,7 +304,7 @@ class ChoiceWidget(QtWidgets.QWidget):
|
||||
def get_strings(self) -> str:
|
||||
opts = []
|
||||
for i in range(self.table.rowCount()):
|
||||
name = self.table.item(i, 0).text()
|
||||
name = self.table.cellWidget(i, 0).text()
|
||||
val = self._make_value(i)
|
||||
opts.append(f'{name!r}: {val!r}')
|
||||
|
||||
@ -471,15 +475,6 @@ class DescWidget(QtWidgets.QWidget):
|
||||
stringi = f'class {self.klass_lineedit.text()}:\n' \
|
||||
f' name = {self.name_lineedit.text()!r}\n' \
|
||||
f' type = {self.group_lineedit.text()!r}\n' \
|
||||
f' equation = {self.eq_lineedit.text()!r}\n'
|
||||
f" equation = r'{self.eq_lineedit.text()}'\n"
|
||||
|
||||
return stringi
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
app = QtWidgets.QApplication([])
|
||||
win = QUserFitCreator()
|
||||
win.show()
|
||||
|
||||
sys.exit(app.exec())
|
||||
|
@ -1,8 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from math import isnan
|
||||
|
||||
from pyqtgraph import mkBrush
|
||||
from pyqtgraph import mkBrush, mkPen, mkColor
|
||||
from numpy import abs as np_abs, isfinite as np_isfinite
|
||||
|
||||
from nmreval.utils.text import convert
|
||||
from ..lib.graph_items import logTickValues
|
||||
|
||||
from ..lib.utils import RdBuCMap
|
||||
from ..Qt import QtWidgets, QtGui, QtCore
|
||||
@ -14,7 +18,7 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
||||
closed = QtCore.pyqtSignal(dict, list, str, bool, bool, list)
|
||||
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)
|
||||
self.setupUi(self)
|
||||
|
||||
@ -26,71 +30,98 @@ 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.minx_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._prevs = {}
|
||||
self._models = {}
|
||||
self._previous_fits = {}
|
||||
self._opts = []
|
||||
self._results = {}
|
||||
self.graph_opts = {}
|
||||
self.last_idx = None
|
||||
self.func_colors = sub_colors
|
||||
|
||||
self.fit_plot = self.graphicsView.addPlot(row=1, col=0, title='Fit')
|
||||
self.resid_plot = self.graphicsView.addPlot(row=0, col=0, title='Residual')
|
||||
|
||||
for orient in ['top', 'bottom', 'left', 'right']:
|
||||
self.fit_plot.getAxis(orient).logTickValues = logTickValues
|
||||
self.resid_plot.getAxis(orient).logTickValues = logTickValues
|
||||
|
||||
self.graphicsView.ci.layout.setRowStretchFactor(0, 1)
|
||||
self.graphicsView.ci.layout.setRowStretchFactor(1, 2)
|
||||
|
||||
self.resid_graph = PlotItem(
|
||||
x=[], y=[],
|
||||
symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)),
|
||||
pen=None
|
||||
)
|
||||
self.resid_graph_imag = PlotItem(
|
||||
x=[], y=[],
|
||||
symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)),
|
||||
pen=None
|
||||
)
|
||||
self.resid_plot.addItem(self.resid_graph)
|
||||
self.resid_plot.addItem(self.resid_graph_imag)
|
||||
|
||||
self.data_graph = PlotItem(
|
||||
x=[], y=[],
|
||||
symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)),
|
||||
pen=None
|
||||
)
|
||||
self.data_graph_imag = PlotItem(
|
||||
x=[], y=[],
|
||||
symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)),
|
||||
pen=None
|
||||
)
|
||||
self.fit_plot.addItem(self.data_graph)
|
||||
self.fit_plot.addItem(self.data_graph_imag)
|
||||
|
||||
self.fit_graph = PlotItem(x=[], y=[])
|
||||
self.fit_graph_imag = PlotItem(x=[], y=[])
|
||||
self.fit_plot.addItem(self.fit_graph)
|
||||
self.fit_plot.addItem(self.fit_graph_imag)
|
||||
|
||||
self.cmap = RdBuCMap(vmin=-1, vmax=1)
|
||||
|
||||
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.logx_box.stateChanged.connect(lambda x: self.fit_plot.setLogMode(x=bool(x)))
|
||||
self.resid_plot.setXLink(self.fit_plot)
|
||||
|
||||
self.buttonGroup.buttonToggled.connect(self._plot_residuals)
|
||||
|
||||
self.set_results(results)
|
||||
|
||||
def __call__(self, results: list, sub_colors: dict):
|
||||
self._previous_fits = {}
|
||||
self.sets_comboBox.blockSignals(True)
|
||||
self.sets_comboBox.clear()
|
||||
self.sets_comboBox.blockSignals(False)
|
||||
self._results = {}
|
||||
self._opts = {}
|
||||
self.func_colors = sub_colors
|
||||
|
||||
self.set_results(results)
|
||||
|
||||
def set_results(self, results: list):
|
||||
self.sets_comboBox.blockSignals(True)
|
||||
for res in results:
|
||||
idx = res.idx
|
||||
data_k = management.data[idx]
|
||||
data_k = self._management.data[idx]
|
||||
|
||||
if res.name not in self._models:
|
||||
self._models[res.name] = []
|
||||
|
||||
self._models[res.name].append(idx)
|
||||
|
||||
self._prevs[idx] = []
|
||||
self._previous_fits[idx] = []
|
||||
for fit in data_k.get_fits():
|
||||
self._prevs[idx].append((fit.name, fit.statistics, fit.nobs-fit.nvar))
|
||||
self._previous_fits[idx].append((fit.name, fit.statistics, fit.nobs - fit.nvar))
|
||||
|
||||
self.sets_comboBox.addItem(data_k.name, userData=idx)
|
||||
self.sets_comboBox.blockSignals(False)
|
||||
|
||||
self._results = {res.idx: res for res in results}
|
||||
self._opts = [(False, False) for _ in range(len(self._results))]
|
||||
|
||||
self.residplot = self.graphicsView.addPlot(row=0, col=0)
|
||||
self.resid_graph = PlotItem(x=[], y=[],
|
||||
symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)),
|
||||
pen=None)
|
||||
self.resid_graph_imag = PlotItem(x=[], y=[],
|
||||
symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)),
|
||||
pen=None)
|
||||
self.residplot.addItem(self.resid_graph)
|
||||
self.residplot.addItem(self.resid_graph_imag)
|
||||
self.residplot.setLabel('left', 'Residual')
|
||||
|
||||
self.fitplot = self.graphicsView.addPlot(row=1, col=0)
|
||||
self.data_graph = PlotItem(x=[], y=[],
|
||||
symbol='o', symbolPen=None, symbolBrush=mkBrush(color=(31, 119, 180)),
|
||||
pen=None)
|
||||
self.data_graph_imag = PlotItem(x=[], y=[],
|
||||
symbol='s', symbolPen=None, symbolBrush=mkBrush(color=(255, 127, 14)),
|
||||
pen=None)
|
||||
self.fitplot.addItem(self.data_graph)
|
||||
self.fitplot.addItem(self.data_graph_imag)
|
||||
self.fitplot.setLabel('left', 'Function')
|
||||
|
||||
self.fit_graph = PlotItem(x=[], y=[])
|
||||
self.fit_graph_imag = PlotItem(x=[], y=[])
|
||||
self.fitplot.addItem(self.fit_graph)
|
||||
self.fitplot.addItem(self.fit_graph_imag)
|
||||
|
||||
self.cmap = RdBuCMap(vmin=-1, vmax=1)
|
||||
|
||||
self.sets_comboBox.blockSignals(True)
|
||||
for n in self._models.keys():
|
||||
self.sets_comboBox.addItem(n)
|
||||
self.sets_comboBox.blockSignals(False)
|
||||
|
||||
self.set_parameter(0)
|
||||
self.buttonBox.accepted.connect(self.accept)
|
||||
|
||||
self.param_tableWidget.itemClicked.connect(self.show_results)
|
||||
self.param_tableWidget.horizontalHeader().sectionClicked.connect(lambda i: self.show_results(None, idx=i))
|
||||
|
||||
self.graph_checkBox.stateChanged.connect(lambda x: self.graph_comboBox.setEnabled(x == QtCore.Qt.Unchecked))
|
||||
|
||||
self.logy_box.stateChanged.connect(lambda x: self.fitplot.setLogMode(y=bool(x)))
|
||||
self.logx_box.stateChanged.connect(lambda x: self.fitplot.setLogMode(x=bool(x)))
|
||||
self.residplot.setXLink(self.fitplot)
|
||||
|
||||
def add_graphs(self, graphs: list):
|
||||
self.graph_comboBox.clear()
|
||||
@ -99,56 +130,40 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_sets_comboBox_currentIndexChanged')
|
||||
def set_parameter(self, idx: int):
|
||||
model_name = self.sets_comboBox.itemText(idx)
|
||||
sets = self._models[model_name]
|
||||
self.param_tableWidget.setColumnCount(len(sets))
|
||||
|
||||
r = self._results[sets[0]]
|
||||
self.param_tableWidget.setRowCount(len(r.parameter))
|
||||
|
||||
for i, pval in enumerate(r.parameter.values()):
|
||||
name = pval.full_name
|
||||
p_header = QtWidgets.QTableWidgetItem(convert(name, 'tex', 'html', brackets=False))
|
||||
self.param_tableWidget.setVerticalHeaderItem(i, p_header)
|
||||
|
||||
for i, set_id in enumerate(sets):
|
||||
data_i = self._management[set_id]
|
||||
header_item = QtWidgets.QTableWidgetItem(data_i.name)
|
||||
header_item.setData(QtCore.Qt.UserRole, set_id)
|
||||
self.param_tableWidget.setHorizontalHeaderItem(i, header_item)
|
||||
set_id = self.sets_comboBox.itemData(idx, QtCore.Qt.ItemDataRole.UserRole)
|
||||
|
||||
res = self._results[set_id]
|
||||
for j, pvalue in enumerate(res.parameter.values()):
|
||||
self.param_tableWidget.setRowCount(len(res.parameter))
|
||||
for j, (pkey, pvalue) in enumerate(res.parameter.items()):
|
||||
name = pkey
|
||||
p_header = QtWidgets.QTableWidgetItem(convert(name, 'tex', 'str', brackets=True))
|
||||
self.param_tableWidget.setVerticalHeaderItem(j, p_header)
|
||||
|
||||
item_text = f'{pvalue.value:.4g}'
|
||||
if pvalue.error is not None:
|
||||
item_text += f' \u00b1 {pvalue.error:.4g}'
|
||||
self.param_tableWidget.setItem(2*j+1, i, QtWidgets.QTableWidgetItem('-'))
|
||||
self.param_tableWidget.setItem(2*j+1, 0, QtWidgets.QTableWidgetItem('-'))
|
||||
else:
|
||||
self.param_tableWidget.setItem(2*j+1, i, QtWidgets.QTableWidgetItem())
|
||||
self.param_tableWidget.setItem(2*j+1, 0, QtWidgets.QTableWidgetItem())
|
||||
item = QtWidgets.QTableWidgetItem(item_text)
|
||||
self.param_tableWidget.setItem(j, i, item)
|
||||
self.param_tableWidget.setItem(j, 0, item)
|
||||
|
||||
self.param_tableWidget.resizeColumnsToContents()
|
||||
self.param_tableWidget.selectColumn(0)
|
||||
self.show_results(None, idx=0)
|
||||
self.param_tableWidget.resizeColumnToContents(0)
|
||||
self.show_results(idx)
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_reject_fit_checkBox_stateChanged')
|
||||
@QtCore.pyqtSlot(int, name='on_del_prev_checkBox_stateChanged')
|
||||
def change_opts(self, _):
|
||||
idx = self.param_tableWidget.currentIndex().column()
|
||||
idx = self.sets_comboBox.currentIndex()
|
||||
|
||||
self._opts[idx] = (self.reject_fit_checkBox.checkState() == QtCore.Qt.Checked,
|
||||
self.del_prev_checkBox.checkState() == QtCore.Qt.Checked)
|
||||
self._opts[idx] = (self.reject_fit_checkBox.checkState() == QtCore.Qt.CheckState.Checked,
|
||||
self.del_prev_checkBox.checkState() == QtCore.Qt.CheckState.Checked)
|
||||
|
||||
def show_results(self, item, idx=None):
|
||||
if item is not None:
|
||||
idx = self.param_tableWidget.indexFromItem(item).column()
|
||||
|
||||
set_id = self.param_tableWidget.horizontalHeaderItem(idx).data(QtCore.Qt.UserRole)
|
||||
def show_results(self, idx):
|
||||
set_id = self.sets_comboBox.itemData(idx, QtCore.Qt.ItemDataRole.UserRole)
|
||||
self.set_plot(set_id)
|
||||
self.set_correlation(set_id)
|
||||
self.set_statistics(set_id)
|
||||
|
||||
self.reject_fit_checkBox.blockSignals(True)
|
||||
self.reject_fit_checkBox.setChecked(self._opts[idx][0])
|
||||
self.reject_fit_checkBox.blockSignals(False)
|
||||
@ -156,27 +171,97 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.del_prev_checkBox.setChecked(self._opts[idx][1])
|
||||
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):
|
||||
if self.last_idx is not None:
|
||||
self.graph_opts[self.last_idx] = (
|
||||
self.fit_plot.viewRange(),
|
||||
self.logx_box.isChecked(),
|
||||
self.logy_box.isChecked(),
|
||||
)
|
||||
|
||||
self.last_idx = idx
|
||||
res = self._results[idx]
|
||||
iscomplex = res.iscomplex
|
||||
|
||||
sub_funcs = res.sub(res.x)
|
||||
for item in self.fit_plot.items[::-1]:
|
||||
if item not in [self.data_graph, self.data_graph_imag, self.fit_graph, self.fit_graph_imag]:
|
||||
self.fit_plot.removeItem(item)
|
||||
|
||||
if iscomplex:
|
||||
self.data_graph.setData(x=res.x_data, y=res.y_data.real)
|
||||
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_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 f, c in zip(sub_funcs, self.func_colors[idx]):
|
||||
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)
|
||||
item = PlotItem(x=f.x, y=f.y.imag, pen=mkPen({'color': col, 'style': 2}))
|
||||
self.fit_plot.addItem(item)
|
||||
|
||||
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_imag.setData(x=[], y=[])
|
||||
self.fit_graph.setData(x=res.x, y=res.y)
|
||||
self.fit_graph_imag.setData(x=[], y=[])
|
||||
|
||||
self.fitplot.setLogMode(x=res.islog)
|
||||
self.residplot.setLogMode(x=res.islog)
|
||||
for f, c in zip(sub_funcs, self.func_colors[idx]):
|
||||
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._plot_residuals(idx)
|
||||
|
||||
self.logx_box.blockSignals(True)
|
||||
self.logx_box.setChecked(res.islog)
|
||||
self.logx_box.blockSignals(False)
|
||||
|
||||
self.fit_plot.setLogMode(x=res.islog)
|
||||
self.resid_plot.setLogMode(x=res.islog)
|
||||
|
||||
if idx in self.graph_opts:
|
||||
view_range, logx, logy = self.graph_opts[idx]
|
||||
self.fit_plot.setRange(xRange=view_range[0], yRange=view_range[1], padding=0)
|
||||
self.fit_plot.setLogMode(x=logx, y=logy)
|
||||
self.logx_box.blockSignals(True)
|
||||
self.logx_box.setChecked(logx)
|
||||
self.logx_box.blockSignals(False)
|
||||
self.logy_box.blockSignals(True)
|
||||
self.logy_box.setChecked(logy)
|
||||
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):
|
||||
while self.corr_tableWidget.rowCount():
|
||||
@ -207,35 +292,35 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
res = self._results[idx]
|
||||
|
||||
self.stats_tableWidget.setColumnCount(1 + len(self._prevs[idx]))
|
||||
self.stats_tableWidget.setColumnCount(1 + len(self._previous_fits[idx]))
|
||||
self.stats_tableWidget.setRowCount(len(res.statistics)+3)
|
||||
|
||||
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.setItem(0, 0, it)
|
||||
|
||||
for col, (name, _, dof) in enumerate(self._prevs[idx], start=1):
|
||||
for col, (name, _, dof) in enumerate(self._previous_fits[idx], start=1):
|
||||
self.stats_tableWidget.setHorizontalHeaderItem(0, QtWidgets.QTableWidgetItem(name))
|
||||
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)
|
||||
|
||||
for row, (k, v) in enumerate(res.statistics.items(), start=1):
|
||||
self.stats_tableWidget.setVerticalHeaderItem(row, QtWidgets.QTableWidgetItem(k))
|
||||
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)
|
||||
|
||||
best_idx = -1
|
||||
best_val = v
|
||||
for col, (_, stats, _) in enumerate(self._prevs[idx], start=1):
|
||||
for col, (_, stats, _) in enumerate(self._previous_fits[idx], start=1):
|
||||
if k in ['adj. R^2', 'R^2']:
|
||||
best_idx = col if best_val < stats[k] else max(0, best_idx)
|
||||
else:
|
||||
best_idx = col if best_val > stats[k] else max(0, best_idx)
|
||||
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)
|
||||
|
||||
if best_idx > -1:
|
||||
@ -249,14 +334,14 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.stats_tableWidget.setVerticalHeaderItem(row+1, QtWidgets.QTableWidgetItem('Pr(>F)'))
|
||||
self.stats_tableWidget.setItem(row+1, 0, QtWidgets.QTableWidgetItem('-'))
|
||||
|
||||
for col, (_, stats, dof) in enumerate(self._prevs[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)
|
||||
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)
|
||||
|
||||
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:
|
||||
it.setBackground(QtGui.QColor('green'))
|
||||
it.setForeground(QtGui.QColor('white'))
|
||||
@ -272,32 +357,37 @@ class QFitResult(QtWidgets.QDialog, Ui_Dialog):
|
||||
elif button_type == self.buttonBox.Ok:
|
||||
graph = '-1'
|
||||
if self.parameter_checkbox.isChecked():
|
||||
if self.graph_checkBox.checkState() == QtCore.Qt.Checked:
|
||||
if self.graph_checkBox.checkState() == QtCore.Qt.CheckState.Checked:
|
||||
graph = ''
|
||||
else:
|
||||
graph = self.graph_comboBox.currentData()
|
||||
|
||||
plot_fits = self.curve_checkbox.isChecked()
|
||||
|
||||
parts = self.partial_checkBox.checkState() == QtCore.Qt.CheckState.Checked
|
||||
|
||||
parts = self.partial_checkBox.checkState() == QtCore.Qt.Checked
|
||||
|
||||
extrapolate = [None, None, None]
|
||||
extrapolate = [None, None, None, None]
|
||||
error = []
|
||||
if self.extrapolate_box.isChecked():
|
||||
try:
|
||||
extrapolate[0] = float(self.minx_line.text())
|
||||
except TypeError:
|
||||
pass
|
||||
except (TypeError, ValueError):
|
||||
error.append('Start value is missing')
|
||||
try:
|
||||
extrapolate[1] = float(self.maxx_line.text())
|
||||
except TypeError:
|
||||
pass
|
||||
except (TypeError, ValueError):
|
||||
error.append('End value is missing')
|
||||
try:
|
||||
extrapolate[2] = int(self.numx_line.text())
|
||||
except TypeError:
|
||||
pass
|
||||
except (TypeError, ValueError):
|
||||
error.append('Number of points is missing')
|
||||
|
||||
extrapolate[3] = self.newx_log_checkbox.isChecked()
|
||||
|
||||
if error:
|
||||
msg = QtWidgets.QMessageBox.warning(self, 'Error', 'Extrapolation failed because:\n' + '\n'.join(error))
|
||||
return
|
||||
else:
|
||||
self.closed.emit(self._results, self._opts, graph, plot_fits, parts, extrapolate)
|
||||
self.accept()
|
||||
|
||||
@ -331,10 +421,13 @@ class FitExtension(QtWidgets.QDialog):
|
||||
self.num_pts.setValidator(QtGui.QIntValidator())
|
||||
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.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
gridLayout.addWidget(self.buttonBox, 3, 0, 1, 2)
|
||||
self.buttonBox.setOrientation(QtCore.Qt.Orientation.Horizontal)
|
||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok)
|
||||
gridLayout.addWidget(self.buttonBox, 4, 0, 1, 2)
|
||||
|
||||
self.setLayout(gridLayout)
|
||||
|
||||
@ -342,12 +435,13 @@ class FitExtension(QtWidgets.QDialog):
|
||||
self.buttonBox.rejected.connect(self.reject)
|
||||
|
||||
@property
|
||||
def values(self):
|
||||
def values(self) -> tuple[float, float, int, bool] | None:
|
||||
try:
|
||||
xmin = float(self.min_line.text())
|
||||
xmax = float(self.max_line.text())
|
||||
nums = int(self.num_pts.text())
|
||||
logx = self.logx_checkbox.isChecked()
|
||||
except TypeError:
|
||||
return None
|
||||
|
||||
return xmin, xmax, nums
|
||||
return xmin, xmax, nums, logx
|
||||
|
@ -138,9 +138,7 @@ class DrawingsWidget(QtWidgets.QWidget, Ui_Form):
|
||||
graph_id = self.graph_comboBox.currentData()
|
||||
current_lines = self.lines[graph_id]
|
||||
|
||||
print(remove_rows)
|
||||
for i in reversed(remove_rows):
|
||||
print(i)
|
||||
self.tableWidget.removeRow(i)
|
||||
self.line_deleted.emit(current_lines[i], graph_id)
|
||||
|
||||
|
@ -4,19 +4,21 @@ import itertools
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from math import isnan
|
||||
from math import isfinite
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from numpy import errstate, floor, log10
|
||||
from pyqtgraph import GraphicsObject, getConfigOption, mkColor
|
||||
|
||||
from nmreval.lib.logger import logger
|
||||
from nmreval.utils.text import convert
|
||||
from ..io.filedialog import FileDialog
|
||||
|
||||
from ..lib.pg_objects import LegendItemBlock, RegionItem
|
||||
from ..Qt import QtCore, QtWidgets, QtGui
|
||||
from .._py.graph import Ui_GraphWindow
|
||||
from ..lib import make_action_icons
|
||||
from ..lib.iconloading import make_action_icons
|
||||
from ..lib.configurations import GraceMsgBox
|
||||
|
||||
|
||||
@ -24,7 +26,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
mousePositionChanged = QtCore.pyqtSignal(float, float)
|
||||
mouseDoubleClicked = QtCore.pyqtSignal()
|
||||
positionClicked = QtCore.pyqtSignal(tuple, bool)
|
||||
aboutToClose = QtCore.pyqtSignal(str)
|
||||
aboutToClose = QtCore.pyqtSignal(list)
|
||||
newData = QtCore.pyqtSignal(list, str)
|
||||
|
||||
counter = itertools.count()
|
||||
|
||||
@ -43,7 +46,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
self.id = str(uuid.uuid4())
|
||||
|
||||
self.sets = []
|
||||
self.active = []
|
||||
self._active = []
|
||||
|
||||
self.real_plots = {}
|
||||
self.imag_plots = {}
|
||||
@ -53,12 +56,24 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
self._external_items = []
|
||||
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.log = [False, False]
|
||||
|
||||
self.scene = self.plotItem.scene()
|
||||
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.limit_button.toggled.connect(lambda x: self.limit_widget.setVisible(x))
|
||||
self.gridbutton.toggled.connect(lambda x: self.graphic.showGrid(x=x, y=x))
|
||||
@ -71,6 +86,11 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
self.scene.contextMenu[0].disconnect()
|
||||
self.scene.contextMenu[0].triggered.connect(self.export_dialog)
|
||||
|
||||
self.bwbutton.toggled.connect(self.change_background)
|
||||
|
||||
self.setAcceptDrops(True)
|
||||
self.graphic.installEventFilter(self)
|
||||
|
||||
def _init_gui(self):
|
||||
self.setWindowTitle('Graph ' + str(next(QGraphWindow.counter)))
|
||||
|
||||
@ -103,6 +123,34 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
for lineedit in [self.xmin_lineedit, self.xmax_lineedit, self.ymin_lineedit, self.ymax_lineedit]:
|
||||
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):
|
||||
return item in self.sets
|
||||
|
||||
@ -110,11 +158,11 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return iter(self.active)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.active)
|
||||
return len(self._active)
|
||||
|
||||
def curves(self) -> tuple:
|
||||
for set_id in self.sets:
|
||||
if set_id in self.active:
|
||||
if set_id in self._active:
|
||||
if self.real_button.isChecked():
|
||||
if self.error_plots[set_id] is not None:
|
||||
yield self.real_plots[set_id], self.error_plots[set_id]
|
||||
@ -137,19 +185,44 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
r = self.plotItem.getViewBox().viewRange()
|
||||
for i in [0, 1]:
|
||||
if self.log[i]:
|
||||
r[i] = tuple([10**x for x in r[i]])
|
||||
tmp = [np.nan, np.nan]
|
||||
for j, x in enumerate(r[i]):
|
||||
try:
|
||||
tmp[j] = 10**min(x, 199)
|
||||
except OverflowError:
|
||||
pass
|
||||
r[i] = tuple(tmp)
|
||||
else:
|
||||
r[i] = tuple(r[i])
|
||||
|
||||
return tuple(r)
|
||||
|
||||
@property
|
||||
def active(self) -> list:
|
||||
return [set_id for set_id in self.sets if set_id in self._active]
|
||||
|
||||
@active.setter
|
||||
def active(self, value: list):
|
||||
self._active = value
|
||||
|
||||
def block(self, state: bool):
|
||||
self._block = state
|
||||
|
||||
if not self._block:
|
||||
# self.graphic.enableAutoRange()
|
||||
self._update_zorder()
|
||||
self.show_legend()
|
||||
else:
|
||||
self.graphic.disableAutoRange()
|
||||
|
||||
def add(self, name: str | list, plots: list):
|
||||
if isinstance(name, str):
|
||||
name = [name]
|
||||
plots = [plots]
|
||||
|
||||
for (real_plot, imag_plot, err_plot), n in zip(plots, name):
|
||||
toplevel = len(self.sets)
|
||||
|
||||
self.listWidget.blockSignals(True)
|
||||
for (real_plot, imag_plot, err_plot), n in zip(plots, name):
|
||||
self.sets.append(n)
|
||||
|
||||
if real_plot:
|
||||
@ -164,12 +237,25 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
self.error_plots[n] = err_plot
|
||||
|
||||
list_item = QtWidgets.QListWidgetItem(real_plot.opts.get('name', ''))
|
||||
list_item.setData(QtCore.Qt.UserRole, n)
|
||||
list_item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable)
|
||||
list_item.setCheckState(QtCore.Qt.Checked)
|
||||
list_item.setData(QtCore.Qt.ItemDataRole.UserRole, n)
|
||||
list_item.setFlags(
|
||||
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||
)
|
||||
list_item.setCheckState(QtCore.Qt.CheckState.Checked)
|
||||
self.listWidget.addItem(list_item)
|
||||
|
||||
toplevel += 1
|
||||
self.listWidget.blockSignals(False)
|
||||
|
||||
if len(name) < 200:
|
||||
self.show_item(name)
|
||||
else:
|
||||
QtWidgets.QMessageBox.warning(self, 'Display disabled',
|
||||
'If more than 200 sets are added at once, they are not displayed to avoid major performance issues.\n'
|
||||
'The checkmark in the data tree is invalid.\n'
|
||||
'Please display them manually in smaller batches, thank you!')
|
||||
|
||||
def remove(self, name: str | list):
|
||||
if isinstance(name, str):
|
||||
@ -181,19 +267,20 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
for plot in [self.real_plots, self.imag_plots, self.error_plots]:
|
||||
self.graphic.removeItem(plot[n])
|
||||
|
||||
if n in self.active:
|
||||
self.active.remove(n)
|
||||
if n in self._active:
|
||||
self._active.remove(n)
|
||||
|
||||
# remove from label list
|
||||
self.listWidget.blockSignals(True)
|
||||
|
||||
for i in range(self.listWidget.count()-1, 0, -1):
|
||||
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.blockSignals(False)
|
||||
|
||||
if not self._block:
|
||||
self._update_zorder()
|
||||
self.show_legend()
|
||||
|
||||
@ -225,8 +312,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return
|
||||
|
||||
for a in idlist:
|
||||
if a not in self.active:
|
||||
self.active.append(a)
|
||||
if a not in self._active:
|
||||
self._active.append(a)
|
||||
|
||||
for (bttn, plot_dic) in [
|
||||
(self.real_button, self.real_plots),
|
||||
@ -245,14 +332,16 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return
|
||||
|
||||
for r in idlist:
|
||||
if r in self.active:
|
||||
self.active.remove(r)
|
||||
if r in self._active:
|
||||
self._active.remove(r)
|
||||
|
||||
for plt in [self.real_plots, self.imag_plots, self.error_plots]:
|
||||
item = plt[r]
|
||||
if item in self.graphic.items():
|
||||
self.graphic.removeItem(item)
|
||||
|
||||
self.show_legend()
|
||||
|
||||
@QtCore.pyqtSlot(bool, name='on_imag_button_toggled')
|
||||
@QtCore.pyqtSlot(bool, name='on_real_button_toggled')
|
||||
def set_imag_visible(self, visible: bool):
|
||||
@ -268,7 +357,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
else:
|
||||
func = self.graphic.removeItem
|
||||
|
||||
for a in self.active:
|
||||
for a in self._active:
|
||||
item = plots[a]
|
||||
if item is not None:
|
||||
func(item)
|
||||
@ -285,12 +374,12 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
return
|
||||
|
||||
if visible:
|
||||
for a in self.active:
|
||||
for a in self._active:
|
||||
item = self.error_plots[a]
|
||||
if (item is not None) and (item not in self.graphic.items()):
|
||||
self.graphic.addItem(item)
|
||||
else:
|
||||
for a in self.active:
|
||||
for a in self._active:
|
||||
item = self.error_plots[a]
|
||||
if (item is not None) and (item in self.graphic.items()):
|
||||
self.graphic.removeItem(item)
|
||||
@ -354,7 +443,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
|
||||
|
||||
if res == QtWidgets.QMessageBox.Yes:
|
||||
self.aboutToClose.emit(self.id)
|
||||
self.aboutToClose.emit([self.id])
|
||||
evt.accept()
|
||||
else:
|
||||
evt.ignore()
|
||||
@ -380,28 +469,44 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
_y = pos.y()
|
||||
self.mousePositionChanged.emit(_x, _y)
|
||||
|
||||
@QtCore.pyqtSlot(name='on_title_lineedit_returnPressed')
|
||||
@QtCore.pyqtSlot(name='on_xaxis_linedit_returnPressed')
|
||||
@QtCore.pyqtSlot(name='on_yaxis_linedit_returnPressed')
|
||||
def labels_changed(self):
|
||||
label = {self.title_lineedit: 'title', self.xaxis_linedit: 'x', self.yaxis_linedit: 'y'}[self.sender()]
|
||||
self.set_label(**{label: self.sender().text()})
|
||||
@QtCore.pyqtSlot(str, name='on_title_lineedit_textChanged')
|
||||
@QtCore.pyqtSlot(str, name='on_xaxis_linedit_textChanged')
|
||||
@QtCore.pyqtSlot(str, name='on_yaxis_linedit_textChanged')
|
||||
def labels_changed(self, text: str):
|
||||
label = {
|
||||
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:
|
||||
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:
|
||||
self.plotItem.setLabel('bottom', convert(x, old='tex', new='html'),
|
||||
**{'font-size': '10pt', 'color': self._fgcolor.name()})
|
||||
self.plotItem.setLabel(
|
||||
'bottom',
|
||||
convert(x, old='tex', new='html'),
|
||||
**{'font-size': '10pt', 'color': self._fgcolor.name()},
|
||||
)
|
||||
|
||||
if y is not None:
|
||||
self.plotItem.setLabel('left', convert(y, old='tex', new='html'),
|
||||
**{'font-size': '10pt', 'color': self._fgcolor.name()})
|
||||
self.plotItem.setLabel(
|
||||
'left',
|
||||
convert(y, old='tex', new='html'),
|
||||
**{'font-size': '10pt', 'color': self._fgcolor.name()},
|
||||
)
|
||||
|
||||
def set_logmode(self, xmode: bool = None, ymode: bool = None):
|
||||
r = self.ranges
|
||||
|
||||
self.plotItem.setXRange(*r[0])
|
||||
self.plotItem.setYRange(*r[1])
|
||||
|
||||
if xmode is None:
|
||||
xmode = self.plotItem.ctrl.logXCheck.isChecked()
|
||||
else:
|
||||
@ -418,8 +523,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
item.logmode[0] = self.log[:]
|
||||
|
||||
self.plotItem.updateLogMode()
|
||||
|
||||
self.plotItem.enableAutoRange()
|
||||
self.set_range(x=r[0], y=r[1])
|
||||
|
||||
def enable_picking(self, enabled: bool):
|
||||
if enabled:
|
||||
@ -435,6 +539,10 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
|
||||
if self.graphic.plotItem.sceneBoundingRect().contains(evt.scenePos()) and evt.button() == 1:
|
||||
pos = vb.mapSceneToView(evt.scenePos())
|
||||
|
||||
if not _inside_range(pos.x(), pos.y(), vb.viewRange()):
|
||||
return
|
||||
|
||||
_x, _y = pos.x(), pos.y()
|
||||
|
||||
if self.log[0]:
|
||||
@ -460,9 +568,9 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
with errstate(all='ignore'):
|
||||
xy = [log10(val) for val in xy]
|
||||
|
||||
if isnan(xy[1]):
|
||||
if not isfinite(xy[1]):
|
||||
xy = [-1, 1]
|
||||
elif isnan(xy[0]):
|
||||
elif not isfinite(xy[0]):
|
||||
xy[0] = xy[1]-4
|
||||
|
||||
func(xy[0], xy[1], padding=0)
|
||||
@ -494,11 +602,14 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
self.checkBox.setVisible(visible)
|
||||
|
||||
def update_legend(self, sid, name):
|
||||
if self._block:
|
||||
return
|
||||
|
||||
self.listWidget.blockSignals(True)
|
||||
|
||||
for i in range(self.listWidget.count()):
|
||||
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'))
|
||||
|
||||
self.listWidget.blockSignals(False)
|
||||
@ -520,16 +631,14 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
elif other_item in self.graphic.items():
|
||||
self.legend.addItem(other_item, convert(other_item.opts.get('name', ''), old='tex', new='html'))
|
||||
|
||||
def export_dialog(self, path=None):
|
||||
def export_dialog(self, _=None):
|
||||
filters = 'All files (*.*);;AGR (*.agr);;SVG (*.svg);;PDF (*.pdf)'
|
||||
for imgformat in QtGui.QImageWriter.supportedImageFormats():
|
||||
str_format = imgformat.data().decode('utf-8')
|
||||
filters += ';;' + str_format.upper() + ' (*.' + str_format + ')'
|
||||
|
||||
if path is None:
|
||||
path = ''
|
||||
outfile = None
|
||||
f = FileDialog(caption='Export graphic', directory=str(path), filter=filters, mode='save')
|
||||
f = FileDialog(caption='Export graphic', filter=filters, mode='save')
|
||||
f.setOption(FileDialog.DontConfirmOverwrite)
|
||||
mode = f.exec()
|
||||
if mode == QtWidgets.QDialog.Accepted:
|
||||
@ -565,11 +674,14 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
|
||||
else:
|
||||
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'Do you REALLY want to replace it?',
|
||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
|
||||
QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
||||
QtWidgets.QMessageBox.No
|
||||
) == QtWidgets.QMessageBox.No:
|
||||
return
|
||||
|
||||
bg_color = self._bgcolor
|
||||
@ -608,21 +720,25 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
try:
|
||||
item_dic = plot_item.get_data_opts()
|
||||
except Exception as e:
|
||||
print(f'{item} could not exported because {e.args}')
|
||||
logger.exception(f'{item} could not exported because {e.args}')
|
||||
continue
|
||||
|
||||
if item_dic:
|
||||
if len(item) == 2:
|
||||
# plot can show errorbars
|
||||
if len(item_dic['x']):
|
||||
item_dic['yerr'] = item[1].opts['topData']
|
||||
|
||||
if item_dic:
|
||||
else:
|
||||
item_dic['yerr'] = []
|
||||
dic['items'].append(item_dic)
|
||||
|
||||
for item in self._external_items:
|
||||
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:
|
||||
print(f'{item} could not be exported because {e.args}')
|
||||
logger.exception(f'{item} could not be exported because {e.args}')
|
||||
continue
|
||||
|
||||
in_legend.append(False)
|
||||
@ -645,7 +761,8 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
'legend': self.legend.isVisible(),
|
||||
'plots': (self.real_button.isChecked(), self.imag_button.isChecked(), self.error_button.isChecked()),
|
||||
'children': self.sets,
|
||||
'active': self.active,
|
||||
'active': self._active,
|
||||
'invert': (self.plotItem.vb.state['xInverted'], self.plotItem.vb.state['yInverted']),
|
||||
}
|
||||
|
||||
in_legend = []
|
||||
@ -692,7 +809,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
|
||||
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.imag_button.setChecked(state['plots'][1])
|
||||
@ -708,7 +825,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
if background is not None:
|
||||
self._bgcolor = mkColor(background)
|
||||
self.graphic.setBackground(self._bgcolor)
|
||||
self.legend.setBrush(self._bgcolor)
|
||||
# self.legend.setBrush(self._bgcolor)
|
||||
|
||||
if foreground is not None:
|
||||
self._fgcolor = mkColor(foreground)
|
||||
@ -725,7 +842,7 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
self.show_legend()
|
||||
|
||||
title = self.plotItem.titleLabel.text
|
||||
if title is not None:
|
||||
if title is not None and title != '':
|
||||
self.plotItem.setTitle(title, **{'size': '10pt', 'color': self._fgcolor})
|
||||
|
||||
x = self.plotItem.getAxis('bottom').labelText
|
||||
@ -736,8 +853,12 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
||||
if y is not None:
|
||||
self.plotItem.setLabel('left', y, **{'font-size': '10pt', 'color': self._fgcolor.name()})
|
||||
|
||||
@QtCore.pyqtSlot(bool, name='on_bwbutton_toggled')
|
||||
def change_background(self, _):
|
||||
temp = self._fgcolor, self._bgcolor
|
||||
self.set_color(foreground=self._prev_colors[0], background=self._prev_colors[1])
|
||||
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])
|
@ -1,4 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
from nmreval.io.asciireader import AsciiReader
|
||||
from nmreval.utils import NUMBER_RE, numbers_from_string
|
||||
|
||||
from ..Qt import QtGui, QtCore, QtWidgets
|
||||
from .._py.asciidialog import Ui_ascii_reader
|
||||
@ -13,6 +18,9 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
||||
self.setupUi(self)
|
||||
|
||||
self.reader = None
|
||||
self._matches = []
|
||||
self.regex_input.setText(NUMBER_RE.pattern)
|
||||
self.custom_input.setValidator(QtGui.QDoubleValidator())
|
||||
|
||||
self.comment_textfield = QtWidgets.QPlainTextEdit(self.header_widget)
|
||||
self.comment_textfield.setReadOnly(True)
|
||||
@ -30,7 +38,7 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
||||
self.changestaggeredrange(0)
|
||||
|
||||
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.skip = False
|
||||
@ -41,6 +49,8 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
||||
def __call__(self, fname, *args, **kwargs):
|
||||
self.reader = AsciiReader(fname)
|
||||
|
||||
self.check_filename(self.regex_input.text())
|
||||
|
||||
if self.skip:
|
||||
self.accept()
|
||||
return
|
||||
@ -52,9 +62,10 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
||||
self.log_checkBox.setChecked(False)
|
||||
|
||||
self.set_gui()
|
||||
self.set_column_names(1)
|
||||
|
||||
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)
|
||||
|
||||
return self
|
||||
@ -63,12 +74,14 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
||||
for text in self.reader.header:
|
||||
self.comment_textfield.appendPlainText(text)
|
||||
|
||||
tmp = self.line_spinBox.value()
|
||||
if self.reader.header:
|
||||
self.line_spinBox.setMaximum(len(self.reader.header))
|
||||
else:
|
||||
self.line_spinBox.setValue(0)
|
||||
self.line_spinBox.setEnabled(False)
|
||||
self.show_preview(10)
|
||||
self.line_spinBox.setValue(tmp)
|
||||
|
||||
if self.reader.delays is not None:
|
||||
set_string = ''.join(str(d) + '\n' for d in self.reader.delays)
|
||||
@ -98,15 +111,19 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_preview_spinBox_valueChanged')
|
||||
def show_preview(self, line_no: int):
|
||||
preview, width = self.reader.make_preview(line_no)
|
||||
preview, width, comments = self.reader.make_preview(line_no)
|
||||
self.ascii_table.setRowCount(min(line_no, len(preview)))
|
||||
self.ascii_table.setColumnCount(width)
|
||||
self.ascii_table.setColumnCount(width + 1)
|
||||
|
||||
for i, line in enumerate(preview):
|
||||
comment_line = comments[i]
|
||||
for j, field in enumerate(line):
|
||||
it = QtWidgets.QTableWidgetItem(field)
|
||||
self.ascii_table.setItem(i, j, it)
|
||||
|
||||
it = QtWidgets.QTableWidgetItem(comment_line)
|
||||
self.ascii_table.setItem(i, len(line), it)
|
||||
|
||||
self.ascii_table.resizeColumnsToContents()
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_column_checkBox_stateChanged')
|
||||
@ -115,7 +132,10 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
||||
self.ascii_table.setHorizontalHeaderLabels(map(str, range(1, self.ascii_table.columnCount() + 1)))
|
||||
if self.column_checkBox.isChecked() and self.line_spinBox.isEnabled():
|
||||
header_line = self.reader.header[self.line_spinBox.value()-1]
|
||||
self.ascii_table.setHorizontalHeaderLabels(header_line.split())
|
||||
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')
|
||||
def changestaggeredrange(self, state: int):
|
||||
@ -161,26 +181,49 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
||||
@QtCore.pyqtSlot()
|
||||
def accept(self):
|
||||
if self.apply():
|
||||
self.close()
|
||||
super().accept()
|
||||
|
||||
def apply(self):
|
||||
# default row for x is the first row, it will be superseded if an integer number is given.
|
||||
x = self.x_lineedit.text()
|
||||
is_valid = True
|
||||
if x:
|
||||
try:
|
||||
x = int(self.x_lineedit.text())-1
|
||||
print(x)
|
||||
x = int(x)-1
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
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:
|
||||
y = [int(t)-1 for t in self.y_lineedit.text().split(' ')]
|
||||
except ValueError:
|
||||
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:
|
||||
y_err = [int(t)-1 for t in self.deltay_lineEdit.text().split(' ')]
|
||||
except ValueError:
|
||||
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
|
||||
if self.column_checkBox.isChecked():
|
||||
col_header = []
|
||||
@ -191,25 +234,103 @@ class QAsciiReader(QtWidgets.QDialog, Ui_ascii_reader):
|
||||
col_header.append(i)
|
||||
|
||||
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:
|
||||
ret_dic = self.reader.export(x=x, y=y, yerr=y_err,
|
||||
mode=self.buttonGroup.checkedButton().text(),
|
||||
col_names=col_header)
|
||||
ret_dic = self.reader.export(
|
||||
x=x,
|
||||
y=y,
|
||||
yerr=y_err,
|
||||
mode=mode,
|
||||
col_names=col_header,
|
||||
num_value=self.get_numerical_value(),
|
||||
)
|
||||
self.data_read.emit(ret_dic)
|
||||
|
||||
except Exception as e:
|
||||
_ = 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
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_buttonGroup_buttonClicked')
|
||||
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')
|
||||
def skip_next_dial(self, _: int):
|
||||
print('skippy das buschkänguru', _)
|
||||
self.skip = self.skippy_checkbox.isChecked()
|
||||
|
||||
@QtCore.pyqtSlot(str, name='on_regex_input_textChanged')
|
||||
def check_filename(self, pattern: str = NUMBER_RE.pattern):
|
||||
if self.reader is None:
|
||||
return
|
||||
|
||||
success = True
|
||||
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.setMaximum(len(self._matches))
|
||||
self.re_match_index.blockSignals(False)
|
||||
else:
|
||||
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())
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_re_match_index_valueChanged')
|
||||
def show_match(self, idx: int = 0):
|
||||
fname = str(self.reader.fname.stem)
|
||||
|
||||
if self._matches:
|
||||
m = self._matches[idx-1]
|
||||
self.label_8.setText(f'{fname[:m.start()]}<b>{fname[m.start():m.end()]}</b>{fname[m.end():]}')
|
||||
else:
|
||||
self.label_8.setText(fname)
|
||||
|
||||
def get_numerical_value(self) -> float:
|
||||
val = 0
|
||||
if self.re_button.isChecked() and self._matches:
|
||||
m = self._matches[self.re_match_index.value()-1]
|
||||
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():
|
||||
val = float(self.custom_input.text())
|
||||
|
||||
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
|
||||
|
||||
|
@ -5,7 +5,7 @@ from pathlib import Path
|
||||
import numpy as np
|
||||
from pyqtgraph import PlotDataItem
|
||||
|
||||
from nmreval.data.points import Points
|
||||
from nmreval.data import DSC
|
||||
from nmreval.io.dsc import Cyclohexane, DSCCalibrator, DSCSample
|
||||
|
||||
from ..Qt import QtWidgets, QtCore
|
||||
@ -78,14 +78,22 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
for opts in self.sample.steps:
|
||||
item = QtWidgets.QListWidgetItem()
|
||||
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable)
|
||||
item.setCheckState(QtCore.Qt.Unchecked)
|
||||
item.setFlags(
|
||||
QtCore.Qt.ItemFlag.ItemIsEnabled |
|
||||
QtCore.Qt.ItemFlag.ItemIsSelectable |
|
||||
QtCore.Qt.ItemFlag.ItemIsUserCheckable
|
||||
)
|
||||
item.setCheckState(QtCore.Qt.CheckState.Unchecked)
|
||||
|
||||
if opts[0] == 'i':
|
||||
item.setFlags(QtCore.Qt.NoItemFlags)
|
||||
item.setText(f'{opts[1]:.2f} K for {opts[1] / 60:.0f} min')
|
||||
item.setFlags(QtCore.Qt.ItemFlag.NoItemFlags)
|
||||
item.setText(f'{opts[1]:.2f} K for {opts[2] / 60:.0f} min')
|
||||
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')
|
||||
|
||||
self.step_listWidget.addItem(item)
|
||||
@ -97,7 +105,12 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
if empty:
|
||||
self.empty = self.calibrator.set_measurement(empty, mode='empty')
|
||||
self.empty_label.setText(str(self.empty.fname.name))
|
||||
|
||||
# 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())))
|
||||
else:
|
||||
self.empty_label.setText(str(self.empty.fname))
|
||||
|
||||
self.update_plots()
|
||||
|
||||
@ -118,8 +131,8 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
self.references.append(ref)
|
||||
item = QtWidgets.QTableWidgetItem(str(ref.fname.name))
|
||||
item.setData(QtCore.Qt.UserRole, ref.fname)
|
||||
item.setFlags(QtCore.Qt.ItemIsEnabled)
|
||||
item.setData(QtCore.Qt.ItemDataRole.UserRole, ref.fname)
|
||||
item.setFlags(QtCore.Qt.ItemFlag.ItemIsEnabled)
|
||||
|
||||
rowcnt = self.reference_tableWidget.rowCount()
|
||||
self.reference_tableWidget.setRowCount(rowcnt+1)
|
||||
@ -132,7 +145,7 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
@QtCore.pyqtSlot(name='on_ref_remove_pushButton_clicked')
|
||||
def remove_reference(self):
|
||||
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.update_plots()
|
||||
@ -145,10 +158,10 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
for row in range(self.step_listWidget.count()):
|
||||
if idx == row:
|
||||
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)
|
||||
|
||||
if item.checkState() == QtCore.Qt.Checked:
|
||||
if item.checkState() == QtCore.Qt.CheckState.Checked:
|
||||
mode, rate, _, _ = self.sample.steps[idx]
|
||||
self.current_run = (rate, mode)
|
||||
self.sample_idx = idx
|
||||
@ -158,20 +171,28 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.sample_idx = None
|
||||
self.clear_plots()
|
||||
|
||||
def get_data(self, ):
|
||||
def get_data(self):
|
||||
if self.sample_idx is None:
|
||||
return
|
||||
|
||||
rate = self.current_run[0]
|
||||
slope_type = {self.none_radioButton: None,
|
||||
slope_type = {
|
||||
self.none_radioButton: None,
|
||||
self.isotherm_radioButton: 'iso',
|
||||
self.slope_radioButton: 'curve'}[self.buttonGroup.checkedButton()]
|
||||
self.slope_radioButton: 'curve',
|
||||
}[self.buttonGroup.checkedButton()]
|
||||
|
||||
limit = None
|
||||
if slope_type == 'curve':
|
||||
try:
|
||||
limit = float(self.limit1_lineedit.text())*60, float(self.limit2_lineedit.text())*60
|
||||
except ValueError:
|
||||
limit = None
|
||||
|
||||
try:
|
||||
raw_sample, drift_value, sample_data, empty_data, slope = self.calibrator.get_data(self.sample_idx,
|
||||
slope=slope_type)
|
||||
raw_sample, drift_value, sample_data, empty_data, slope = self.calibrator.get_data(self.sample_idx, slope=slope_type, limits=limit)
|
||||
except ValueError as e:
|
||||
_msg = QtWidgets.QMessageBox.warning(self, 'No rate found', e.args[0])
|
||||
_msg = QtWidgets.QMessageBox.warning(self, f'Data collection with error', e.args[0])
|
||||
return
|
||||
|
||||
self.calibrator.ref_list = []
|
||||
@ -194,8 +215,14 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
@QtCore.pyqtSlot(QtWidgets.QAbstractButton, name='on_buttonGroup_buttonClicked')
|
||||
@QtCore.pyqtSlot(int, name='on_cp_checkBox_stateChanged')
|
||||
@QtCore.pyqtSlot(str, name='on_limit1_lineedit_textChanged')
|
||||
@QtCore.pyqtSlot(str, name='on_limit2_lineedit_textChanged')
|
||||
def update_plots(self, _=None):
|
||||
sample_data, raw_sample, empty_data, drift_value, slope, calib_x, calib_y, regions = self.get_data()
|
||||
res = self.get_data()
|
||||
if res is None:
|
||||
return
|
||||
|
||||
sample_data, raw_sample, empty_data, drift_value, slope, calib_x, calib_y, regions = res
|
||||
|
||||
self.raw_sample.setData(x=raw_sample[0], y=raw_sample[1])
|
||||
self.drift_sample.setData(x=drift_value[0], y=drift_value[1])
|
||||
@ -203,6 +230,8 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
if empty_data is not None:
|
||||
self.empty_sample.setData(x=empty_data[0], y=empty_data[1])
|
||||
else:
|
||||
self.empty_sample.setData(x=[], y=[])
|
||||
|
||||
self.calib_graph.clear()
|
||||
|
||||
@ -235,11 +264,17 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
except TypeError:
|
||||
return
|
||||
|
||||
if self.cp_checkBox.isChecked() and self.references:
|
||||
y_label = 'cp'
|
||||
else:
|
||||
y_label = 'q'
|
||||
|
||||
rate, mode = self.current_run
|
||||
new_val = Points(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:
|
||||
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
|
||||
else:
|
||||
self.data_read.emit([new_val])
|
||||
|
||||
@ -250,7 +285,7 @@ class QDSCReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
def button_clicked(self, bttn: QtWidgets.QAbstractButton):
|
||||
bttn_value = self.buttonBox.standardButton(bttn)
|
||||
if bttn_value in (self.buttonBox.Ok, self.buttonBox.Apply, self.buttonBox.Save):
|
||||
self.export_data(filesave=bttn_value==self.buttonBox.Save, close_after=bttn_value==self.buttonBox.Ok)
|
||||
self.export_data(filesave=bttn_value == self.buttonBox.Save, close_after=bttn_value == self.buttonBox.Ok)
|
||||
else:
|
||||
super().close()
|
||||
|
||||
|
@ -28,14 +28,19 @@ class GraceExporter:
|
||||
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_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': ', '.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'):
|
||||
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 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'])
|
||||
g_idx = new_g.idx
|
||||
else:
|
||||
@ -55,12 +60,17 @@ class GraceExporter:
|
||||
break
|
||||
|
||||
if c_num == -1:
|
||||
c_num = max(colors.keys())
|
||||
colors[c_num + 1] = (f'color{c_num + 1}', sc)
|
||||
new_colors.append((c_num + 1, f'color{c_num + 1}', sc))
|
||||
c_num = max(colors.keys())+1
|
||||
colors[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,
|
||||
'fill color': c_num, 'fill pattern': 1})
|
||||
new_s.set_symbol(**{
|
||||
'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])
|
||||
|
||||
lc = item['linecolor']
|
||||
@ -74,12 +84,17 @@ class GraceExporter:
|
||||
colors[c_num + 1] = ()
|
||||
new_colors.append((c_num, f'color{c_num + 1}', sc))
|
||||
|
||||
new_s.set_line(**{'color': c_num, 'linewidth': item['linewidth'],
|
||||
'linestyle': item['linestyle'].to_agr()})
|
||||
new_s.set_line(**{
|
||||
'color': c_num,
|
||||
'linewidth': item['linewidth'],
|
||||
'linestyle': item['linestyle'].to_agr()
|
||||
})
|
||||
|
||||
if plot_label:
|
||||
new_s.set_property(comment=f'"{item["name"]}"',
|
||||
legend=f'"{convert(item["name"], old="tex", new="agr")}"')
|
||||
new_s.set_property(
|
||||
comment=f'"{item["name"]}"',
|
||||
legend=f'"{convert(item["name"], old="tex", new="agr")}"'
|
||||
)
|
||||
else:
|
||||
new_s.set_property(comment=f'"{item["name"]}"')
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
|
||||
from nmreval.io.fcbatchreader import FCReader
|
||||
@ -20,46 +22,67 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog):
|
||||
self.start_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)
|
||||
|
||||
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:
|
||||
# intercept key press in listwidget to allow deletion with Del
|
||||
if evt.type() == QtCore.QEvent.KeyPress:
|
||||
if evt.key() == QtCore.Qt.Key_Delete:
|
||||
if evt.type() == QtCore.QEvent.Type.KeyPress:
|
||||
if evt.key() == QtCore.Qt.Key.Key_Delete:
|
||||
self.listWidget.takeItem(self.listWidget.currentRow())
|
||||
return True
|
||||
|
||||
return super().eventFilter(src, evt)
|
||||
|
||||
def add_graphs(self, graphs: list[tuple[str, str]]):
|
||||
for gid, graph_name in graphs:
|
||||
self.graph_comboBox.addItem(graph_name, gid)
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_region_checkBox_stateChanged')
|
||||
def use_region(self, state: int):
|
||||
self.start_lineedit.setEnabled(state == QtCore.Qt.Checked)
|
||||
self.stop_lineedit.setEnabled(state == QtCore.Qt.Checked)
|
||||
self.start_lineedit.setEnabled(state == QtCore.Qt.CheckState.Checked)
|
||||
self.stop_lineedit.setEnabled(state == QtCore.Qt.CheckState.Checked)
|
||||
|
||||
@QtCore.pyqtSlot(name='on_file_pushbutton_clicked')
|
||||
@QtCore.pyqtSlot(name='on_dir_pushbutton_clicked')
|
||||
def get_input(self):
|
||||
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),
|
||||
filter='HDF files (*.h5)')
|
||||
if infiles:
|
||||
self.listWidget.addItems(infiles)
|
||||
self.label.setText(str(pathlib.Path(infiles[-1]).parent))
|
||||
filter='HDF files (*.h5)',
|
||||
)
|
||||
|
||||
else:
|
||||
infiles = QtWidgets.QFileDialog.getExistingDirectory(caption='Select input directory',
|
||||
infiles = QtWidgets.QFileDialog.getExistingDirectory(
|
||||
caption='Select input directory',
|
||||
directory=str(self.path),
|
||||
options=QtWidgets.QFileDialog.ShowDirsOnly)
|
||||
options=QtWidgets.QFileDialog.ShowDirsOnly,
|
||||
)
|
||||
infiles = [infiles] if infiles else infiles
|
||||
|
||||
if infiles:
|
||||
self.listWidget.addItem(infiles)
|
||||
self.label.setText(str(pathlib.Path(infiles).parent))
|
||||
self.listWidget.addItems(infiles)
|
||||
self.path = pathlib.Path(infiles[-1]).parent
|
||||
self.label.setText(str(self.path))
|
||||
|
||||
@QtCore.pyqtSlot(name='on_savebutton_clicked')
|
||||
def save_path(self):
|
||||
outfile = QtWidgets.QFileDialog.getExistingDirectory(self, caption='Select directory',
|
||||
outfile = QtWidgets.QFileDialog.getExistingDirectory(
|
||||
self,
|
||||
caption='Select directory',
|
||||
directory=self.label.text(),
|
||||
options=QtWidgets.QFileDialog.ShowDirsOnly)
|
||||
options=QtWidgets.QFileDialog.ShowDirsOnly,
|
||||
)
|
||||
if outfile:
|
||||
self.label.setText(outfile)
|
||||
|
||||
@ -72,15 +95,15 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog):
|
||||
self.close()
|
||||
|
||||
def read(self, items):
|
||||
region = (None, None)
|
||||
region = None
|
||||
if self.region_box.isChecked():
|
||||
start = None
|
||||
if self.start_lineedit.text():
|
||||
start = float(self.start_lineedit.text())
|
||||
start = float(self.start_lineedit.text())*1e-6
|
||||
|
||||
stop = None
|
||||
if self.stop_lineedit.text():
|
||||
stop = float(self.stop_lineedit.text())
|
||||
stop = float(self.stop_lineedit.text())*1e-6
|
||||
region = (start, stop)
|
||||
|
||||
fc_eval = FCReader(items)
|
||||
@ -99,9 +122,10 @@ class QFCReader(QtWidgets.QDialog, Ui_FCEval_dialog):
|
||||
|
||||
ret_vals = []
|
||||
ret_vals.extend(fc_eval.get_parameter(path=self.label.text(), kind='temp', parameter=save_variables))
|
||||
print(ret_vals)
|
||||
|
||||
grp = ''
|
||||
if self.graph_checkbox.isChecked():
|
||||
grp = self.graph_comboBox.currentData(QtCore.Qt.UserRole)
|
||||
if not self.graph_checkbox.isChecked():
|
||||
grp = self.graph_comboBox.currentData(QtCore.Qt.ItemDataRole.UserRole)
|
||||
|
||||
self.data_read.emit(ret_vals, grp)
|
||||
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
from pathlib import Path
|
||||
import struct
|
||||
|
||||
from ..Qt import QtCore
|
||||
from ..Qt import QtCore, QtWidgets
|
||||
from .asciireader import QAsciiReader
|
||||
from .hdfreader import QHdfViewer
|
||||
from .bdsreader import QBDSReader
|
||||
@ -26,8 +26,12 @@ class QFileReader(QtCore.QObject):
|
||||
self.reader = {}
|
||||
|
||||
for ext, reader in [
|
||||
('txt', QAsciiReader), ('dsc', QDSCReader), ('agr', QGraceReader),
|
||||
('bds', QBDSReader), ('hdf', QHdfViewer), ('nmr', QNMRReader)
|
||||
('txt', QAsciiReader),
|
||||
('dsc', QDSCReader),
|
||||
('agr', QGraceReader),
|
||||
('bds', QBDSReader),
|
||||
('hdf', QHdfViewer),
|
||||
('nmr', QNMRReader),
|
||||
]:
|
||||
self.register(ext, reader)
|
||||
|
||||
@ -47,6 +51,7 @@ class QFileReader(QtCore.QObject):
|
||||
if not isinstance(fname, list):
|
||||
fname = [fname]
|
||||
|
||||
status = QtWidgets.QDialog.Accepted
|
||||
for f in fname:
|
||||
f = Path(f)
|
||||
dtype = self.guess_type(f)
|
||||
@ -57,7 +62,10 @@ class QFileReader(QtCore.QObject):
|
||||
|
||||
try:
|
||||
# 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:
|
||||
pass
|
||||
|
||||
|
@ -4,6 +4,7 @@ from nmreval.lib.lines import LineStyle
|
||||
from nmreval.lib.symbols import SymbolStyle
|
||||
from nmreval.data.points import Points
|
||||
from nmreval.io.graceeditor import GraceEditor
|
||||
from nmreval.utils.text import convert
|
||||
|
||||
from ..Qt import QtCore, QtWidgets, QtGui
|
||||
from .._py.gracereader import Ui_Dialog
|
||||
@ -55,8 +56,12 @@ class QGraceReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
if ds is None:
|
||||
continue
|
||||
|
||||
item_2 = QtWidgets.QTreeWidgetItem([f'Set {gset.idx} (Label: {gset.get_property("legend")}, '
|
||||
legend = gset.get_property('legend')
|
||||
legend_str = convert(legend, old='agr', new='str') if legend is not None else ''
|
||||
|
||||
item_2 = QtWidgets.QTreeWidgetItem([f'Set {gset.idx} (Label: {legend_str}, '
|
||||
f'shape: {ds.shape})'])
|
||||
|
||||
item_2.setCheckState(0, QtCore.Qt.Checked)
|
||||
item_2.setData(0, QtCore.Qt.UserRole, (graphs.idx, gset.idx))
|
||||
item.addChild(item_2)
|
||||
@ -89,8 +94,12 @@ class QGraceReader(QtWidgets.QDialog, Ui_Dialog):
|
||||
item = iterator.value()
|
||||
key = (item.data(0, QtCore.Qt.UserRole))
|
||||
s = self._reader.dataset(*key)
|
||||
label = self._reader.get_property(*key, 'legend').replace('"', '')
|
||||
# label = self._reader.graphs[key[0]].sets[key[1]]['legend'].replace('"', '')
|
||||
label = self._reader.get_property(*key, 'legend')
|
||||
if label is None:
|
||||
label = ''
|
||||
else:
|
||||
label = label.replace('"', '')
|
||||
label = convert(label, old='agr', new='str')
|
||||
sd = s.data
|
||||
sd = np.atleast_2d(sd)
|
||||
if s.type == 'xydy':
|
||||
|
@ -1,80 +1 @@
|
||||
import sys
|
||||
|
||||
if sys.version_info < (3, 7):
|
||||
HAS_IMPORTLIB_RESOURCE = False
|
||||
from pkg_resources import resource_filename
|
||||
else:
|
||||
HAS_IMPORTLIB_RESOURCE = True
|
||||
from importlib.resources import path
|
||||
|
||||
from ..Qt import QtGui, QtWidgets
|
||||
|
||||
|
||||
# def get_path_importlib(package, resource):
|
||||
# return path(package, resource)
|
||||
#
|
||||
#
|
||||
# def _get_path_pkg(package, resource):
|
||||
# return resource_filename(package, resource)
|
||||
#
|
||||
#
|
||||
# if HAS_IMPORTLIB_RESOURCE:
|
||||
# get_path = get_path_importlib
|
||||
# else:
|
||||
# get_path = _get_path_pkg
|
||||
|
||||
|
||||
def make_action_icons(widget):
|
||||
global HAS_IMPORTLIB_RESOURCE
|
||||
icon_type = QtWidgets.QApplication.instance().theme
|
||||
from json import loads
|
||||
|
||||
if HAS_IMPORTLIB_RESOURCE:
|
||||
with path('resources.icons', 'icons.json') as fp:
|
||||
with fp.open('r') as f:
|
||||
icon_list = loads(f.read())
|
||||
|
||||
for ac, img in icon_list[widget.objectName()].items():
|
||||
dirname = 'resources.icons.%s_light' % icon_type
|
||||
with path(dirname, img+'.png') as imgpath:
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(str(imgpath)), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
getattr(widget, ac).setIcon(icon)
|
||||
|
||||
else:
|
||||
with open(resource_filename('resources.icons', 'icons.json'), 'r') as f:
|
||||
icon_list = loads(f.read())
|
||||
|
||||
for ac, img in icon_list[widget.objectName()].items():
|
||||
dirname = 'resources.icons.%s_light' % icon_type
|
||||
imgpath = resource_filename(dirname, img+'.png')
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(str(imgpath)), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
getattr(widget, ac).setIcon(icon)
|
||||
|
||||
|
||||
def get_icon(icon_name):
|
||||
try:
|
||||
icon_type = QtWidgets.QApplication.instance().theme
|
||||
except AttributeError:
|
||||
icon_type = 'normal'
|
||||
|
||||
global HAS_IMPORTLIB_RESOURCE
|
||||
|
||||
if icon_name != 'logo':
|
||||
dirname = f'resources.icons.{icon_type}_light'
|
||||
else:
|
||||
dirname = 'resources.icons'
|
||||
|
||||
if HAS_IMPORTLIB_RESOURCE:
|
||||
with path(dirname, icon_name+'.png') as imgpath:
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(str(imgpath)), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
|
||||
return icon
|
||||
else:
|
||||
imgpath = resource_filename(dirname, icon_name+'.png')
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(imgpath), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
|
||||
return icon
|
||||
from .enums import Relations
|
||||
|
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()
|
||||
|
@ -30,7 +30,7 @@ class PropertyDelegate(QtWidgets.QStyledItemDelegate):
|
||||
|
||||
rect = options.rect
|
||||
rect.adjust(5, 0, -5, 0)
|
||||
mid = (rect.bottom()+rect.top()) / 2
|
||||
mid = int((rect.bottom()+rect.top()) / 2)
|
||||
painter.drawLine(rect.left(), mid, rect.right(), mid)
|
||||
painter.restore()
|
||||
|
||||
@ -42,7 +42,7 @@ class PropertyDelegate(QtWidgets.QStyledItemDelegate):
|
||||
painter.setPen(pen)
|
||||
|
||||
pm = make_symbol_pixmap(r)
|
||||
painter.drawPixmap(options.rect.topLeft()+QtCore.QPoint(3, (options.rect.height()-pm.height())/2), pm)
|
||||
painter.drawPixmap(options.rect.topLeft()+QtCore.QPoint(3, int((options.rect.height()-pm.height())/2)), pm)
|
||||
|
||||
style = QtWidgets.QApplication.style()
|
||||
text_rect = style.subElementRect(QtWidgets.QStyle.SE_ItemViewItemText, options, None)
|
||||
@ -171,7 +171,7 @@ class LineStyleEditor(QtWidgets.QComboBox):
|
||||
rect = painter.style().subControlRect(QtWidgets.QStyle.CC_ComboBox,
|
||||
opt, QtWidgets.QStyle.SC_ComboBoxEditField, None)
|
||||
rect.adjust(+10, 0, -10, 0)
|
||||
mid = (rect.bottom() + rect.top()) / 2
|
||||
mid = int((rect.bottom() + rect.top()) / 2)
|
||||
painter.drawLine(rect.left(), mid, rect.right(), mid)
|
||||
painter.end()
|
||||
else:
|
||||
@ -193,7 +193,7 @@ class LineStyleDelegate(QtWidgets.QStyledItemDelegate):
|
||||
|
||||
rect = option.rect
|
||||
rect.adjust(+10, 0, -10, 0)
|
||||
mid = (rect.bottom()+rect.top()) / 2
|
||||
mid = int((rect.bottom()+rect.top()) / 2)
|
||||
painter.drawLine(rect.left(), mid, rect.right(), mid)
|
||||
else:
|
||||
QtWidgets.QStyledItemDelegate.paint(self, painter, option, index)
|
||||
|
8
src/gui_qt/lib/enums.py
Normal file
8
src/gui_qt/lib/enums.py
Normal file
@ -0,0 +1,8 @@
|
||||
from enum import IntEnum, auto
|
||||
|
||||
|
||||
class Relations(IntEnum):
|
||||
isFitOf = auto()
|
||||
hasFit = auto()
|
||||
isFitPartOf = auto()
|
||||
hasFitPart = auto()
|
@ -1,3 +1,5 @@
|
||||
from typing import Any
|
||||
|
||||
from numpy import inf
|
||||
|
||||
from nmreval.utils.text import convert
|
||||
@ -50,19 +52,24 @@ class QDelayWidget(QtWidgets.QWidget):
|
||||
|
||||
class LineEdit(QtWidgets.QLineEdit):
|
||||
values_requested = QtCore.pyqtSignal()
|
||||
replace_single_values = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
def contextMenuEvent(self, evt):
|
||||
menu = self.createStandardContextMenu()
|
||||
request_action = menu.addAction('Use value of sets')
|
||||
request_action = menu.addAction('Use numeric value of sets')
|
||||
set_value_action = menu.addAction('Replace single set values')
|
||||
|
||||
action = menu.exec(evt.globalPos())
|
||||
|
||||
if action == request_action:
|
||||
self.values_requested.emit()
|
||||
|
||||
elif action == set_value_action:
|
||||
self.replace_single_values.emit()
|
||||
|
||||
|
||||
class LineEditPost(QtWidgets.QLineEdit):
|
||||
values_requested = QtCore.pyqtSignal()
|
||||
@ -404,3 +411,21 @@ class ElideComboBox(QtWidgets.QComboBox):
|
||||
|
||||
opt.currentText = painter.fontMetrics().elidedText(opt.currentText, QtCore.Qt.ElideRight, rect.width())
|
||||
painter.drawControl(QtWidgets.QStyle.CE_ComboBoxLabel, opt)
|
||||
|
||||
|
||||
class CheckCombobox(QtWidgets.QComboBox):
|
||||
|
||||
def addItem(self, text: str, userData: Any=None) -> None:
|
||||
super().addItem(text, userData=userData)
|
||||
|
||||
item = self.model().item(self.count()-1)
|
||||
item.setFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable)
|
||||
item.setCheckState(QtCore.Qt.Checked)
|
||||
|
||||
def addItems(self, text):
|
||||
for text_i in text:
|
||||
self.addItem(text_i)
|
||||
|
||||
def isChecked(self, idx: int) -> bool:
|
||||
return bool(self.model().item(idx).checkState())
|
||||
|
||||
|
53
src/gui_qt/lib/graph_items.py
Normal file
53
src/gui_qt/lib/graph_items.py
Normal file
@ -0,0 +1,53 @@
|
||||
from numpy import log10, arange, floor, ceil
|
||||
from pyqtgraph import PlotWidget, PlotItem
|
||||
|
||||
|
||||
__all__ = ['NMRPlotWidget', 'logTickValues']
|
||||
|
||||
|
||||
class NMRPlotWidget(PlotWidget):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
for orient in ['top', 'bottom', 'left', 'right']:
|
||||
# BAD HACK!!! but seems to work, see function for explanation
|
||||
self.plotItem.getAxis(orient).logTickValues = logTickValues
|
||||
|
||||
|
||||
class NMRPlotItem(PlotItem):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
for orient in ['top', 'bottom', 'left', 'right']:
|
||||
self.plotItem.getAxis(orient).logTickValues = logTickValues
|
||||
|
||||
|
||||
def logTickValues(minVal, maxVal, size, stdTicks):
|
||||
# TODO FIND A BETTER SOLUTION!!!
|
||||
# Sometimes minVal and maxVal are not log-scaled values and the loop from v1 to v2 is humongous,
|
||||
# The minor list then fills the RAM completely and freezes everything
|
||||
# Until there is a better solution, we overwrite this function for every AxesItem
|
||||
# and do not draw minor ticks at all if there are too many
|
||||
|
||||
# start with the tick spacing given by tickValues().
|
||||
# Any level whose spacing is < 1 needs to be converted to log scale
|
||||
ticks = []
|
||||
for (spacing, t) in stdTicks:
|
||||
if spacing >= 1.0:
|
||||
ticks.append((spacing, t))
|
||||
|
||||
if len(ticks) < 3:
|
||||
v1 = int(floor(minVal))
|
||||
v2 = int(ceil(maxVal))
|
||||
# major = list(range(v1+1, v2))
|
||||
minor = []
|
||||
|
||||
if v2 - v1 < 400:
|
||||
for v in range(v1, v2):
|
||||
minor.extend(v + log10(arange(1, 10)))
|
||||
minor = [x for x in minor if minVal < x < maxVal]
|
||||
ticks.append((None, minor))
|
||||
return ticks
|
||||
|
66
src/gui_qt/lib/iconloading.py
Normal file
66
src/gui_qt/lib/iconloading.py
Normal file
@ -0,0 +1,66 @@
|
||||
import sys
|
||||
|
||||
if sys.version_info < (3, 7):
|
||||
HAS_IMPORTLIB_RESOURCE = False
|
||||
from pkg_resources import resource_filename
|
||||
else:
|
||||
HAS_IMPORTLIB_RESOURCE = True
|
||||
from importlib.resources import path
|
||||
|
||||
from ..Qt import QtGui, QtWidgets
|
||||
|
||||
|
||||
def make_action_icons(widget):
|
||||
global HAS_IMPORTLIB_RESOURCE
|
||||
icon_type = QtWidgets.QApplication.instance().theme
|
||||
from json import loads
|
||||
|
||||
if HAS_IMPORTLIB_RESOURCE:
|
||||
with path('resources.icons', 'icons.json') as fp:
|
||||
with fp.open('r') as f:
|
||||
icon_list = loads(f.read())
|
||||
|
||||
for ac, img in icon_list[widget.objectName()].items():
|
||||
dirname = 'resources.icons.%s_light' % icon_type
|
||||
with path(dirname, img+'.png') as imgpath:
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(str(imgpath)), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
getattr(widget, ac).setIcon(icon)
|
||||
|
||||
else:
|
||||
with open(resource_filename('resources.icons', 'icons.json'), 'r') as f:
|
||||
icon_list = loads(f.read())
|
||||
|
||||
for ac, img in icon_list[widget.objectName()].items():
|
||||
dirname = 'resources.icons.%s_light' % icon_type
|
||||
imgpath = resource_filename(dirname, img+'.png')
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(str(imgpath)), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
getattr(widget, ac).setIcon(icon)
|
||||
|
||||
|
||||
def get_icon(icon_name):
|
||||
try:
|
||||
icon_type = QtWidgets.QApplication.instance().theme
|
||||
except AttributeError:
|
||||
icon_type = 'normal'
|
||||
|
||||
global HAS_IMPORTLIB_RESOURCE
|
||||
|
||||
if icon_name != 'logo':
|
||||
dirname = f'resources.icons.{icon_type}_light'
|
||||
else:
|
||||
dirname = 'resources.icons'
|
||||
|
||||
if HAS_IMPORTLIB_RESOURCE:
|
||||
with path(dirname, icon_name+'.png') as imgpath:
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(str(imgpath)), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
|
||||
return icon
|
||||
else:
|
||||
imgpath = resource_filename(dirname, icon_name+'.png')
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap(imgpath), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
|
||||
return icon
|
20
src/gui_qt/lib/listwidget.py
Normal file
20
src/gui_qt/lib/listwidget.py
Normal file
@ -0,0 +1,20 @@
|
||||
from ..Qt import QtWidgets, QtGui, QtCore
|
||||
|
||||
|
||||
class QListWidgetSelect(QtWidgets.QListWidget):
|
||||
"""
|
||||
Extension of QListWidget to change the check state of all selected QListWidgetItems with space key
|
||||
"""
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
def keyPressEvent(self, evt: QtGui.QKeyEvent):
|
||||
if evt.key() == QtCore.Qt.Key.Key_Space:
|
||||
for idx in self.selectedIndexes():
|
||||
item = self.itemFromIndex(idx)
|
||||
cs = item.checkState()
|
||||
item.setCheckState(QtCore.Qt.CheckState.Unchecked if cs == QtCore.Qt.CheckState.Checked
|
||||
else QtCore.Qt.CheckState.Checked)
|
||||
else:
|
||||
super().keyPressEvent(evt)
|
@ -1,17 +1,21 @@
|
||||
import sys
|
||||
import logging
|
||||
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 nmreval.configs import config_paths
|
||||
|
||||
|
||||
STYLES = {'INFO': _make_textformats('black'),
|
||||
STYLES = {
|
||||
'INFO': _make_textformats('black'),
|
||||
'WARNING': _make_textformats('blue'),
|
||||
'ERROR': _make_textformats('red', 'bold'),
|
||||
'DEBUG': _make_textformats('black', 'italic'),
|
||||
'file': _make_textformats('red', 'italic'),
|
||||
'PyError': _make_textformats('red', 'bold-italic')}
|
||||
'PyError': _make_textformats('red', 'bold-italic'),
|
||||
}
|
||||
|
||||
|
||||
class LogHighlighter(QtGui.QSyntaxHighlighter):
|
||||
@ -112,3 +116,28 @@ class QLog(QtWidgets.QDialog):
|
||||
|
||||
for lines in text[-100:]:
|
||||
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()
|
||||
|
57
src/gui_qt/lib/mdiarea.py
Normal file
57
src/gui_qt/lib/mdiarea.py
Normal file
@ -0,0 +1,57 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from ..Qt import QtWidgets, QtCore
|
||||
|
||||
from nmreval.lib.logger import logger
|
||||
from ..graphs.graphwindow import QGraphWindow
|
||||
|
||||
|
||||
class MdiAreaTile(QtWidgets.QMdiArea):
|
||||
newData = QtCore.pyqtSignal(list)
|
||||
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setAcceptDrops(True)
|
||||
|
||||
def tileSubWindowsVertically(self):
|
||||
window_list = self.subWindowList()
|
||||
rect = QtCore.QRect(0, 0, self.width(), int(self.height() / len(window_list)))
|
||||
pos = QtCore.QPoint(0, 0)
|
||||
|
||||
for win in window_list:
|
||||
win.setGeometry(rect)
|
||||
win.move(pos)
|
||||
|
||||
pos.setY(pos.y() + win.height())
|
||||
|
||||
def tileSubWindowsHorizontally(self):
|
||||
window_list = self.subWindowList()
|
||||
rect = QtCore.QRect(0, 0, int(self.width() / len(window_list)), self.height())
|
||||
pos = QtCore.QPoint(0, 0)
|
||||
|
||||
for win in window_list:
|
||||
win.setGeometry(rect)
|
||||
win.move(pos)
|
||||
|
||||
pos.setX(pos.x() + win.width())
|
||||
|
||||
def addSubWindow(self, widget: QtWidgets.QWidget, flags: QtCore.Qt.WindowFlags = QtCore.Qt.WindowFlags()) -> QtWidgets.QMdiSubWindow | None:
|
||||
subwindow = super().addSubWindow(widget)
|
||||
subwindow.setOption(QtWidgets.QMdiSubWindow.RubberBandMove, True)
|
||||
subwindow.setOption(QtWidgets.QMdiSubWindow.RubberBandResize, True)
|
||||
subwindow.setMinimumHeight(240)
|
||||
subwindow.setMinimumWidth(360)
|
||||
|
||||
return subwindow
|
||||
|
||||
def setActiveSubWidget(self, key: str):
|
||||
for win in self.subWindowList():
|
||||
wdgt = win.widget()
|
||||
if isinstance(wdgt, QGraphWindow) and wdgt.id == key:
|
||||
self.setActiveSubWindow(win)
|
||||
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 nmreval
|
||||
|
||||
from nmreval import models
|
||||
from nmreval.configs import config_paths
|
||||
from nmreval.lib.importer import find_models, import_
|
||||
@ -21,36 +23,62 @@ class Namespace:
|
||||
self.top_levels = {}
|
||||
|
||||
if basic:
|
||||
self.add_namespace({'x': (None, 'x values'), 'y': (None, 'x values'), 'y_err': (None, 'y error values'),
|
||||
'fit': (None, 'dictionary of fit parameter', 'fit["PIKA"]'), 'np': (np, 'numpy module')},
|
||||
parents=('Basic', 'General'))
|
||||
self.add_namespace(
|
||||
{
|
||||
'x': (None, 'x values'),
|
||||
'y': (None, 'x values'),
|
||||
'y_err': (None, 'y error values'),
|
||||
'fit': (None, 'dictionary of fit parameter', 'fit["PIKA"]'),
|
||||
'np': (np, 'numpy module'),
|
||||
'nmreval': (nmreval, 'built-in classes and stuff')
|
||||
},
|
||||
parents=('Basic', 'General'),
|
||||
)
|
||||
|
||||
self.add_namespace({'sin': (np.sin, 'Sine', 'sin(PIKA)'), 'cos': (np.cos, 'Cosine', 'cos(PIKA)'),
|
||||
'tan': (np.tan, 'Tangens', 'tan(PIKA)'), 'ln': (np.log, 'Natural Logarithm', 'ln(PIKA)'),
|
||||
self.add_namespace(
|
||||
{
|
||||
'sin': (np.sin, 'Sine', 'sin(PIKA)'),
|
||||
'cos': (np.cos, 'Cosine', 'cos(PIKA)'),
|
||||
'tan': (np.tan, 'Tangens', 'tan(PIKA)'),
|
||||
'ln': (np.log, 'Natural Logarithm', 'ln(PIKA)'),
|
||||
'log': (np.log10, 'Logarithm (base 10)', 'log(PIKA)'),
|
||||
'exp': (np.exp, 'Exponential', 'exp(PIKA)'), 'sqrt': (np.sqrt, 'Root', 'sqrt(PIKA)'),
|
||||
'lin_range': (np.linspace, 'N evenly spaced over interval [start, stop]',
|
||||
'lin_range(start, stop, N)'),
|
||||
'log_range': (np.geomspace, 'N evenly spaced (log-scale) over interval [start, stop]',
|
||||
'lin_range(start, stop, N)')},
|
||||
'exp': (np.exp, 'Exponential', 'exp(PIKA)'),
|
||||
'sqrt': (np.sqrt, 'Root', 'sqrt(PIKA)'),
|
||||
'lin_range': (np.linspace, 'N evenly spaced over interval [start, stop]', 'lin_range(start, stop, N)'),
|
||||
'log_range': (np.geomspace, 'N evenly spaced (log-scale) over interval [start, stop]', 'lin_range(start, stop, N)'),
|
||||
},
|
||||
parents=('Basic', 'Functions'))
|
||||
|
||||
self.add_namespace({'max': (np.max, 'Maximum value', 'max(PIKA)'),
|
||||
self.add_namespace(
|
||||
{
|
||||
'max': (np.max, 'Maximum value', 'max(PIKA)'),
|
||||
'min': (np.min, 'Minimum value', 'min(PIKA)'),
|
||||
'argmax': (np.argmax, 'Index of maximum value', 'argmax(PIKA)'),
|
||||
'argmin': (np.argmax, 'Index of minimum value', 'argmin(PIKA)')},
|
||||
parents=('Basic', 'Values'))
|
||||
'argmin': (np.argmax, 'Index of minimum value', 'argmin(PIKA)'),
|
||||
},
|
||||
parents=('Basic', 'Values')),
|
||||
|
||||
if const:
|
||||
self.add_namespace({'e': (constants.e, 'e / As'), 'eps0': (constants.epsilon0, 'epsilon0 / As/Vm'),
|
||||
'Eu': (constants.Eu,), 'h': (constants.h, 'h / eVs'),
|
||||
'hbar': (constants.hbar, 'hbar / eVs'), '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'))
|
||||
self.add_namespace(
|
||||
{
|
||||
'e': (constants.e, 'e / As'),
|
||||
'eps0': (constants.epsilon0, 'epsilon0 / As/Vm'),
|
||||
'Eu': (constants.Eu,),
|
||||
'h': (constants.h, 'h / eVs'),
|
||||
'hbar': (constants.hbar, 'hbar / eVs'),
|
||||
'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'),
|
||||
)
|
||||
|
||||
self.add_namespace({f'gamma["{k}"]': (v, k, f'gamma["{k}"]') for k, v in constants.gamma.items()},
|
||||
parents=('Constants', 'Magnetogyric ratios (in 1/(sT))'))
|
||||
self.add_namespace(
|
||||
{f'gamma["{k}"]': (v, k, f'gamma["{k}"]') for k, v in constants.gamma.items()},
|
||||
parents=('Constants', 'Gyromagnetic ratios (in 1/(sT))')
|
||||
)
|
||||
|
||||
if fitfuncs:
|
||||
self.make_dict_from_fitmodule(models)
|
||||
@ -104,9 +132,18 @@ class Namespace:
|
||||
graph = namedtuple('graphs', ['s'])
|
||||
sets = namedtuple('sets', ['x', 'y', 'y_err', 'value', 'fit'], defaults=(None,))
|
||||
|
||||
gamma = {}
|
||||
|
||||
gs = re.compile(r'g\[(\d+)].s\[(\d+)].(x|y(?:_err)*|value|fit)')
|
||||
gamma_re = re.compile(r'gamma\["(\w+)"\]')
|
||||
|
||||
for k, v in self.namespace.items():
|
||||
m = gamma_re.match(k)
|
||||
if m:
|
||||
gamma[m.group(1)] = v[0]
|
||||
|
||||
continue
|
||||
|
||||
m = gs.match(k)
|
||||
if m:
|
||||
if 'g' not in ret_dic:
|
||||
@ -118,7 +155,7 @@ class Namespace:
|
||||
|
||||
gg = ret_dic['g'][int(g_num)]
|
||||
if int(s_num) not in gg.s:
|
||||
gg.s[int(s_num)] = sets('', '', '', '')
|
||||
gg.s[int(s_num)] = sets('', '', '', '', {})
|
||||
|
||||
ss = gg.s[int(s_num)]
|
||||
if pos == 'fit':
|
||||
@ -130,9 +167,12 @@ class Namespace:
|
||||
else:
|
||||
ret_dic['g'][int(g_num)].s[int(s_num)] = ss._replace(**{pos: v[0]})
|
||||
|
||||
else:
|
||||
continue
|
||||
|
||||
ret_dic[k] = v[0]
|
||||
|
||||
ret_dic['gamma'] = gamma
|
||||
|
||||
return ret_dic
|
||||
|
||||
|
||||
@ -170,7 +210,7 @@ class QNamespaceWidget(QtWidgets.QWidget, Ui_Form):
|
||||
|
||||
for entry in subspace:
|
||||
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]
|
||||
|
||||
@ -185,12 +225,12 @@ class QNamespaceWidget(QtWidgets.QWidget, Ui_Form):
|
||||
display = vals[1]
|
||||
|
||||
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.UserRole+1, entry)
|
||||
value_item.setData(QtCore.Qt.UserRole, alias)
|
||||
value_item.setData(QtCore.Qt.UserRole+1, entry)
|
||||
key_item.setData(QtCore.Qt.ItemDataRole.UserRole, alias)
|
||||
key_item.setData(QtCore.Qt.ItemDataRole.UserRole+1, entry)
|
||||
value_item.setData(QtCore.Qt.ItemDataRole.UserRole, alias)
|
||||
value_item.setData(QtCore.Qt.ItemDataRole.UserRole+1, entry)
|
||||
|
||||
row = self.namespace_table.rowCount()
|
||||
self.namespace_table.setRowCount(row+1)
|
||||
@ -212,5 +252,5 @@ class QNamespaceWidget(QtWidgets.QWidget, Ui_Form):
|
||||
|
||||
@QtCore.pyqtSlot(QtWidgets.QTableWidgetItem, name='on_namespace_table_itemDoubleClicked')
|
||||
def item_selected(self, item: QtWidgets.QTableWidgetItem):
|
||||
self.selected.emit(item.data(QtCore.Qt.UserRole))
|
||||
self.sendKey.emit(item.data(QtCore.Qt.UserRole+1))
|
||||
self.selected.emit(item.data(QtCore.Qt.ItemDataRole.UserRole))
|
||||
self.sendKey.emit(item.data(QtCore.Qt.ItemDataRole.UserRole+1))
|
||||
|
@ -174,6 +174,7 @@ class PlotItem(PlotDataItem):
|
||||
pen = self.opts['pen']
|
||||
if isinstance(pen, tuple):
|
||||
self.opts['linecolor'] = pen
|
||||
self.opts['pen'] = mkPen(color=pen)
|
||||
else:
|
||||
c = pen.color()
|
||||
self.opts['linecolor'] = c.red(), c.green(), c.blue()
|
||||
@ -182,6 +183,8 @@ class PlotItem(PlotDataItem):
|
||||
brush = self.opts['symbolBrush']
|
||||
if isinstance(brush, tuple):
|
||||
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:
|
||||
c = brush.color()
|
||||
self.opts['symbolcolor'] = c.red(), c.green(), c.blue()
|
||||
@ -279,7 +282,7 @@ class PlotItem(PlotDataItem):
|
||||
else:
|
||||
self.scatter.hide()
|
||||
|
||||
def set_symbol(self, symbol=None, size=None, color=None):
|
||||
def set_symbol(self, *, symbol=None, size=None, color=None):
|
||||
if symbol is not None:
|
||||
if isinstance(symbol, int):
|
||||
self.setSymbol(SymbolStyle(symbol).to_str())
|
||||
@ -313,14 +316,13 @@ class PlotItem(PlotDataItem):
|
||||
self.opts['pen'] = pen
|
||||
self.updateItems()
|
||||
|
||||
def set_line(self, style=None, width=None, color=None):
|
||||
def set_line(self, *, style=None, width=None, color=None):
|
||||
pen = self.opts['pen']
|
||||
if pen is None:
|
||||
pen = mkPen(style=QtCore.Qt.NoPen)
|
||||
|
||||
if width is not None:
|
||||
pen.setWidthF(width)
|
||||
|
||||
if style is not None:
|
||||
if isinstance(style, LineStyle):
|
||||
style = style.value
|
||||
@ -340,7 +342,8 @@ class PlotItem(PlotDataItem):
|
||||
|
||||
opts = self.opts
|
||||
item_dic = {
|
||||
'x': x, 'y': y,
|
||||
'x': x,
|
||||
'y': y,
|
||||
'name': opts.get('name', ''),
|
||||
'symbolsize': opts['symbolSize'],
|
||||
}
|
||||
@ -375,7 +378,6 @@ class PlotItem(PlotDataItem):
|
||||
class RegionItem(LinearRegionItem):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.mode = kwargs.pop('mode', 'half')
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.logmode = False
|
||||
@ -383,6 +385,10 @@ class RegionItem(LinearRegionItem):
|
||||
if not hasattr(self, '_bounds') and hasattr(self, '_boundingRectCache'):
|
||||
self._bounds = self._boundingRectCache
|
||||
|
||||
for l in self.lines:
|
||||
# higher z for borderlines improves chances that you can move it when multiple regions overlap
|
||||
l.setZValue(self.zValue() + 1)
|
||||
|
||||
def setLogMode(self, xmode, _):
|
||||
if self.logmode == xmode:
|
||||
return
|
||||
@ -418,6 +424,15 @@ class RegionItem(LinearRegionItem):
|
||||
else:
|
||||
return region
|
||||
|
||||
def setRegion(self, region, use_log=False):
|
||||
if self.logmode and use_log:
|
||||
region = np.log10(region[0]), np.log10(region[1])
|
||||
|
||||
if not np.all(np.isfinite(region)):
|
||||
raise ValueError(f'Invalid region limits ({region[0]}, {region[1]})')
|
||||
else:
|
||||
super().setRegion(region)
|
||||
|
||||
def boundingRect(self):
|
||||
# overwrite to draw correct rect in logmode
|
||||
|
||||
@ -460,11 +475,18 @@ class LegendItemBlock(LegendItem):
|
||||
def mouseDragEvent(self, ev):
|
||||
if ev.button() == QtCore.Qt.LeftButton:
|
||||
ev.accept()
|
||||
|
||||
dpos = ev.pos() - ev.lastPos()
|
||||
|
||||
upper_left = self.pos()
|
||||
lower_right = self.pos()
|
||||
lower_right.setX(lower_right.x() + self.width())
|
||||
lower_right.setY(lower_right.y() + self.height())
|
||||
|
||||
vb_rect = self.parentItem().rect()
|
||||
pos = self.pos()
|
||||
# upper left corner and a point a little more to the bottom right must be inside
|
||||
if vb_rect.contains(pos+dpos) and vb_rect.contains(pos+dpos+QtCore.QPointF(20., 20.)):
|
||||
self.autoAnchor(pos + dpos)
|
||||
|
||||
# upper left and lower right corner must be inside viewbox
|
||||
if vb_rect.contains(upper_left + dpos) and vb_rect.contains(lower_right + dpos):
|
||||
self.autoAnchor(upper_left + dpos)
|
||||
else:
|
||||
self.autoAnchor(pos)
|
||||
self.autoAnchor(upper_left)
|
||||
|
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
|
@ -1,110 +0,0 @@
|
||||
import os.path
|
||||
import json
|
||||
import urllib.request
|
||||
import webbrowser
|
||||
import random
|
||||
|
||||
from ..Qt import QtGui, QtCore, QtWidgets
|
||||
from .._py.pokemon import Ui_Dialog
|
||||
|
||||
random.seed()
|
||||
|
||||
|
||||
class QPokemon(QtWidgets.QDialog, Ui_Dialog):
|
||||
def __init__(self, number=None, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
self.setupUi(self)
|
||||
self._js = json.load(open(os.path.join(path_to_module, 'utils', 'pokemon.json'), 'r'), encoding='UTF-8')
|
||||
self._id = 0
|
||||
|
||||
if number is not None and number in range(1, len(self._js)+1):
|
||||
poke_nr = f'{number:03d}'
|
||||
self._id = number
|
||||
else:
|
||||
poke_nr = f'{random.randint(1, len(self._js)):03d}'
|
||||
self._id = int(poke_nr)
|
||||
|
||||
self._pokemon = None
|
||||
self.show_pokemon(poke_nr)
|
||||
self.label_15.linkActivated.connect(lambda x: webbrowser.open(x))
|
||||
|
||||
self.buttonBox.clicked.connect(self.randomize)
|
||||
self.next_button.clicked.connect(self.show_next)
|
||||
self.prev_button.clicked.connect(self.show_prev)
|
||||
|
||||
def show_pokemon(self, nr):
|
||||
self._pokemon = self._js[nr]
|
||||
self.setWindowTitle('Pokémon: ' + self._pokemon['Deutsch'])
|
||||
|
||||
for i in range(self.tabWidget.count(), -1, -1):
|
||||
print('i', self.tabWidget.count(), i)
|
||||
try:
|
||||
self.tabWidget.widget(i).deleteLater()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
for n, img in self._pokemon['Bilder']:
|
||||
w = QtWidgets.QWidget()
|
||||
vl = QtWidgets.QVBoxLayout()
|
||||
l = QtWidgets.QLabel(self)
|
||||
l.setAlignment(QtCore.Qt.AlignHCenter)
|
||||
pixmap = QtGui.QPixmap()
|
||||
|
||||
try:
|
||||
pixmap.loadFromData(urllib.request.urlopen(img, timeout=0.5).read())
|
||||
except IOError:
|
||||
l.setText(n)
|
||||
else:
|
||||
sc_pixmap = pixmap.scaled(256, 256, QtCore.Qt.KeepAspectRatio)
|
||||
l.setPixmap(sc_pixmap)
|
||||
|
||||
vl.addWidget(l)
|
||||
w.setLayout(vl)
|
||||
self.tabWidget.addTab(w, n)
|
||||
|
||||
if len(self._pokemon['Bilder']) <= 1:
|
||||
self.tabWidget.tabBar().setVisible(False)
|
||||
else:
|
||||
self.tabWidget.tabBar().setVisible(True)
|
||||
self.tabWidget.adjustSize()
|
||||
|
||||
self.name.clear()
|
||||
keys = ['National-Dex', 'Kategorie', 'Typ', 'Größe', 'Gewicht', 'Farbe', 'Link']
|
||||
label_list = [self.pokedex_nr, self.category, self.poketype, self.weight, self.height, self.color, self.info]
|
||||
for (k, label) in zip(keys, label_list):
|
||||
v = self._pokemon[k]
|
||||
if isinstance(v, list):
|
||||
v = os.path.join('', *v)
|
||||
|
||||
if k == 'Link':
|
||||
v = '<a href={}>{}</a>'.format(v, v)
|
||||
|
||||
label.setText(v)
|
||||
|
||||
for k in ['Deutsch', 'Japanisch', 'Englisch', 'Französisch']:
|
||||
v = self._pokemon[k]
|
||||
self.name.addItem(k + ': ' + v)
|
||||
|
||||
self.adjustSize()
|
||||
|
||||
def randomize(self, idd):
|
||||
if idd.text() == 'Retry':
|
||||
new_number = f'{random.randint(1, len(self._js)):03d}'
|
||||
self._id = int(new_number)
|
||||
self.show_pokemon(new_number)
|
||||
else:
|
||||
self.close()
|
||||
|
||||
def show_next(self):
|
||||
new_number = self._id + 1
|
||||
if new_number > len(self._js):
|
||||
new_number = 1
|
||||
self._id = new_number
|
||||
self.show_pokemon(f'{new_number:03d}')
|
||||
|
||||
def show_prev(self):
|
||||
new_number = self._id - 1
|
||||
if new_number == 0:
|
||||
new_number = len(self._js)
|
||||
self._id = new_number
|
||||
self.show_pokemon(f'{new_number:03d}')
|
@ -34,9 +34,9 @@ class SciSpinBox(QtWidgets.QDoubleSpinBox):
|
||||
|
||||
new_value = self._prev_value
|
||||
if new_value != 0.0:
|
||||
new_value *= 10**(step/19.)
|
||||
new_value *= 10**(step/99.)
|
||||
else:
|
||||
new_value = 0.001
|
||||
new_value = 0.00001
|
||||
|
||||
self.setValue(new_value)
|
||||
self.lineEdit().setText(f'{new_value:.3e}')
|
||||
|
100
src/gui_qt/lib/starter.py
Normal file
100
src/gui_qt/lib/starter.py
Normal file
@ -0,0 +1,100 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from shutil import copyfile
|
||||
from pathlib import Path
|
||||
import os
|
||||
from configparser import ConfigParser
|
||||
from importlib.resources import path as resource_path
|
||||
|
||||
from nmreval.configs import config_paths
|
||||
from nmreval.lib.logger import logger
|
||||
|
||||
|
||||
def make_starter(app_file: str | None):
|
||||
if app_file is not None:
|
||||
make_starter_appimage(Path(app_file))
|
||||
else:
|
||||
make_starter_src()
|
||||
|
||||
|
||||
def make_starter_appimage(app_file: Path):
|
||||
new_path = Path.home() / '.local' / 'bin'
|
||||
|
||||
if not new_path.exists():
|
||||
new_path.mkdir(parents=True)
|
||||
|
||||
new_path /= app_file.name
|
||||
|
||||
if app_file != new_path:
|
||||
app_file.rename(new_path)
|
||||
|
||||
create_desktop_file(new_path)
|
||||
|
||||
|
||||
def make_starter_src():
|
||||
home = Path.home()
|
||||
p = Path.home()
|
||||
for p in Path(__file__).parents:
|
||||
if p.stem == 'src':
|
||||
break
|
||||
elif p == home:
|
||||
break
|
||||
|
||||
success = p != Path.home()
|
||||
if success:
|
||||
bin_path = p.with_name('bin') / 'evaluate.py'
|
||||
success = bin_path.exists()
|
||||
|
||||
if not success:
|
||||
logger.warning('Location of evaluate.py could not be determined')
|
||||
return False
|
||||
|
||||
create_desktop_file(bin_path)
|
||||
|
||||
|
||||
def create_desktop_file(new_path: Path):
|
||||
logo_path = config_paths() / 'logo.png'
|
||||
if not logo_path.exists():
|
||||
with resource_path('resources', 'logo.png') as fp:
|
||||
copyfile(fp, logo_path)
|
||||
desktop_entry = f"""\
|
||||
[Desktop Entry]
|
||||
Name=NMReval
|
||||
Comment=Best program ever (maybe)
|
||||
Exec={new_path}
|
||||
Icon={logo_path}
|
||||
Type=Application
|
||||
Terminal=false
|
||||
Categories=Science;NumericalAnalysis;Physics;DataVisualization;Other;
|
||||
NoDisplay=false
|
||||
"""
|
||||
file_name = 'pkm.vogel.nmreval.desktop'
|
||||
with Path('~/.local/share/applications/', file_name).expanduser().open('w') as f:
|
||||
f.write(desktop_entry)
|
||||
|
||||
desktop_dir = get_xkg_user_dirs('desktop')
|
||||
if desktop_dir is not None:
|
||||
desk_file = Path(desktop_dir, file_name)
|
||||
with desk_file.open('w') as f:
|
||||
f.write(desktop_entry)
|
||||
|
||||
desk_file.chmod(0o755)
|
||||
|
||||
|
||||
def get_xkg_user_dirs(dir_type: str) -> str | None:
|
||||
xdg_conf_home = os.getenv('XDG_CONFIG_HOME') or str(Path.home() / '.config')
|
||||
|
||||
with Path(xdg_conf_home, 'user-dirs.dirs').open('r') as f:
|
||||
conf_string = '[XDG_USER_DIRS]\n' + f.read()
|
||||
conf_string = re.sub(r'\$HOME', str(Path.home()), conf_string)
|
||||
conf_string = re.sub('"', '', conf_string)
|
||||
|
||||
config = ConfigParser()
|
||||
config.read_string(conf_string)
|
||||
|
||||
return config['XDG_USER_DIRS'].get(f'xdg_{dir_type}_dir')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
make_starter()
|
@ -6,7 +6,7 @@ import numpy as np
|
||||
from ..Qt import QtWidgets, QtCore, QtGui
|
||||
|
||||
|
||||
__all__ = ['Game']
|
||||
__all__ = ['Game', 'QMines']
|
||||
|
||||
|
||||
class Game(QtWidgets.QDialog):
|
||||
|
@ -1,4 +1,4 @@
|
||||
from . import HAS_IMPORTLIB_RESOURCE
|
||||
from .iconloading import HAS_IMPORTLIB_RESOURCE
|
||||
from ..Qt import QtGui, QtWidgets, QtCore
|
||||
|
||||
|
||||
|
@ -29,3 +29,16 @@ class TreeWidget(QtWidgets.QTreeWidget):
|
||||
it.setCheckState(0, QtCore.Qt.Unchecked if it.checkState(0) == QtCore.Qt.Checked else QtCore.Qt.Checked)
|
||||
else:
|
||||
super().keyPressEvent(evt)
|
||||
|
||||
|
||||
class TableWidget(QtWidgets.QTableWidget):
|
||||
def keyPressEvent(self, evt: QtGui.QKeyEvent):
|
||||
if evt.key() == QtCore.Qt.Key.Key_Space:
|
||||
for idx in self.selectedIndexes():
|
||||
item = self.itemFromIndex(idx)
|
||||
cs = item.checkState()
|
||||
item.setCheckState(QtCore.Qt.CheckState.Unchecked if cs == QtCore.Qt.CheckState.Checked
|
||||
else QtCore.Qt.CheckState.Checked)
|
||||
else:
|
||||
super().keyPressEvent(evt)
|
||||
|
||||
|
@ -1,7 +1,10 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
|
||||
from numpy import argsort
|
||||
|
||||
from . import Relations
|
||||
from ..Qt import QtWidgets, QtCore
|
||||
from ..data.container import FitContainer
|
||||
from ..graphs.graphwindow import QGraphWindow
|
||||
@ -84,6 +87,21 @@ class ShiftCommand(QtWidgets.QUndoCommand):
|
||||
self.__data.apply('ls', self.__args)
|
||||
|
||||
|
||||
class EditCommand(QtWidgets.QUndoCommand):
|
||||
def __init__(self, data, *args):
|
||||
super().__init__('Edit signal')
|
||||
|
||||
self.__data = data
|
||||
self.__arguments = args
|
||||
self.__original = copy.deepcopy(self.__data.data)
|
||||
|
||||
def undo(self):
|
||||
self.__data.data = copy.deepcopy(self.__original)
|
||||
|
||||
def redo(self):
|
||||
self.__data.edit_signal(*self.__arguments)
|
||||
|
||||
|
||||
class NormCommand(QtWidgets.QUndoCommand):
|
||||
def __init__(self, data, mode):
|
||||
super().__init__('Normalize')
|
||||
@ -216,33 +234,69 @@ class DeleteGraphCommand(QtWidgets.QUndoCommand):
|
||||
|
||||
|
||||
class DeleteCommand(QtWidgets.QUndoCommand):
|
||||
def __init__(self, container, key, signal1, signal2):
|
||||
def __init__(self, container: dict, keys: list[str], graphs: dict, graphid: str,
|
||||
signal1: QtCore.pyqtSignal, signal2: QtCore.pyqtSignal):
|
||||
super().__init__('Delete data')
|
||||
|
||||
self.__container = container
|
||||
self.__value = self.__container[key]
|
||||
self.__key = key
|
||||
self.__graph_container = graphs
|
||||
self.__graph_key = graphid
|
||||
self.__value = {}
|
||||
for k in keys:
|
||||
self.__value[k] = self.__container[k]
|
||||
self.__keys = tuple(keys)
|
||||
self.__signal_add = signal1
|
||||
self.__signal_remove = signal2
|
||||
|
||||
def redo(self):
|
||||
self.__signal_remove.emit(self.__key)
|
||||
if isinstance(self.__value, FitContainer):
|
||||
# stop graph from rescaling and updating legend
|
||||
self.__graph_container[self.__graph_key].block(True)
|
||||
|
||||
self.__signal_remove.emit(list(self.__keys[::-1]))
|
||||
for sid in self.__keys[::-1]:
|
||||
val = self.__value[sid]
|
||||
|
||||
if isinstance(val, FitContainer):
|
||||
try:
|
||||
self.__container[self.__value.fitted_key]._fits.remove(self.__key)
|
||||
self.__container[val.fitted_key]._fits.remove(sid)
|
||||
except KeyError:
|
||||
pass
|
||||
del self.__container[self.__key]
|
||||
|
||||
for (flag1, flag2) in ((Relations.isFitPartOf, Relations.hasFitPart), (Relations.hasFitPart, Relations.isFitPartOf)):
|
||||
for related_item in val.get_relation(flag1):
|
||||
try:
|
||||
self.__container[related_item].remove_relation(flag2, sid)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
del self.__container[sid]
|
||||
|
||||
self.__graph_container[self.__graph_key].block(False)
|
||||
|
||||
def undo(self):
|
||||
self.__container[self.__key] = self.__value
|
||||
if isinstance(self.__value, FitContainer):
|
||||
# stop graph from rescaling and updating legend
|
||||
self.__graph_container[self.__graph_key].block(True)
|
||||
|
||||
for sid in self.__keys:
|
||||
val = self.__value[sid]
|
||||
self.__container[sid] = val
|
||||
|
||||
if isinstance(val, FitContainer):
|
||||
try:
|
||||
self.__container[self.__value.fitted_key]._fits.append(self.__key)
|
||||
self.__container[val.fitted_key]._fits.append(sid)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
self.__signal_add.emit([self.__key], self.__value.graph)
|
||||
for (flag1, flag2) in (('isFitPartOf', 'hasFitPartOf'), ('hasFitPartOf', 'isFitPartOf')):
|
||||
for related_item in val.get_relation(flag1):
|
||||
try:
|
||||
self.__container[related_item].add_relation(flag2, sid)
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
self.__signal_add.emit(list(self.__keys), self.__graph_key)
|
||||
|
||||
self.__graph_container[self.__graph_key].block(False)
|
||||
|
||||
|
||||
class EvalCommand(QtWidgets.QUndoCommand):
|
||||
|
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,28 +1,16 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from functools import lru_cache
|
||||
from os import getenv, stat
|
||||
from os.path import exists
|
||||
import hashlib
|
||||
import subprocess
|
||||
from datetime import datetime
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
|
||||
import requests
|
||||
from numpy import linspace
|
||||
from scipy.interpolate import interp1d
|
||||
|
||||
from nmreval.lib.logger import logger
|
||||
|
||||
from ..Qt import QtGui, QtWidgets, QtCore
|
||||
|
||||
|
||||
@contextmanager
|
||||
def busy_cursor():
|
||||
try:
|
||||
cursor = QtGui.QCursor(QtCore.Qt.ForbiddenCursor)
|
||||
cursor = QtGui.QCursor(QtCore.Qt.CursorShape.ForbiddenCursor)
|
||||
QtWidgets.QApplication.setOverrideCursor(cursor)
|
||||
yield
|
||||
|
||||
@ -59,246 +47,8 @@ class RdBuCMap:
|
||||
elif val < self.min:
|
||||
col = QtGui.QColor.fromRgb(*RdBuCMap._rdbu[-1])
|
||||
else:
|
||||
col = QtGui.QColor.fromRgb(*(float(self.spline[i](val)) for i in range(3)))
|
||||
col = QtGui.QColor.fromRgb(*(int(self.spline[i](val)) for i in range(3)))
|
||||
|
||||
return col
|
||||
|
||||
|
||||
class UpdateDialog(QtWidgets.QDialog):
|
||||
startDownload = QtCore.pyqtSignal(list)
|
||||
|
||||
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.success = False
|
||||
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)
|
||||
|
||||
if m_time_zsync is None:
|
||||
label_text = '<p>Retrieval of version information failed.</p>' \
|
||||
'<p>Please try later (or complain to people that it does not work).</p>'
|
||||
dialog_bttns = QtWidgets.QDialogButtonBox.Close
|
||||
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>'
|
||||
|
||||
if is_updateble is None:
|
||||
self.status.setText('Could not determine if this version is newer, please update manually (if necessary).')
|
||||
dialog_bttns = QtWidgets.QDialogButtonBox.Close
|
||||
elif is_updateble:
|
||||
self.status.setText(f'<p>Newer version available. Press Ok to download new version, Cancel to ignore.')
|
||||
dialog_bttns = QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Cancel
|
||||
else:
|
||||
self.status.setText(f'Version may be already up-to-date.')
|
||||
dialog_bttns = QtWidgets.QDialogButtonBox.Close
|
||||
|
||||
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 = ['-i', self._appfile, self.updater.zsync_url]
|
||||
|
||||
args = [self.updater.zsync_url]
|
||||
|
||||
self.dialog_button.setEnabled(False)
|
||||
|
||||
self.startDownload.emit(args)
|
||||
self.status.show()
|
||||
|
||||
@QtCore.pyqtSlot(int)
|
||||
def finish_update(self, retcode: int):
|
||||
# print('finished with', retcode)
|
||||
self.success = retcode == 0
|
||||
if retcode == 0:
|
||||
self.status.setText('Download complete.')
|
||||
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()
|
||||
|
||||
if self.success:
|
||||
appname = self.updater.get_zsync()[2]
|
||||
if self._appfile is not None:
|
||||
appimage_path = appname
|
||||
old_version = Path(self._appfile).rename(self._appfile+'.old')
|
||||
appimage_path = Path(appimage_path).replace(self._appfile)
|
||||
else:
|
||||
appimage_path = Path().cwd() / appname
|
||||
# rename to version-agnostic name
|
||||
appimage_path = appimage_path.rename('NMReval.AppImage')
|
||||
appimage_path.chmod(appimage_path.stat().st_mode | 73) # 73 = 0o111 = a+x
|
||||
|
||||
_ = QtWidgets.QMessageBox.information(self, 'Complete',
|
||||
f'New AppImage available at<br>{appimage_path}')
|
||||
|
||||
super().closeEvent(evt)
|
||||
|
||||
|
||||
class Downloader(QtCore.QObject):
|
||||
started = QtCore.pyqtSignal()
|
||||
finished = QtCore.pyqtSignal(int)
|
||||
progressChanged = QtCore.pyqtSignal(str)
|
||||
|
||||
@QtCore.pyqtSlot(list)
|
||||
def run_download(self, args: list[str]):
|
||||
logger.info(f'Download with args {args}')
|
||||
process = subprocess.Popen(['zsync'] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1, universal_newlines=True)
|
||||
while True:
|
||||
nextline = process.stdout.readline().strip()
|
||||
if nextline:
|
||||
self.progressChanged.emit(nextline)
|
||||
|
||||
# line = process.stderr.readline().strip()
|
||||
|
||||
if process.poll() is not None:
|
||||
break
|
||||
|
||||
self.finished.emit(process.returncode)
|
||||
|
||||
|
||||
class Updater:
|
||||
host = 'mirror.infra.pkm'
|
||||
bucket = 'nmreval'
|
||||
version = 'NMReval-latest-x86_64'
|
||||
|
||||
@property
|
||||
def zsync_url(self):
|
||||
return f'http://{Updater.host}/{Updater.bucket}/{Updater.version}.AppImage.zsync'
|
||||
|
||||
@staticmethod
|
||||
@lru_cache(3)
|
||||
def get_zsync():
|
||||
url_zsync = f'http://{Updater.host}/{Updater.bucket}/{Updater.version}.AppImage.zsync'
|
||||
m_time_zsync = None
|
||||
checksum_zsync = None
|
||||
zsync_file = None
|
||||
filename = None
|
||||
try:
|
||||
response = requests.get(url_zsync)
|
||||
if response.status_code == requests.codes['\o/']:
|
||||
zsync_file = response.content
|
||||
else:
|
||||
logger.error(f'Request for zsync returned code {response.statuse_code}')
|
||||
except Exception:
|
||||
logger.exception('Download of zsync failed')
|
||||
|
||||
if zsync_file is not None:
|
||||
for line in zsync_file.split(b'\n'):
|
||||
try:
|
||||
kw, val = line.split(b': ')
|
||||
if kw == b'MTime':
|
||||
m_time_zsync = datetime.strptime(str(val, encoding='utf-8'), '%a, %d %b %Y %H:%M:%S %z').astimezone(None)
|
||||
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()
|
||||
|
||||
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.info(f'zsync information {m_time_zsync}, {checksum_zsync}, {appname}')
|
||||
logger.info(f'file information {m_time_file}, {checksum_zsync}')
|
||||
|
||||
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
|
||||
|
||||
|
||||
def open_bug_report():
|
||||
form_entries = {
|
||||
'description': 'Please state the nature of the medical emergency.',
|
||||
'title': 'Everything is awesome?',
|
||||
'assign[0]': 'dominik',
|
||||
'subscribers[0]': 'dominik',
|
||||
'tag': 'nmreval',
|
||||
'priority': 'normal',
|
||||
'status': 'open',
|
||||
}
|
||||
full_url = 'https://chaos3.fkp.physik.tu-darmstadt.de/maniphest/task/edit/?'
|
||||
|
||||
for k, v in form_entries.items():
|
||||
full_url += f'{k}={v}&'
|
||||
full_url.replace(' ', '+')
|
||||
|
||||
import webbrowser
|
||||
webbrowser.open(full_url)
|
||||
|
3
src/gui_qt/main/console.py
Normal file
3
src/gui_qt/main/console.py
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
@ -9,18 +8,24 @@ from numpy import geomspace, linspace
|
||||
from pyqtgraph import ViewBox
|
||||
|
||||
from nmreval.configs import *
|
||||
from nmreval.lib.logger import logger
|
||||
from nmreval.io.sessionwriter import NMRWriter
|
||||
|
||||
from .management import UpperManagement
|
||||
from ..lib.logger import QTextHandler
|
||||
from ..Qt import QtGui, QtPrintSupport
|
||||
from ..data.shift_graphs import QShift
|
||||
from ..data.signaledit import QApodDialog, QBaselineDialog, QPhasedialog
|
||||
from ..data.signaledit import QPreviewDialog, QBaselineDialog
|
||||
from ..dsc.glass_dialog import TgCalculator
|
||||
from ..fit.fit_toolbar import FitToolbar
|
||||
from ..fit.result import FitExtension, QFitResult
|
||||
from ..graphs.graphwindow import QGraphWindow
|
||||
from ..graphs.movedialog import QMover
|
||||
from ..io.fcbatchreader import QFCReader
|
||||
from ..io.filedialog import *
|
||||
from ..lib import get_icon, make_action_icons
|
||||
from ..lib.pg_objects import RegionItem
|
||||
from ..lib.iconloading import make_action_icons, get_icon
|
||||
from ..lib.starter import make_starter
|
||||
from ..math.binning import BinningWindow
|
||||
from ..math.evaluation import QEvalDialog
|
||||
from ..math.interpol import InterpolDialog
|
||||
from ..math.mean_dialog import QMeanTimes
|
||||
@ -28,7 +33,7 @@ from ..math.smooth import QSmooth
|
||||
from ..nmr.coupling_calc import QCoupCalcDialog
|
||||
from ..nmr.t1_from_tau import QRelaxCalc
|
||||
from .._py.basewindow import Ui_BaseWindow
|
||||
from ..lib.utils import UpdateDialog, open_bug_report, Updater
|
||||
from ..lib.update import UpdateDialog
|
||||
|
||||
|
||||
class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
@ -37,7 +42,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
save_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)
|
||||
|
||||
if path is None:
|
||||
@ -53,8 +58,17 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.fitpreview = []
|
||||
self._fit_plot_id = None
|
||||
self.savefitdialog = None
|
||||
self._tg_dialog = None
|
||||
self.fitresult_dialog = None
|
||||
self.eval = 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)
|
||||
|
||||
@ -63,14 +77,20 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self._block_window_change = False
|
||||
|
||||
self.fname = None
|
||||
self.tim = QtCore.QTimer()
|
||||
|
||||
self.settings = QtCore.QSettings('NMREVal', 'settings')
|
||||
self._init_gui()
|
||||
self._init_signals()
|
||||
|
||||
if os.getenv('APPIMAGE') is not None:
|
||||
if Updater.get_update_information(os.getenv('APPIMAGE'))[0]:
|
||||
self.fit_timer = QtCore.QTimer()
|
||||
self.fit_timer.setInterval(500)
|
||||
self.fit_timer.timeout.connect(
|
||||
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):
|
||||
@ -84,14 +104,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.norm_toolbutton.setIcon(get_icon('normal'))
|
||||
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:
|
||||
self.tabWidget.removeTab(self.tabWidget.count()-1)
|
||||
|
||||
@ -103,29 +115,32 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
|
||||
self.mousepos = QtWidgets.QLabel('')
|
||||
self.status = QtWidgets.QLabel('')
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
self.statusBar.addWidget(self.status)
|
||||
# noinspection PyUnresolvedReferences
|
||||
self.statusBar.addWidget(self.mousepos)
|
||||
|
||||
self.fitregion = RegionItem()
|
||||
self._fit_plot_id = None
|
||||
|
||||
self.setGeometry(QtWidgets.QStyle.alignedRect(QtCore.Qt.LeftToRight, QtCore.Qt.AlignCenter,
|
||||
self.size(), QtWidgets.qApp.desktop().availableGeometry()))
|
||||
self.fit_toolbar = FitToolbar(self.action_FitWidget, self.menuLimits, self)
|
||||
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.integralwidget.management = self.management
|
||||
self.drawingswidget.graphs = self.management.graphs
|
||||
|
||||
self.ac_group = QtWidgets.QActionGroup(self)
|
||||
self.ac_group.addAction(self.action_lm_fit)
|
||||
self.ac_group.addAction(self.action_nm_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):
|
||||
self.actionRedo = self.management.undostack.createRedoAction(self)
|
||||
icon = QtGui.QIcon.fromTheme("edit-redo")
|
||||
@ -139,20 +154,24 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.actionUndo.setIcon(icon)
|
||||
self.menuData.insertAction(self.actionRedo, self.actionUndo)
|
||||
|
||||
# # self.actionSave.triggered.connect(lambda: self.management.save('/autohome/dominik/nmreval/testdata/test.nmr', ''))
|
||||
# self.actionSave.triggered.connect(self.save)
|
||||
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.action_edit.triggered.connect(lambda: self._show_tab('signal'))
|
||||
self.action_edit.triggered.connect(self.do_preview)
|
||||
self.actionPick_position.triggered.connect(lambda: self._show_tab('pick'))
|
||||
self.actionIntegration.triggered.connect(lambda: self._show_tab('integrate'))
|
||||
self.action_FitWidget.triggered.connect(lambda: self._show_tab('fit'))
|
||||
self.action_draw_object.triggered.connect(lambda: self._show_tab('drawing'))
|
||||
|
||||
self.action_new_set.triggered.connect(self.management.create_empty)
|
||||
|
||||
self.actionDelete_window.triggered.connect(self.management.delete_sets)
|
||||
self.actionCascade_windows.triggered.connect(self.area.cascadeSubWindows)
|
||||
self.actionTile.triggered.connect(self.area.tileSubWindows)
|
||||
self.actionTileHorizontal.triggered.connect(self.area.tileSubWindowsHorizontally)
|
||||
self.actionTileVertical.triggered.connect(self.area.tileSubWindowsVertically)
|
||||
|
||||
self.datawidget.keyChanged.connect(self.management.change_keys)
|
||||
self.datawidget.tree.deleteItem.connect(self.management.delete_sets)
|
||||
self.datawidget.tree.moveItem.connect(self.management.move_sets)
|
||||
@ -166,7 +185,8 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.datawidget.tree.saveFits.connect(self.save_fit_parameter)
|
||||
self.datawidget.tree.extendFits.connect(self.extend_fit)
|
||||
|
||||
self.management.newData.connect(self.show_new_data)
|
||||
self.management.newData[list, str].connect(self.show_new_data)
|
||||
self.management.newData[list, str, bool].connect(self.show_new_data)
|
||||
self.management.newGraph.connect(self.new_graph)
|
||||
self.management.dataChanged.connect(self.update_data)
|
||||
self.management.deleteData.connect(self.delete_data)
|
||||
@ -176,10 +196,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.management.unset_state.connect(lambda x: self.datawidget.uncheck_sets(x))
|
||||
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.preview_emit.connect(self.show_fit_preview)
|
||||
self.fit_dialog.fitStartSig.connect(self.start_fit)
|
||||
self.fit_dialog.abortFit.connect(lambda : self.management.stopFit.emit())
|
||||
self.fit_dialog.abortFit.connect(lambda: self.management.stopFit.emit())
|
||||
|
||||
self.movedialog.moveData.connect(self.move_sets)
|
||||
self.movedialog.copyData.connect(self.management.copy_sets)
|
||||
@ -189,7 +211,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.t1tauwidget.newData.connect(self.management.add_new_data)
|
||||
|
||||
self.editsignalwidget.do_something.connect(self.management.apply)
|
||||
self.editsignalwidget.preview_triggered.connect(self.do_preview)
|
||||
# self.editsignalwidget.preview_triggered.connect(self.do_preview)
|
||||
|
||||
self.action_sort_pts.triggered.connect(lambda: self.management.apply('sort', ()))
|
||||
self.action_calc_eps_derivative.triggered.connect(self.management.bds_deriv)
|
||||
@ -208,16 +230,17 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.actionNext_window.triggered.connect(lambda: self.area.activateNextSubWindow())
|
||||
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_abs.triggered.connect(lambda: self.management.apply('norm', ('maxabs',)))
|
||||
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_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())
|
||||
|
||||
self.management.graphs.valueChanged.connect(self.update_graph_list)
|
||||
|
||||
@QtCore.pyqtSlot(name='on_action_open_triggered')
|
||||
def open(self):
|
||||
@ -232,8 +255,11 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
|
||||
filedialog.set_graphs(self.management.graphs.list())
|
||||
|
||||
filedialog.exec()
|
||||
accepted = filedialog.exec()
|
||||
if accepted:
|
||||
fname = filedialog.selectedFiles()
|
||||
else:
|
||||
fname = []
|
||||
|
||||
if fname:
|
||||
self.path = Path(fname[0]).parent
|
||||
@ -241,11 +267,15 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionOpen_FC_triggered')
|
||||
def read_fc(self):
|
||||
reader = QFCReader(path=self.path, parent=self)
|
||||
reader.data_read.connect(self.management.add_new_data)
|
||||
reader.exec()
|
||||
if self.fc_reader is None:
|
||||
self.fc_reader = QFCReader(path=self.path, parent=self)
|
||||
self.fc_reader.data_read.connect(self.management.add_new_data)
|
||||
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')
|
||||
def print(self):
|
||||
@ -262,10 +292,11 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
selected_filter = save_dialog.selectedNameFilter()
|
||||
|
||||
if savefile is not None:
|
||||
self.path = savefile.parent
|
||||
use_underscore = save_dialog.checkBox.isChecked()
|
||||
self.management.save(savefile, selected_filter, strip_spaces=use_underscore)
|
||||
|
||||
param_outfile = re.sub('[_\s-]?<label>[_\s-]?', '', savefile.stem)
|
||||
param_outfile = re.sub(r'[_\s-]?<label>[_\s-]?', '', savefile.stem)
|
||||
|
||||
bad_character = r'/*<>\|:"'
|
||||
for c in bad_character:
|
||||
@ -307,10 +338,15 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
return w.id
|
||||
|
||||
@QtCore.pyqtSlot(list, str)
|
||||
def show_new_data(self, sets: list, graph: str):
|
||||
@QtCore.pyqtSlot(list, str, bool)
|
||||
def show_new_data(self, sets: list, graph: str, skip_change: bool = False):
|
||||
if len(sets) == 0:
|
||||
return
|
||||
|
||||
prev_graph = ''
|
||||
if skip_change:
|
||||
prev_graph = self.management.current_graph
|
||||
|
||||
if graph == '':
|
||||
graph = self.new_graph()
|
||||
|
||||
@ -319,39 +355,47 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
for idd in sets:
|
||||
new_item = self.management[idd]
|
||||
self.datawidget.blockSignals(True)
|
||||
self.datawidget.add_item(new_item.id, new_item.name, graph)
|
||||
self.datawidget.add_item(new_item.id, new_item.name, new_item.value, graph, update=False)
|
||||
self.datawidget.blockSignals(False)
|
||||
self.datawidget.tree.update_indexes()
|
||||
|
||||
if graph == self.fit_dialog.connected_figure:
|
||||
self.fit_dialog.load(self.management.graphs.active(graph))
|
||||
# if graph == self.fit_dialog.connected_figure:
|
||||
# self.fit_dialog.load(self.management.graphs.active(graph))
|
||||
if skip_change:
|
||||
self.area.setActiveSubWidget(prev_graph)
|
||||
|
||||
if self.valuewidget.isVisible():
|
||||
self.valuewidget(self.management.graphs.tree())
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionDelete_window_triggered')
|
||||
def delete_windows(self):
|
||||
self.management.delete_sets()
|
||||
|
||||
@QtCore.pyqtSlot(str)
|
||||
def remove_graph(self, gid: str):
|
||||
self.datawidget.remove_item(gid)
|
||||
self.datawidget.remove_item([gid])
|
||||
val_figure = self.valuewidget.connected_figure
|
||||
self.valuewidget.remove_graph()
|
||||
|
||||
_remove_pts = False
|
||||
_remove_t1 = False
|
||||
_move_to_data_tab = False
|
||||
|
||||
w = None
|
||||
for w in self.area.subWindowList():
|
||||
wdgt = w.widget()
|
||||
if wdgt.id == gid:
|
||||
wdgt.disconnect()
|
||||
wdgt.scene.disconnect()
|
||||
|
||||
if wdgt == self.current_graph_widget:
|
||||
if self.ptsselectwidget.connected_figure == gid:
|
||||
self.ptsselectwidget.connected_figure = None
|
||||
self.tabWidget.removeTab(self.tabWidget.indexOf(self.ptsselectwidget))
|
||||
for line in self.ptsselectwidget.pts_lines:
|
||||
self.current_graph_widget.remove_external(line)
|
||||
_remove_pts = True
|
||||
|
||||
if self.t1tauwidget.connected_figure == gid:
|
||||
self.t1tauwidget.connected_figure = None
|
||||
self.tabWidget.removeTab(self.tabWidget.indexOf(self.t1tauwidget))
|
||||
self.current_graph_widget.remove_external(self.t1tauwidget.min_pos)
|
||||
self.current_graph_widget.remove_external(self.t1tauwidget.parabola)
|
||||
_remove_t1 = True
|
||||
|
||||
if self.fit_dialog.connected_figure == gid:
|
||||
self.fit_dialog.connected_figure = None
|
||||
@ -359,12 +403,15 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.current_graph_widget.remove_external(item)
|
||||
|
||||
if val_figure == gid:
|
||||
self.tabWidget.setCurrentIndex(0)
|
||||
self.valuewidget.connected_figure = None
|
||||
self.current_graph_widget.remove_external(self.valuewidget.selection_real)
|
||||
self.current_graph_widget.remove_external(self.valuewidget.selection_imag)
|
||||
_move_to_data_tab = True
|
||||
|
||||
self.current_graph_widget.enable_picking(False)
|
||||
|
||||
self.current_graph_widget = None
|
||||
self.management.current_graph = ''
|
||||
self.management.current_graph = None
|
||||
self.current_plotitem = None
|
||||
|
||||
wdgt.setParent(None)
|
||||
@ -375,6 +422,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
|
||||
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:
|
||||
self.area.removeSubWindow(w)
|
||||
@ -388,6 +441,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
if self.area.subWindowList():
|
||||
self.area.activateNextSubWindow()
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def update_graph_list(self):
|
||||
graph_list = self.management.graphs.list()
|
||||
self.t1tauwidget.set_graphs(graph_list)
|
||||
self.ptsselectwidget.set_graphs(graph_list)
|
||||
|
||||
@QtCore.pyqtSlot(str)
|
||||
def set_graph(self, key: str):
|
||||
w = self.management.graphs[key]
|
||||
@ -405,8 +464,9 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.datawidget.blockSignals(False)
|
||||
|
||||
w.mousePositionChanged.connect(self.mousemoved)
|
||||
w.aboutToClose.connect(self.delete_windows)
|
||||
w.aboutToClose.connect(self.management.delete_sets)
|
||||
w.positionClicked.connect(self.point_selected)
|
||||
w.newData.connect(lambda x, y: self.management.load_files(x, new_plot=y))
|
||||
w.show()
|
||||
|
||||
graph_list = self.management.graphs.list()
|
||||
@ -416,7 +476,9 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
@QtCore.pyqtSlot(QtWidgets.QMdiSubWindow, name='on_area_subWindowActivated')
|
||||
def change_window(self, wd):
|
||||
""" Called every time focus moves from or to a subwindow. Returns None if current focus is not on a subwindow"""
|
||||
if wd is not None:
|
||||
if wd is None:
|
||||
return
|
||||
|
||||
if self.current_graph_widget is not None:
|
||||
self.current_graph_widget.closable = True
|
||||
|
||||
@ -445,14 +507,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.datawidget.tree.highlight(self.management.current_graph)
|
||||
self.datawidget.tree.blockSignals(False)
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionCascade_windows_triggered')
|
||||
@QtCore.pyqtSlot(name='on_actionTile_triggered')
|
||||
def change_window_size(self):
|
||||
if self.sender() == self.actionCascade_windows:
|
||||
self.area.cascadeSubWindows()
|
||||
elif self.sender() == self.actionTile:
|
||||
self.area.tileSubWindows()
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionChange_datatypes_triggered')
|
||||
def type_change_dialog(self):
|
||||
from ..data.conversion import ConversionDialog
|
||||
@ -475,7 +529,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
'signal': (self.editsignalwidget, 'Signals'),
|
||||
'pick': (self.ptsselectwidget, 'Pick points'),
|
||||
'fit': (self.fit_dialog, 'Fit'),
|
||||
'drawing': (self.drawingswidget, 'Draw'),
|
||||
'integrate': (self.integralwidget, 'Integrate'),
|
||||
}[mode]
|
||||
|
||||
@ -511,7 +564,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self._select_valuewidget(widget == self.valuewidget)
|
||||
pick_required, block_window = self._select_t1tauwidget(widget == self.t1tauwidget, pick_required, block_window)
|
||||
block_window = self._select_fitwidget(widget == self.fit_dialog, block_window)
|
||||
self._select_drawingswidget(widget == self.drawingswidget)
|
||||
pick_required = self._select_integralwidget(widget == self.integralwidget, pick_required, block_window)
|
||||
|
||||
self._set_pick_block(pick_required, block_window)
|
||||
@ -527,10 +579,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.ptsselectwidget.connected_figure = self.management.current_graph
|
||||
pick_required = True
|
||||
else:
|
||||
if self.ptsselectwidget.connected_figure:
|
||||
if self.ptsselectwidget.connected_figure in self.management.graphs:
|
||||
g = self.management.graphs[self.ptsselectwidget.connected_figure]
|
||||
for line in self.ptsselectwidget.pts_lines:
|
||||
g.remove_external(line)
|
||||
else:
|
||||
self.ptsselectwidget.connected_figure = None
|
||||
# self.ptsselectwidget.clear()
|
||||
|
||||
return pick_required, block_window
|
||||
@ -543,9 +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_imag)
|
||||
else:
|
||||
if self.valuewidget.connected_figure is not None:
|
||||
self.management.graphs[self.valuewidget.connected_figure].remove_external(self.valuewidget.selection_real)
|
||||
self.management.graphs[self.valuewidget.connected_figure].remove_external(self.valuewidget.selection_imag)
|
||||
if self.valuewidget.connected_figure in self.management.graphs:
|
||||
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_imag)
|
||||
else:
|
||||
self.valuewidget.connected_figure = None
|
||||
|
||||
def _select_integralwidget(self, onoff: bool, pick_required: bool, block_window: bool) -> tuple[bool, bool]:
|
||||
if self.current_graph_widget is None:
|
||||
@ -559,11 +616,13 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
pick_required = True
|
||||
block_window = True
|
||||
else:
|
||||
if self.integralwidget.connected_figure:
|
||||
if self.integralwidget.connected_figure in self.management.graphs:
|
||||
g = self.management.graphs[self.integralwidget.connected_figure]
|
||||
for line in self.integralwidget.lines:
|
||||
g.remove_external(line[0])
|
||||
g.remove_external(line[1])
|
||||
else:
|
||||
self.integralwidget.connected_figure = None
|
||||
self.integralwidget.clear()
|
||||
|
||||
return pick_required, block_window
|
||||
@ -592,23 +651,18 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
pick_required = True
|
||||
block_window = True
|
||||
else:
|
||||
if self.t1tauwidget.connected_figure:
|
||||
if self.t1tauwidget.connected_figure in self.management.graphs:
|
||||
g = self.management.graphs[self.t1tauwidget.connected_figure]
|
||||
g.remove_external(self.t1tauwidget.min_pos)
|
||||
g.remove_external(self.t1tauwidget.parabola)
|
||||
else:
|
||||
self.t1tauwidget.connected_figure = None
|
||||
|
||||
return pick_required, block_window
|
||||
|
||||
def _select_drawingswidget(self, onoff):
|
||||
if onoff:
|
||||
if self.drawingswidget.graphs is None:
|
||||
self.drawingswidget.graphs = self.management.graphs
|
||||
self.drawingswidget.update_tree()
|
||||
else:
|
||||
self.drawingswidget.clear()
|
||||
|
||||
@QtCore.pyqtSlot(str)
|
||||
def get_data(self, key: str):
|
||||
if hasattr(self.sender(), 'set_data'):
|
||||
self.sender().set_data(self.management[key])
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionCalculateT1_triggered')
|
||||
@ -623,8 +677,9 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
from ..math.skipping import QSkipDialog
|
||||
|
||||
dial = QSkipDialog(self)
|
||||
dial.exec()
|
||||
res = dial.exec()
|
||||
|
||||
if res:
|
||||
self.management.skip_points(**dial.get_arguments())
|
||||
|
||||
@QtCore.pyqtSlot(name='on_action_coup_calc_triggered')
|
||||
@ -651,10 +706,13 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
return
|
||||
|
||||
gnames = self.management.graphs.tree()
|
||||
dialog = InterpolDialog(parent=self)
|
||||
dialog.set_data(gnames, self.current_graph_widget.id)
|
||||
dialog.new_data.connect(self.management.interpolate_data)
|
||||
dialog.show()
|
||||
if self._interpol_dialog is None:
|
||||
self._interpol_dialog = InterpolDialog(parent=self)
|
||||
self._interpol_dialog.new_data.connect(self.management.interpolate_data)
|
||||
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')
|
||||
def open_eval_dialog(self):
|
||||
@ -683,6 +741,14 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
|
||||
self.eval.exec()
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionBinning_triggered')
|
||||
def open_binning(self):
|
||||
dialog = BinningWindow(self)
|
||||
res = dialog.exec()
|
||||
if res:
|
||||
digits = float(dialog.spinbox.text())
|
||||
self.management.binning(digits)
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionDerivation_triggered')
|
||||
# @QtCore.pyqtSlot(name='on_actionIntegration_triggered')
|
||||
@QtCore.pyqtSlot(name='on_actionFilon_triggered')
|
||||
@ -719,9 +785,10 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
|
||||
self.datawidget.set_name(sid, self.management[sid].name)
|
||||
|
||||
@QtCore.pyqtSlot(str)
|
||||
def delete_data(self, sid):
|
||||
if self.valuewidget.shown_set == sid:
|
||||
@QtCore.pyqtSlot(list)
|
||||
def delete_data(self, sid: list[str]):
|
||||
for key in sid:
|
||||
if self.valuewidget.shown_set == key:
|
||||
self.tabWidget.setCurrentIndex(0)
|
||||
|
||||
self.datawidget.remove_item(sid)
|
||||
@ -744,29 +811,22 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
editor.finished.connect(self.management.apply)
|
||||
editor.exec()
|
||||
|
||||
@QtCore.pyqtSlot(str)
|
||||
def do_preview(self, mode):
|
||||
@QtCore.pyqtSlot()
|
||||
def do_preview(self):
|
||||
dialog = QPreviewDialog(self)
|
||||
|
||||
if mode == 'ap':
|
||||
dialog = QApodDialog(parent=self)
|
||||
elif mode == 'ph':
|
||||
dialog = QPhasedialog(parent=self)
|
||||
else:
|
||||
raise ValueError('Unknown preview mode %s' % str(mode))
|
||||
|
||||
dialog.setRange(*self.current_graph_widget.ranges, self.current_graph_widget.log)
|
||||
success = True
|
||||
|
||||
for sid in self.current_graph_widget.active:
|
||||
data_mode = self.management[sid].mode
|
||||
tobeadded = False
|
||||
if (data_mode == 'fid') or (data_mode == 'spectrum' and mode == 'ph'):
|
||||
tobeadded = True
|
||||
if data_mode in ('fid', 'spectrum'):
|
||||
success = dialog.add_data(self.management[sid].data)
|
||||
|
||||
if tobeadded:
|
||||
dialog.add_data(*self.management.get_data(sid, xy_only=True))
|
||||
if not success:
|
||||
break
|
||||
|
||||
if dialog.exec() == QtWidgets.QDialog.Accepted:
|
||||
self.management.apply(mode, dialog.get_value())
|
||||
if success and dialog.exec() == QtWidgets.QDialog.Accepted:
|
||||
self.management.edit_signals(dialog.get_value())
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionMove_between_plots_triggered')
|
||||
def move_sets_dialog(self):
|
||||
@ -803,10 +863,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
def item_from_graph(self, item, graph_id):
|
||||
self.management.graphs[graph_id].remove_external(item)
|
||||
|
||||
def closeEvent(self, evt):
|
||||
# self._write_settings()
|
||||
self.close()
|
||||
|
||||
@QtCore.pyqtSlot(int)
|
||||
def request_data(self, idx):
|
||||
idd = self.datawidget.get_indexes(idx=idx-1)
|
||||
@ -817,6 +873,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
except KeyError:
|
||||
ret_val = None
|
||||
|
||||
# noinspection PyUnresolvedReferences
|
||||
self.sender().receive_data(ret_val)
|
||||
|
||||
return ret_val
|
||||
@ -845,30 +902,29 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.fit_dialog.load(self.management.active_sets)
|
||||
for item in self.fit_dialog.preview_lines:
|
||||
self.current_graph_widget.add_external(item)
|
||||
if self.action_custom_range.isChecked():
|
||||
self.current_graph_widget.add_external(self.fitregion)
|
||||
if self.action_custom_range.isChecked() or self.actionExclude_region.isChecked():
|
||||
self.current_graph_widget.add_external(self.fit_toolbar.region)
|
||||
|
||||
block_window = True
|
||||
else:
|
||||
for item in self.fit_dialog.preview_lines:
|
||||
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
|
||||
|
||||
@QtCore.pyqtSlot(QtWidgets.QAction)
|
||||
def change_fit_limits(self, action: QtWidgets.QAction):
|
||||
if action == self.action_custom_range and self.fit_dialog.isVisible():
|
||||
self.current_graph_widget.add_external(self.fitregion)
|
||||
if self.current_graph_widget is None:
|
||||
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:
|
||||
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):
|
||||
fit_options['limits'] = {
|
||||
self.action_no_range: 'none',
|
||||
self.action_x_range: 'x',
|
||||
self.action_custom_range: self.fitregion.getRegion()
|
||||
}[self.ac_group2.checkedAction()]
|
||||
fit_options['limits'] = self.fit_toolbar.get_limit()
|
||||
|
||||
fit_options['fit_mode'] = {
|
||||
self.action_lm_fit: 'lsq',
|
||||
@ -876,12 +932,18 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
self.action_odr_fit: 'odr'
|
||||
}[self.ac_group.checkedAction()]
|
||||
|
||||
fit_is_ready = self.management.prepare_fit(parameter, links, fit_options)
|
||||
if fit_is_ready:
|
||||
self.management.start_fit()
|
||||
self.fit_dialog.fit_button.setEnabled(False)
|
||||
self.management.start_fit(parameter, links, fit_options)
|
||||
self.status.setText('Fit running...'.format(self.management.fitter.step))
|
||||
self.fit_timer.start(500)
|
||||
|
||||
@QtCore.pyqtSlot(dict, int, bool)
|
||||
def show_fit_preview(self, funcs: dict, num: int, show: bool):
|
||||
if self.fit_dialog.connected_figure is None:
|
||||
if not self.fit_dialog.connected_figure:
|
||||
logger.warning(f'Fit dialog is not connected graph: Fit {self.fit_dialog.connected_figure}, '
|
||||
f'current graph: {self.management.current_graph} ({self.management.current_graph in self.management.graphs})')
|
||||
return
|
||||
|
||||
g = self.management.graphs[self.fit_dialog.connected_figure]
|
||||
@ -898,40 +960,59 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
for item in self.fit_dialog.preview_lines:
|
||||
g.add_external(item)
|
||||
|
||||
@QtCore.pyqtSlot(list)
|
||||
def show_fit_results(self, results: list):
|
||||
@QtCore.pyqtSlot(list, dict)
|
||||
def show_fit_results(self, results: list, sub_colors: dict[str, tuple[float, float, float]]):
|
||||
self.fit_dialog.fit_button.setEnabled(True)
|
||||
self.fit_timer.stop()
|
||||
self.status.setText('')
|
||||
if results:
|
||||
res_dialog = QFitResult(results, self.management, parent=self)
|
||||
res_dialog.add_graphs(self.management.graphs.list())
|
||||
res_dialog.closed.connect(self.accepts_fit)
|
||||
res_dialog.redoFit.connect(self.management.redo_fits)
|
||||
res_dialog.show()
|
||||
if self.fitresult_dialog is None:
|
||||
self.fitresult_dialog = QFitResult(results, sub_colors, self.management, parent=self)
|
||||
self.fitresult_dialog.add_graphs(self.management.graphs.list())
|
||||
self.fitresult_dialog.closed.connect(self.accepts_fit)
|
||||
self.fitresult_dialog.redoFit.connect(self.management.redo_fits)
|
||||
else:
|
||||
self.fitresult_dialog(results, sub_colors)
|
||||
self.fitresult_dialog.add_graphs(self.management.graphs.list())
|
||||
self.fitresult_dialog.show()
|
||||
|
||||
@QtCore.pyqtSlot(dict, list, str, bool, bool, list)
|
||||
def accepts_fit(self, res: dict, opts: list, param_graph: str, show_fit: bool, parts: bool, extrapolate: list) -> None:
|
||||
def accepts_fit(self, res: dict, opts: list, param_graph: str,
|
||||
show_fit: bool, parts: bool, extrapolate: list) -> None:
|
||||
self.fit_dialog.set_parameter(res)
|
||||
self.management.make_fits(res, opts, param_graph, show_fit, parts, extrapolate)
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionFunction_editor_triggered')
|
||||
def edit_models(self):
|
||||
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.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()
|
||||
|
||||
@QtCore.pyqtSlot(list)
|
||||
def extend_fit(self, sets: list):
|
||||
@QtCore.pyqtSlot(name='on_actionUse_script_triggered')
|
||||
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)
|
||||
res = w.exec()
|
||||
print(res)
|
||||
if res:
|
||||
p = w.values
|
||||
x = linspace(p[0], p[1], num=p[2])
|
||||
self.management.extend_fits(sets, x)
|
||||
spacefunc = geomspace if p[3] else linspace
|
||||
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')
|
||||
def open_fitmodel_wizard(self):
|
||||
@ -955,9 +1036,10 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
@staticmethod
|
||||
@QtCore.pyqtSlot(name='on_actionDocumentation_triggered')
|
||||
def open_doc():
|
||||
docpath = '/autohome/dominik/auswerteprogramm3/doc/_build/html/index.html'
|
||||
import webbrowser
|
||||
webbrowser.open(docpath)
|
||||
pass
|
||||
# docpath = '/autohome/dominik/auswerteprogramm3/doc/_build/html/index.html'
|
||||
# import webbrowser
|
||||
# webbrowser.open(docpath)
|
||||
|
||||
def dropEvent(self, evt):
|
||||
if evt.mimeData().hasUrls():
|
||||
@ -986,13 +1068,13 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
if self.sender() == self.actionLife:
|
||||
from ..lib.gol import QGameOfLife
|
||||
game = QGameOfLife(parent=self)
|
||||
game.setWindowModality(QtCore.Qt.NonModal)
|
||||
game.setWindowModality(QtCore.Qt.WindowModality.NonModal)
|
||||
game.show()
|
||||
|
||||
elif self.sender() == self.actionMine:
|
||||
from ..lib.stuff import QMines
|
||||
game = QMines(parent=self)
|
||||
game.setWindowModality(QtCore.Qt.NonModal)
|
||||
game.setWindowModality(QtCore.Qt.WindowModality.NonModal)
|
||||
game.show()
|
||||
|
||||
else:
|
||||
@ -1043,3 +1125,32 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
|
||||
|
||||
QLog(parent=self).show()
|
||||
|
||||
def autosave(self) -> bool:
|
||||
self.status.setText('Autosave...')
|
||||
success = NMRWriter(self.management.graphs, self.management.data).export(self.__backup_path.with_suffix('.nmr.0'))
|
||||
|
||||
if success:
|
||||
self.__backup_path.with_suffix('.nmr.0').rename(self.__backup_path)
|
||||
|
||||
self.status.setText('')
|
||||
|
||||
return success
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionCreate_starter_triggered')
|
||||
def create_starter(self):
|
||||
make_starter(os.getenv('APPIMAGE'))
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionAbout_triggered')
|
||||
def show_version(self):
|
||||
from nmreval.version import __version__
|
||||
QtWidgets.QMessageBox.about(self, 'Version', f'Build date of AppImage: {__version__}')
|
||||
|
||||
@QtCore.pyqtSlot(name='on_actionTNMH_model_triggered')
|
||||
@QtCore.pyqtSlot(name='on_actionTNMH_triggered')
|
||||
def show_tg_dialog(self):
|
||||
if self._tg_dialog is None:
|
||||
self._tg_dialog = TgCalculator(self.management, parent=self)
|
||||
self._tg_dialog.newData.connect(self.management.addTg)
|
||||
else:
|
||||
self._tg_dialog()
|
||||
self._tg_dialog.show()
|
||||
|
@ -18,6 +18,7 @@ from nmreval.math.smooth import smooth
|
||||
from nmreval.nmr.relaxation import Relaxation
|
||||
|
||||
from ..Qt import QtCore, QtWidgets
|
||||
from ..lib import Relations
|
||||
from ..lib.undos import *
|
||||
from ..data.container import *
|
||||
from ..io.filereaders import QFileReader
|
||||
@ -57,11 +58,18 @@ class GraphDict(OrderedDict):
|
||||
def list(self):
|
||||
return [(k, v.title) for k, v in self.items()]
|
||||
|
||||
def active(self, key: str):
|
||||
if key:
|
||||
return [(self._data[i].id, self._data[i].name) for i in self[key]]
|
||||
else:
|
||||
def active(self, key: str, return_val: str = 'both'):
|
||||
if not key:
|
||||
return []
|
||||
else:
|
||||
if return_val == 'both':
|
||||
return [(self._data[i].id, self._data[i].name) for i in self[key]]
|
||||
elif return_val == 'id':
|
||||
return [self._data[i].id for i in self[key]]
|
||||
elif return_val == 'name':
|
||||
return [self._data[i].name for i in self[key]]
|
||||
else:
|
||||
raise ValueError(f'return_val got wrong value {return_val!r}')
|
||||
|
||||
def current_sets(self, key: str):
|
||||
if key:
|
||||
@ -74,10 +82,10 @@ class UpperManagement(QtCore.QObject):
|
||||
newGraph = QtCore.pyqtSignal()
|
||||
restoreGraph = QtCore.pyqtSignal(str)
|
||||
deleteGraph = QtCore.pyqtSignal(str)
|
||||
newData = QtCore.pyqtSignal(list, str)
|
||||
deleteData = QtCore.pyqtSignal(str)
|
||||
newData = QtCore.pyqtSignal([list, str], [list, str, bool])
|
||||
deleteData = QtCore.pyqtSignal(list)
|
||||
dataChanged = QtCore.pyqtSignal(str)
|
||||
fitFinished = QtCore.pyqtSignal(list)
|
||||
fitFinished = QtCore.pyqtSignal(list, dict)
|
||||
stopFit = QtCore.pyqtSignal()
|
||||
properties_collected = QtCore.pyqtSignal(dict)
|
||||
unset_state = QtCore.pyqtSignal(list)
|
||||
@ -110,7 +118,7 @@ class UpperManagement(QtCore.QObject):
|
||||
self.counter = 0
|
||||
self.data = OrderedDict()
|
||||
self.window = window
|
||||
self.current_graph = ''
|
||||
self.current_graph = None
|
||||
self.graphs = GraphDict(self.data)
|
||||
self.namespace = None
|
||||
self.undostack = QtWidgets.QUndoStack()
|
||||
@ -147,6 +155,10 @@ class UpperManagement(QtCore.QObject):
|
||||
def active_sets(self):
|
||||
return self.graphs.active(self.current_graph)
|
||||
|
||||
@property
|
||||
def active_id(self):
|
||||
return self.graphs.active(self.current_graph, return_val='id')
|
||||
|
||||
def get_attributes(self, graph_id: str, attr: str) -> dict[str, Any]:
|
||||
return {self.data[i].id: getattr(self.data[i], attr) for i in self.graphs[graph_id].sets}
|
||||
|
||||
@ -180,7 +192,10 @@ class UpperManagement(QtCore.QObject):
|
||||
graph.active = active
|
||||
graph.listWidget.blockSignals(True)
|
||||
for i, l in enumerate(g['in_legend']):
|
||||
graph.listWidget.item(i).setCheckState(l)
|
||||
try:
|
||||
graph.listWidget.item(i).setCheckState(QtCore.Qt.Checked if l else QtCore.Qt.Unchecked)
|
||||
except AttributeError:
|
||||
pass
|
||||
graph.listWidget.blockSignals(False)
|
||||
|
||||
# set unchecked in tree and hide/show in plot
|
||||
@ -231,9 +246,17 @@ class UpperManagement(QtCore.QObject):
|
||||
for k in plotkeys:
|
||||
self.data[k].graph = gid
|
||||
|
||||
@QtCore.pyqtSlot(str)
|
||||
def plot_from_graph(self, key: str):
|
||||
self.graphs[self.data[key].graph].remove(key)
|
||||
@QtCore.pyqtSlot(list)
|
||||
def plot_from_graph(self, key: list[str]):
|
||||
sort_graph = {}
|
||||
for sid in key:
|
||||
v = self.data[sid].graph
|
||||
if v not in sort_graph:
|
||||
sort_graph[v] = []
|
||||
sort_graph[v].append(sid)
|
||||
|
||||
for gid, sets in sort_graph.items():
|
||||
self.graphs[gid].remove(sets)
|
||||
|
||||
@QtCore.pyqtSlot(list, str, str)
|
||||
def move_sets(self, sets: list, dest: str, src: (str|list), pos: int = -1):
|
||||
@ -256,13 +279,16 @@ class UpperManagement(QtCore.QObject):
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
@QtCore.pyqtSlot(list, str)
|
||||
def copy_sets(self, sets: list = None, src: str = None):
|
||||
if sets is None:
|
||||
sets = self.graphs[self.current_graph].active[:]
|
||||
|
||||
def copy_sets(self, sets: list = None, src: str = None, dest: str = None):
|
||||
if src is None:
|
||||
src = self.current_graph
|
||||
|
||||
if sets is None:
|
||||
sets = self.graphs[src].active[:]
|
||||
|
||||
if dest is None:
|
||||
dest = src
|
||||
|
||||
new_ids = []
|
||||
for s in sets:
|
||||
copy_of_s = self.data[s].copy(full=True)
|
||||
@ -270,12 +296,26 @@ class UpperManagement(QtCore.QObject):
|
||||
new_ids.append(copy_of_s.id)
|
||||
self.data[copy_of_s.id] = copy_of_s
|
||||
|
||||
self.newData.emit(new_ids, src)
|
||||
self.newData.emit(new_ids, dest)
|
||||
|
||||
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(str)
|
||||
@QtCore.pyqtSlot()
|
||||
def delete_sets(self, rm_sets: list = None):
|
||||
rm_graphs = []
|
||||
|
||||
@ -284,12 +324,29 @@ class UpperManagement(QtCore.QObject):
|
||||
|
||||
self.undostack.beginMacro('Delete')
|
||||
|
||||
rm_set_by_graph = {}
|
||||
|
||||
for k in rm_sets[::-1]:
|
||||
if k in self.data:
|
||||
cmd = DeleteCommand(self.data, k, self.newData, self.deleteData)
|
||||
self.undostack.push(cmd)
|
||||
else:
|
||||
parent_graph = self.data[k].graph
|
||||
if parent_graph not in rm_set_by_graph:
|
||||
rm_set_by_graph[parent_graph] = set()
|
||||
|
||||
rm_set_by_graph[parent_graph].add(k)
|
||||
|
||||
elif k in self.graphs:
|
||||
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:
|
||||
logger.warning(f'delete_sets: {k} is not in data or graph found')
|
||||
|
||||
for gid, sid_list in rm_set_by_graph.items():
|
||||
cmd = DeleteCommand(self.data, list(sid_list), self.graphs, gid, self.newData, self.deleteData)
|
||||
self.undostack.push(cmd)
|
||||
|
||||
for k in rm_graphs:
|
||||
cmd = DeleteGraphCommand(self.graphs, k, self.restoreGraph, self.deleteGraph)
|
||||
@ -306,6 +363,7 @@ class UpperManagement(QtCore.QObject):
|
||||
group_set = set()
|
||||
name_set = set()
|
||||
value_set = set()
|
||||
graph_set = set()
|
||||
|
||||
if src_sets is None:
|
||||
if self.current_graph:
|
||||
@ -318,11 +376,12 @@ class UpperManagement(QtCore.QObject):
|
||||
if joined is None:
|
||||
joined = data_i.copy()
|
||||
else:
|
||||
joined.append(data_i.x, data_i.y, data_i.y_err)
|
||||
joined.append(data_i.data.x, data_i.data.y, y_err=data_i.data.y_err, mask=data_i.data.mask)
|
||||
|
||||
name_set.add(data_i.name)
|
||||
group_set.add(data_i.group)
|
||||
value_set.add(data_i.value)
|
||||
graph_set.add(data_i.graph)
|
||||
|
||||
if joined is not None:
|
||||
joined.group = '+'.join(group_set)
|
||||
@ -333,7 +392,9 @@ class UpperManagement(QtCore.QObject):
|
||||
else:
|
||||
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):
|
||||
"""
|
||||
@ -348,12 +409,16 @@ class UpperManagement(QtCore.QObject):
|
||||
|
||||
def change_visibility(self, selected: list, deselected: list):
|
||||
"""Change status of list of ids after status change in datawidget"""
|
||||
for item_list, func in [(selected, 'show_item'), (deselected, 'hide_item')]:
|
||||
grouping = {}
|
||||
for s in item_list:
|
||||
g = self.data[s].graph
|
||||
if g not in grouping:
|
||||
grouping[g] = []
|
||||
grouping[g].append(s)
|
||||
|
||||
for s in selected:
|
||||
self.graphs[self.data[s].graph].show_item([s])
|
||||
|
||||
for d in deselected:
|
||||
self.graphs[self.data[d].graph].hide_item([d])
|
||||
for k, v in grouping.items():
|
||||
getattr(self.graphs[k], func)(v)
|
||||
|
||||
@QtCore.pyqtSlot(str, str)
|
||||
def change_keys(self, identifier: str, name: str):
|
||||
@ -363,6 +428,7 @@ class UpperManagement(QtCore.QObject):
|
||||
self.graphs[d.graph].update_legend(identifier, name)
|
||||
elif identifier in self.graphs:
|
||||
self.graphs[identifier].title = name
|
||||
self.graphs.valueChanged.emit()
|
||||
else:
|
||||
raise KeyError('Unknown ID ' + str(identifier))
|
||||
|
||||
@ -377,78 +443,140 @@ class UpperManagement(QtCore.QObject):
|
||||
self.undostack.push(single_undo)
|
||||
self.undostack.endMacro()
|
||||
|
||||
def cut(self):
|
||||
def edit_signals(self: UpperManagement, args: list[tuple]) -> None:
|
||||
self.undostack.beginMacro('Edit signals')
|
||||
for sid in self.graphs[self.current_graph]:
|
||||
single_undo = EditCommand(self.data[sid], *args)
|
||||
self.undostack.push(single_undo)
|
||||
self.undostack.endMacro()
|
||||
|
||||
def cut(self, x: bool = False, y: bool = False) -> None:
|
||||
if self.current_graph:
|
||||
xlim, _ = self.graphs[self.current_graph].ranges
|
||||
self.apply('cut', xlim)
|
||||
xlim, ylim = self.graphs[self.current_graph].ranges
|
||||
|
||||
if x is False:
|
||||
xlim = (None, None)
|
||||
|
||||
if y is False:
|
||||
ylim = (None, None)
|
||||
|
||||
self.apply('cut', (*xlim, *ylim))
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def unmask(self):
|
||||
for d in self.data.values():
|
||||
d.mask = np.ones_like(d.mask, dtype=bool)
|
||||
|
||||
def start_fit(self, parameter: dict, links: list, fit_options: dict):
|
||||
def prepare_fit(self, parameter: dict, links: list, fit_options: dict) -> bool:
|
||||
if self._fit_active:
|
||||
return
|
||||
return False
|
||||
|
||||
self.__fit_options = (parameter, links, fit_options)
|
||||
|
||||
fitter = FitRoutine()
|
||||
self.fitter = FitRoutine()
|
||||
models = {}
|
||||
fit_limits = fit_options['limits']
|
||||
fit_mode = fit_options['fit_mode']
|
||||
we = fit_options['we']
|
||||
we_option = fit_options['we']
|
||||
|
||||
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
|
||||
try:
|
||||
for model_id, model_p in parameter.items():
|
||||
m = Model(model_p['func'])
|
||||
m = model_p['func']
|
||||
models[model_id] = m
|
||||
|
||||
m_complex = model_p['complex']
|
||||
|
||||
for set_id, set_params in model_p['parameter'].items():
|
||||
for set_id in list_ids:
|
||||
if set_id not in model_p['data_parameter']:
|
||||
continue
|
||||
|
||||
try:
|
||||
data_i = self.data[set_id]
|
||||
if we.lower() == 'deltay':
|
||||
except KeyError as e:
|
||||
raise KeyError(f'{set_id} not found') from e
|
||||
|
||||
set_params = model_p['data_parameter'][set_id]
|
||||
|
||||
if we_option.lower() == 'deltay':
|
||||
we = data_i.y_err**2
|
||||
else:
|
||||
we = we_option
|
||||
|
||||
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
|
||||
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
|
||||
data_complex = 2
|
||||
else:
|
||||
# data is real
|
||||
_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
|
||||
|
||||
# options for fit limits 'none', 'x', ('in', custom region), ('out', excluded region)
|
||||
if fit_limits == 'none':
|
||||
inside = slice(None)
|
||||
elif fit_limits == 'x':
|
||||
x_lim, _ = self.graphs[self.current_graph].ranges
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
raise Exception(f'Setting data failed for {data_i.name}') from e
|
||||
|
||||
d.set_model(m)
|
||||
d.set_parameter(set_params[0], var=model_p['var'],
|
||||
lb=model_p['lb'], ub=model_p['ub'],
|
||||
fun_kwargs=set_params[1])
|
||||
try:
|
||||
d.set_parameter(set_params[0], fun_kwargs=set_params[1])
|
||||
except Exception as e:
|
||||
raise Exception('Setting parameter failed') from e
|
||||
|
||||
fitter.add_data(d)
|
||||
|
||||
model_globs = model_p['glob']
|
||||
if model_globs:
|
||||
m.set_global_parameter(**model_p['glob'])
|
||||
self.fitter.add_data(d)
|
||||
|
||||
for links_i in links:
|
||||
fitter.set_link_parameter((models[links_i[0]], links_i[1]),
|
||||
self.fitter.set_link_parameter((models[links_i[0]], links_i[1]),
|
||||
(models[links_i[2]], links_i[3]))
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f'Fit preparation failed with error: {e.args}')
|
||||
QtWidgets.QMessageBox.warning(QtWidgets.QWidget(),
|
||||
'Fit prep failed',
|
||||
f'Fit preparation failed:\n'
|
||||
'Message:\n'
|
||||
f'{e.args}:\n')
|
||||
return False
|
||||
|
||||
def start_fit(self):
|
||||
with busy_cursor():
|
||||
self.fit_worker = FitWorker(fitter, fit_mode)
|
||||
self.fit_worker = FitWorker(self.fitter)
|
||||
self.fit_thread = QtCore.QThread()
|
||||
self.fit_worker.moveToThread(self.fit_thread)
|
||||
|
||||
@ -464,13 +592,25 @@ class UpperManagement(QtCore.QObject):
|
||||
|
||||
@QtCore.pyqtSlot(list, bool)
|
||||
def end_fit(self, result: list, success: bool):
|
||||
print('FIT FINISHED')
|
||||
if success:
|
||||
self.fitFinished.emit(result)
|
||||
logger.info('Successful fit')
|
||||
|
||||
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:
|
||||
QtWidgets.QMessageBox.warning(QtWidgets.QWidget(), 'Fit failed',
|
||||
'Fit kaput with exception: \n' + "\n".join(result[0]))
|
||||
self.fitFinished.emit([])
|
||||
e = result[0]
|
||||
logger.exception(e, exc_info=True)
|
||||
QtWidgets.QMessageBox.warning(
|
||||
QtWidgets.QWidget(),
|
||||
'Fit failed',
|
||||
f'Fit kaput with exception: \n\n{e!r}'
|
||||
)
|
||||
self.fitFinished.emit([], {})
|
||||
|
||||
self._fit_active = False
|
||||
|
||||
@QtCore.pyqtSlot(dict)
|
||||
@ -482,7 +622,8 @@ class UpperManagement(QtCore.QObject):
|
||||
for set_id, set_parameter in parameter.items():
|
||||
new_values = [v.value for v in res[set_id].parameter.values()]
|
||||
parameter[set_id] = (new_values, set_parameter[1])
|
||||
self.start_fit(*self.__fit_options)
|
||||
if self.prepare_fit(*self.__fit_options):
|
||||
self.start_fit()
|
||||
|
||||
def make_fits(self, res: dict, opts: list, param_graph: str, show_fit: bool, parts: bool, extrapolate: list) -> None:
|
||||
"""
|
||||
@ -507,7 +648,7 @@ class UpperManagement(QtCore.QObject):
|
||||
continue
|
||||
|
||||
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()
|
||||
xmax = fit.x.max()
|
||||
@ -558,6 +699,9 @@ class UpperManagement(QtCore.QObject):
|
||||
subfunc.name += data_name
|
||||
sub_f_id = self.add(subfunc, color=col, linestyle=LineStyle.Dashed, symbol=SymbolStyle.No)
|
||||
|
||||
self[sub_f_id].add_relation(Relations.isFitPartOf, f_id)
|
||||
self[f_id].add_relation(Relations.hasFitPart, sub_f_id)
|
||||
|
||||
f_id_list.append(sub_f_id)
|
||||
gid = data_k.graph
|
||||
self.delete_sets(tobedeleted)
|
||||
@ -567,16 +711,20 @@ class UpperManagement(QtCore.QObject):
|
||||
|
||||
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 = {}
|
||||
for sid in set_id:
|
||||
data = self[sid]
|
||||
fit = data.copy(full=True, keep_color=True)
|
||||
fit.data = fit.data.with_new_x(x_range)
|
||||
data = fit = self[sid]
|
||||
|
||||
graph_id = data.graph
|
||||
if graph_id not in graphs:
|
||||
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))
|
||||
|
||||
color_scheme = available_cycles['colorblind']
|
||||
@ -600,11 +748,11 @@ class UpperManagement(QtCore.QObject):
|
||||
if not graph_id:
|
||||
graph_id = ''
|
||||
|
||||
self.newData.emit(p_id_list, graph_id)
|
||||
self.newData[list, str, bool].emit(p_id_list, graph_id, True)
|
||||
|
||||
def save_fit_parameter(self, fname: str | pathlib.Path, fit_sets: list[str] = None):
|
||||
if fit_sets is None:
|
||||
fit_sets = [s for (s, _) in self.active_sets]
|
||||
fit_sets = [s for s in self.active_id]
|
||||
|
||||
for set_id in fit_sets:
|
||||
data = self.data[set_id]
|
||||
@ -626,12 +774,10 @@ class UpperManagement(QtCore.QObject):
|
||||
else:
|
||||
continue
|
||||
|
||||
for key, pvalue in data.parameter.items():
|
||||
name = pvalue.full_name
|
||||
fit_key = key + data.model_name
|
||||
for fit_key, pvalue in data.parameter.items():
|
||||
|
||||
if fit_key not in fit_dict:
|
||||
fit_dict[fit_key] = [[], name]
|
||||
fit_dict[fit_key] = [[], fit_key]
|
||||
|
||||
err = 0 if pvalue.error is None else pvalue.error
|
||||
|
||||
@ -645,14 +791,27 @@ class UpperManagement(QtCore.QObject):
|
||||
_active = self.graphs[self.current_graph].active
|
||||
|
||||
new_datasets = {}
|
||||
groupby = params.pop('groupby')
|
||||
|
||||
for sid in _active:
|
||||
data_i = self.data[sid]
|
||||
pts = data_i.points(params)
|
||||
|
||||
if groupby == 'group':
|
||||
if data_i.group not in new_datasets:
|
||||
new_datasets[data_i.group] = [], []
|
||||
new_x_axis, _temp = new_datasets[data_i.group]
|
||||
|
||||
if pts:
|
||||
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 = []
|
||||
for label, (new_x_axis, _temp) in new_datasets.items():
|
||||
@ -668,7 +827,7 @@ class UpperManagement(QtCore.QObject):
|
||||
key = self.add(Points(x=new_x_axis, y=_temp[:, i, 1], y_err=_temp[:, i, 2], name=label))
|
||||
key_list.append(key)
|
||||
|
||||
self.newData.emit(key_list, gid)
|
||||
self.newData[list, str, bool].emit(key_list, gid, True)
|
||||
|
||||
@QtCore.pyqtSlot(list)
|
||||
def get_properties(self, sid: list) -> dict:
|
||||
@ -733,12 +892,67 @@ class UpperManagement(QtCore.QObject):
|
||||
new_x = self.data[new_axis[0]].x
|
||||
|
||||
new_key = []
|
||||
missed = []
|
||||
for ids in data_ids:
|
||||
try:
|
||||
k = self.add(interpolate(self.data[ids], new_x, xlog=xlog, ylog=ylog, kind=mode, extrapolate=True))
|
||||
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)
|
||||
|
||||
def binning(self, digits: float):
|
||||
_active = self.graphs[self.current_graph].active
|
||||
new_data = []
|
||||
for sid in _active:
|
||||
key = self.add(self.data[sid].binning(digits=digits))
|
||||
new_data.append(key)
|
||||
|
||||
self.newData.emit(new_data, self.current_graph)
|
||||
|
||||
@QtCore.pyqtSlot(dict, str)
|
||||
def addTg(self, dic: dict, dtype: str):
|
||||
graph_id = self.current_graph if dtype == 'tg' else dic.pop('graph')
|
||||
|
||||
set_id_list = []
|
||||
|
||||
if dtype == 'hodge':
|
||||
for v in dic.values():
|
||||
set_id_list.append(self.add(v))
|
||||
|
||||
else:
|
||||
for k, (data, lines) in dic.items():
|
||||
p: ExperimentContainer = self[k]
|
||||
col = p.plot_real.linecolor
|
||||
|
||||
if data is not None:
|
||||
set_id_list.append(self.add(data, color=col))
|
||||
|
||||
if dtype == 'tnmh':
|
||||
if lines is not None:
|
||||
lines = [lines]
|
||||
else:
|
||||
lines = []
|
||||
|
||||
for line in lines:
|
||||
set_id = self.add(line, color=col)
|
||||
self[set_id].setLine(style=LineStyle.Dashed)
|
||||
self[set_id].setSymbol(symbol=SymbolStyle.No)
|
||||
set_id_list.append(set_id)
|
||||
|
||||
self.newData.emit(set_id_list, graph_id)
|
||||
|
||||
@QtCore.pyqtSlot(int, dict)
|
||||
def smooth_data(self, npoints, param_kwargs):
|
||||
_active = self.graphs[self.current_graph].active
|
||||
@ -771,13 +985,10 @@ class UpperManagement(QtCore.QObject):
|
||||
d_k = self.data[k]
|
||||
|
||||
if copy_data is None:
|
||||
d_k.x = d_k.x*v[1][0] + v[0][0]
|
||||
d_k.y = d_k.y*v[1][1] + v[0][1]
|
||||
d_k.shift_scale(v[0], v[1])
|
||||
else:
|
||||
new_data = d_k.copy(full=True)
|
||||
new_data.update({'shift': v[0], 'scale': v[1]})
|
||||
new_data.data.x = new_data.x*v[1][0] + v[0][0]
|
||||
new_data.y = new_data.y*v[1][1] + v[0][1]
|
||||
new_data.shift_scale(v[0], v[1])
|
||||
|
||||
sid = self.add(new_data)
|
||||
sid_list.append(sid)
|
||||
@ -833,7 +1044,7 @@ class UpperManagement(QtCore.QObject):
|
||||
else:
|
||||
data = self.data[sets[0]]
|
||||
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
|
||||
|
||||
new_data = new_type(data.x, np.zeros(data.x.size))
|
||||
@ -867,17 +1078,24 @@ class UpperManagement(QtCore.QObject):
|
||||
|
||||
@QtCore.pyqtSlot(list, list, 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()
|
||||
|
||||
if overwrite:
|
||||
self.undostack.beginMacro('Evaluate expression')
|
||||
|
||||
failures = []
|
||||
for sid in set_ids:
|
||||
for i, g in enumerate(self.graphs.values()):
|
||||
for j, sid in enumerate(g.sets):
|
||||
|
||||
if sid not in set_ids:
|
||||
continue
|
||||
|
||||
data_i = self.data[sid]
|
||||
try:
|
||||
# use a copy of original namespace
|
||||
new_data = data_i.eval_expression(cmds, dict(ns))
|
||||
new_data = data_i.eval_expression(cmds, dict(ns), i=i, j=j)
|
||||
if overwrite:
|
||||
cmd = EvalCommand(self.data, sid, new_data, 'Evaluate expression')
|
||||
self.undostack.push(cmd)
|
||||
@ -886,7 +1104,7 @@ class UpperManagement(QtCore.QObject):
|
||||
self.data[new_id[0]].data = new_data
|
||||
except Exception as e:
|
||||
failures.append((data_i, e))
|
||||
print(str(data_i) + ' failed with Exception: ' + ''.join(e.args))
|
||||
logger.warning(str(data_i) + ' failed with Exception: ' + ''.join(e.args))
|
||||
continue
|
||||
|
||||
if overwrite:
|
||||
@ -894,13 +1112,28 @@ class UpperManagement(QtCore.QObject):
|
||||
|
||||
if failures:
|
||||
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.exec()
|
||||
|
||||
self.sender().success = not failures
|
||||
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)
|
||||
def create_from_function(self, cmds: list, opts: dict):
|
||||
ns = dict(self.namespace.flatten())
|
||||
@ -921,9 +1154,9 @@ class UpperManagement(QtCore.QObject):
|
||||
self.newData.emit([s_id], graph)
|
||||
|
||||
except Exception as err:
|
||||
print('Creation failed with error: ' + ', '.join(err.args))
|
||||
logger.exception('Creation failed with error: ' + ', '.join(err.args))
|
||||
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('Creation failed with error: ' + ', '.join(err.args))
|
||||
err_msg.exec()
|
||||
|
||||
@ -932,7 +1165,7 @@ class UpperManagement(QtCore.QObject):
|
||||
def show_statistics(self, mode):
|
||||
x, y, = [], []
|
||||
|
||||
for i, _ in self.active_sets:
|
||||
for i in self.active_id:
|
||||
_temp = self.data[i]
|
||||
try:
|
||||
x.append(float(_temp.name))
|
||||
@ -943,7 +1176,7 @@ class UpperManagement(QtCore.QObject):
|
||||
@QtCore.pyqtSlot()
|
||||
def calc_magn(self):
|
||||
new_id = []
|
||||
for k, _ in self.active_sets:
|
||||
for k in self.active_id:
|
||||
dataset = self.data[k]
|
||||
if isinstance(dataset, SignalContainer):
|
||||
new_value = dataset.copy(full=True)
|
||||
@ -955,7 +1188,7 @@ class UpperManagement(QtCore.QObject):
|
||||
@QtCore.pyqtSlot()
|
||||
def center(self):
|
||||
new_id = []
|
||||
for k, _ in self.active_sets:
|
||||
for k in self.active_id:
|
||||
new_value = self.data[k].copy(full=True)
|
||||
new_value.x -= new_value.x[np.argmax(new_value.y.real)]
|
||||
new_id.append(self.add(new_value))
|
||||
@ -994,7 +1227,7 @@ class UpperManagement(QtCore.QObject):
|
||||
def bds_deriv(self):
|
||||
new_sets = []
|
||||
|
||||
for (set_id, _) in self.active_sets:
|
||||
for set_id in self.active_id:
|
||||
data_i = self.data[set_id]
|
||||
diff = data_i.data.diff(log=True)
|
||||
new_data = Points(x=diff.x, y=-np.pi/2*diff.y.real)
|
||||
@ -1007,13 +1240,14 @@ class UpperManagement(QtCore.QObject):
|
||||
def logft(self, **kwargs):
|
||||
new_sets = []
|
||||
ft_mode = kwargs['ft_mode']
|
||||
return_f = kwargs['return_f']
|
||||
|
||||
for set_id in kwargs['sets']:
|
||||
data_i = self.data[set_id]
|
||||
if ft_mode in ['cos', 'sin']:
|
||||
new_data = Points(*logft(data_i.x, data_i.y, mode=ft_mode))
|
||||
new_data = Points(*logft(data_i.x, data_i.y, mode=ft_mode, return_f=return_f))
|
||||
else:
|
||||
new_data = Signal(*logft(data_i.x, data_i.y, mode=ft_mode))
|
||||
new_data = Signal(*logft(data_i.x, data_i.y, mode=ft_mode, return_f=return_f))
|
||||
|
||||
new_sets.append(self.add(new_data, color=data_i['color'], symbol=data_i['symbol'], line=data_i['line']))
|
||||
self.data[new_sets[-1]].update(data_i.data.meta)
|
||||
@ -1021,7 +1255,7 @@ class UpperManagement(QtCore.QObject):
|
||||
self.newData.emit(new_sets, kwargs['graph'])
|
||||
|
||||
def skip_points(self, offset: int, step: int, invert: bool = False, copy: bool = False):
|
||||
for k, _ in self.active_sets:
|
||||
for k in self.active_id:
|
||||
src = self.data[k]
|
||||
if invert:
|
||||
mask = np.mod(np.arange(offset, src.x.size+offset), step) != 0
|
||||
@ -1047,9 +1281,11 @@ class UpperManagement(QtCore.QObject):
|
||||
params = opts['pts']
|
||||
if len(params) == 4:
|
||||
if params[3]:
|
||||
_x = x1 = np.geomspace(params[0], params[1], num=params[2])
|
||||
_x = np.geomspace(params[0], params[1], num=params[2])
|
||||
x1 = np.geomspace(params[0], params[1], num=params[2])
|
||||
else:
|
||||
_x = x1 = np.linspace(params[0], params[1], num=params[2])
|
||||
_x = np.linspace(params[0], params[1], num=params[2])
|
||||
x1 = np.linspace(params[0], params[1], num=params[2])
|
||||
|
||||
if opts['axis1'] in ['t', 'invt1000']:
|
||||
t_p = opts['t_param']
|
||||
@ -1068,21 +1304,23 @@ class UpperManagement(QtCore.QObject):
|
||||
_x = x1 = self.data[params[0]].x
|
||||
|
||||
x2 = opts['val2']
|
||||
|
||||
sd = opts['spec_dens']
|
||||
sd_param = [self.data[p].y.real if isinstance(p, str) else p for p in opts['sd_param'][0]]
|
||||
sd.convert(_x, *sd_param, from_=opts['tau_type'], to_='raw')
|
||||
sd_param = list(zip(*[self.data[p].y.real if isinstance(p, str) else [p]*len(_x) for p in opts['sd_param'][0]]))
|
||||
|
||||
relax = Relaxation()
|
||||
relax.set_distribution(sd, parameter=sd_param, keywords=opts['sd_param'][1])
|
||||
relax.set_distribution(sd, keywords=opts['sd_param'][1])
|
||||
|
||||
cp_param = [self.data[p].y.real if isinstance(p, str) else p for p in opts['cp_param'][0]]
|
||||
relax.set_coupling(opts['coup'], parameter=cp_param, keywords=opts['cp_param'][1])
|
||||
cp_param = list(zip(*[self.data[p].y.real if isinstance(p, str) else [p]*len(_x) for p in opts['cp_param'][0]]))
|
||||
# relax.set_coupling(opts['coup'], parameter=cp_param, keywords=opts['cp_param'][1])
|
||||
|
||||
if opts['out'] == 't1':
|
||||
y = relax.t1(x2, _x)
|
||||
else:
|
||||
y = relax.t2(x2, _x)
|
||||
relax_func = relax.t1 if opts['out'] == 't1' else relax.t2
|
||||
y = np.zeros(_x.size)
|
||||
|
||||
for i in range(_x.size):
|
||||
_x_i = sd.convert(_x[i], *sd_param[i], from_=opts['tau_type'], to_='raw')
|
||||
relax.dist_parameter = sd_param[i]
|
||||
relax.set_coupling(opts['coup'], parameter=cp_param[i], keywords=opts['cp_param'][1])
|
||||
y[i] = relax_func(x2, _x_i)
|
||||
|
||||
pts = Points(x1, y, name=sd.name)
|
||||
pts.meta.update(opts)
|
||||
@ -1176,18 +1414,17 @@ class UpperManagement(QtCore.QObject):
|
||||
class FitWorker(QtCore.QObject):
|
||||
finished = QtCore.pyqtSignal(list, bool)
|
||||
|
||||
def __init__(self, fitter, mode):
|
||||
def __init__(self, fitter):
|
||||
super().__init__()
|
||||
|
||||
self.fitter = fitter
|
||||
self.mode = mode
|
||||
|
||||
@QtCore.pyqtSlot()
|
||||
def run(self):
|
||||
try:
|
||||
res = self.fitter.run(mode=self.mode)
|
||||
res = self.fitter.run()
|
||||
success = True
|
||||
except Exception as e:
|
||||
res = [e.args]
|
||||
res = [e]
|
||||
success = False
|
||||
self.finished.emit(res, success)
|
||||
|
21
src/gui_qt/math/binning.py
Normal file
21
src/gui_qt/math/binning.py
Normal file
@ -0,0 +1,21 @@
|
||||
from ..Qt import QtWidgets, QtGui
|
||||
|
||||
|
||||
class BinningWindow(QtWidgets.QDialog):
|
||||
def __init__(self, parent=None):
|
||||
super().__init__(parent=parent)
|
||||
|
||||
layout = QtWidgets.QFormLayout()
|
||||
|
||||
self.label = QtWidgets.QLabel('Digits (negative values position left of decimal point)')
|
||||
self.spinbox = QtWidgets.QLineEdit()
|
||||
self.spinbox.setValidator(QtGui.QDoubleValidator())
|
||||
self.spinbox.setText('1')
|
||||
layout.addRow(self.label, self.spinbox)
|
||||
|
||||
self.dialogbox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel)
|
||||
self.dialogbox.accepted.connect(self.accept)
|
||||
self.dialogbox.rejected.connect(self.reject)
|
||||
layout.addWidget(self.dialogbox)
|
||||
|
||||
self.setLayout(layout)
|
@ -31,14 +31,36 @@ class QEvalDialog(QtWidgets.QDialog, Ui_CalcDialog):
|
||||
self.namespace_widget.set_namespace(self.namespace)
|
||||
|
||||
def add_data(self, data):
|
||||
self.listWidget.clear()
|
||||
# self.listWidget.clear()
|
||||
tmp = []
|
||||
while self.listWidget.count():
|
||||
tmp.append(self.listWidget.takeItem(0))
|
||||
|
||||
for set_id, name in data:
|
||||
# search if set was used before
|
||||
new_one = True
|
||||
for i in range(len(tmp)):
|
||||
w = tmp[i]
|
||||
if w.data(QtCore.Qt.UserRole) == set_id:
|
||||
w.setText(name)
|
||||
self.listWidget.addItem(w)
|
||||
tmp.pop(i)
|
||||
new_one = False
|
||||
break
|
||||
|
||||
# new set, create item
|
||||
if new_one:
|
||||
item = QtWidgets.QListWidgetItem(name)
|
||||
item.setData(QtCore.Qt.UserRole, set_id)
|
||||
item.setFlags(item.flags() ^ QtCore.Qt.ItemIsEditable)
|
||||
item.setCheckState(QtCore.Qt.Checked)
|
||||
self.listWidget.addItem(item)
|
||||
|
||||
while len(tmp):
|
||||
# delete remaining ListWidgetItems
|
||||
w = tmp.pop()
|
||||
del w
|
||||
|
||||
def set_graphs(self, graphs: list):
|
||||
self.graph_comboBox.clear()
|
||||
self.graph_comboBox.addItem('New graph', userData='')
|
||||
|
@ -16,16 +16,19 @@ class QDeriveIntegrate(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.start_lineedit.setValidator(QtGui.QDoubleValidator())
|
||||
self.stop_lineedit.setValidator(QtGui.QDoubleValidator())
|
||||
self.ft_comboBox.hide()
|
||||
self.freq_box.hide()
|
||||
|
||||
elif self.mode == 'd':
|
||||
self.setWindowTitle('Differentiation dialog')
|
||||
self.widget.hide()
|
||||
self.ft_comboBox.hide()
|
||||
self.freq_box.hide()
|
||||
|
||||
elif self.mode == 'l':
|
||||
self.setWindowTitle('Logarithmic FT dialog')
|
||||
self.log_checkbox.hide()
|
||||
self.widget.hide()
|
||||
self.freq_box.show()
|
||||
|
||||
else:
|
||||
raise ValueError(f'Unknown mode {mode}, use "d", "i", or "l".')
|
||||
@ -54,8 +57,10 @@ class QDeriveIntegrate(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.stop_lineedit.setEnabled(full_range != QtCore.Qt.Checked)
|
||||
|
||||
def get_options(self):
|
||||
opts = {'graph': '' if self.newgraph_checkbox.isChecked() else self.graph_combobox.currentData(),
|
||||
'mode': self.mode, 'sets': []}
|
||||
opts = {
|
||||
'graph': '' if self.newgraph_checkbox.isChecked() else self.graph_combobox.currentData(),
|
||||
'mode': self.mode, 'sets': []
|
||||
}
|
||||
|
||||
if self.mode == 'i':
|
||||
start = None
|
||||
@ -75,6 +80,7 @@ class QDeriveIntegrate(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
if self.mode == 'l':
|
||||
opts['ft_mode'] = ['cos', 'sin', 'complex'][self.ft_comboBox.currentIndex()]
|
||||
opts['return_f'] = self.freq_box.isChecked()
|
||||
else:
|
||||
opts['log'] = self.log_checkbox.isChecked()
|
||||
|
||||
|
@ -16,6 +16,12 @@ class InterpolDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.step_lineEdit.setValidator(QtGui.QIntValidator())
|
||||
|
||||
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')
|
||||
def change_x_source(self, idx: int):
|
||||
@ -25,29 +31,41 @@ class InterpolDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
def set_data(self, data, current_gid):
|
||||
self.graph_combobox.blockSignals(True)
|
||||
self._data = {}
|
||||
dest_idx = 0
|
||||
for (gid, graph_name), sets in data.items():
|
||||
self.graph_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:
|
||||
self.make_list(sets)
|
||||
self._data[gid] = sets
|
||||
self.graph_combobox.blockSignals(False)
|
||||
self.change_graph(0)
|
||||
self.change_graph(dest_idx)
|
||||
|
||||
def make_list(self, current_sets):
|
||||
for sid, set_name in current_sets:
|
||||
item = QtWidgets.QListWidgetItem(set_name)
|
||||
item.setData(QtCore.Qt.UserRole, sid)
|
||||
item.setCheckState(QtCore.Qt.Checked)
|
||||
item.setData(QtCore.Qt.ItemDataRole.UserRole, sid)
|
||||
item.setCheckState(QtCore.Qt.CheckState.Checked)
|
||||
self.listWidget.addItem(item)
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_graph_combobox_currentIndexChanged')
|
||||
def change_graph(self, idx: int):
|
||||
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:
|
||||
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)
|
||||
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):
|
||||
xlog = self.xlog_checkBox.isChecked()
|
||||
@ -71,21 +89,35 @@ class InterpolDialog(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
x_src = (start, stop, step, loggy)
|
||||
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 = []
|
||||
for i in range(self.listWidget.count()):
|
||||
item = self.listWidget.item(i)
|
||||
if item.checkState() == QtCore.Qt.Checked:
|
||||
use_data.append(item.data(QtCore.Qt.UserRole))
|
||||
if item.checkState() == QtCore.Qt.CheckState.Checked:
|
||||
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
|
||||
|
||||
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()
|
||||
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')
|
||||
def change_mode(self, idx: int):
|
||||
if idx == 2:
|
||||
if idx == 1:
|
||||
self.widget.show()
|
||||
self.widget_2.hide()
|
||||
elif idx == 3:
|
||||
elif idx == 2:
|
||||
self.widget.show()
|
||||
self.widget_2.show()
|
||||
else:
|
||||
@ -29,12 +29,24 @@ class QSmooth(QtWidgets.QDialog, Ui_SmoothDialog):
|
||||
idx = self.comboBox.currentIndex()
|
||||
|
||||
# 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()
|
||||
|
||||
if idx == 3:
|
||||
# LOESS needs also polynomial degree and number of iterations
|
||||
if idx == 2:
|
||||
para['deg'] = self.polynom_spinBox.value()
|
||||
para['it'] = self.iter_spinBox.value()
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
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.text import convert
|
||||
|
||||
@ -19,7 +19,7 @@ class QRelaxCalc(QtWidgets.QDialog, Ui_Dialog):
|
||||
|
||||
self.graphs = {}
|
||||
|
||||
self.specdens = [ColeCole, ColeDavidson, HavriliakNegami, KWW]
|
||||
self.specdens = [ColeCole, ColeDavidson, HavriliakNegami, KWW, LogGaussian, GGAlpha]
|
||||
self.coupling = [Quadrupolar, HomoDipolar, Czjzek]
|
||||
self.tau_parameter = []
|
||||
|
||||
@ -131,7 +131,7 @@ class QRelaxCalc(QtWidgets.QDialog, Ui_Dialog):
|
||||
self.verticalLayout_3.addWidget(_temp)
|
||||
|
||||
def get_taus(self, dic: dict):
|
||||
dic['tau_type'] = {0: 'raw', 1: 'mean', 2: 'peak', 3: 'logmean'}[self.xtype_combobox.currentIndex()]
|
||||
dic['tau_type'] = {0: 'raw', 1: 'peak', 2: 'mean', 3: 'logmean'}[self.xtype_combobox.currentIndex()]
|
||||
dic['axis1'] = {self.radioButton: 'tau', self.radioButton_2: 'omega',
|
||||
self.radioButton_3: 't', self.radioButton_4: 'invt1000'}[self.buttonGroup.checkedButton()]
|
||||
|
||||
@ -199,3 +199,9 @@ class QRelaxCalc(QtWidgets.QDialog, Ui_Dialog):
|
||||
def accept(self):
|
||||
self.calc_relaxation()
|
||||
super().accept()
|
||||
|
||||
@QtCore.pyqtSlot(QtWidgets.QAbstractButton)
|
||||
def on_buttonBox_clicked(self, button: QtWidgets.QAbstractButton):
|
||||
role = self.buttonBox.buttonRole(button)
|
||||
if role == self.buttonBox.ApplyRole:
|
||||
self.calc_relaxation()
|
||||
|
@ -31,7 +31,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
self.t1calculator = RelaxationEvaluation()
|
||||
|
||||
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:
|
||||
self.specdens_combobox.addItem(i.name)
|
||||
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.minimum = (1, np.inf)
|
||||
self.min_pos = PlotItem(x=np.array([]), y=np.array([]),
|
||||
symbol='+', symbolBrush=mkBrush(color='r'), symbolPen=mkPen(color='r'), symbolSize=14)
|
||||
self.min_pos = PlotItem(
|
||||
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.lineEdit_2.setValidator(QtGui.QDoubleValidator())
|
||||
@ -61,6 +67,8 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
self.freq_combox.currentIndexChanged.connect(lambda x: self.update_model())
|
||||
self.freq_spinbox.valueChanged.connect(lambda x: self.update_model())
|
||||
|
||||
self.checkBox_interpol.setVisible(False)
|
||||
|
||||
self.update_specdens(0)
|
||||
self.update_coupling(0)
|
||||
|
||||
@ -81,10 +89,10 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
right_b = min(np.argmin(y)+3, len(x)-1)
|
||||
|
||||
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_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.t1calculator.set_data(x, y)
|
||||
@ -108,6 +116,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
|
||||
if self.sdmodels[idx].parameter is not None:
|
||||
for name in self.sdmodels[idx].parameter:
|
||||
print(name)
|
||||
_temp = FormWidget(parent=self, name=name, fixable=True)
|
||||
_temp.value = 1
|
||||
_temp.setChecked(True)
|
||||
@ -131,7 +140,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
try:
|
||||
for i, v, in enumerate(values):
|
||||
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)
|
||||
except IndexError:
|
||||
pass
|
||||
@ -217,7 +226,7 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
self.update_model()
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_interpol_combobox_currentIndexChanged')
|
||||
def determine_minimum(self, idx):
|
||||
def determine_minimum(self, idx: int):
|
||||
if idx == 0:
|
||||
self.checkBox_interpol.setChecked(False)
|
||||
self.checkBox_interpol.hide()
|
||||
@ -227,9 +236,10 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
self.checkBox_interpol.show()
|
||||
self.frame.show()
|
||||
try:
|
||||
m, i_func = self.t1calculator.calculate_t1_min(interpolate=idx,
|
||||
trange=(float(self.lineEdit_2.text()),
|
||||
float(self.lineEdit_3.text())))
|
||||
m, i_func = self.t1calculator.calculate_t1_min(
|
||||
interpolate=idx,
|
||||
trange=(float(self.lineEdit_2.text()), float(self.lineEdit_3.text())),
|
||||
)
|
||||
except ValueError:
|
||||
m, i_func = self.t1calculator.calculate_t1_min(interpolate=None)
|
||||
|
||||
@ -271,11 +281,13 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
return
|
||||
|
||||
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,
|
||||
omega=2*np.pi*self.frequency,
|
||||
dist_parameter=sd_args, prefactor=cp_args,
|
||||
coupling_kwargs=cp_kwargs)
|
||||
coupling_kwargs=cp_kwargs
|
||||
)
|
||||
|
||||
self.label_t1min.setText(f'{mini:.4g} s')
|
||||
|
||||
@ -290,9 +302,13 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
sd_args, _ = self.get_sd_values()
|
||||
cp_args, cp_kwargs, _ = self.get_cp_values()
|
||||
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,
|
||||
mode=tau_mode, interpolate=self.checkBox_interpol.isChecked())
|
||||
mode=tau_mode,
|
||||
interpolate=self.checkBox_interpol.isChecked()
|
||||
)
|
||||
|
||||
name = self.name + '-' + str(self.t1calculator) + '('
|
||||
name += ','.join([f'{a:.3g}' for a in sd_args])
|
||||
@ -330,4 +346,4 @@ class QT1Widget(QtWidgets.QDialog, Ui_t1dialog):
|
||||
|
||||
@QtCore.pyqtSlot(int, name='on_graph_checkbox_stateChanged')
|
||||
def changed_state(self, checked):
|
||||
self.graph_combobox.setEnabled(checked != QtCore.Qt.Checked)
|
||||
self.graph_combobox.setEnabled(checked != QtCore.Qt.CheckState.Checked)
|
||||
|
175
src/nmreval/clib/integrate.c
Normal file
175
src/nmreval/clib/integrate.c
Normal file
@ -0,0 +1,175 @@
|
||||
/* integrands used in quadrature integration with scipy's LowLevelCallables */
|
||||
#include <math.h>
|
||||
|
||||
const double KB = 8.617333262145179e-05;
|
||||
|
||||
/* FFHS functions */
|
||||
double ffhsSD(double x, void *user_data) {
|
||||
double *c = (double *)user_data;
|
||||
|
||||
double omega = c[0];
|
||||
double tau = c[1];
|
||||
|
||||
double u = x*x;
|
||||
double res = u*u * tau;
|
||||
|
||||
res /= 81. + 9.*u - 2.*u*u + u*u*u;
|
||||
res /= u*u + omega*omega * tau*tau;
|
||||
return res;
|
||||
}
|
||||
|
||||
/* log-gaussian functions */
|
||||
double logNormalDist(double tau, double tau0, double sigma) {
|
||||
return exp(- pow((log(tau/tau0) / sigma), 2) / 2.) / sqrt(2*M_PI)/sigma;
|
||||
}
|
||||
|
||||
double logGaussian_imag_high(double u, void *user_data) {
|
||||
double *c = (double *)user_data;
|
||||
|
||||
double omega = c[0];
|
||||
double tau = c[1];
|
||||
double sigma = c[2];
|
||||
|
||||
double uu = exp(-u);
|
||||
double dist = logNormalDist(1./uu, tau, sigma);
|
||||
|
||||
return dist * omega * uu / (pow(uu, 2) + pow(omega, 2));
|
||||
}
|
||||
|
||||
double logGaussian_imag_low(double u, void *user_data) {
|
||||
double *c = (double *)user_data;
|
||||
|
||||
double omega = c[0];
|
||||
double tau = c[1];
|
||||
double sigma = c[2];
|
||||
|
||||
double uu = exp(u);
|
||||
|
||||
double dist = logNormalDist(uu, tau, sigma);
|
||||
|
||||
return dist * omega * uu / (1. + pow(omega*uu, 2));
|
||||
}
|
||||
|
||||
double logGaussian_real_high(double u, void *user_data) {
|
||||
double *c = (double *)user_data;
|
||||
|
||||
double omega = c[0];
|
||||
double tau = c[1];
|
||||
double sigma = c[2];
|
||||
|
||||
double uu = exp(-2.*u);
|
||||
double dist = logNormalDist(exp(uu), tau, sigma);
|
||||
|
||||
return dist * uu / (uu + pow(omega, 2));
|
||||
}
|
||||
|
||||
double logGaussian_real_low(double u, void *user_data) {
|
||||
double *c = (double *)user_data;
|
||||
|
||||
double omega = c[0];
|
||||
double tau = c[1];
|
||||
double sigma = c[2];
|
||||
|
||||
double uu = exp(u);
|
||||
|
||||
double dist = logNormalDist(uu, tau, sigma);
|
||||
|
||||
return dist / (1. + pow(omega*uu, 2));
|
||||
}
|
||||
|
||||
double logGaussianCorrelation(double x, void *user_data) {
|
||||
double *c = (double *)user_data;
|
||||
|
||||
double t = c[0];
|
||||
double tau = c[1];
|
||||
double sigma = c[2];
|
||||
|
||||
double uu = exp(x);
|
||||
|
||||
double dist = logNormalDist(uu, tau, sigma);
|
||||
|
||||
return dist * exp(-t/uu);
|
||||
}
|
||||
|
||||
// functions for distribution of energy
|
||||
double normalDist(double x, double x0, double sigma) {
|
||||
return exp(- pow((x-x0) / sigma, 2) / 2.) / sqrt(2 * M_PI) / sigma;
|
||||
}
|
||||
|
||||
double rate(double tau0, double ea, double t) {
|
||||
return exp(-ea / t / KB) / tau0;
|
||||
}
|
||||
|
||||
double energyDist_SD(double x, void *user_data) {
|
||||
double *c = (double *)user_data;
|
||||
|
||||
double omega = c[0];
|
||||
double tau0 = c[1];
|
||||
double e_m = c[2];
|
||||
double e_b = c[3];
|
||||
double temp = c[4];
|
||||
|
||||
double r = rate(tau0, x, temp);
|
||||
|
||||
return r/(pow(r, 2) + pow(omega, 2)) * normalDist(x, e_m, e_b);
|
||||
}
|
||||
|
||||
double energyDistSuscReal(double x, void *user_data) {
|
||||
double *c = (double *)user_data;
|
||||
|
||||
double omega = c[0];
|
||||
double tau0 = c[1];
|
||||
double e_m = c[2];
|
||||
double e_b = c[3];
|
||||
double temp = c[4];
|
||||
|
||||
double r = rate(tau0, x, temp);
|
||||
|
||||
return 1 / (pow(r, 2) + pow(omega, 2)) * normalDist(x, e_m, e_b);
|
||||
}
|
||||
|
||||
double energyDistSuscImag(double x, void *user_data) {
|
||||
double *c = (double *)user_data;
|
||||
|
||||
double omega = c[0];
|
||||
double tau0 = c[1];
|
||||
double e_m = c[2];
|
||||
double e_b = c[3];
|
||||
double temp = c[4];
|
||||
|
||||
double r = rate(tau0, x, temp);
|
||||
|
||||
return omega * r / (pow(r, 2) + pow(omega, 2)) * normalDist(x, e_m, e_b);
|
||||
}
|
||||
|
||||
double energyDistCorrelation(double x, void *user_data) {
|
||||
double *c = (double *)user_data;
|
||||
|
||||
double t = c[0];
|
||||
double tau0 = c[1];
|
||||
double e_m = c[2];
|
||||
double e_b = c[3];
|
||||
double temp = c[4];
|
||||
|
||||
double r = rate(tau0, x, temp);
|
||||
|
||||
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);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user