From 0ff63ddb4a472536d2fc7f7b0f78cfa788e42e3c Mon Sep 17 00:00:00 2001 From: chrin Date: Mon, 1 May 2023 10:40:03 +0200 Subject: [PATCH] Initial commit --- .gitignore | 9 + help/README.md | 6 + help/hush.qrc | 10 + help/hush.qrc~ | 10 + help/hush_resources.py | 196 +++++ help/index.html | 18 + help/index.html~ | 25 + help/make_and_install.sh | 2 + help/makefile | 9 + help/makefile~ | 9 + help/page1.html | 7 + help/page2.html | 7 + help/page3.html | 7 + help/page4.html | 7 + help/page5.html | 7 + hush.json | 67 ++ hush.json- | 52 ++ hush.json~ | 67 ++ hush.py | 231 ++++++ hush.py~ | 213 ++++++ hush.sh | 100 +++ hush.sh~ | 98 +++ .../__pycache__/hush_resources.cpython-37.pyc | Bin 0 -> 2832 bytes pyrcc5/hush_resources.py | 196 +++++ pyrcc5/hush_resources.py- | 196 +++++ pyrcc5/hush_resources.py-- | 196 +++++ pyrcc5/hush_resources.py--- | 194 +++++ src/__pycache__/gui.cpython-37.pyc | Bin 0 -> 15782 bytes src/gui.py | 705 ++++++++++++++++++ src/gui.py- | 542 ++++++++++++++ src/gui.py~ | 596 +++++++++++++++ 31 files changed, 3782 insertions(+) create mode 100644 .gitignore create mode 100644 help/README.md create mode 100644 help/hush.qrc create mode 100644 help/hush.qrc~ create mode 100644 help/hush_resources.py create mode 100755 help/index.html create mode 100755 help/index.html~ create mode 100644 help/make_and_install.sh create mode 100644 help/makefile create mode 100644 help/makefile~ create mode 100755 help/page1.html create mode 100755 help/page2.html create mode 100755 help/page3.html create mode 100755 help/page4.html create mode 100755 help/page5.html create mode 100755 hush.json create mode 100755 hush.json- create mode 100755 hush.json~ create mode 100644 hush.py create mode 100644 hush.py~ create mode 100755 hush.sh create mode 100755 hush.sh~ create mode 100644 pyrcc5/__pycache__/hush_resources.cpython-37.pyc create mode 100644 pyrcc5/hush_resources.py create mode 100644 pyrcc5/hush_resources.py- create mode 100644 pyrcc5/hush_resources.py-- create mode 100644 pyrcc5/hush_resources.py--- create mode 100644 src/__pycache__/gui.cpython-37.pyc create mode 100644 src/gui.py create mode 100644 src/gui.py- create mode 100644 src/gui.py~ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2bbbfca --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +rm *.*~ +rm *.*-* +rm *.*+* +rm pyrcc5 +rm pyrcc5/*.* +rm src/*.*~ +rm src/*.*-* +rm src/*.*+* + diff --git a/help/README.md b/help/README.md new file mode 100644 index 0000000..a7f649a --- /dev/null +++ b/help/README.md @@ -0,0 +1,6 @@ +# to compile hush.qrc: +make +# to install compiled hush_respources.py +make install + +The latter installs hush_respources.py to the ../pyqrcc5 directory \ No newline at end of file diff --git a/help/hush.qrc b/help/hush.qrc new file mode 100644 index 0000000..eefb6cb --- /dev/null +++ b/help/hush.qrc @@ -0,0 +1,10 @@ + + +page5.html +page4.html +page3.html +page2.html +page1.html +index.html + + diff --git a/help/hush.qrc~ b/help/hush.qrc~ new file mode 100644 index 0000000..e39df96 --- /dev/null +++ b/help/hush.qrc~ @@ -0,0 +1,10 @@ + + +help/page5.html +help/page4.html +help/page3.html +help/page2.html +help/page1.html +help/index.html + + diff --git a/help/hush_resources.py b/help/hush_resources.py new file mode 100644 index 0000000..447a733 --- /dev/null +++ b/help/hush_resources.py @@ -0,0 +1,196 @@ +# -*- coding: utf-8 -*- + +# Resource object code +# +# Created by: The Resource Compiler for PyQt5 (Qt v5.9.6) +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore + +qt_resource_data = b"\ +\x00\x00\x00\xa7\ +\x3c\ +\x68\x74\x6d\x6c\x3e\x3c\x68\x65\x61\x64\x3e\x3c\x74\x69\x74\x6c\ +\x65\x3e\x57\x65\x62\x20\x48\x65\x6c\x70\x3c\x2f\x74\x69\x74\x6c\ +\x65\x3e\x3c\x2f\x68\x65\x61\x64\x3e\x0a\x3c\x62\x6f\x64\x79\x3e\ +\x0a\x0a\x3c\x70\x3e\x3c\x62\x3e\x50\x61\x67\x65\x20\x32\x20\x6f\ +\x66\x20\x77\x65\x62\x20\x68\x65\x6c\x70\x3c\x2f\x62\x3e\x3c\x2f\ +\x70\x3e\x0a\x3c\x70\x3e\x20\x20\x3c\x61\x20\x68\x72\x65\x66\x3d\ +\x22\x70\x61\x67\x65\x33\x2e\x68\x74\x6d\x6c\x22\x3e\x20\x4e\x65\ +\x78\x74\x3c\x2f\x61\x3e\x3c\x2f\x70\x3e\x0a\x3c\x70\x3e\x3c\x62\ +\x3e\x65\x74\x63\x2e\x2e\x2e\x3c\x2f\x62\x3e\x20\x65\x74\x63\x2e\ +\x2e\x2e\x3c\x2f\x70\x3e\x0a\x3c\x2f\x62\x6f\x64\x79\x3e\x3c\x2f\ +\x68\x74\x6d\x6c\x3e\x0a\ +\x00\x00\x00\xa7\ +\x3c\ +\x68\x74\x6d\x6c\x3e\x3c\x68\x65\x61\x64\x3e\x3c\x74\x69\x74\x6c\ +\x65\x3e\x57\x65\x62\x20\x48\x65\x6c\x70\x3c\x2f\x74\x69\x74\x6c\ +\x65\x3e\x3c\x2f\x68\x65\x61\x64\x3e\x0a\x3c\x62\x6f\x64\x79\x3e\ +\x0a\x0a\x3c\x70\x3e\x3c\x62\x3e\x50\x61\x67\x65\x20\x31\x20\x6f\ +\x66\x20\x77\x65\x62\x20\x68\x65\x6c\x70\x3c\x2f\x62\x3e\x3c\x2f\ +\x70\x3e\x0a\x3c\x70\x3e\x20\x20\x3c\x61\x20\x68\x72\x65\x66\x3d\ +\x22\x70\x61\x67\x65\x32\x2e\x68\x74\x6d\x6c\x22\x3e\x20\x4e\x65\ +\x78\x74\x3c\x2f\x61\x3e\x3c\x2f\x70\x3e\x0a\x3c\x70\x3e\x3c\x62\ +\x3e\x65\x74\x63\x2e\x2e\x2e\x3c\x2f\x62\x3e\x20\x65\x74\x63\x2e\ +\x2e\x2e\x3c\x2f\x70\x3e\x0a\x3c\x2f\x62\x6f\x64\x79\x3e\x3c\x2f\ +\x68\x74\x6d\x6c\x3e\x0a\ +\x00\x00\x00\xa7\ +\x3c\ +\x68\x74\x6d\x6c\x3e\x3c\x68\x65\x61\x64\x3e\x3c\x74\x69\x74\x6c\ +\x65\x3e\x57\x65\x62\x20\x48\x65\x6c\x70\x3c\x2f\x74\x69\x74\x6c\ +\x65\x3e\x3c\x2f\x68\x65\x61\x64\x3e\x0a\x3c\x62\x6f\x64\x79\x3e\ +\x0a\x0a\x3c\x70\x3e\x3c\x62\x3e\x50\x61\x67\x65\x20\x34\x20\x6f\ +\x66\x20\x77\x65\x62\x20\x68\x65\x6c\x70\x3c\x2f\x62\x3e\x3c\x2f\ +\x70\x3e\x0a\x3c\x70\x3e\x20\x20\x3c\x61\x20\x68\x72\x65\x66\x3d\ +\x22\x70\x61\x67\x65\x35\x2e\x68\x74\x6d\x6c\x22\x3e\x20\x4e\x65\ +\x78\x74\x3c\x2f\x61\x3e\x3c\x2f\x70\x3e\x0a\x3c\x70\x3e\x3c\x62\ +\x3e\x65\x74\x63\x2e\x2e\x2e\x3c\x2f\x62\x3e\x20\x65\x74\x63\x2e\ +\x2e\x2e\x3c\x2f\x70\x3e\x0a\x3c\x2f\x62\x6f\x64\x79\x3e\x3c\x2f\ +\x68\x74\x6d\x6c\x3e\x0a\ +\x00\x00\x00\xa7\ +\x3c\ +\x68\x74\x6d\x6c\x3e\x3c\x68\x65\x61\x64\x3e\x3c\x74\x69\x74\x6c\ +\x65\x3e\x57\x65\x62\x20\x48\x65\x6c\x70\x3c\x2f\x74\x69\x74\x6c\ +\x65\x3e\x3c\x2f\x68\x65\x61\x64\x3e\x0a\x3c\x62\x6f\x64\x79\x3e\ +\x0a\x0a\x3c\x70\x3e\x3c\x62\x3e\x50\x61\x67\x65\x20\x33\x20\x6f\ +\x66\x20\x77\x65\x62\x20\x68\x65\x6c\x70\x3c\x2f\x62\x3e\x3c\x2f\ +\x70\x3e\x0a\x3c\x70\x3e\x20\x20\x3c\x61\x20\x68\x72\x65\x66\x3d\ +\x22\x70\x61\x67\x65\x34\x2e\x68\x74\x6d\x6c\x22\x3e\x20\x4e\x65\ +\x78\x74\x3c\x2f\x61\x3e\x3c\x2f\x70\x3e\x0a\x3c\x70\x3e\x3c\x62\ +\x3e\x65\x74\x63\x2e\x2e\x2e\x3c\x2f\x62\x3e\x20\x65\x74\x63\x2e\ +\x2e\x2e\x3c\x2f\x70\x3e\x0a\x3c\x2f\x62\x6f\x64\x79\x3e\x3c\x2f\ +\x68\x74\x6d\x6c\x3e\x0a\ +\x00\x00\x03\x13\ +\x3c\ +\x68\x74\x6d\x6c\x3e\x3c\x68\x65\x61\x64\x3e\x3c\x74\x69\x74\x6c\ +\x65\x3e\x48\x49\x50\x41\x20\x50\x6f\x77\x65\x72\x20\x55\x73\x61\ +\x67\x65\x20\x61\x6e\x64\x20\x53\x61\x76\x69\x6e\x67\x20\x48\x69\ +\x67\x68\x6c\x69\x67\x68\x74\x73\x2c\x20\x48\x55\x53\x48\x21\x3c\ +\x2f\x74\x69\x74\x6c\x65\x3e\x3c\x2f\x68\x65\x61\x64\x3e\x0a\x3c\ +\x62\x6f\x64\x79\x3e\x0a\x0a\x3c\x68\x35\x20\x20\x73\x74\x79\x6c\ +\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x67\x72\x61\x79\x3b\x22\x3e\ +\x53\x70\x72\x69\x6e\x67\x20\x32\x30\x32\x33\x2c\x20\x4a\x61\x6e\ +\x20\x43\x68\x72\x69\x6e\x20\x61\x6e\x64\x20\x2e\x2e\x2e\x3c\x2f\ +\x68\x35\x3e\x0a\x3c\x68\x34\x3e\x20\x3c\x73\x70\x61\x6e\x20\x73\ +\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x20\x72\x65\x64\ +\x3b\x22\x3e\x48\x3c\x2f\x73\x70\x61\x6e\x3e\x49\x50\x41\x20\x3c\ +\x73\x70\x61\x6e\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\ +\x72\x3a\x20\x67\x72\x61\x79\x3b\x22\x3e\x50\x6f\x77\x65\x72\x3c\ +\x2f\x73\x70\x61\x6e\x3e\x20\x3c\x73\x70\x61\x6e\x20\x73\x74\x79\ +\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x20\x72\x65\x64\x3b\x22\ +\x3e\x55\x3c\x2f\x73\x70\x61\x6e\x3e\x73\x61\x67\x65\x20\x61\x6e\ +\x64\x20\x3c\x73\x70\x61\x6e\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\ +\x6f\x6c\x6f\x72\x3a\x20\x72\x65\x64\x3b\x22\x3e\x53\x3c\x2f\x73\ +\x70\x61\x6e\x3e\x61\x76\x69\x6e\x67\x20\x3c\x73\x70\x61\x6e\x20\ +\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x20\x72\x65\ +\x64\x3b\x22\x3e\x48\x3c\x2f\x73\x70\x61\x6e\x3e\x69\x67\x68\x6c\ +\x69\x67\x68\x74\x73\x2c\x20\x3c\x73\x70\x61\x6e\x20\x73\x74\x79\ +\x6c\x65\x3d\x22\x63\x6f\x6c\x6f\x72\x3a\x20\x72\x65\x64\x3b\x22\ +\x3e\x48\x55\x53\x48\x21\x3c\x2f\x73\x70\x61\x6e\x3e\x3c\x2f\x68\ +\x34\x3e\x0a\x3c\x68\x32\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\ +\x6c\x6f\x72\x3a\x62\x6c\x75\x65\x3b\x22\x3e\x41\x62\x6f\x75\x74\ +\x3c\x2f\x68\x32\x3e\x0a\x0a\x3c\x70\x3e\x54\x68\x69\x73\x20\x3c\ +\x62\x3e\x68\x75\x73\x68\x3c\x2f\x62\x3e\x20\x61\x70\x70\x6c\x69\ +\x63\x61\x74\x69\x6f\x6e\x20\x69\x6e\x68\x65\x72\x69\x74\x73\x20\ +\x66\x72\x6f\x6d\x20\x74\x68\x65\x20\x57\x69\x6e\x64\x6f\x77\x20\ +\x62\x61\x73\x65\x20\x63\x6c\x61\x73\x73\x2e\x3c\x62\x72\x3e\x20\ +\x20\x0a\x3c\x70\x3e\x69\x6e\x66\x6f\x72\x6d\x61\x74\x69\x6f\x6e\ +\x20\x63\x6f\x6e\x63\x65\x72\x6e\x69\x6e\x67\x20\x74\x68\x69\x73\ +\x20\x61\x70\x70\x6c\x69\x63\x61\x74\x69\x6f\x6e\x2c\x20\x73\x75\ +\x63\x68\x20\x61\x73\x20\x63\x6f\x6e\x66\x69\x67\x75\x72\x61\x74\ +\x69\x6f\x6e\x20\x70\x61\x72\x61\x6d\x65\x74\x65\x72\x73\x20\x6f\ +\x72\x20\x6f\x74\x68\x65\x72\x2c\x20\x6d\x61\x79\x20\x62\x65\x20\ +\x65\x6e\x74\x65\x72\x65\x64\x2c\x20\x65\x2e\x67\x2e\x2c\x20\x3c\ +\x61\x20\x68\x72\x65\x66\x3d\x22\x70\x61\x67\x65\x31\x2e\x68\x74\ +\x6d\x6c\x22\x3e\x68\x65\x72\x65\x3c\x2f\x61\x3e\x3c\x2f\x70\x3e\ +\x0a\x0a\x3c\x68\x32\x20\x73\x74\x79\x6c\x65\x3d\x22\x63\x6f\x6c\ +\x6f\x72\x3a\x62\x6c\x75\x65\x3b\x22\x3e\x54\x68\x65\x20\x50\x61\ +\x6e\x65\x6c\x3c\x2f\x68\x32\x3e\x0a\x0a\x3c\x70\x3e\x54\x68\x65\ +\x73\x65\x20\x77\x65\x62\x20\x70\x61\x67\x65\x73\x20\x61\x72\x65\ +\x20\x74\x6f\x20\x62\x65\x20\x63\x6f\x6d\x70\x6c\x65\x74\x65\x64\ +\x20\x62\x79\x20\x74\x68\x65\x20\x61\x70\x70\x6c\x69\x63\x61\x74\ +\x69\x6f\x6e\x20\x6f\x77\x6e\x65\x72\x2e\x3c\x62\x72\x3e\x0a\x0a\ +\x0a\x0a\x0a\x3c\x2f\x62\x6f\x64\x79\x3e\x3c\x2f\x68\x74\x6d\x6c\ +\x3e\x0a\ +\x00\x00\x00\x80\ +\x3c\ +\x68\x74\x6d\x6c\x3e\x3c\x68\x65\x61\x64\x3e\x3c\x74\x69\x74\x6c\ +\x65\x3e\x57\x65\x62\x20\x48\x65\x6c\x70\x3c\x2f\x74\x69\x74\x6c\ +\x65\x3e\x3c\x2f\x68\x65\x61\x64\x3e\x0a\x3c\x62\x6f\x64\x79\x3e\ +\x0a\x0a\x3c\x70\x3e\x3c\x62\x3e\x50\x61\x67\x65\x20\x35\x20\x6f\ +\x66\x20\x77\x65\x62\x20\x68\x65\x6c\x70\x3c\x2f\x62\x3e\x3c\x2f\ +\x70\x3e\x0a\x0a\x3c\x70\x3e\x3c\x62\x3e\x65\x74\x63\x2e\x2e\x2e\ +\x3c\x2f\x62\x3e\x20\x65\x74\x63\x2e\x2e\x2e\x3c\x2f\x70\x3e\x0a\ +\x3c\x2f\x62\x6f\x64\x79\x3e\x3c\x2f\x68\x74\x6d\x6c\x3e\x0a\ +" + +qt_resource_name = b"\ +\x00\x0a\ +\x08\x5a\x34\x9c\ +\x00\x70\ +\x00\x61\x00\x67\x00\x65\x00\x32\x00\x2e\x00\x68\x00\x74\x00\x6d\x00\x6c\ +\x00\x0a\ +\x08\x4a\x34\x9c\ +\x00\x70\ +\x00\x61\x00\x67\x00\x65\x00\x31\x00\x2e\x00\x68\x00\x74\x00\x6d\x00\x6c\ +\x00\x0a\ +\x08\x7a\x34\x9c\ +\x00\x70\ +\x00\x61\x00\x67\x00\x65\x00\x34\x00\x2e\x00\x68\x00\x74\x00\x6d\x00\x6c\ +\x00\x0a\ +\x08\x6a\x34\x9c\ +\x00\x70\ +\x00\x61\x00\x67\x00\x65\x00\x33\x00\x2e\x00\x68\x00\x74\x00\x6d\x00\x6c\ +\x00\x0a\ +\x0c\xba\xf2\x7c\ +\x00\x69\ +\x00\x6e\x00\x64\x00\x65\x00\x78\x00\x2e\x00\x68\x00\x74\x00\x6d\x00\x6c\ +\x00\x0a\ +\x08\x8a\x34\x9c\ +\x00\x70\ +\x00\x61\x00\x67\x00\x65\x00\x35\x00\x2e\x00\x68\x00\x74\x00\x6d\x00\x6c\ +" + +qt_resource_struct_v1 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x01\ +\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x01\x00\x00\x00\xab\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x00\x4e\x00\x00\x00\x00\x00\x01\x00\x00\x02\x01\ +\x00\x00\x00\x34\x00\x00\x00\x00\x00\x01\x00\x00\x01\x56\ +\x00\x00\x00\x82\x00\x00\x00\x00\x00\x01\x00\x00\x05\xc3\ +\x00\x00\x00\x68\x00\x00\x00\x00\x00\x01\x00\x00\x02\xac\ +" + +qt_resource_struct_v2 = b"\ +\x00\x00\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x01\ +\x00\x00\x00\x00\x00\x00\x00\x00\ +\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x01\x00\x00\x00\xab\ +\x00\x00\x01\x87\x70\x19\x8f\x40\ +\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ +\x00\x00\x01\x87\x70\x19\x8f\x40\ +\x00\x00\x00\x4e\x00\x00\x00\x00\x00\x01\x00\x00\x02\x01\ +\x00\x00\x01\x87\x70\x19\x8f\x40\ +\x00\x00\x00\x34\x00\x00\x00\x00\x00\x01\x00\x00\x01\x56\ +\x00\x00\x01\x87\x70\x19\x8f\x40\ +\x00\x00\x00\x82\x00\x00\x00\x00\x00\x01\x00\x00\x05\xc3\ +\x00\x00\x01\x87\x70\x19\x8f\x40\ +\x00\x00\x00\x68\x00\x00\x00\x00\x00\x01\x00\x00\x02\xac\ +\x00\x00\x01\x87\x70\x5b\x10\xc8\ +" + +qt_version = QtCore.qVersion().split('.') +if qt_version < ['5', '8', '0']: + rcc_version = 1 + qt_resource_struct = qt_resource_struct_v1 +else: + rcc_version = 2 + qt_resource_struct = qt_resource_struct_v2 + +def qInitResources(): + QtCore.qRegisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +def qCleanupResources(): + QtCore.qUnregisterResourceData(rcc_version, qt_resource_struct, qt_resource_name, qt_resource_data) + +qInitResources() diff --git a/help/index.html b/help/index.html new file mode 100755 index 0000000..8686ce4 --- /dev/null +++ b/help/index.html @@ -0,0 +1,18 @@ +HIPA Power Usage and Saving Highlights, HUSH! + + +
Spring 2023, Jan Chrin and ...
+

HIPA Power Usage and Saving Highlights, HUSH!

+

About

+ +

This hush application inherits from the Window base class.
+

information concerning this application, such as configuration parameters or other, may be entered, e.g., here

+ +

The Panel

+ +

These web pages are to be completed by the application owner.
+ + + + + diff --git a/help/index.html~ b/help/index.html~ new file mode 100755 index 0000000..8297404 --- /dev/null +++ b/help/index.html~ @@ -0,0 +1,25 @@ +Lifetime Measurement + + +

Fall 2021, Andreas Streun, Jan Chrin
+

Beam lifetime measurement

+

About

+ +

This Example Application inherits from the SLSMainWindow base class.
+

information concerning this application, such as configuration parameters or other, may be entered, e.g., here

+ +

The Panel

+ +

These web pages are to be completed by the application owner.
+They are located in the following directory:
+/afs/psi.ch/intranet/SF/Beamdynamics/common/qrc_resources/help/<appname>
+where <appname>.py is the name of the application program

+ +

After modification, execute the following script to incorporate changes
+into qrc_resource.py for (automatic) import into PyQt4- and PyQt5-based applications:

+ +

cd /afs/psi.ch/intranet/SF/Beamdynamics/common/qrc_resources

+

./make_and_install.sh + + + diff --git a/help/make_and_install.sh b/help/make_and_install.sh new file mode 100644 index 0000000..e7c2b22 --- /dev/null +++ b/help/make_and_install.sh @@ -0,0 +1,2 @@ +make compile +make install diff --git a/help/makefile b/help/makefile new file mode 100644 index 0000000..3ff7d5e --- /dev/null +++ b/help/makefile @@ -0,0 +1,9 @@ +compile: + pyrcc5 hush.qrc > hush_resources.py + +install: + if [ ! -f hush_resources.py ]; then echo "pyrcc5 compilation of resources.qrc failed"; fi + if [ -f hush_resources.py -a -f ../pyrcc5/hush_resources.py-- ]; then cp ../pyrcc5/hush_resources.py-- ../pyrcc5/hush_resources.py---; fi + if [ -f hush_resources.py -a -f ../pyrcc5/hush_resources.py- ]; then cp ../pyrcc5/hush_resources.py- ../pyrcc5/hush_resources.py--; fi + if [ -f hush_resources.py -a -f ../pyrcc5/hush_resources.py ]; then cp ../pyrcc5/hush_resources.py ../pyrcc5/hush_resources.py-; fi + if [ -f hush_resources.py ]; then cp hush_resources.py ../pyrcc5/hush_resources.py; fi diff --git a/help/makefile~ b/help/makefile~ new file mode 100644 index 0000000..275741c --- /dev/null +++ b/help/makefile~ @@ -0,0 +1,9 @@ +compile: + pyrcc5 hush.qrc > hush_resources.py + +install: + if [ ! -f hush_resources.py ]; then echo "pyrcc5 compilation of resources.qrc failed"; fi + if [ -f hush_resources.py -a -f pyrcc5/hush_resources.py-- ]; then cp pyrcc5/hush_resources.py-- pyrcc5/hush_resources.py---; fi + if [ -f hush_resources.py -a -f pyrcc5/hush_resources.py- ]; then cp pyrcc5/hush_resources.py- pyrcc5/hush_resources.py--; fi + if [ -f hush_resources.py -a -f pyrcc5/hush_resources.py ]; then cp pyrcc5/hush_resources.py pyrcc5/hush_resources.py-; fi + if [ -f hush_resources.py ]; then cp hush_resources.py pyrcc5/hush_resources.py; fi diff --git a/help/page1.html b/help/page1.html new file mode 100755 index 0000000..6fa49c5 --- /dev/null +++ b/help/page1.html @@ -0,0 +1,7 @@ +Web Help + + +

Page 1 of web help

+

Next

+

etc... etc...

+ diff --git a/help/page2.html b/help/page2.html new file mode 100755 index 0000000..10f6352 --- /dev/null +++ b/help/page2.html @@ -0,0 +1,7 @@ +Web Help + + +

Page 2 of web help

+

Next

+

etc... etc...

+ diff --git a/help/page3.html b/help/page3.html new file mode 100755 index 0000000..f12e898 --- /dev/null +++ b/help/page3.html @@ -0,0 +1,7 @@ +Web Help + + +

Page 3 of web help

+

Next

+

etc... etc...

+ diff --git a/help/page4.html b/help/page4.html new file mode 100755 index 0000000..64c0eb6 --- /dev/null +++ b/help/page4.html @@ -0,0 +1,7 @@ +Web Help + + +

Page 4 of web help

+

Next

+

etc... etc...

+ diff --git a/help/page5.html b/help/page5.html new file mode 100755 index 0000000..639d750 --- /dev/null +++ b/help/page5.html @@ -0,0 +1,7 @@ +Web Help + + +

Page 5 of web help

+ +

etc... etc...

+ diff --git a/hush.json b/hush.json new file mode 100755 index 0000000..afbb146 --- /dev/null +++ b/hush.json @@ -0,0 +1,67 @@ +{ + "menuFlags":{ + "hasFile": 0, + "loadInitFile": 0, + "hasDaq": 0, + "hasH5": 0, + "hasEpics": 0 + }, + "hdf": { + "destination" : "./" + }, + "IP2":{ + "standby": [-10.0025, 10.0025, 10.0025, 0.05, 0.05, 40.000, 0.05, 0.005, + 10.0025, -10.0025, 10.0025, 0.1392, -25.006, 0.05, 0.05, 2.175, + 0.05, 10.0025, -10.0025, 0.05, 0.05, 0.05, 0.05, -10.0025, + -10.0025] + }, + "IW2":{ + "standby": [-5.001, 5.001, 0.05, -5.001, 5.001, 5.001, -5.001, 0.05, + 0.05, 0.05, 5.001, -5.001, -5.001, 5.001, 0.05, 0.05, + 0.05, -5.001, 10.0025, 27.605, -10.0025, 21.899, 0.05, -6.000, + 6.00, 6.0, 0.05, 0.05, 34.152, 0.5, -0.5, 0.05, + 40.591, 62.5], + "ref" : [-79.00, 87.58, 496, -89.3, 80.5, 82.9, -83.77, -1.81, + 0.40, 1.39, 77.80, -41.43, -62.33, 63.97, -0.33, -0.25, + 0.25, -52.27, 83.98, 520.41, -105.96, 433.61, 0.23, -54.25, + 50.51, 23.46, -40.14, -4.66, 622.91, 2.00, -7.17, -0.73, + 806.99, 1147.69] + }, + "PK1":{ + "standby": [56.791, 0.05, -2.0005, 2.0005, 0.05, 0.05, 44.9525, -2.0005, + -2.0005, 0.05, 25.006, -25.006, 0.05, 0.05, 64.066] + }, + + "PK2":{ + "standby": [0.05, -25.006, 25.006, 17.4, 10.0025, -2.0005, 0.05, 0.05, + 25.85, -10.0025, 10.0025, 0.05, 0.05, -25.006, 25.006, -25.006, + 0.05, 0.05, 0.05, 0.05, 25.006, -25.006, 25.006, -25.006, + 0.05, 25.006, 25.1877, 0.05] + }, + + "SINQ":{ + "standby": [-25.006, 0.05, 25.006, 10.0025, -12.608, 0.05, 10.98, + 15.6045, -18.3075, 0.05, 20.462, 0.05, 21.9925, -19.005, + 46.5345, 18.01, -21.3675] + }, + "UCN":{ + "standby": [9.404, 25.006, -25.006, 0.05, 0.05, 0.05, 0.05, 25.006, + -25.006, 20.625, 10.0025, -10.0025, 0.05, 20.625, 25.006 + ] + }, + + "Parameters":{ + + "drawLine" : {"flag" : 0, "data":{ "widget": "QHLine", "text" : "None", "value" : "None"}} + + }, + "Expert":{ + "debug": {"flag" : 1, "data":{ "widget": "None", "text" : "Debug", "value" : 0}}, + "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Dry run", "value" : 1}} + }, + "GUI": { + "resultsTabTitle" : "Results", + "subResultsTabTitle" : [], + "resultsSeq" : [] + } +} diff --git a/hush.json- b/hush.json- new file mode 100755 index 0000000..bae95a9 --- /dev/null +++ b/hush.json- @@ -0,0 +1,52 @@ +{ + "menuFlags":{ + "hasFile": 0, + "loadInitFile": 0, + "hasDaq": 0, + "hasH5": 0, + "hasEpics": 0 + }, + "hdf": { + "destination" : "./" + }, + "SLS" : ["Injector", "Booster", "Ring"], + "SLS2" : {"test": ["Injector", "Booster", "Ring"]}, + "QTabViking":{ + "Vikings": { + "radiobutton" : {"data":{ "widget": "QRadioButton", "text" : "Radio Gaga", "value": ["This", "That", "The Other"], "startIdx": 1}}, + "readonly" : {"data":{ "widget": "QLineRead", "text" :"ReadOnly:", "value" : "input"}}, + "npts" : {"data":{ "widget": "QLineEdit", "text" :"No Events:", "value" : 22, "min": 0.01, "max": 0.99}}, + "nspins" : {"data":{ "widget": "QSpinBox", "text" : "No. Points:", "min": 1, "max": 10, "step": 1,"value": 1 }}, + "ndspins" : {"data":{ "widget": "QDoubleSpinBox", "text" : "No. Points:", "min": 1, "max": 10.0, "step": 0.1,"value": 1.5 }}, + "facility": {"data" : {"widget": "QComboBox", "text" : "Facility:", "link": ["SLS2", "test"],"layout" : "Horizontal"}}, + "checkbox" : {"data":{ "widget": "QCheckBox", "orientation" : "Qt.LeftToRight", "text" : "Checkbox", "value" : 1}} + }, + "Saxons": { + "nevents" : {"data":{ "widget": "QLineEdit", "text" :"No. Iterations:", "value" : 33}}, + "niter" : {"data":{ "widget": "QSpinBox", "text" : "Step size:", "min": 1, "max": 10, "step": 1,"value": 1 }} + } + }, + + "Parameters":{ + "maxmin" : {"flag" : 1, "data":{ "widget": "QRadioButton", "text" : "", "value": ["Maximize", "Minimize" ]}}, + "facility": {"flag": 0, "data" : {"widget": "QComboBox", "text" : "Facility:", + "link": ["SLS"],"layout" : "Horizontal"}}, + "N_events" : {"flag" : 1, "data":{ "widget": "QLineEdit", "text" : "No. events: ", "value": 2 }}, + "N_points" : {"flag" : 1, "data":{ "widget": "QSpinBox", "text" : "No. points:", "min": 1, "max": 10, "step": 1,"value": 1 }}, + "drawLine" : {"flag" : 0, "data":{ "widget": "QHLine", "text" : "None", "value" : "None"}}, + "checkbox" : {"flag" : 1, "data":{ "widget": "QCheckBox", "orientation" : "Qt.LeftToRight", + "text" : " Checkbox", "value" : 1}}, + "drawLine2" : {"flag" : 0, "data":{ "widget": "QHLine", "text" : "None", "value" : "None"}}, + "qtabdata" : {"flag" : 1, "data":{ "widget": "QTabWidget", "text" : "Measurement: ", "value" : 0, "link" : "QTabViking", "color" : ["#0080aa", "#0000ff"]}} + + }, + "Expert":{ + "debug": {"flag" : 1, "data":{ "widget": "None", "text" : "Debug", "value" : 0}}, + "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Simulation", "value" : 1}} + }, + "GUI": { + "resultsTabTitle" : "Results", + "subResultsTabTitle" : ["Plots", "Plot-2"], + "resultsSeq" : [10, 1] + } +} diff --git a/hush.json~ b/hush.json~ new file mode 100755 index 0000000..c845405 --- /dev/null +++ b/hush.json~ @@ -0,0 +1,67 @@ +{ + "menuFlags":{ + "hasFile": 0, + "loadInitFile": 0, + "hasDaq": 0, + "hasH5": 0, + "hasEpics": 0 + }, + "hdf": { + "destination" : "./" + }, + "IP2":{ + "standby": [-10.0025, 10.0025, 10.0025, 0.05, 0.05, 40.000, 0.05, 0.005, + 10.0025, -10.0025, 10.0025, 0.1392, -25.006, 0.05, 0.05, 2.175, + 0.05, 10.0025, -10.0025, 0.05, 0.05, 0.05, 0.05, -10.0025, + -10.0025] + }, + "IW2":{ + "standby": [-5.001, 5.001, 0.05, -5.001, 5.001, 5.001, -5.001, 0.05, + 0.05, 0.05, 5.001, -5.001, -5.001, 5.001, 0.05, 0.05, + 0.05, -5.001, 10.0025, 27.605, -10.0025, 21.899, 0.05, -6, + 6, 6, 0.05, 0.05, 34.152, 0.5, -0.5, 0.05, + 40.591, 62.5], + "ref" : [-79.00, 87.58, 496, -89.3, 80.5, 82.9, -83.77, -1.81, + 0.40, 1.39, 77.80, -41.43, -62.33, 63.97, -0.33, -0.25, + 0.25, -52.27, 83.98, 520.41, -105.96, 433.61, 0.23, -54.25, + 50.51, 23.46, -40.14, -4.66, 622.91, 2.00, -7.17, -0.73, + 806.99, 1147.69] + }, + "PK1":{ + "standby": [56.791, 0.05, -2.0005, 2.0005, 0.05, 0.05, 44.9525, -2.0005, + -2.0005, 0.05, 25.006, -25.006, 0.05, 0.05, 64.066] + }, + + "PK2":{ + "standby": [0.05, -25.006, 25.006, 17.4, 10.0025, -2.0005, 0.05, 0.05, + 25.85, -10.0025, 10.0025, 0.05, 0.05, -25.006, 25.006, -25.006, + 0.05, 0.05, 0.05, 0.05, 25.006, -25.006, 25.006, -25.006, + 0.05, 25.006, 25.1877, 0.05] + }, + + "SINQ":{ + "standby": [-25.006, 0.05, 25.006, 10.0025, -12.608, 0.05, 10.98, + 15.6045, -18.3075, 0.05, 20.462, 0.05, 21.9925, -19.005, + 46.5345, 18.01, -21.3675] + }, + "UCN":{ + "standby": [9.404, 25.006, -25.006, 0.05, 0.05, 0.05, 0.05, 25.006, + -25.006, 20.625, 10.0025, -10.0025, 0.05, 20.625, 25.006 + ] + }, + + "Parameters":{ + + "drawLine" : {"flag" : 0, "data":{ "widget": "QHLine", "text" : "None", "value" : "None"}} + + }, + "Expert":{ + "debug": {"flag" : 1, "data":{ "widget": "None", "text" : "Debug", "value" : 0}}, + "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Dry run", "value" : 1}} + }, + "GUI": { + "resultsTabTitle" : "Results", + "subResultsTabTitle" : [], + "resultsSeq" : [] + } +} diff --git a/hush.py b/hush.py new file mode 100644 index 0000000..670b4c9 --- /dev/null +++ b/hush.py @@ -0,0 +1,231 @@ +import inspect +import logging +import os +import platform +import random +import sys +import time + +from qtpy import QtCore, QtGui +from qtpy.QtGui import QColor, QFont, QIcon +from qtpy.QtCore import __version__ as QT_VERSION_STR +from qtpy.QtCore import ( + PYQT_VERSION_STR, QFile, QIODevice, Qt, QThread, Signal, Slot) +from qtpy.QtWidgets import ( + QApplication, QDockWidget, QGridLayout, QGroupBox, QHBoxLayout, QLabel, + QMainWindow, QMessageBox, QProgressBar, QPushButton, QSizePolicy, + QSpacerItem, QTabWidget, QTableWidget, QTableWidgetItem, QVBoxLayout, + QWidget) + +from apps4ops.bdbase.base import BaseWindow +from apps4ops.bdbase.enumkind import MsgSeverity, UserMode, Facility +from apps4ops.bdbase.helpbrowser import HelpBrowser +from apps4ops.hipa.sendeloghipa import QSendToELOG + +from apps4ops.hipa.enumkind import ElogHIPA + +from src.gui import AppGui +from pyrcc5 import hush_resources + +_pymodule = os.path.basename(__file__) +_appname, _appext = _pymodule.split(".") +_appversion = "1.0.0" +#_title = """HIPA Power Usage & Saving Hierarchy""" #, HUSH!""" +_title = """HUSH!""" + +def _line(): + """Macro to return the current line number. + + The current line number within the file is used when + reporting messages to the message logging window. + + Returns: + int: Current line number. + """ + return inspect.currentframe().f_back.f_lineno + +class StartMain(BaseWindow): + trigger_log_message = Signal(str, str, int, str, dict) + + def __init__(self, parent=None): + super(StartMain, self).__init__( + parent=parent, pymodule=_pymodule, appversion=_appversion, + title=_title, user_mode=UserMode.OPERATION, facility=Facility.HIPA, + has_optics=False, has_procedure=False) + + self.appname = _appname + self.gui = AppGui(self) + + + + @Slot() + def send_to_elog(self): + + @Slot() + def save_fig_thread_finished(): + + time.sleep(0.2) + + if self.all_data: + QSendToELOG(self, logbook=self.logbook, + projektIdx=self.projekt_idx, + eintragIdx=self.eintrag_idx, + systemIdx=self.system_idx, + statusIdx=self.status_idx, + ordIdx=self.ort_idx, + effektIdx=self.effekt_idx, + title=self.title, + message=self.message, + attachFile=self.attach_files) + + time.sleep(1.0) + return + + #if not self.verify_send_to_elog(): + # return + + + elog = ElogHIPA() + self.projekt_idx = elog.projekt.NONE + self.system_idx = elog.system.MAGNET_POWER_SUPPLIES + self.eintrag_idx = elog.eintrag.INFO + self.ort_idx = elog.ort.GLOBAL + self.status_idx = elog.status.NONE + self.effekt_idx = elog.effekt.NO + + + self.attach_files = [] + + _simulation = self.input_parameters['simulation'] + + if self.all_data: + if self.all_data['Input data'] is not None: + try: + _simulation = self.all_data['Input data']['simulation'] + except KeyError: + _simulation = self.input_parameters['simulation'] + pass + + + self.logbook = "Sandkasten" if _simulation else None + self.title = _title + + sector = ["
IP2: ","
IW2: ","
PK1: ", "
PK2: ","
SNQ: ", + "
UCN: ","
------------------
Tot: "] + pvlist = ['SEC-IP2:TOTSAVE', 'SEC-IW2:TOTSAVE', 'SEC-PK1:TOTSAVE', + 'SEC-PK2:TOTSAVE', 'SEC-SINQ:TOTSAVE', 'SEC-UCN:TOTSAVE', + 'HUSH:TOTSAVE'] + + value, stat, stat_list =self.cafe.getScalarList(pvlist, cacheFlag=True) + + message = "Power saved for the current year stands at {:.3f} MWh:".format( + value[-1]) + for label, val in zip(sector, value): + message += label + "{:.3f}".format(val) + " MWh" + + ''' + message += "IP2: " + str(value[0])+ " MWh
" + message += "IW2: " + str(value[1])+ " MWh
" + message += "PK1: " + str(value[2])+ " MWh
" + message += "PK2: " + str(value[3])+ " MWh
" + message += "SNQ: " + str(value[4])+ " MWh
" + message += "UCN: " + str(value[5])+ " MWh
" + message += "Tot: " + str(value[6])+ " MWh" + ''' + self.message = message + print(self.message, flush=True) + + if not self.all_data: + QSendToELOG(self, logbook=self.logbook, + projektIdx=self.projekt_idx, + eintragIdx=self.eintrag_idx, + systemIdx=self.system_idx, + statusIdx=self.status_idx, + ortIdx=self.ort_idx, + effektIdx=self.effekt_idx, + title=self.title, + message=self.message, + attachFile=self.attach_files) + return + + + _folder_name = self.elog_dest + if not os.path.exists(_folder_name): + os.makedirs(_folder_name) + + time_in_seconds = self.all_data['Ambient data']['Time in seconds'] + if self.all_data['Processed data']['Reanalysis time']: + reanalysis_time = self.all_data['Processed data'][ + 'Reanalysis time in seconds'] + else: + reanalysis_time = None + + self.folder_name = _folder_name + + save_fig_thread = self.SaveFigureThread( + self, self.folder_name, time_in_seconds, reanalysis_time) + save_fig_thread.finished.connect(save_fig_thread_finished) + + save_fig_thread.start() + time.sleep(0.05) + + + @Slot() + def closeEvent(self, event): + + if not self.verify_close_event(): + event.ignore() + return + + BaseWindow.closeEvent(self, event) + + @Slot() + def show_about(self): + """ To overide by application + """ + QApplication.processEvents() + QMessageBox.about( + self, "About", + """{0} v {1} +

Copyright © Paul Scherrer Institut (PSI). + All rights reserved.

+

Author: J. Chrin, Spring 2023

+

(EPICS db adapted from A. Kovach, 2016)

+

IOC Administrator: H. Lutz

+

1st Responsible: A. Barchetti, Tel. 4779 + or 3301 (Control Room)

+ +

Initiates energy saving procedures and records power saved

+

Python {2} - Qt {3} - PyQt {4}
+ cafe {5} - epics {6} on {7}""".format( + _pymodule, _appversion, platform.python_version(), + QT_VERSION_STR, PYQT_VERSION_STR, + self.cafe.CAFE_version(), self.cafe.EPICS_version(), + platform.system())) + QApplication.processEvents() + + @Slot() + def show_help(self): + """ Invoke help pages from hush_resources + """ + index_html ="index.html" #self.appname + "/index.html" + help_base = ":" # + self.appname + help_page = HelpBrowser(help_base, index_html, self) + help_page.show() + +######################################################################### +if __name__ == "__main__": + + app = QApplication(sys.argv) + splash = BaseWindow.initialize_application( + app, appname=_appname, delay=20, facility=Facility.HIPA) + + myapp = StartMain() + + myapp.show() + + if splash is not None: + splash.finish(myapp) + + app.exec_() + diff --git a/hush.py~ b/hush.py~ new file mode 100644 index 0000000..87887a2 --- /dev/null +++ b/hush.py~ @@ -0,0 +1,213 @@ +import inspect +import logging +import os +import platform +import random +import sys +import time + +from qtpy import QtCore, QtGui +from qtpy.QtGui import QColor, QFont, QIcon +from qtpy.QtCore import __version__ as QT_VERSION_STR +from qtpy.QtCore import ( + PYQT_VERSION_STR, QFile, QIODevice, Qt, QThread, Signal, Slot) +from qtpy.QtWidgets import ( + QApplication, QDockWidget, QGridLayout, QGroupBox, QHBoxLayout, QLabel, + QMainWindow, QMessageBox, QProgressBar, QPushButton, QSizePolicy, + QSpacerItem, QTabWidget, QTableWidget, QTableWidgetItem, QVBoxLayout, + QWidget) + +from apps4ops.bdbase.base import BaseWindow +from apps4ops.bdbase.enumkind import MsgSeverity, UserMode, Facility +from apps4ops.bdbase.helpbrowser import HelpBrowser +from apps4ops.hipa.sendeloghipa import QSendToELOG + +from apps4ops.hipa.enumkind import ElogHIPA + +from src.gui import AppGui +from pyrcc5 import hush_resources + +_pymodule = os.path.basename(__file__) +_appname, _appext = _pymodule.split(".") +_appversion = "1.0.0" +_title = """HIPA Power Usage and Saving Hierarchy, HUSH!""" + + + +def _line(): + """Macro to return the current line number. + + The current line number within the file is used when + reporting messages to the message logging window. + + Returns: + int: Current line number. + """ + return inspect.currentframe().f_back.f_lineno + +class StartMain(BaseWindow): + trigger_log_message = Signal(str, str, int, str, dict) + + def __init__(self, parent=None): + super(StartMain, self).__init__( + parent=parent, pymodule=_pymodule, appversion=_appversion, + title=_title, user_mode=UserMode.OPERATION, facility=Facility.HIPA, + has_optics=False, has_procedure=False) + + self.appname = _appname + self.gui = AppGui(self) + + + + @Slot() + def send_to_elog(self): + + @Slot() + def save_fig_thread_finished(): + + time.sleep(0.2) + + if self.all_data: + QSendToELOG(self, logbook=self.logbook, + projektIdx=self.projekt_idx, + eintragIdx=self.eintrag_idx, + systemIdx=self.system_idx, + statusIdx=self.status_idx, + autoIdx=self.auto_idx, + title=self.title, + message=self.message, + attachFile=self.attach_files) + + time.sleep(1.0) + return + + if not self.verify_send_to_elog(): + return + + + elog = ElogHIPA() + self.projekt_idx = elog.projekt.OPTICS + self.system_idx = elog.system.BEAMDYNAMICS + self.eintrag_idx = elog.eintrag.INFO + self.auto_idx = elog.auto.NO + self.status_idx = elog.status.NONE + + + self.attach_files = [] + + _simulation = self.input_parameters['simulation'] + + if self.all_data: + if self.all_data['Input data'] is not None: + try: + _simulation = self.all_data['Input data']['simulation'] + except KeyError: + _simulation = self.input_parameters['simulation'] + pass + + + self.logbook = "Sandkasten" if _simulation else None + self.title = _title + + if not self.all_data: + QSendToELOG(self, logbook=self.logbook, + projektIdx=self.projekt_idx, + eintragIdx=self.eintrag_idx, + systemIdx=self.system_idx, + statusIdx=self.status_idx, + autoIdx=self.auto_idx, + title=self.title, + attachFile=self.attach_files) + + + return + + + message = "" + + _folder_name = self.elog_dest + if not os.path.exists(_folder_name): + os.makedirs(_folder_name) + + time_in_seconds = self.all_data['Ambient data']['Time in seconds'] + if self.all_data['Processed data']['Reanalysis time']: + reanalysis_time = self.all_data['Processed data'][ + 'Reanalysis time in seconds'] + else: + reanalysis_time = None + + self.message = message + + print(message, flush=True) + + self.folder_name = _folder_name + + save_fig_thread = self.SaveFigureThread( + self, self.folder_name, time_in_seconds, reanalysis_time) + save_fig_thread.finished.connect(save_fig_thread_finished) + + save_fig_thread.start() + time.sleep(0.05) + + + + + @Slot() + def closeEvent(self, event): + + if not self.verify_close_event(): + event.ignore() + return + + BaseWindow.closeEvent(self, event) + + @Slot() + def show_about(self): + """ To overide by application + """ + QApplication.processEvents() + QMessageBox.about( + self, "About", + """{0} v {1} +

Copyright © Paul Scherrer Institut (PSI). + All rights reserved.

+

Author: J. Chrin, Spring 2023

+

(EPICS db adapted from A. Kovach, 2016)

+

IOC Administrator: H. Lutz

+

1st Responsible: A. Barchetti, Tel. 4779 + or 3301 (Control Room)

+ +

Initiates energy saving procedures and records power saved

+

Python {2} - Qt {3} - PyQt {4}
+ cafe {5} - epics {6} on {7}""".format( + _pymodule, _appversion, platform.python_version(), + QT_VERSION_STR, PYQT_VERSION_STR, + self.cafe.CAFE_version(), self.cafe.EPICS_version(), + platform.system())) + QApplication.processEvents() + + @Slot() + def show_help(self): + """ Invoke help pages from hush_resources + """ + index_html ="index.html" #self.appname + "/index.html" + help_base = ":" # + self.appname + help_page = HelpBrowser(help_base, index_html, self) + help_page.show() + +######################################################################### +if __name__ == "__main__": + + app = QApplication(sys.argv) + splash = BaseWindow.initialize_application( + app, appname=_appname, delay=20, facility=Facility.HIPA) + + myapp = StartMain() + + myapp.show() + + if splash is not None: + splash.finish(myapp) + + app.exec_() + diff --git a/hush.sh b/hush.sh new file mode 100755 index 0000000..e955f27 --- /dev/null +++ b/hush.sh @@ -0,0 +1,100 @@ +#!/bin/bash +cd /afs/psi.ch/project/pyqtacc/apps4ops/examples/hush/1.0.0 + +# For use if script is sourced rather than executed +appNameDefault="hush.sh" + +module unload gcc +module load gcc/7.3.0 + +if [ -z "$PS1" ] # no prompt? +### if [ -v PS1 ] # On Bash 4.2+ ... +then + # non-interactive + echo "Non-interactive script" +else + # interactive + echo "Interactive/sourced script" +fi + +# Select Python Version here. Currently one of 3.5, 3.7 +PYTHON_VERSION=3.7 + +if [ "$1" ]; then + + if [ "$1" == "3.5" -o "$1" == "35" ]; then + echo "Using default version $PYTHON_VERSION" + elif [ "$1" == "3.7" -o "$1" == "37" ]; then + PYTHON_VERSION=3.7 + else + echo "Requested Python version is not supported" + echo "Using default version $PYTHON_VERSION" + fi + +fi + +echo "PYTHON_VERSION $PYTHON_VERSION" + + +_EPICS_HOST_ARCH=${EPICS_HOST_ARCH} +. /opt/gfa/python $PYTHON_VERSION + +#/sf/bd/applications/OnlineModel/current/PythonModule:/sf/bd/applications/OnlineModel/current +#/sf/bd/applications/OnlineModel/default/scripts/VA: + +#C_EXT version for Py 3.7: +export PYTHONPATH=.:/opt/gfa/cafe/python/pycafe/cafe-1.18.0/lib/${_EPICS_HOST_ARCH}:/afs/psi.ch/project/cafe/gitlab/CAFE:/afs/psi.ch/project/pyqtacc + +#:/afs/psi.ch/intranet/SLS/Controls/BD/pyqtacc/v1.5.2 + +echo $PYTHONPATH + +STDOUT_DIR="/tmp" +#Set to 0 if you do not wish std::out to write to logger +STDOUT_FLAG=1 + +if [ "$#" -gt "0" ]; then + appName=$0 + if [ "$appName" == "-bash" ]; then + appName=$appNameDefault + fi +else +appName=$appNameDefault +fi + +#echo "$appName $@ $#" +baseName="${appName##*/}" +name=$(echo "$baseName" | cut -f 1 -d '.') +nameLog=${name}-$USER +echo "Application: $name" +echo "nameLog: $nameLog" + +#Configuration files can be overwritten +#python ${name}.py -s="/sf/bd/deps/pyqtacc/common/config/style.json" -f="/sf/bd/deps/pyqtacc/v1.0.0/pyqtacc/qrc_resources/facility/sf/config/base.json" -q="/sf/bd/deps/pyqtacc/common/config/acc.qss" & + +if [ "${STDOUT_FLAG}" -gt "0" ] ; then +#if changing the std::out destination, remember to also change it in your json config file (for reading) + if test -f "$STDOUT_DIR/${nameLog}.log---"; then + rm -f $STDOUT_DIR/${nameLog}.log--- + fi + if test -f "$STDOUT_DIR/${nameLog}.log--"; then + cp $STDOUT_DIR/${nameLog}.log-- $STDOUT_DIR/${nameLog}.log--- + rm -f $STDOUT_DIR/${nameLog}.log-- + fi + if test -f "$STDOUT_DIR/${nameLog}.log-"; then + cp $STDOUT_DIR/${nameLog}.log- $STDOUT_DIR/${nameLog}.log-- + rm -f $STDOUT_DIR/${nameLog}.log- + fi + if test -f "$STDOUT_DIR/${nameLog}.log"; then + cp $STDOUT_DIR/${nameLog}.log $STDOUT_DIR/${nameLog}.log- + rm -f $STDOUT_DIR/${nameLog}.log + fi + + python ${name}.py -u ${name}.json >> $STDOUT_DIR/${nameLog}.log 2>&1 & + chmod 777 $STDOUT_DIR/${nameLog}.log +else +#Run instead without std::out + python ${name}.py -u ${name}.json & +fi + + diff --git a/hush.sh~ b/hush.sh~ new file mode 100755 index 0000000..a980a90 --- /dev/null +++ b/hush.sh~ @@ -0,0 +1,98 @@ +#!/bin/bash +cd /afs/psi.ch/project/pyqtacc/apps4ops/examples/hush/1.0.0 + +# For use if script is sourced rather than executed +appNameDefault="hush.sh" + +module unload gcc +module load gcc/7.3.0 + +if [ -z "$PS1" ] # no prompt? +### if [ -v PS1 ] # On Bash 4.2+ ... +then + # non-interactive + echo "Non-interactive script" +else + # interactive + echo "Interactive/sourced script" +fi + +# Select Python Version here. Currently one of 3.5, 3.7 +PYTHON_VERSION=3.7 + +if [ "$1" ]; then + + if [ "$1" == "3.5" -o "$1" == "35" ]; then + echo "Using default version $PYTHON_VERSION" + elif [ "$1" == "3.7" -o "$1" == "37" ]; then + PYTHON_VERSION=3.7 + else + echo "Requested Python version is not supported" + echo "Using default version $PYTHON_VERSION" + fi + +fi + +echo "PYTHON_VERSION $PYTHON_VERSION" + + +_EPICS_HOST_ARCH=${EPICS_HOST_ARCH} +. /opt/gfa/python $PYTHON_VERSION + +#/sf/bd/applications/OnlineModel/current/PythonModule:/sf/bd/applications/OnlineModel/current +#/sf/bd/applications/OnlineModel/default/scripts/VA: + +#C_EXT version for Py 3.7: +export PYTHONPATH=.:/opt/gfa/cafe/python/pycafe/cafe-1.18.0/lib/${_EPICS_HOST_ARCH}:/afs/psi.ch/project/pyqtacc:/afs/psi.ch/intranet/SLS/Controls/BD/pyqtacc/v1.5.2 + +echo $PYTHONPATH + +STDOUT_DIR="/tmp" +#Set to 0 if you do not wish std::out to write to logger +STDOUT_FLAG=1 + +if [ "$#" -gt "0" ]; then + appName=$0 + if [ "$appName" == "-bash" ]; then + appName=$appNameDefault + fi +else +appName=$appNameDefault +fi + +#echo "$appName $@ $#" +baseName="${appName##*/}" +name=$(echo "$baseName" | cut -f 1 -d '.') +nameLog=${name}-$USER +echo "Application: $name" +echo "nameLog: $nameLog" + +#Configuration files can be overwritten +#python ${name}.py -s="/sf/bd/deps/pyqtacc/common/config/style.json" -f="/sf/bd/deps/pyqtacc/v1.0.0/pyqtacc/qrc_resources/facility/sf/config/base.json" -q="/sf/bd/deps/pyqtacc/common/config/acc.qss" & + +if [ "${STDOUT_FLAG}" -gt "0" ] ; then +#if changing the std::out destination, remember to also change it in your json config file (for reading) + if test -f "$STDOUT_DIR/${nameLog}.log---"; then + rm -f $STDOUT_DIR/${nameLog}.log--- + fi + if test -f "$STDOUT_DIR/${nameLog}.log--"; then + cp $STDOUT_DIR/${nameLog}.log-- $STDOUT_DIR/${nameLog}.log--- + rm -f $STDOUT_DIR/${nameLog}.log-- + fi + if test -f "$STDOUT_DIR/${nameLog}.log-"; then + cp $STDOUT_DIR/${nameLog}.log- $STDOUT_DIR/${nameLog}.log-- + rm -f $STDOUT_DIR/${nameLog}.log- + fi + if test -f "$STDOUT_DIR/${nameLog}.log"; then + cp $STDOUT_DIR/${nameLog}.log $STDOUT_DIR/${nameLog}.log- + rm -f $STDOUT_DIR/${nameLog}.log + fi + + python ${name}.py -u ${name}.json >> $STDOUT_DIR/${nameLog}.log 2>&1 & + chmod 777 $STDOUT_DIR/${nameLog}.log +else +#Run instead without std::out + python ${name}.py -u ${name}.json & +fi + + diff --git a/pyrcc5/__pycache__/hush_resources.cpython-37.pyc b/pyrcc5/__pycache__/hush_resources.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bb5f0e0c0a3fb73176eab7e17010e6a4ab44ab4b GIT binary patch literal 2832 zcmc&$PjBNy6dxx}HckI*yRbsQWhkdgk=>?=gurX*fWW}IJPr0 zX&b}=0TL1y?r0C~2_g6d9FPzfJ^&|QIrYks6K|Y2>xgt!*uz?y@tgPFy!U(0^PcDa z@^T%)Q#oqWKi);?PqoM&9f-Ry1ciwrs)eYpIhuxO$tlsYQ>MD3(~47J+IjT?o!_9< z3(cvq8ofblbfH)N1o8W{?kq6fsYf-s2vo(X(=8o3cU&MCARn_0-LJ`Xk+aX zJfRIOt?tX6m^1NFRWZ=_mM{CEZTXB)+me9{nSI1u++ks2nd7x(X41Ol#&l%Y>sDf0 zuDwTk3^#Gy#iyX}XZo&fnTf3wFt!NxIqTk8Pe5_oP;S<3yvxp{Ws<2L7-G^h48t;A z8|S35VP@XIx5B4V`I1n#t_ijI>Y=u-3AO#|p>AIjYU|~pmS3B5Ryz;&?%}=olyQ70 z)QKb!#Rudhh-Isym7(Tl zbGv~bk_hkkz{q@LN7iq{LG@cUwnPHb855W@3MM+1sbsdoIZtciDGOnuI#+LO?Qo(p z4RxN$vFgD@b)1W<^>ToPWW7LnoW?97D9x4%zd0MX8x9%7eb0@DQ0abi+%O*dfxuAg z{!sW?sgooL1CPicj&Kn9j0aNSE|2?I`V1ch5sgo=O9aDSNQ5vfmqSxgttE)MG4GFe zdU5129;uHcm4|}W1{Ool$3$RI>IS_bA8$zrCw(Rv7dYlP25-E9`(%V&hFJuBMjMzJ zJ)<$(!nP(S81&h+gIyW^V+dl8L@X?(fI&2>S*nf*SUJNoR&KqxpM(I3Vt15_;vOCyDxq|r!4+M3vbV@;7OCu8}bW#vv{WdB=wrpdWI52P!BQGL26g>|W5dQ%WUsMPGh5U;}|(YYo| zvMhC3xzOPrf#4pY?QT@L+LzuQJYu~-K*2m>A|7&&eMlrp7rEyhpFnj%VW+nS@)+(K znecV9YIJ)7S(hz|zh*Qxw8TM(N7nK@`Xww)jOwtYShMUxoR9r{s;nVZ`So zg{$ieUsThQnwHfxjc`oe1YWu}*a;blhRGD$ufWc+-2!@dV>zwtjrL_b`wC-I%BXX@ znAdTxk59Jdvzuvc@MQ9hDgqj@bn38u^4SV-RXVuxI~Q)v>c?~lH^v3f5bA(04fVJ6 Wy1u5DRXAn6m0D_b&uBJTTv1(_ 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 literal 0 HcmV?d00001 diff --git a/src/gui.py b/src/gui.py new file mode 100644 index 0000000..2bc8f08 --- /dev/null +++ b/src/gui.py @@ -0,0 +1,705 @@ +import inspect +import os +import platform +import random +import sys +import time +from datetime import timedelta + + +from qtpy import QtCore, QtGui +from qtpy.QtGui import QColor, QFont, QIcon +from qtpy.QtCore import __version__ as QT_VERSION_STR +from qtpy.QtCore import ( + PYQT_VERSION_STR, QDate, QDateTime, QEventLoop, Qt, Signal, Slot) +from qtpy.QtWidgets import ( + QApplication, QDockWidget, QFrame, QGridLayout, QGroupBox, QHBoxLayout, + QLabel, QMainWindow, QMessageBox, QProgressBar, QPushButton, QSizePolicy, + QSpacerItem, QStackedWidget, QTabBar, QTabWidget, QTableWidget, + QTableWidgetItem, QVBoxLayout, QWidget) + + +from apps4ops.bdbase.base import BaseWindow +from apps4ops.bdbase.enumkind import MsgSeverity, UserMode, Facility +from caqtwidgets.pvwidgets import CAQLabel, CAQLineEdit, CAQTableWidget, QHLine + +_pymodule = os.path.basename(__file__) + +def _line(): + """Macro to return the current line number.688 + + The current line number within the file is used when + reporting messages to the message logging window. + + Returns: + int: Current line number. + """ + return inspect.currentframe().f_back.f_lineno + +class AppGui(QWidget): + + def __init__(self, parent): + super(AppGui, self).__init__() + self.parent = parent + self.cafe = self.parent.cafe + self.cyca = self.parent.cyca + self.gui_frame = self.parent.gui_frame + self.gui_header = self.parent.gui_header + self.font_gui = self.parent.gui_frame.font_gui + self.input_parameters = self.parent.input_parameters + self.input_labels = self.parent.input_labels + self.expert_parameters = self.parent.expert_parameters + self.gui_frame.expert_parameters_group.setFixedWidth(260) + self.gui_frame.operator_parameters_group.setFixedWidth(260) + #self.gui_frame.operator_parameters_group.setFixedHeight(260) + self.gui_frame.measurement_tab_wgt.setMinimumWidth(440) + self.gui_frame.measurement_tab_wgt.setFixedHeight(280) + #self.gui_frame.operator_wgt.setFixedHeight(240) + #self.gui_frame.expert_wgt.setFixedHeight(240) + + self.gui_frame.central_tab_widget.tabBar().setTabText(0, "Control") + self.gui_frame.central_tab_widget.tabBar().setTabText(1, "Savings") + + self.expert_labels = self.parent.expert_labels + self.settings = self.parent.settings + + self.obj_to_upper = True if random.randint(1, 10) > 3 else False + + self.table_sol_dict = {} + self.table_pwr_dict = {} + self.offtime_dict = {} + + wgt = self.group_sector_qtabwidget() + self.gui_frame.measurement_layout.addWidget( + wgt, 0, 1, 6, 3, alignment=Qt.AlignTop) + + status_wgt = self.group_sector_status() + + + self.gui_frame.measurement_layout.addWidget( + status_wgt, 2, 0, 2, 1, alignment=Qt.AlignTop) # | Qt.AlignHCenter) + + qf = QFrame() + qf.setFixedHeight(6) + self.gui_frame.measurement_layout.addWidget( + qf, 4, 0, 1, 1, alignment=Qt.AlignTop) + + + self.sectorI_dict = {} + self.sectorI_dict['IP2'] = 0 + self.sectorI_dict['IW2'] = 0 + self.sectorI_dict['PK1'] = 0 + self.sectorI_dict['PK2'] = 0 + self.sectorI_dict['SINQ'] = 0 + self.sectorI_dict['UCN'] = 0 + self.I_min = 0.009 + + ucn_line = ["PK1", "PK2"] + sinq_line = ["PK1", "PK2"] + pk1_line = ["IW2"] + pk2_line = ["IW2"] + + def enable_disable_end(sector, sector_line, value): + self.sectorI_dict[sector] = value + for sector in sector_line: + if self.sectorI_dict['UCN'] > self.I_min or self.sectorI_dict[ + 'SINQ'] > self.I_min: + if self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(False) + else: + if not self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(True) + + def enable_disable_pk(sector, sector_line, value): + self.sectorI_dict[sector] = value + for sector in sector_line: + if self.sectorI_dict['PK1'] > self.I_min or self.sectorI_dict[ + 'PK2'] > self.I_min: + if self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(False) + else: + if not self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(True) + + + def receive_ucn_update(value, status, alarm_severity): + enable_disable_end('UCN', ucn_line, value) + def receive_sinq_update(value, status, alarm_severity): + enable_disable_end('SINQ', sinq_line, value) + def receive_pk1_update(value, status, alarm_severity): + enable_disable_pk('PK1', pk1_line, value) + def receive_pk2_update(value, status, alarm_severity): + enable_disable_pk('PK2', pk2_line, value) + + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_ucn_update) + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_sinq_update) + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_pk1_update) + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_pk2_update) + + + #self.cafe.monitor("MWC2:IST:2", cb) + #print(dir(self.gui_header.header_wgt.layout().widget()), flush=True) + + + def group_sector_status(self): + qgrid = QGridLayout() + #Connect all channels + #Heading + idx = self.settings.data["header"].index("IP2") + #Sector + + qlp = QLabel("Power \n(kW)") + f = qlp.font() + f.setPixelSize(13) + qlp.setFont(f) + qlp.setAlignment(Qt.AlignCenter) + + qli = QLabel("Initial \n(kW)") + f = qli.font() + f.setPixelSize(13) + qli.setFont(f) + qli.setAlignment(Qt.AlignCenter) + qgrid.addWidget(qli, 0, 1, 1, 1) + + qsa = QLabel("Saving \n(MWh)") + f = qsa.font() + f.setPixelSize(13) + qsa.setFont(f) + qsa.setAlignment(Qt.AlignCenter) + + qti = QLabel("Time \nin Standby") + f = qti.font() + f.setPixelSize(13) + qti.setFont(f) + qti.setAlignment(Qt.AlignCenter) + + + qtotsav = QLabel("Tot Saved \n(MWh)") + f = qtotsav.font() + f.setPixelSize(13) + qtotsav.setFont(f) + qtotsav.setAlignment(Qt.AlignCenter) + + qgrid.addWidget(qlp, 0, 2, 1, 1) + qgrid.addWidget(qsa, 0, 3, 1, 1) + qgrid.addWidget(qti, 0, 4, 1, 1) + qgrid.addWidget(qtotsav, 0, 5, 1, 1) + + + for i, sector in enumerate(self.settings.data["header"][idx:]): + a, b, c, d, e, f = self.sector_status(sector) + qgrid.addWidget(a, i+1, 0, 1, 1) + qgrid.addWidget(b, i+1, 1, 1, 1) + qgrid.addWidget(c, i+1, 2, 1, 1) + qgrid.addWidget(d, i+1, 3, 1, 1) + qgrid.addWidget(e, i+1, 4, 1, 1) + qgrid.addWidget(f, i+1, 5, 1, 1) + _line = QHLine() + _line.setFixedHeight(10) + _row = qgrid.rowCount() + qgrid.addWidget(_line, _row, 1, 1, 5) + #qgrid.setRowMinimumHeight(_row, 60) + + + qtot = QLabel("Total:") + f = qtot.font() + f.setPixelSize(13) + qtot.setFont(f) + qgrid.addWidget(qtot, _row+1, 0, 1, 1) + qgrid.addWidget( + CAQLineEdit(self, pv_name="HUSH:TOTPWR", show_units=True), + _row+1, 2, 1, 2) + qgrid.addWidget( + CAQLineEdit(self, pv_name="HUSH:TOTSAVE", show_units=False), + _row+1, 5, 1, 1) + + qgrid.setContentsMargins(9, 20, 9, 9) + + qw = QGroupBox("Savings Overview") + qw.setContentsMargins(9, 9, 9, 9) + qw.setObjectName("OUTER") + qw.setLayout(qgrid) + qw.setFixedWidth(490) #480 + return qw + + + + + def sector_status(self, sector): + '''Create each sector line for inclusion into group + ''' + device = "SEC-" + sector + #Qlabel + qsector = QLabel(sector+":") + f = qsector.font() + f.setPixelSize(13) + qsector.setFont(f) + _color = "black" + try: + _color = self.settings.data[sector]["color"] + except KeyError as ex: + print(ex, self.settings.data[sector]) + + _color_str = "color : {0};".format(_color) + + _incolor = "QLabel {" + _color_str + "}" + + qsector.setStyleSheet(_incolor) + #Savings + pv_pwr_tot = device + ":TOTPWR" + pv_pwr_last = device + ":LASTPWR" + pv_pwr_saved = device + ":LASTSAVE" + pv_pwr_timeout = device + ":OFFTIME" + pv_pwr_totsave = device + ":TOTSAVE" + + self.cafe.openPrepare() + self.cafe.open([pv_pwr_tot, pv_pwr_last, pv_pwr_saved, pv_pwr_timeout]) + self.cafe.openNowAndWait(2.0) + time.sleep(0.5) + + #print("device", device, flush=True) + def cb_outtime(handle, pv, pvdata): + #print("cb", pv, handle, pvdata.value[0]) + #_off = 6000000 + _delta = "{}".format(str(timedelta(seconds=(pvdata.value[0])))) + if ", " in _delta: + _split = _delta.split(", ") + if len(_split[1]) == len("0:00:00"): + _delta = _split[0] + ", " + _split[1] + if 'days,' in _delta: + _delta = _delta.replace("days,", "d") + elif 'day,' in _delta: + _delta = _delta.replace("day,", "d") + try: + self.offtime_dict[pv].setText(_delta) + except KeyError: + pass + + now = QDateTime.currentDateTime() + xdate = QDate(now.date().year(), 1, 15) + xstart = QDateTime(xdate) + #print("delta t ", xstart.secsTo(now)) + #print("{}".format(str(timedelta(seconds=xstart.secsTo(now))))) + + qpinit = CAQLineEdit(self, pv_name=pv_pwr_last, show_units=False) + qpnow = CAQLineEdit(self, pv_name=pv_pwr_tot, show_units=False) + qpsave = CAQLineEdit(self, pv_name=pv_pwr_saved, show_units=False) + qptotsave = CAQLineEdit(self, pv_name=pv_pwr_totsave, show_units=False) + qptime = CAQLineEdit(self, pv_name=pv_pwr_timeout, + monitor_callback=cb_outtime, show_units=True) + + self.offtime_dict[pv_pwr_timeout] = qptime + qptime.setFixedWidth(104) + + #qtdis = QBasicTimer() + #qpnow.setAlignment(Qt.AlignRight) + #qpnow.style().polish(qpnow) + return qsector, qpinit, qpnow, qpsave, qptime, qptotsave + + def group_sector_qtabwidget(self): + + idx_inj = self.settings.data["header"].index("INJ2") + idx = self.settings.data["header"].index("IP2") + #open all PVS + pv = [] + for sector in self.settings.data["header"][idx_inj:]: + device_list = self.settings.data[sector]["device"] + attribute_list = self.settings.data[sector]["attribute"] + for att in attribute_list: + for dev in device_list: + pv.append(dev + ":" + att) + + self.cafe.openPrepare() + self.cafe.open(pv) + self.cafe.openNowAndWait(1.0) + #self.cafe.supplementHandles() + + sector_wgt_dict = {} + sector_wgt_dict["INJ2"] = self.ca_table_rf_widget(sector="INJ2") + + for sector in self.settings.data["header"][idx:]: + sector_wgt_dict[sector] = self.ca_table_sector_widget(sector=sector) + + sector_tab_widget = QTabWidget() + sector_tab_widget.setFont(self.font_gui) + sector_tab_widget.setStyleSheet("QTabBar {font-size: 12pt;}") + sector_tab_widget.tabBar().setShape(QTabBar.TriangularNorth) + + for i, sector in enumerate(self.settings.data["header"][idx:]): + #if sector == "INJ2": + # _title = "RF" + #else: + # _title = sector + sector_tab_widget.addTab(sector_wgt_dict[sector], sector) + color = self.settings.data[sector]["color"] + sector_tab_widget.tabBar().setTabTextColor(i, QColor(color)) + + sector_tab_widget.addTab(sector_wgt_dict["INJ2"], "RF") + color = self.settings.data["INJ2"]["color"] + sector_tab_widget.tabBar().setTabTextColor( + len(self.settings.data["header"][idx:]), QColor(color)) + + return sector_tab_widget + + + def ca_table_rf_widget(self, sector: str="", color: str="MACHINE"): + device_list = self.settings.data[sector]["device"] + attribute_list = self.settings.data[sector]["attribute"] + + pv_dict = {} + for att in attribute_list: + pv_dict[att] = [] #[None] * len(device_list) + for dev in device_list: + pv_dict[att].append(dev + ":" + att) + + table_pwr = [None] * 2 + table_pwr[0] = CAQTableWidget( + self, pv_list=pv_dict['IST:2'][0:4], show_units=False, notify_freq_hz=0, + suffix = "kW", + notify_unison=False, scale_factor=0.001, show_timestamp=False, + init_column=True, pv_list_show=device_list[0:4]) + + table_pwr[1] = CAQTableWidget( + self, pv_list=pv_dict['IST:2'][4:], show_units=False, notify_freq_hz=0, + suffix = "kW", + notify_unison=False, scale_factor=0.001, show_timestamp=False, + init_column=True, pv_list_show=device_list[4:]) + + for tab in table_pwr: + header_item = QTableWidgetItem() + header_init = QTableWidgetItem() + header_standby = QTableWidgetItem() + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_item.setFont(f) + header_item.setText('Device') + header_init.setFont(f) + header_init.setText('Init. Value') + header_value.setFont(f) + header_value.setText('IST:2') + tab.setContentsMargins(15, 0, 15, 10) + tab.setHorizontalHeaderItem(0, header_item) + tab.setHorizontalHeaderItem(1, header_init) + tab.setHorizontalHeaderItem(2, header_value) + tab.setColumnWidth(0, 80) + tab.setColumnWidth(1, 88) + tab.setColumnWidth(2, 88) + tab.setFixedWidth(304) + # _table_height = 700 + #tab.setFixedHeight(_table_height) + tab.restore_layout.removeWidget(tab.restore_value_button) + tab.restore_value_button.deleteLater() + tab.restore_value_button= None + + tab.init_value_button.setToolTip( + ("Shows initial, pre-standby values. Update is also " + + "executed automatically before the standby procedure.")) + + + box = QVBoxLayout() + box.addWidget(table_pwr[0]) + box.addWidget(table_pwr[1]) + box.setAlignment(Qt.AlignTop | Qt.AlignRight) + box.setSpacing(10) + qw = QWidget() + qw.setLayout(box) + + obj_name = self.settings.data[sector]["colorObj"] + if self.obj_to_upper: + obj_name = obj_name.upper() + + qw.setObjectName(obj_name) + + return qw + + + + def check_status_list(self, pv_list, status_list, line): + _brk = ("------------------------------------------------------" + + "------------------------------------------------------") + self.parent.trigger_log_message.emit( + MsgSeverity.INFO.name, _pymodule, line, _brk, {}) + + _options = {} + + for pv, stat in zip(pv_list, status_list): + if stat != self.cyca.ICAFE_NORMAL: + _mess = ("Error in 'set' for " + pv + " ") + _options['statusCode'] = ( + str(stat) + " " + + self.cafe.getStatusCodeAsString(stat)) + _options['statusInfo'] = self.cafe.getStatusInfo(stat) + + self.parent.trigger_log_message.emit( + MsgSeverity.WARN.name, _pymodule, line, _mess, _options) + + + self.parent.trigger_log_message.emit( + MsgSeverity.INFO.name, _pymodule, line, _brk, {}) + + _mess = ("The following devices reported an error " + + "in 'set' operation:") + self.parent.trigger_log_message.emit( + MsgSeverity.INFO.name, _pymodule, line, _mess, {}) + + def check_status(self, pv, stat, line): + if stat != self.cyca.ICAFE_NORMAL: + _mess = ("Error in 'set' for " + pv + ".") + _options = {} + _options['statusCode'] = ( + str(stat) + " " + + self.cafe.getStatusCodeAsString(stat)) + _options['statusInfo'] = self.cafe.getStatusInfo( + stat) + self.parent.trigger_log_message.emit( + MsgSeverity.WARN.name, _pymodule, line, + _mess, _options) + + + + + def on_sector_standby(self): + target = self.sender() + sector = target.sector + _table = self.table_sol_dict[sector] + ##_text = _table.standby_value_button.text() + #_table.standby_value_button + ##target.setText("Downing..") + ##target.setEnabled(False) + QApplication.processEvents(QEventLoop.AllEvents, 1.0) + #QApplication.processEvents() + + #disenable widgets to avoid circular behaviour since + #updates of SOL also update PWR, and vice-versa + self.table_pwr_dict[sector].init_value_button.setEnabled(False) + _table.init_value_button.click() + time.sleep(0.05) + self.table_pwr_dict[sector].init_value_button.setEnabled(True) + + _table.init_value_button.setEnabled(False) + self.table_pwr_dict[sector].init_value_button.click() + time.sleep(0.05) + self.table_sol_dict[sector].init_value_button.setEnabled(True) + + QApplication.processEvents(QEventLoop.AllEvents, 1.0) + + + ''' + #Now read LAST POWER: + _pv = "SEC-" + target.sector + ":TOTPWR" + tot_power = self.cafe.get(_pv, dt='float') + print("TOTAL PWER===>", tot_power, _pv, flush=True) + status = self.cafe.getStatus(_pv) + print(self.cafe.getStatusCodeAsString(status)) + + _pv_target = "SEC-" + target.sector + ":LASTPWR" + status = self.cafe.set(_pv_target, tot_power) + print("TOTAL PWER STATUS SET", _pv_target, status, flush=True) + print(self.cafe.getStatusCodeAsString(status)) + ''' + + if not self.input_parameters['simulation']: + status, status_list, pv_list = _table.set_standby_values() + + if status != self.cyca.ICAFE_NORMAL: + self.check_status_list(pv_list, status_list, _line()) + + #time.sleep(1.5) + #QApplication.processEvents() + ##target.setText(_text) + ##target.setEnabled(False) + ##QApplication.processEvents(QEventLoop.AllEvents, 1.0) + #QApplication.flush() + #QApplication.processEvents() + ##target.setEnabled(True) + ###_table.standby_value_button.style().polish(_table.standby_value_button) + pv = target.sector + ":SAVESTATE" + stat = self.cafe.set(pv, 0) + self.check_status(pv, stat, _line()) + + + def on_sector_restore(self): + target = self.sender() + sector = target.sector + _table = self.table_sol_dict[sector] + + if not self.input_parameters['simulation']: + status, status_list, pv_list = _table.restore_init_values() + + if status != self.cyca.ICAFE_NORMAL: + self.check_status_list(pv_list, status_list, _line()) + + pv = target.sector + ":SAVESTATE" + stat = self.cafe.set(pv, 1) + self.check_status(pv, stat, _line()) + + + def ca_table_sector_widget(self, sector: str="", color: str="MACHINE"): + device_list = self.settings.data[sector]["device"] + attribute_list = self.settings.data[sector]["attribute"] + try: + _standby_values = self.settings.data[sector]["standby"] + except KeyError as ex: + print("On Standby values not given") + + pv_dict = {} + for att in attribute_list: + pv_dict[att] = [] #[None] * len(device_list) + for dev in device_list: + pv_dict[att].append(dev + ":" + att) + + _table_height = 700 + + table_sol = CAQTableWidget( + self, pv_list=pv_dict['SOL:2'], show_units=True, notify_freq_hz=0, + notify_unison=False, scale_factor=1, show_timestamp=False, + init_column=True, pv_list_show=device_list, standby_column=True, + standby_values=_standby_values, standby_delay = 0.09) + + table_sol.restore_value_button.setToolTip( + ("Restore devices to their pre-standby values")) + table_sol.init_value_button.setToolTip( + ("Shows initial, pre-standby values. Update is also " + + "executed automatically before the standby procedure.")) + + table_sol.standby_value_button.sector = sector + table_sol.standby_value_button.clicked.disconnect() + table_sol.standby_value_button.clicked.connect(self.on_sector_standby) + table_sol.restore_value_button.sector = sector + table_sol.restore_value_button.clicked.disconnect() + table_sol.restore_value_button.clicked.connect(self.on_sector_restore) + + self.table_sol_dict[sector] = table_sol + + table_ist = CAQTableWidget( + self, pv_list=pv_dict['IST:2'], show_units=True, notify_freq_hz=2, + notify_unison=True, scale_factor=1, show_timestamp=False, + init_column=False, pv_list_show=[False]) + + table_pwr = CAQTableWidget( + self, pv_list=pv_dict['PWR:2'], show_units=False, notify_freq_hz=0, + suffix = "kW", + notify_unison=False, scale_factor=0.001, show_timestamp=False, + init_column=True, init_list=pv_dict['PWR:2'], pv_list_show=[False]) + + table_pwr.init_value_button.setToolTip( + ("Shows initial, pre-standby values. Update is also " + + "executed automatically before the standby procedure.")) + + self.table_pwr_dict[sector] = table_pwr + + header_item = QTableWidgetItem() + header_init = QTableWidgetItem() + header_standby = QTableWidgetItem() + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_item.setFont(f) + header_item.setText('Device') + header_init.setFont(f) + header_init.setText('Init. Value') + header_standby.setFont(f) + header_standby.setText('Standby') + header_value.setFont(f) + header_value.setText('SOL:2') + table_sol.setContentsMargins(15, 0, 15, 10) + table_sol.setHorizontalHeaderItem(0, header_item) + table_sol.setHorizontalHeaderItem(1, header_init) + table_sol.setHorizontalHeaderItem(2, header_standby) + table_sol.setHorizontalHeaderItem(3, header_value) + table_sol.setColumnWidth(0, 80) + table_sol.setColumnWidth(1, 88) + table_sol.setColumnWidth(2, 80) + table_sol.setColumnWidth(3, 88) + table_sol.setFixedWidth(386) + #table_sol.setFixedHeight(_table_height) + + + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_value.setFont(f) + header_value.setText('IST:2') + table_ist.setContentsMargins(15, 0, 15, 10) + table_ist.setHorizontalHeaderItem(0, header_value) + table_ist.setColumnWidth(0, 90) + table_ist.setFixedWidth(140) + #table_ist .setFixedHeight(_table_height) + + + header_init = QTableWidgetItem() + f = header_init.font() + header_init.setFont(f) + header_init.setText('Init. Value') + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_value.setFont(f) + header_value.setText('PWR:2') + table_pwr.setContentsMargins(15, 0, 15, 10) + table_pwr.setHorizontalHeaderItem(0, header_init) + table_pwr.setHorizontalHeaderItem(1, header_value) + table_pwr.setColumnWidth(0, 88) + table_pwr.setColumnWidth(1, 88) + table_pwr.setFixedWidth(226) + #table_pwr.setFixedHeight(_table_height) + + #table_pwr.restore_layout.removeWidget(table_pwr.restore_value_button) + #table_pwr.restore_value_button.deleteLater() + #table_pwr.restore_value_button= None + + #update_wgt_item = QTableWidgetItem() + #update_wgt = table_pwr.init_value_button + + #table_pwr.init_layout.removeWidget(table_pwr.init_value_button) + #table_pwr.setCellWidget(table_pwr.rowCount()-1, 0, update_wgt) + + def on_sol_update(): + table_sol.init_value_button.setEnabled(False) + table_pwr.init_value_button.click() + time.sleep(0.1) + table_sol.init_value_button.setEnabled(True) + + def on_init_update(): + table_pwr.init_value_button.setEnabled(False) + table_sol.init_value_button.click() + time.sleep(0.1) + table_pwr.init_value_button.setEnabled(True) + + table_sol.init_value_button.sector = sector + table_sol.init_value_button.clicked.connect(on_sol_update) + table_pwr.init_value_button.sector = sector + table_pwr.init_value_button.clicked.connect(on_init_update) + + hbox = QHBoxLayout() + hbox.addWidget(table_sol) + hbox.addWidget(table_ist) + hbox.addWidget(table_pwr) + #hbox.setContentsMargins(40, 40, 40, 40) + hbox.setSpacing(10) + hbox.setAlignment(Qt.AlignTop) + qw = QWidget() + qw.setLayout(hbox) + #qw.setStyleSheet("background-color: {0};".format( + # self.settings.data[sector]["qlingrad"])) + + obj_name = self.settings.data[sector]["colorObj"] + if self.obj_to_upper: + obj_name = obj_name.upper() + + qw.setObjectName(obj_name) + + return qw diff --git a/src/gui.py- b/src/gui.py- new file mode 100644 index 0000000..e57fa8f --- /dev/null +++ b/src/gui.py- @@ -0,0 +1,542 @@ +import inspect +import os +import platform +import random +import sys +import time + +from qtpy import QtCore, QtGui +from qtpy.QtGui import QColor, QFont, QIcon +from qtpy.QtCore import __version__ as QT_VERSION_STR +from qtpy.QtCore import ( + PYQT_VERSION_STR, QFile, QIODevice, Qt, QThread, Signal, Slot) +from qtpy.QtWidgets import ( + QApplication, QDockWidget, QFrame, QGridLayout, QGroupBox, QHBoxLayout, + QLabel, QMainWindow, QMessageBox, QProgressBar, QPushButton, QSizePolicy, + QSpacerItem, QStackedWidget, QTabBar, QTabWidget, QTableWidget, + QTableWidgetItem, QVBoxLayout, QWidget) + + +from apps4ops.bdbase.base import BaseWindow +from apps4ops.bdbase.enumkind import MsgSeverity, UserMode, Facility +from caqtwidgets.pvwidgets import CAQTableWidget + +_pymodule = os.path.basename(__file__) + +def _line(): + """Macro to return the current line number.688 + + The current line number within the file is used when + reporting messages to the message logging window. + + Returns: + int: Current line number. + """ + return inspect.currentframe().f_back.f_lineno + +class AppGui(QWidget): + + def __init__(self, parent): + super(AppGui, self).__init__() + self.parent = parent + self.cafe = self.parent.cafe + self.cyca = self.parent.cyca + self.gui_frame = self.parent.gui_frame + self.gui_header = self.parent.gui_header + self.font_gui = self.parent.gui_frame.font_gui + self.input_parameters = self.parent.input_parameters + self.input_labels = self.parent.input_labels + self.expert_parameters = self.parent.expert_parameters + self.gui_frame.expert_parameters_group.setFixedWidth(260) + self.gui_frame.operator_parameters_group.setFixedWidth(260) + #self.gui_frame.operator_parameters_group.setFixedHeight(260) + self.gui_frame.measurement_tab_wgt.setMinimumWidth(280) + self.gui_frame.operator_wgt.setFixedHeight(240) + self.gui_frame.expert_wgt.setFixedHeight(240) + + self.gui_frame.central_tab_widget.tabBar().setTabText(0, "Control") + self.gui_frame.central_tab_widget.tabBar().setTabText(1, "Savings") + + self.expert_labels = self.parent.expert_labels + self.settings = self.parent.settings + + + self.obj_to_upper = True if random.randint(1, 10) > 3 else False + + + self.table_sol_dict = {} + + #wgt = self.ca_table_sector_widget(sector="IP2") + wgt = self.group_sector_qtabwidget() + self.gui_frame.measurement_layout.addWidget( + wgt, 0, 1, 3, 3, alignment=Qt.AlignTop) + qf = QFrame() + qf.setFixedHeight(600) + self.gui_frame.measurement_layout.addWidget( + qf, 1, 0, 1, 1, alignment=Qt.AlignTop) + + self.sectorI_dict = {} + self.sectorI_dict['IP2'] = 0 + self.sectorI_dict['IW2'] = 0 + self.sectorI_dict['PK1'] = 0 + self.sectorI_dict['PK2'] = 0 + self.sectorI_dict['SINQ'] = 0 + self.sectorI_dict['UCN'] = 0 + self.I_min = 10.10 + + ucn_line = ["PK1", "PK2"] + sinq_line = ["PK1", "PK2"] + pk1_line = ["IW2"] + pk2_line = ["IW2"] + + def enable_disable_end(sector, sector_line, value): + self.sectorI_dict[sector] = value + for sector in sector_line: + if self.sectorI_dict['UCN'] > self.I_min or self.sectorI_dict[ + 'SINQ'] > self.I_min: + if self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(False) + else: + if not self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(True) + + def enable_disable_pk(sector, sector_line, value): + self.sectorI_dict[sector] = value + for sector in sector_line: + if self.sectorI_dict['PK1'] > self.I_min or self.sectorI_dict[ + 'PK2'] > self.I_min: + if self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(False) + else: + if not self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(True) + + + def receive_ucn_update(value, status, alarm_severity): + enable_disable_end('UCN', ucn_line, value) + def receive_sinq_update(value, status, alarm_severity): + enable_disable_end('SINQ', sinq_line, value) + def receive_pk1_update(value, status, alarm_severity): + enable_disable_pk('PK1', pk1_line, value) + def receive_pk2_update(value, status, alarm_severity): + enable_disable_pk('PK2', pk2_line, value) + + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_ucn_update) + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_sinq_update) + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_pk1_update) + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_pk2_update) + + + #self.cafe.monitor("MWC2:IST:2", cb) + + #print(dir(self.gui_header.header_wgt.layout().widget()), flush=True) + + + def group_sector_qtabwidget(self): + + idx_inj = self.settings.data["header"].index("INJ2") + idx = self.settings.data["header"].index("IP2") + #open all PVS + pv = [] + for sector in self.settings.data["header"][idx_inj:]: + device_list = self.settings.data[sector]["device"] + attribute_list = self.settings.data[sector]["attribute"] + for att in attribute_list: + for dev in device_list: + pv.append(dev + ":" + att) + + self.cafe.openPrepare() + self.cafe.open(pv) + self.cafe.openNowAndWait(0.5) + + sector_wgt_dict = {} + sector_wgt_dict["INJ2"] = self.ca_table_rf_widget(sector="INJ2") + + for sector in self.settings.data["header"][idx:]: + sector_wgt_dict[sector] = self.ca_table_sector_widget(sector=sector) + + sector_tab_widget = QTabWidget() + sector_tab_widget.setFont(self.font_gui) + sector_tab_widget.setStyleSheet("QTabBar {font-size: 12pt;}") + sector_tab_widget.tabBar().setShape(QTabBar.TriangularNorth) + + for i, sector in enumerate(self.settings.data["header"][idx:]): + #if sector == "INJ2": + # _title = "RF" + #else: + # _title = sector + sector_tab_widget.addTab(sector_wgt_dict[sector], sector) + color = self.settings.data[sector]["color"] + sector_tab_widget.tabBar().setTabTextColor(i, QColor(color)) + + sector_tab_widget.addTab(sector_wgt_dict["INJ2"], "RF") + color = self.settings.data["INJ2"]["color"] + sector_tab_widget.tabBar().setTabTextColor( + len(self.settings.data["header"][idx:]), QColor(color)) + + return sector_tab_widget + + + def ca_table_rf_widget(self, sector: str="", color: str="MACHINE"): + device_list = self.settings.data[sector]["device"] + attribute_list = self.settings.data[sector]["attribute"] + + pv_dict = {} + for att in attribute_list: + pv_dict[att] = [] #[None] * len(device_list) + for dev in device_list: + pv_dict[att].append(dev + ":" + att) + + table_pwr = [None] * 2 + table_pwr[0] = CAQTableWidget( + self, pv_list=pv_dict['IST:2'][0:4], show_units=False, notify_freq_hz=0, + suffix = "kW", + notify_unison=False, scale_factor=0.001, show_timestamp=False, + init_column=True, pv_list_show=device_list[0:4]) + + table_pwr[1] = CAQTableWidget( + self, pv_list=pv_dict['IST:2'][4:], show_units=False, notify_freq_hz=0, + suffix = "kW", + notify_unison=False, scale_factor=0.001, show_timestamp=False, + init_column=True, pv_list_show=device_list[4:]) + + + for tab in table_pwr: + header_item = QTableWidgetItem() + header_init = QTableWidgetItem() + header_standby = QTableWidgetItem() + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_item.setFont(f) + header_item.setText('Device') + header_init.setFont(f) + header_init.setText('Init. Value') + header_value.setFont(f) + header_value.setText('IST:2') + tab.setContentsMargins(15, 0, 15, 10) + tab.setHorizontalHeaderItem(0, header_item) + tab.setHorizontalHeaderItem(1, header_init) + tab.setHorizontalHeaderItem(2, header_value) + tab.setColumnWidth(0, 80) + tab.setColumnWidth(1, 88) + tab.setColumnWidth(2, 88) + tab.setFixedWidth(304) + # _table_height = 700 + #tab.setFixedHeight(_table_height) + tab.restore_layout.removeWidget(tab.restore_value_button) + tab.restore_value_button.deleteLater() + tab.restore_value_button= None + + tab.init_value_button.setToolTip( + ("Shows initial, pre-standby values. Update is also " + + "executed automatically before the standby procedure.")) + + + + + box = QVBoxLayout() + box.addWidget(table_pwr[0]) + box.addWidget(table_pwr[1]) + box.setAlignment(Qt.AlignTop | Qt.AlignRight) + box.setSpacing(10) + qw = QWidget() + qw.setLayout(box) + + obj_name = self.settings.data[sector]["colorObj"] + if self.obj_to_upper: + obj_name = obj_name.upper() + + qw.setObjectName(obj_name) + + return qw + + + ''' + def check_status_list(self, pv_list, status_list, line): + _mess = ("The following device(s) reported an error " + + "in 'set' operation: ") + _options = {} + stat_previous = self.cyca.ICAFE_NORMAL + for pv, stat in zip(pv_list, status_list): + if stat != self.cyca.ICAFE_NORMAL: + _mess += pv + " " #("Error in 'set' for " + pv + ".") + if stat != stat_previous: + _options['statusCode'] = ( + str(stat) + " " + + self.cafe.getStatusCodeAsString(stat)) + _options['statusInfo'] = self.cafe.getStatusInfo(stat) + if stat_previous != self.cyca.ICAFE_NORMAL: + self.parent.trigger_log_message.emit( + MsgSeverity.WARN.name, _pymodule, line, _mess, + _options) + _mess = "" + stat_previous = stat + + if _mess: + self.parent.trigger_log_message.emit( + MsgSeverity.WARN.name, _pymodule, line, _mess, _options) + + ''' + + def check_status_list(self, pv_list, status_list, line): + _brk = ("------------------------------------------------------" + + "------------------------------------------------------") + self.parent.trigger_log_message.emit( + MsgSeverity.INFO.name, _pymodule, line, _brk, {}) + + _options = {} + + for pv, stat in zip(pv_list, status_list): + if stat != self.cyca.ICAFE_NORMAL: + _mess = ("Error in 'set' for " + pv + " ") + _options['statusCode'] = ( + str(stat) + " " + + self.cafe.getStatusCodeAsString(stat)) + _options['statusInfo'] = self.cafe.getStatusInfo(stat) + + self.parent.trigger_log_message.emit( + MsgSeverity.WARN.name, _pymodule, line, _mess, _options) + + + self.parent.trigger_log_message.emit( + MsgSeverity.INFO.name, _pymodule, line, _brk, {}) + + _mess = ("The following devices reported an error " + + "in 'set' operation:") + self.parent.trigger_log_message.emit( + MsgSeverity.INFO.name, _pymodule, line, _mess, {}) + + def check_status(self, pv, stat, line): + if stat != self.cyca.ICAFE_NORMAL: + _mess = ("Error in 'set' for " + pv + ".") + _options = {} + _options['statusCode'] = ( + str(stat) + " " + + self.cafe.getStatusCodeAsString(stat)) + _options['statusInfo'] = self.cafe.getStatusInfo( + stat) + self.parent.trigger_log_message.emit( + MsgSeverity.WARN.name, _pymodule, line, + _mess, _options) + + + class StandByThread(QThread): + def __init__(self, parent, table): + QThread.__init__(self) + self.parent = parent + self.table = table + self.cafe = self.parent.cafe + self.cyca = self.parent.cyca + print("INIT", flush=True) + + + def __del__(self): + print("WAITING", flush=True) + ##self.wait() + + def run(self): + print("RUNNING", flush=True) + _handles = self.cafe.getHandles()[0] + _status = self.cafe.attachContext(_handles[0]) + status, status_list, pv_list = self.table.set_standby_values() + time.sleep(3) + print("END RUNNING", flush=True) + #return status, status_list, pv_list + + def on_sector_standby(self): + target = self.sender() + + _table = self.table_sol_dict[target.sector] + _text = _table.standby_value_button.text() + + _table.standby_value_button.setEnabled(False) + _table.standby_value_button.setText("Downing..") + QApplication.processEvents() + + status, status_list, pv_list = _table.set_standby_values() + + if status != self.cyca.ICAFE_NORMAL: + self.check_status_list(pv_list, status_list, _line()) + + _table.standby_value_button.setText(_text) + _table.standby_value_button.setEnabled(True) + QApplication.processEvents() + + pv = target.sector + ":SAVESTATE" + stat = self.cafe.set(pv, 1) + self.check_status(pv, stat, _line()) + + ''' + @Slot() + def standby_thread_finished(): + print("FIN", flush=True) + _table.standby_value_button.setText(_text) + _table.standby_value_button.setEnabled(True) + QApplication.processEvents() + + standby_thread = self.StandByThread(self, _table) + print("HERE", flush=True) + standby_thread.finished.connect(standby_thread_finished) + print("HERE2", flush=True) + standby_thread.start() + print("HERE3", flush=True) + time.sleep(0.05) + print("HERE4", flush=True) + ''' + + def on_sector_restore(self): + target = self.sender() + pv = target.sector + ":SAVESTATE" + stat = self.cafe.set(pv, 0) + self.check_status(pv, stat, _line()) + + + def ca_table_sector_widget(self, sector: str="", color: str="MACHINE"): + + device_list = self.settings.data[sector]["device"] + attribute_list = self.settings.data[sector]["attribute"] + try: + _standby_values = self.settings.data[sector]["standby"] + except KeyError as ex: + print("On Standby values not given") + + + pv_dict = {} + for att in attribute_list: + pv_dict[att] = [] #[None] * len(device_list) + for dev in device_list: + pv_dict[att].append(dev + ":" + att) + ''' + self.cafe.openPrepare() + self.cafe.open(pv_dict['SOL:2']) + self.cafe.open(pv_dict['IST:2']) + self.cafe.open(pv_dict['PWR:2']) + self.cafe.openNowAndWait(0.5) + ''' + + _table_height = 700 + + + table_sol = CAQTableWidget( + self, pv_list=pv_dict['SOL:2'], show_units=True, notify_freq_hz=0, + notify_unison=False, scale_factor=1, show_timestamp=False, + init_column=True, pv_list_show=device_list, standby_column=True, + standby_values=_standby_values, standby_delay = 0.09) + + table_sol.restore_value_button.setToolTip( + ("Restore devices to their pre-standby values")) + table_sol.init_value_button.setToolTip( + ("Shows initial, pre-standby values. Update is also " + + "executed automatically before the standby procedure.")) + + table_sol.standby_value_button.sector = sector + table_sol.standby_value_button.clicked.disconnect() + table_sol.standby_value_button.clicked.connect(self.on_sector_standby) + table_sol.restore_value_button.sector = sector + table_sol.restore_value_button.clicked.connect(self.on_sector_restore) + + self.table_sol_dict[sector] = table_sol + + table_ist = CAQTableWidget( + self, pv_list=pv_dict['IST:2'], show_units=True, notify_freq_hz=2, + notify_unison=True, scale_factor=1, show_timestamp=False, + init_column=False, pv_list_show=[False]) + + table_pwr = CAQTableWidget( + self, pv_list=pv_dict['PWR:2'], show_units=False, notify_freq_hz=0, + suffix = "kW", + notify_unison=False, scale_factor=0.001, show_timestamp=False, + init_column=True, init_list=pv_dict['PWR:2'], pv_list_show=[False]) + + header_item = QTableWidgetItem() + header_init = QTableWidgetItem() + header_standby = QTableWidgetItem() + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_item.setFont(f) + header_item.setText('Device') + header_init.setFont(f) + header_init.setText('Init. Value') + header_standby.setFont(f) + header_standby.setText('Standby') + header_value.setFont(f) + header_value.setText('SOL:2') + table_sol.setContentsMargins(15, 0, 15, 10) + table_sol.setHorizontalHeaderItem(0, header_item) + table_sol.setHorizontalHeaderItem(1, header_init) + table_sol.setHorizontalHeaderItem(2, header_standby) + table_sol.setHorizontalHeaderItem(3, header_value) + table_sol.setColumnWidth(0, 80) + table_sol.setColumnWidth(1, 88) + table_sol.setColumnWidth(2, 80) + table_sol.setColumnWidth(3, 88) + table_sol.setFixedWidth(386) + #table_sol.setFixedHeight(_table_height) + + + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_value.setFont(f) + header_value.setText('IST:2') + table_ist.setContentsMargins(15, 0, 15, 10) + table_ist.setHorizontalHeaderItem(0, header_value) + table_ist.setColumnWidth(0, 90) + table_ist.setFixedWidth(140) + #table_ist .setFixedHeight(_table_height) + + + header_init = QTableWidgetItem() + f = header_init.font() + header_init.setFont(f) + header_init.setText('Init. Value') + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_value.setFont(f) + header_value.setText('PWR:2') + table_pwr.setContentsMargins(15, 0, 15, 10) + table_pwr.setHorizontalHeaderItem(0, header_init) + table_pwr.setHorizontalHeaderItem(1, header_value) + table_pwr.setColumnWidth(0, 88) + table_pwr.setColumnWidth(1, 88) + table_pwr.setFixedWidth(226) + #table_pwr.setFixedHeight(_table_height) + + table_pwr.restore_layout.removeWidget(table_pwr.restore_value_button) + table_pwr.restore_value_button.deleteLater() + table_pwr.restore_value_button= None + + hbox = QHBoxLayout() + hbox.addWidget(table_sol) + hbox.addWidget(table_ist) + hbox.addWidget(table_pwr) + #hbox.setContentsMargins(40, 40, 40, 40) + hbox.setSpacing(10) + hbox.setAlignment(Qt.AlignTop) + qw = QWidget() + qw.setLayout(hbox) + #qw.setStyleSheet("background-color: {0};".format( + # self.settings.data[sector]["qlingrad"])) + + obj_name = self.settings.data[sector]["colorObj"] + if self.obj_to_upper: + obj_name = obj_name.upper() + + qw.setObjectName(obj_name) + + return qw diff --git a/src/gui.py~ b/src/gui.py~ new file mode 100644 index 0000000..153ead6 --- /dev/null +++ b/src/gui.py~ @@ -0,0 +1,596 @@ +import inspect +import os +import platform +import random +import sys +import time +from datetime import timedelta + + +from qtpy import QtCore, QtGui +from qtpy.QtGui import QColor, QFont, QIcon +from qtpy.QtCore import __version__ as QT_VERSION_STR +from qtpy.QtCore import ( + PYQT_VERSION_STR, QDate, QDateTime, QEventLoop, Qt, Signal, Slot) +from qtpy.QtWidgets import ( + QApplication, QDockWidget, QFrame, QGridLayout, QGroupBox, QHBoxLayout, + QLabel, QMainWindow, QMessageBox, QProgressBar, QPushButton, QSizePolicy, + QSpacerItem, QStackedWidget, QTabBar, QTabWidget, QTableWidget, + QTableWidgetItem, QVBoxLayout, QWidget) + + +from apps4ops.bdbase.base import BaseWindow +from apps4ops.bdbase.enumkind import MsgSeverity, UserMode, Facility +from caqtwidgets.pvwidgets import CAQLabel, CAQLineEdit, CAQTableWidget + +_pymodule = os.path.basename(__file__) + +def _line(): + """Macro to return the current line number.688 + + The current line number within the file is used when + reporting messages to the message logging window. + + Returns: + int: Current line number. + """ + return inspect.currentframe().f_back.f_lineno + +class AppGui(QWidget): + + def __init__(self, parent): + super(AppGui, self).__init__() + self.parent = parent + self.cafe = self.parent.cafe + self.cyca = self.parent.cyca + self.gui_frame = self.parent.gui_frame + self.gui_header = self.parent.gui_header + self.font_gui = self.parent.gui_frame.font_gui + self.input_parameters = self.parent.input_parameters + self.input_labels = self.parent.input_labels + self.expert_parameters = self.parent.expert_parameters + self.gui_frame.expert_parameters_group.setFixedWidth(260) + self.gui_frame.operator_parameters_group.setFixedWidth(260) + #self.gui_frame.operator_parameters_group.setFixedHeight(260) + self.gui_frame.measurement_tab_wgt.setMinimumWidth(280) + self.gui_frame.operator_wgt.setFixedHeight(240) + self.gui_frame.expert_wgt.setFixedHeight(240) + + self.gui_frame.central_tab_widget.tabBar().setTabText(0, "Control") + self.gui_frame.central_tab_widget.tabBar().setTabText(1, "Savings") + + self.expert_labels = self.parent.expert_labels + self.settings = self.parent.settings + + + self.obj_to_upper = True if random.randint(1, 10) > 3 else False + + self.table_sol_dict = {} + self.table_pwr_dict = {} + + #wgt = self.ca_table_sector_widget(sector="IP2") + wgt = self.group_sector_qtabwidget() + self.gui_frame.measurement_layout.addWidget( + wgt, 0, 1, 3, 3, alignment=Qt.AlignTop) + + status_wgt = self.group_sector_status() + self.gui_frame.measurement_layout.addWidget( + status_wgt, 1, 0, 2, 1, alignment=Qt.AlignTop) + + qf = QFrame() + qf.setFixedHeight(600) + self.gui_frame.measurement_layout.addWidget( + qf, 2, 0, 1, 1, alignment=Qt.AlignTop) + + + self.sectorI_dict = {} + self.sectorI_dict['IP2'] = 0 + self.sectorI_dict['IW2'] = 0 + self.sectorI_dict['PK1'] = 0 + self.sectorI_dict['PK2'] = 0 + self.sectorI_dict['SINQ'] = 0 + self.sectorI_dict['UCN'] = 0 + self.I_min = 0.017 + + ucn_line = ["PK1", "PK2"] + sinq_line = ["PK1", "PK2"] + pk1_line = ["IW2"] + pk2_line = ["IW2"] + + def enable_disable_end(sector, sector_line, value): + self.sectorI_dict[sector] = value + for sector in sector_line: + if self.sectorI_dict['UCN'] > self.I_min or self.sectorI_dict[ + 'SINQ'] > self.I_min: + if self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(False) + else: + if not self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(True) + + def enable_disable_pk(sector, sector_line, value): + self.sectorI_dict[sector] = value + for sector in sector_line: + if self.sectorI_dict['PK1'] > self.I_min or self.sectorI_dict[ + 'PK2'] > self.I_min: + if self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(False) + else: + if not self.table_sol_dict[ + sector].standby_value_button.isEnabled(): + self.table_sol_dict[ + sector].standby_value_button.setEnabled(True) + + + def receive_ucn_update(value, status, alarm_severity): + enable_disable_end('UCN', ucn_line, value) + def receive_sinq_update(value, status, alarm_severity): + enable_disable_end('SINQ', sinq_line, value) + def receive_pk1_update(value, status, alarm_severity): + enable_disable_pk('PK1', pk1_line, value) + def receive_pk2_update(value, status, alarm_severity): + enable_disable_pk('PK2', pk2_line, value) + + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_ucn_update) + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_sinq_update) + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_pk1_update) + self.gui_header.beam_current_wgt_dict[ + "INJ2"].trigger_monitor_float.connect(receive_pk2_update) + + + #self.cafe.monitor("MWC2:IST:2", cb) + #print(dir(self.gui_header.header_wgt.layout().widget()), flush=True) + + def group_sector_status(self): + vbox = QVBoxLayout() + #Connect all channels + #Heading + idx = self.settings.data["header"].index("IP2") + #Sector + hbox =QHBoxLayout() + hbox.addWidget(QLabel(" ")) + hbox.addWidget(QLabel("Power")) + hbox.addWidget(QLabel("Initial")) + qhead = QWidget() + qhead.setLayout(hbox) + vbox.addWidget(qhead) + for i, sector in enumerate(self.settings.data["header"][idx:]): + vbox.addWidget(self.sector_status(sector)) + + qw = QWidget() + qw.setLayout(vbox) + return qw + + + def sector_status(self, sector): + '''Create each sector line for inclusion into group + ''' + device = "SEC-" + sector + #Qlabel + qsector = QLabel(sector+":") + #Savings + pv_pwr_tot = device + ":TOTPWR" + pv_pwr_last = device + ":LASTPWR" + pv_pwr_saved = device + ":SAVEPWR" + + #print("device", device, flush=True) + + now = QDateTime.currentDateTime() + xdate = QDate(now.date().year(), 1, 15) + xstart = QDateTime(xdate) + print("delta t ", xstart.secsTo(now)) + + print("{}".format(str(timedelta(seconds=xstart.secsTo(now))))) + + qpnow = CAQLabel(self, pv_name=pv_pwr_tot, show_units=True) + qpinit = CAQLabel(self, pv_name=pv_pwr_last, show_units=True) + #qpsave = QCALabel(pv=pv_pwr_tot, show_units=True) + #qpsum = QCALabel(pv=pv_pwr_tot, show_units=True) + #qtdis = QBasicTimer() + + hbox =QHBoxLayout() + hbox.addWidget(qsector) + hbox.addWidget(qpnow) + hbox.addWidget(qpinit) + qw = QWidget() + qw.setLayout(hbox) + return qw + + def group_sector_qtabwidget(self): + + idx_inj = self.settings.data["header"].index("INJ2") + idx = self.settings.data["header"].index("IP2") + #open all PVS + pv = [] + for sector in self.settings.data["header"][idx_inj:]: + device_list = self.settings.data[sector]["device"] + attribute_list = self.settings.data[sector]["attribute"] + for att in attribute_list: + for dev in device_list: + pv.append(dev + ":" + att) + + self.cafe.openPrepare() + self.cafe.open(pv) + self.cafe.openNowAndWait(0.5) + self.cafe.supplementHandles() + + sector_wgt_dict = {} + sector_wgt_dict["INJ2"] = self.ca_table_rf_widget(sector="INJ2") + + for sector in self.settings.data["header"][idx:]: + sector_wgt_dict[sector] = self.ca_table_sector_widget(sector=sector) + + sector_tab_widget = QTabWidget() + sector_tab_widget.setFont(self.font_gui) + sector_tab_widget.setStyleSheet("QTabBar {font-size: 12pt;}") + sector_tab_widget.tabBar().setShape(QTabBar.TriangularNorth) + + for i, sector in enumerate(self.settings.data["header"][idx:]): + #if sector == "INJ2": + # _title = "RF" + #else: + # _title = sector + sector_tab_widget.addTab(sector_wgt_dict[sector], sector) + color = self.settings.data[sector]["color"] + sector_tab_widget.tabBar().setTabTextColor(i, QColor(color)) + + sector_tab_widget.addTab(sector_wgt_dict["INJ2"], "RF") + color = self.settings.data["INJ2"]["color"] + sector_tab_widget.tabBar().setTabTextColor( + len(self.settings.data["header"][idx:]), QColor(color)) + + return sector_tab_widget + + + def ca_table_rf_widget(self, sector: str="", color: str="MACHINE"): + device_list = self.settings.data[sector]["device"] + attribute_list = self.settings.data[sector]["attribute"] + + pv_dict = {} + for att in attribute_list: + pv_dict[att] = [] #[None] * len(device_list) + for dev in device_list: + pv_dict[att].append(dev + ":" + att) + + table_pwr = [None] * 2 + table_pwr[0] = CAQTableWidget( + self, pv_list=pv_dict['IST:2'][0:4], show_units=False, notify_freq_hz=0, + suffix = "kW", + notify_unison=False, scale_factor=0.001, show_timestamp=False, + init_column=True, pv_list_show=device_list[0:4]) + + table_pwr[1] = CAQTableWidget( + self, pv_list=pv_dict['IST:2'][4:], show_units=False, notify_freq_hz=0, + suffix = "kW", + notify_unison=False, scale_factor=0.001, show_timestamp=False, + init_column=True, pv_list_show=device_list[4:]) + + + for tab in table_pwr: + header_item = QTableWidgetItem() + header_init = QTableWidgetItem() + header_standby = QTableWidgetItem() + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_item.setFont(f) + header_item.setText('Device') + header_init.setFont(f) + header_init.setText('Init. Value') + header_value.setFont(f) + header_value.setText('IST:2') + tab.setContentsMargins(15, 0, 15, 10) + tab.setHorizontalHeaderItem(0, header_item) + tab.setHorizontalHeaderItem(1, header_init) + tab.setHorizontalHeaderItem(2, header_value) + tab.setColumnWidth(0, 80) + tab.setColumnWidth(1, 88) + tab.setColumnWidth(2, 88) + tab.setFixedWidth(304) + # _table_height = 700 + #tab.setFixedHeight(_table_height) + tab.restore_layout.removeWidget(tab.restore_value_button) + tab.restore_value_button.deleteLater() + tab.restore_value_button= None + + tab.init_value_button.setToolTip( + ("Shows initial, pre-standby values. Update is also " + + "executed automatically before the standby procedure.")) + + + box = QVBoxLayout() + box.addWidget(table_pwr[0]) + box.addWidget(table_pwr[1]) + box.setAlignment(Qt.AlignTop | Qt.AlignRight) + box.setSpacing(10) + qw = QWidget() + qw.setLayout(box) + + obj_name = self.settings.data[sector]["colorObj"] + if self.obj_to_upper: + obj_name = obj_name.upper() + + qw.setObjectName(obj_name) + + return qw + + + + def check_status_list(self, pv_list, status_list, line): + _brk = ("------------------------------------------------------" + + "------------------------------------------------------") + self.parent.trigger_log_message.emit( + MsgSeverity.INFO.name, _pymodule, line, _brk, {}) + + _options = {} + + for pv, stat in zip(pv_list, status_list): + if stat != self.cyca.ICAFE_NORMAL: + _mess = ("Error in 'set' for " + pv + " ") + _options['statusCode'] = ( + str(stat) + " " + + self.cafe.getStatusCodeAsString(stat)) + _options['statusInfo'] = self.cafe.getStatusInfo(stat) + + self.parent.trigger_log_message.emit( + MsgSeverity.WARN.name, _pymodule, line, _mess, _options) + + + self.parent.trigger_log_message.emit( + MsgSeverity.INFO.name, _pymodule, line, _brk, {}) + + _mess = ("The following devices reported an error " + + "in 'set' operation:") + self.parent.trigger_log_message.emit( + MsgSeverity.INFO.name, _pymodule, line, _mess, {}) + + def check_status(self, pv, stat, line): + if stat != self.cyca.ICAFE_NORMAL: + _mess = ("Error in 'set' for " + pv + ".") + _options = {} + _options['statusCode'] = ( + str(stat) + " " + + self.cafe.getStatusCodeAsString(stat)) + _options['statusInfo'] = self.cafe.getStatusInfo( + stat) + self.parent.trigger_log_message.emit( + MsgSeverity.WARN.name, _pymodule, line, + _mess, _options) + + + + def on_sector_standby(self): + target = self.sender() + sector = target.sector + + _table = self.table_sol_dict[sector] + _text = _table.standby_value_button.text() + + #_table.standby_value_button + target.setText("Downing..") + target.setEnabled(False) + QApplication.processEvents(QEventLoop.AllEvents, 1.0) + #QApplication.processEvents() + + #disenable widgets to avoid circular behaviour since + #updates of SOL also update PWR, and vice-versa + self.table_pwr_dict[sector].init_value_button.setEnabled(False) + _table.init_value_button.click() + time.sleep(0.05) + self.table_pwr_dict[sector].init_value_button.setEnabled(True) + + _table.init_value_button.setEnabled(False) + self.table_pwr_dict[sector].init_value_button.click() + time.sleep(0.05) + self.table_sol_dict[sector].init_value_button.setEnabled(True) + + QApplication.processEvents(QEventLoop.AllEvents, 1.0) + + #Now read LAST POWER: + _pv = "SEC-" + target.sector + ":TOTPWR" + tot_power = self.cafe.get(_pv, dt='float') + print("TOTAL PWER===>", tot_power, _pv, flush=True) + status = self.cafe.getStatus(_pv) + print(self.cafe.getStatusCodeAsString(status)) + + _pv_target = "SEC-" + target.sector + ":LASTPWR" + status = self.cafe.set(_pv_target, tot_power) + print("TOTAL PWER STATUS SET", _pv_target, status, flush=True) + print(self.cafe.getStatusCodeAsString(status)) + + + status, status_list, pv_list = _table.set_standby_values() + + if status != self.cyca.ICAFE_NORMAL: + self.check_status_list(pv_list, status_list, _line()) + + #time.sleep(1.5) + #QApplication.processEvents() + target.setText(_text) + target.setEnabled(False) + QApplication.processEvents(QEventLoop.AllEvents, 1.0) + #QApplication.flush() + #QApplication.processEvents() + target.setEnabled(True) + ###_table.standby_value_button.style().polish(_table.standby_value_button) + + + ##pv = target.sector + ":SAVESTATE" + ##stat = self.cafe.set(pv, 1) + ##self.check_status(pv, stat, _line()) + + + def on_sector_restore(self): + target = self.sender() + pv = target.sector + ":SAVESTATE" + #stat = self.cafe.set(pv, 0) + #self.check_status(pv, stat, _line()) + + + def ca_table_sector_widget(self, sector: str="", color: str="MACHINE"): + + device_list = self.settings.data[sector]["device"] + attribute_list = self.settings.data[sector]["attribute"] + try: + _standby_values = self.settings.data[sector]["standby"] + except KeyError as ex: + print("On Standby values not given") + + pv_dict = {} + for att in attribute_list: + pv_dict[att] = [] #[None] * len(device_list) + for dev in device_list: + pv_dict[att].append(dev + ":" + att) + + _table_height = 700 + + table_sol = CAQTableWidget( + self, pv_list=pv_dict['SOL:2'], show_units=True, notify_freq_hz=0, + notify_unison=False, scale_factor=1, show_timestamp=False, + init_column=True, pv_list_show=device_list, standby_column=True, + standby_values=_standby_values, standby_delay = 0.09) + + table_sol.restore_value_button.setToolTip( + ("Restore devices to their pre-standby values")) + table_sol.init_value_button.setToolTip( + ("Shows initial, pre-standby values. Update is also " + + "executed automatically before the standby procedure.")) + + table_sol.standby_value_button.sector = sector + table_sol.standby_value_button.clicked.disconnect() + table_sol.standby_value_button.clicked.connect(self.on_sector_standby) + table_sol.restore_value_button.sector = sector + table_sol.restore_value_button.clicked.connect(self.on_sector_restore) + + + self.table_sol_dict[sector] = table_sol + + table_ist = CAQTableWidget( + self, pv_list=pv_dict['IST:2'], show_units=True, notify_freq_hz=2, + notify_unison=True, scale_factor=1, show_timestamp=False, + init_column=False, pv_list_show=[False]) + + table_pwr = CAQTableWidget( + self, pv_list=pv_dict['PWR:2'], show_units=False, notify_freq_hz=0, + suffix = "kW", + notify_unison=False, scale_factor=0.001, show_timestamp=False, + init_column=True, init_list=pv_dict['PWR:2'], pv_list_show=[False]) + + table_pwr.init_value_button.setToolTip( + ("Shows initial, pre-standby values. Update is also " + + "executed automatically before the standby procedure.")) + + self.table_pwr_dict[sector] = table_pwr + + + header_item = QTableWidgetItem() + header_init = QTableWidgetItem() + header_standby = QTableWidgetItem() + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_item.setFont(f) + header_item.setText('Device') + header_init.setFont(f) + header_init.setText('Init. Value') + header_standby.setFont(f) + header_standby.setText('Standby') + header_value.setFont(f) + header_value.setText('SOL:2') + table_sol.setContentsMargins(15, 0, 15, 10) + table_sol.setHorizontalHeaderItem(0, header_item) + table_sol.setHorizontalHeaderItem(1, header_init) + table_sol.setHorizontalHeaderItem(2, header_standby) + table_sol.setHorizontalHeaderItem(3, header_value) + table_sol.setColumnWidth(0, 80) + table_sol.setColumnWidth(1, 88) + table_sol.setColumnWidth(2, 80) + table_sol.setColumnWidth(3, 88) + table_sol.setFixedWidth(386) + #table_sol.setFixedHeight(_table_height) + + + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_value.setFont(f) + header_value.setText('IST:2') + table_ist.setContentsMargins(15, 0, 15, 10) + table_ist.setHorizontalHeaderItem(0, header_value) + table_ist.setColumnWidth(0, 90) + table_ist.setFixedWidth(140) + #table_ist .setFixedHeight(_table_height) + + + header_init = QTableWidgetItem() + f = header_init.font() + header_init.setFont(f) + header_init.setText('Init. Value') + header_value = QTableWidgetItem() + f = header_value.font() + f.setPixelSize(13) + header_value.setFont(f) + header_value.setText('PWR:2') + table_pwr.setContentsMargins(15, 0, 15, 10) + table_pwr.setHorizontalHeaderItem(0, header_init) + table_pwr.setHorizontalHeaderItem(1, header_value) + table_pwr.setColumnWidth(0, 88) + table_pwr.setColumnWidth(1, 88) + table_pwr.setFixedWidth(226) + #table_pwr.setFixedHeight(_table_height) + + #table_pwr.restore_layout.removeWidget(table_pwr.restore_value_button) + #table_pwr.restore_value_button.deleteLater() + #table_pwr.restore_value_button= None + + #update_wgt_item = QTableWidgetItem() + #update_wgt = table_pwr.init_value_button + + #table_pwr.init_layout.removeWidget(table_pwr.init_value_button) + #table_pwr.setCellWidget(table_pwr.rowCount()-1, 0, update_wgt) + + def on_sol_update(): + table_sol.init_value_button.setEnabled(False) + table_pwr.init_value_button.click() + time.sleep(0.1) + table_sol.init_value_button.setEnabled(True) + + def on_init_update(): + table_pwr.init_value_button.setEnabled(False) + table_sol.init_value_button.click() + time.sleep(0.1) + table_pwr.init_value_button.setEnabled(True) + + table_sol.init_value_button.sector = sector + table_sol.init_value_button.clicked.connect(on_sol_update) + table_pwr.init_value_button.sector = sector + table_pwr.init_value_button.clicked.connect(on_init_update) + + hbox = QHBoxLayout() + hbox.addWidget(table_sol) + hbox.addWidget(table_ist) + hbox.addWidget(table_pwr) + #hbox.setContentsMargins(40, 40, 40, 40) + hbox.setSpacing(10) + hbox.setAlignment(Qt.AlignTop) + qw = QWidget() + qw.setLayout(hbox) + #qw.setStyleSheet("background-color: {0};".format( + # self.settings.data[sector]["qlingrad"])) + + obj_name = self.settings.data[sector]["colorObj"] + if self.obj_to_upper: + obj_name = obj_name.upper() + + qw.setObjectName(obj_name) + + return qw