From 9bdd59a110b19d1814f2612c107fc45cffe57012 Mon Sep 17 00:00:00 2001 From: chrin Date: Mon, 10 Jan 2022 13:18:29 +0100 Subject: [PATCH] initial commit --- __pycache__/base.cpython-37.pyc | Bin 0 -> 2108 bytes __pycache__/enumkind.cpython-37.pyc | Bin 0 -> 1534 bytes __pycache__/guiheader.cpython-37.pyc | Bin 0 -> 11555 bytes __pycache__/guiheader.cpython-38.pyc | Bin 0 -> 2762 bytes __pycache__/mainwindow.cpython-37.pyc | Bin 0 -> 3049 bytes __pycache__/mainwindow.cpython-38.pyc | Bin 0 -> 2396 bytes enumkind.py | 40 +++ enumkind.py~ | 39 +++ guiheader.py | 438 ++++++++++++++++++++++++++ guiheader.py~ | 438 ++++++++++++++++++++++++++ mainwindow.py | 62 ++++ mainwindow.py~ | 62 ++++ sf.json | 153 +++++++++ sf.json~ | 150 +++++++++ 14 files changed, 1382 insertions(+) create mode 100644 __pycache__/base.cpython-37.pyc create mode 100644 __pycache__/enumkind.cpython-37.pyc create mode 100644 __pycache__/guiheader.cpython-37.pyc create mode 100644 __pycache__/guiheader.cpython-38.pyc create mode 100644 __pycache__/mainwindow.cpython-37.pyc create mode 100644 __pycache__/mainwindow.cpython-38.pyc create mode 100644 enumkind.py create mode 100644 enumkind.py~ create mode 100644 guiheader.py create mode 100644 guiheader.py~ create mode 100644 mainwindow.py create mode 100644 mainwindow.py~ create mode 100644 sf.json create mode 100644 sf.json~ diff --git a/__pycache__/base.cpython-37.pyc b/__pycache__/base.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..65f78ba971b890dc0a7908fbbc0421ba47b3522d GIT binary patch literal 2108 zcmY+FS#R4$5P(VQKCJl6ecN%O9FpT4b`s~Xe5bZ!Muvk90uVI0mYH%$dPyZ#AfOKk zkp6)F0OzrPiLdQT|3aTSBg%10fZxvS&hBsyl8u3ZqC(f$U%#2ZW)QmYE4Jz?z@z4>sDXwlNMRb%n1KvtA&WW4VIJ~WfC3hwh$Sdt8Ok^S11j%J(Y^|t z>d9$$5Qkt0hhZ2;U<5~D6vto;Ps3?E17~_R8TTxngL8Nu&iC}JdjT)PMZ5%;@G@M+ zD{uv`!d1Km*YG-A$8i|P37Ehea04e{5^usyyal(g3RS!fxA6|#!Mku5@4-E+K@ICr z$0?Y?`*0tpVHzL61AGV%@ew@2$M6_uU)Xc8(%a_Rn@yv+{Wi`vot9_1ak}aHQJm429aqGK-mvEF`6RBrSri`~ zOT<}yqaBGunrezDa=cbZ_D$!rh&4T;)ollbjPnOOLWYj-Rn@p;7#|bGFseB+S@2z7 z#%28{(P@f2^IInM+ju-JkB)Q~B#5sM-IYcw4YCI{E<#Hk|I;QKl zs^jsHKEE4A(zK$rNZ^hmKGD8;E21YMhl#Kv{dT}w5V($I_SYKiDDu5ztw4{6yMDtz zq}|EcaY52=c0}pw9i14j z($JsJ>g(pNaLLaP!*$0KOSTiy0qaf}^<9?q4NA#7$Fu!Ul%@^gwJ8rgG)zgR8zKzN zmS6`Jeaj`=ZE+a&&fz5aElCE6=~g@3Pr{{rO-uT&J1>RF3e|DTr>u17fts#k_bPB4 z<$&G{Tr=FKEkbxy$Y#``J{eBNHvwm|zp12e`@Z|b$<9f@IlUi{TKk-tu1(jbs6~nm zGZaZ|7I*3K#oq+J!pj7qfNCqC+39b}o@#4$>T3Z~-;}fhY3lDxTs+CprgglP$5j6g zUy~3ik=j+hXh&LC{jRD?SCePEnx{pnu41ISDLL6qk(MDX+f_cKk8(EIz1K+3(_QG& zZlh=`c!asDoNX zt!SfaR{cD3lGoaCY}M4}<|gHwg5`&$V2g&4#7c76Fb>+Lo2>LsjtBY=X$jXg47o}^ zdZ?;$h2=E{=kF5Tp+?ASJ-zxm*8DIo9YjH=rbi3D6q1)ES5N0eJU0eckZZh0KLo1UE4Eo=n>=@M zZ#Bmf^{H&oJdE@^tF~+R8jB(4cpKODr0j{rMUV4yN#D>fjw;Vd&ZlNmWpzRuRDUm( L)ry)8XQA<-9 literal 0 HcmV?d00001 diff --git a/__pycache__/enumkind.cpython-37.pyc b/__pycache__/enumkind.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cfd3b401dd804e884a91b62415ba5f8ceb5fa9ca GIT binary patch literal 1534 zcmb7E$#T;`5FM?SZ8c`#B9PzbmgR9;6%4RP(xfG}F`lx}`UbMvcI@{p)+&Q3&~s#&Up7HeqIu0R$1! zh>RsJNo0!%Stw^jD5o-)g&L5SR=^(8lJbf>nbFD7c!2hDsGw}Z%-R46;gTS5P7?AN z;R<+DgbLo&L_Jlw2DT=2u=Uc`!LA4cY@@U*q6+uba+8jx2f^22mUU=%Ac12XC^2pa zX7&W&gq%a2gBJY{$M$F zhgyfnUuN-OU}gJO0+f9oPQ=C`+!{s0$#51$8YZCw5Xpq++nviPZ!C9RVH#7|gqht2 zxL}$qLguPaAW!w0n`N?P_6442Ee&Is#N#B2@>&#)r{ZXYx*0`Zj^fecjq0+Fm)CpL z4*EXrQ5KfTUjh@nrC5AyvJ4eNQl)Zbb<|H`%fC@`O{iQK8m|bQ8=}Ii!r(Pg<#kbm zjOyQRT_I*(sxqH+4ICCS0(M1#Arwe!fwUGC1OtGz%yb=O+C;bkkgLpNlp8L4OP$d3 zx!!e|?L1q^=L`9Q>$Y$A+<-UdGI~Sp9&Dun*X(fH3;22|F4iycgT0cLBw;uhYjzU= zNxJ%^_MnPOX|cM$F(+(WpJ z@BrZ#;U{?>fkK*M=2-s|SZ@xZ~|ozufE6Ag_8m)VFarm;Fwz z2k`ZUdt85SJNnX0XmXfRZ_n7;_rBxnsxU literal 0 HcmV?d00001 diff --git a/__pycache__/guiheader.cpython-37.pyc b/__pycache__/guiheader.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9c00d2a19c911e63bfaec4bc42ed26210e123e6b GIT binary patch literal 11555 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 K;uqti=Klh*+iJ)F literal 0 HcmV?d00001 diff --git a/__pycache__/guiheader.cpython-38.pyc b/__pycache__/guiheader.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..764eff302a81678421c7a4b069e53497e9dba3f3 GIT binary patch literal 2762 zcmbtW-ESN<5V!Z^c5m+^A5GJyE#*KUae#7s3!#EYLz5!XkfR?+epzkKn`EQi+pX=R z$?5u(ib_cQ57)>33H&R5|LS)J9hfCX8DHL@ma zW-Zpr+N_<;vAJxX&1Va2AzNgN*(G)`m_9C*AsZrL#FoItOvYW6{~mMd$vLM9Pgj zTfr$DfOM(0`l@Sbx4)4Om2UOFAF4-Dn(#>FqTANZ{#sF_$skfmKGe1ThKRCQH~O0* z;akyhK2o|4gM3un&W~XJE_Bs=t-lrR#wp0Rl3{#@Cko{EVkx8jxK!R5$%ES?rC?>h zf4@kEI34sKM7uvHd_PA02YH@WDvkc5v&FrBsnV_M`SrE_cll^Hjb}^vFjMZ`KyJ3X z2ZMX@aAYiIj+EO6AevdXfd?1TxN@S2G387gtC+x?$nIZBl*r2~xO`OmHf@+V+o z!YF{m;*{CX$sRz3+s}OFaEH6k2y^)Y_qhLzvKp`R0A@Vi;7#a#-r{ZO>wJ#SLmxaR z4q**Q>7uT0KK%Z!N$7aF1AM0(bk@^I%Af<^VCDq+f;^%Ydzk`JM9~R3v8L7wLdk?4 z+7lAm&^ypOoB(xURD-?-y$8Lgd`?fmDy&b)VSO5K>jedTqGdxhPtc|XlGe06A=9}R z#7GIa>uiq$84YDe#v<7}ZNUDgH-U8LwJS$OEW`~MX+I2;VWPrNdr?sg5o5lLl}d*D zQa9v5{-ny6b_UU24D@&q2|SYa_W-!z{wUE+u-M6yp}L=pW8HdUFccod$^L;7b<}N@ z7a>e5+})A`wH{-vZ;8RM*3BfI$w!m*lToy=YJN3Yn}9 z4tj;i595LAp>w_cM5WPgZ+&g!POmtAtfIl7C--{bV!8claV$Ep;vzJ;41~}&_2E}D zG@wnxjTc`fdUY0_0Y&xdLmt~YG>IwZ5b>9ETYLokODaBu&hRDq7>0TwhnSnoJUi^W zFfA=0gpRMD?f4HpU0Z{@pU8pHMSb{OXt=X+;a6Z3IU!H2i8ZAYiU30(z{pn4p$n~c zdp6^7TFLy0;S@j%AQT)nCUk{x3!44A_0*o&(L?V zo>Vu@`0hGPfP!yE5As5Lu)szdDFf68kn&h8fxdVfjU1?-k#3_(auoBsB?jL^(Hu

B6V4IK-bYaBD>dGnFe}!Tbzr zSI#!QpmSkMOaNYT1Fv_00U($c_jmdf0S51_Nj^ZWgvErKh%?s|g4cp7J^+KSp-IFJ!QjDfynOBq=gP;0BmCVgU)3cYS#fJyzwbB3FxFDo$KN1ye3A wBZrTGxPk;Ps#rmC4as#R_(GnGf(eDWUH+{y+TS3^B>LspO*&7%bv|_e2Hv2sH~;_u literal 0 HcmV?d00001 diff --git a/__pycache__/mainwindow.cpython-37.pyc b/__pycache__/mainwindow.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1995cdcf7cfe7535d279b0b6b496fa8a4e24e9e0 GIT binary patch literal 3049 zcmZuzS#R4&5+ptyYn5U^C>3C)^1o*MKtGc?nuIBv6NI}8J``h2m|04B2 z8k{_7B;Mm23{^$36iam!h`%bRIMy7Ery#}Ckmec4@GN9`4su)vo#!FX3sB%iDDo1N z_y~;fGL%(XpTc#cFc#5i=L{c*aXtYPd=e)4Svbq5V2V$}G(QLDBAJYHo?n0q{32Y8 z##!e(ehDt|%W#=rfh)WM6@C@2@@sI7Ux(}b2HfB`;U>QYxA<+i&F{b+UWF>Z3wQZF zxX16qef|I*@EX*39qN1rX81#R$REKY{umzfC-8(ng{S-(Jmb&dIe!5!_)B=nXJMAV zf>-=CyykD<4Sx%7`8#+Q*_3nM^EsG{Xx*9T3$VZ!VKEx#oh7~u%Mo30R`@EcstQy4 zYe#=#AC6U6w~DY~m8_Ak3T&<@R@oZ;s#v3J?l1*gmfBRRWB;d^Y*tI**!G_rJI1G_ zkIl8MO{2N=6m~FWx z8UJLnJzO`}mS_oX7!xbP8~8NxeaCK_32%NNrRT=HJetT`-n{n(SI4@;Vq?*3fBwO? zx=e;;91L0xYx=fJQpLzsiDb61EKJUDaz)tIy1DNSB)Th79Sg7GCz;PS*3A}kaG!62 z>$c05EL)<2bvuyBmc_;fy5tAjwY)ua(*|<~=m+}Dn*v2QSP+<9MjMnH+YZX^urD&w zLr(I#0tI5x?Lp9skBjS?ZQ(i2oM0vmFpk?EdSxFCYC5(RMd0L=BaNo-m_ZMhFy>+) zn{prXWIX@KAj#o*N6{ukMt@t(XNBc!`e)3rcFtG@@Pmb;2V?>q;jMlD}Ak>!sJ&E{Tt{XRxU1+$S3G63^?wzBX?_7S(54s*5} z_^d6%QgVt;ly%vT(K6egL%n0rsa)@0idaNFJ}RiU%?_(~ zZRwb;`oi4uQr+L*m1etL4?1;@iIf=X?}wR4=Vfv+`C7?~WyIgaAVc%`1a}dbLQNht zOJylbvox0OXF8dml#Xhptn}ABWPei93gj?CnXqu0;G3b+&PHk!C5K<4Q}_n|Mv#hB zhsvRLqz%=fHcSoE$7xj=YDXzcJy!ps4HYB(*X%Hj-;B%-m7&s4AJS|Nsa#)2N|$+@ z&qT8YSv*7;qa;V7ZyBY^N27>^{@AgKnoq{L{+VQ4IvS_hZ=(rI`$kV%shB=Gi!!Bz z*5y=xTAq{V4;3r2*HY-vo1t2>|AAMdy^c5K!Njk6QYDb4kj$!H2s6RJXF{yt;X~ap zY}b~CfwS1ZWSBF3-=%(&kr+ZI-jY)XG=+8>mvTBqT)ot+}$D!s0VR2Xb`?ZE# z@B|Z7rh-aGki4Mk6jV)u%1Y=2c>?-_6GZ~*onnNbjDVNPZ+{gEiT0I&Ek;RdjNlBx zIKc$LB*9q(m`KE<3%fb+sX2-%VoxK4<%AsvJrL)JbDrP=!9{}a2rdy&;}KT~Dg;*v zt`S@(xIu7};1wQC7T#qw0`Usj;q>n~cu(`s*zlvgj>G?Z5iH24VxtO%$rA-Zr-q!QQmJ&q zv~S8@sMBUq;bYd(U4$t^xrP5*zp4T%m?%R|FM-pf5B1k^lD@?bqy*$>%=OfZR7t&o R8UN2h39~-V`Lw1Ne*yYSZO{M! literal 0 HcmV?d00001 diff --git a/__pycache__/mainwindow.cpython-38.pyc b/__pycache__/mainwindow.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0fa65c993ab2ec0880196619b941afac98c662a8 GIT binary patch literal 2396 zcmZ9NS##7z5P&7^ec}rU_kAqKuDNf5ZH(Dqz{(n^bfroqOS85dwIq*bfu)=$sG=$l zdCCtkkNkxEk38u$Px%XZO1HF*ok*o`x~F@to}SUGMx(0HGyMG*`;U^Q{mIJiCr`>F z`r;pTO>;F@_ch?s@O3o6z#QZ-4|yy=0gF(?5|pqEWvoC2t5C%n)UXb9Y(PWjb~$R- zggvR8_s4J?#&H5Ba1thQ3Z`%`?8SYs5BJ0V)TiKog9qRM9)yFbUi1&)VK|IO;0PXt zqj(IC;c+;QC*TC0gp+s*PT^@djc4Eto`th`4$k3uIFBu8;RU#W7vUmaf=hTAE@KOaLUbaib(b8Bw>ljhdN{Kp)8 z=juJJ)%c6!{-RY+#+H6Cm#x?H-}kyNUs%26?~`KBTMcYK$@lzFB?a?|=ZmD07Tus9 zlGuIuSiJQdkrd7610~*5RZl481*gF>s?1_zm2&h{cGYoj>t`i1H*<7-{KygPT`81G7O6HRH9_^@QaHY)5 z^-Ox~*?zd%I+cu@Gb^!@wxhaA;A>C3qjocnqM6WunXn+kLBv`V`JQ8sY_kKU!XUF% zXo|QJ&W7))b=G%MGarY}Pj5VTRj8y%%3#G8y~qpLtCogpLrspCUP#n0J zwI#Ve7jbN_3Lcb5}&yk_;&q!gjLi@NBQdEXC zp`P!#=?-kKvSIcj-;UR)i4Xy8WKRt#PbRYRWyFyjHL97*Vd(!m$m^X2m&|NI9|~96 z)9q=>kLs))i)>+}l^0%h)A*5GA^EAWX%-IW?(T>04SwR&1fhZMYGAm!$hmqy_gU-f zuHoiBRUrRa%WF`e{Ld%Vod~{gwmaZX3ZpMaW&A5aX-ePJJ{nubroL%x=Dy@~ZPVDI z&cEnC8k?Gx|2eM;o7$$fp8v>tQI&RSWmWk|Hmj;?X;~+~`c{KjUT=QUsV~;|5R2<$ zBfYvc&b67gH9>NfWmluA8!r;Q-I`1a@gNdXKBO5YWy|scPgxe#QXZ?MWJggzc_;6a z8FH%wPd;F&N|LpfMp52PE0B`oU7ASp4p)rtR9JqRu28YvQRYG;YrET$?I1KA5ztxl zt#|3EfJ!V>mc=ke;#_9UoLhw?9}B;q6eC-bAt^^g4BY|cPn9M#O$ngO1&gJ5lVlowZIR!*$`Pj$`*lXVp`_z0#SRc{1OLh8xOuoKD>D?5wCA z4do22@)&*b6hYIca$`nQZ|Y@w$LMVuA0~HFqrDy2R*{3uA*CQ!Ei0QY$#u)x7});E zQn9vIl8%!!MiY00?^~99Mk8kEvb4zH4Lm|$Y!J#us<)mcMi?ix4HXUBrkV?-kZhKm zl#;Vma+=B_gZ`wNEHf$${>91~qt0kBngqHD{(H|?N4+mla_nKRF~&G!f-%Y9Aj!Q1 zm>jvMw{33_MWIx3ADj0RlIF;q?Qkr=Vaox=LB=7*VFs^N9%b+@$m5I?jFXI03_iy4 z4C5^09OFEr#kjz@$hgF~%xE(@jA_Od##P2O#&yOG#!bd8#%%^?e0mO&d}OP&q`X46 z4{s%JcAx%xv}a4?L%*$^yoAY7Znalj_HQ%fJ$BpwKMS30f~04i~s-t literal 0 HcmV?d00001 diff --git a/enumkind.py b/enumkind.py new file mode 100644 index 0000000..f96bb4e --- /dev/null +++ b/enumkind.py @@ -0,0 +1,40 @@ + +from enum import IntEnum + +class ElogSwissFEL: + def __init__(self): + self.category = self.Category(0) + self.domain = self.Domain(0) + self.system = self.System(0) + + class Category(IntEnum): + INFO = 0 + MEASUREMENT = 1 + + class Domain(IntEnum): + NONE = 0 + INJECTOR = 1 + LINAC1 = 2 + LINAC2 = 3 + LINAC3 = 4 + ARAMIS = 5 + ARAMIS_BEAMLINES = 6 + ATHOS = 7 + ATHOS_BEAMLINES = 8 + + class System(IntEnum): + NONE = 0 + BEAMDYNAMICS = 1 + CONTROLS = 2 + DIAGNOSTICS = 3 + ELECTRICSUPPLY = 4 + INSERTIONDEVICES = 5 + LASER = 6 + MAGNETPOWERSUPPLIES = 7 + OPERATION = 8 + RF = 9 + SAFETY = 10 + VACUUM = 11 + WATERCOOLING = 11 + OTHER = 12 + UNKNOWN = 13 diff --git a/enumkind.py~ b/enumkind.py~ new file mode 100644 index 0000000..c75ad80 --- /dev/null +++ b/enumkind.py~ @@ -0,0 +1,39 @@ +from enum import IntEnum + +class ElogSwissFEL: + def __init__(self): + self.category = self.Category(0) + self.domain = self.Domain(0) + self.system = self.System(0) + + class Category(IntEnum): + INFO = 0 + MEASUREMENT = 1 + + class Domain(IntEnum): + NONE = 0 + INJECTOR = 1 + LINAC1 = 2 + LINAC2 = 3 + LINAC3 = 4 + ARAMIS = 5 + ARAMIS_BEAMLINES = 6 + ATHOS = 7 + ATHOS_BEAMLINES = 8 + + class System(IntEnum): + NONE = 0 + BEAMDYNAMICS = 1 + CONTROLS = 2 + DIAGNOSTICS = 3 + ELECTRICSUPPLY = 4 + INSERTIONDEVICES = 5 + LASER = 6 + MAGNETPOWERSUPPLIES = 7 + OPERATION = 8 + RF = 9 + SAFETY = 10 + VACUUM = 11 + WATERCOOLING = 11 + OTHER = 12 + UNKNOWN = 13 diff --git a/guiheader.py b/guiheader.py new file mode 100644 index 0000000..c40a5f9 --- /dev/null +++ b/guiheader.py @@ -0,0 +1,438 @@ +""" Gui header for SwissFEL +""" +from datetime import datetime +import random +import time + +from qtpy.QtCore import Qt, QTimer +from qtpy.QtGui import QFont, QIntValidator +from qtpy.QtWidgets import (QApplication, QFrame, QGridLayout, QGroupBox, + QHBoxLayout, QLabel, QLineEdit, QMessageBox, + QPushButton, QRadioButton, QSizePolicy, QSpacerItem, + QSpinBox, QTabWidget, QToolButton, QVBoxLayout, + QWidget) +from caqtwidgets.pvwidgets import (CAQDoubleSpinBox, CAQLabel, CAQLineEdit, + CAQMenu, CAQMessageButton, CAQSpinBox, + CAQTableWidget, CAQTextEntry, QHLine, QVLine, + QResultsWidget) + +from pyqtacc.bdbase.enumkind import MsgSeverity, UserMode + + + +class GUIHeader(QWidget): + """ GUI Header Class + """ + def __init__(self, parent, user_mode=UserMode.OPERATION, extended=True): + super(GUIHeader, self).__init__() + self.parent = parent + self.appname = parent.appname + self.title = parent.title + self.settings = parent.settings + self.user_mode = user_mode + self.current_user_mode = user_mode + self.extended = extended + self.cafe = parent.cafe + self.cyca = parent.cyca + + self.input_parameters = parent.input_parameters + self.input_labels = parent.input_labels + self.expert_parameters = parent.expert_parameters + self.expert_labels = parent.expert_labels + + self.aramis_status = None + self.athos_status = None + self.porthos_status = None + + self.font_gui = QFont("sans serif") + self.font_gui.setPointSize(11) + self.font_pts10 = QFont("sans serif") + self.font_pts10.setPointSize(10) + self.widget_height = self.settings.data["StyleGuide"]["widgetHeight"] + self.extra_height = self.settings.data["StyleGuide"]["extraGroupHeight"] + self.aramis_color = self.settings.data["Aramis"]["color"] + self.athos_color = self.settings.data["Athos"]["color"] + self.porthos_color = self.settings.data["Porthos"]["color"] + + beamline = ["Aramis", "Athos", "Porthos"] + pvlist = [] + for item in beamline: + if item not in self.settings.data: + continue + try: + pvlist.append(self.settings.data[item]["laser"]) + pvlist.append(self.settings.data[item]["freq"]) + pvlist.append(self.settings.data[item]["beamStatus"]) + pvlist.append(self.settings.data[item]["energy"]) + pvlist.append(self.settings.data[item]["charge"]) + pvlist.append(self.settings.data[item]["photonEnergy"]) + except KeyError as error: + print("KeyError in guiheader.py __init__", error) + + for key, pv in self.settings.data["OpMsg"].items(): + pvlist.append(pv) + + print(datetime.now()) + self.cafe.openPrepare() + self.cafe.open(pvlist) + self.cafe.openNowAndWait(0.4) + print(datetime.now()) + self.cafe.printDisconnected() + + + self.station_width = 200 #default + self.station_height = 100 + self.hor_layout = QHBoxLayout() + self.hor_layout.addWidget(self.status_widget()) + self.hor_layout.addWidget(self.aramis_widget()) + self.hor_layout.addWidget(self.athos_widget()) + yr_diff = abs(2030 - datetime.now().year) + show_porthos = False + try: + if self.settings.data["showPorthos"]: + show_porthos = True + else: + if random.randint(1, 10) > yr_diff: + show_porthos = True + except KeyError as error: + print("KeyError in guiheader.py initialization:", error) + if random.randint(1, 10) > yr_diff: + show_porthos = True + if show_porthos: + self.hor_layout.addWidget(self.porthos_widget()) + self.hor_layout.setSpacing(10) + #self.header_layout.addItem(QSpacerItem(0, 20)) + self.hor_layout.setAlignment(Qt.AlignLeft) + self.hor_layout.setContentsMargins(5, 0, 5, 0) #default 11 pixels + #self.top_widget = QLabel("SwissFEL") + + #self.top_layout = QVBoxLayout() + #self.top_layout.addWidget(self.top_widget) + #self.top_layout.addLayout(self.hor_layout) + + self.header_wgt = QGroupBox() + self.header_wgt.setObjectName(self.user_mode.name) + self.header_wgt.setLayout(self.hor_layout) + self.header_wgt.setFixedHeight(110) + title = "SwissFEL {0}".format(self.user_mode.name) + if self.title: + title += ": {0}".format(self.title) + self.header_wgt.setTitle(title) + + self.target_beamline = None + + #self.set_target_beamline("Athos", reset=False) + #QApplication.processEvents() + + self.timer = QTimer() + self.timer.timeout.connect(self.blink_target_beamline) + self.timer.start(500) + self.timer_count = 0 + + def blink_target_beamline(self): + self.timer_count += 1 + if self.timer_count < 2: + return + if self.timer_count % 2 == 0: + self.reset_beamline() + else: + self.set_target_beamline(target=self.target_beamline, reset=False) + if self.timer_count > 4: + self.timer.stop() + QApplication.processEvents() + + def set_target_beamline(self, target, reset = True): + """ Select beamline target and modify color scheme accordinly + """ + if not target: + return + if target == "Aramis": + self.aramis_status.setObjectName("TARGET") + self.aramis_status.setTitle("Target: Aramis") + self.aramis_status.style().polish(self.aramis_status) + elif target == "Athos": + self.athos_status.setObjectName("TARGET") + self.athos_status.setTitle("Target: Athos") + self.athos_status.style().polish(self.athos_status) + elif target == "Porthos" and self.porthos_status: + if self.porthos_status: + self.porthos_status.setObjectName("TARGET") + self.porthos_status.setTitle("Target: Porthos") + self.porthos_status.style().polish(self.porthos_status) + + if reset: + self.reset_beamline() + self.target_beamline = target + + def reset_beamline(self): + """ Reset QGroupBox for previous target to original colors + """ + if self.target_beamline == "Aramis": + self.reset_aramis() + elif self.target_beamline == "Athos": + self.reset_athos() + elif self.target_beamline == "Porthos": + self.reset_porthos() + + def reset_aramis(self): + """ Reset Aramis QGroupBox color + """ + self.aramis_status.setObjectName("ARAMIS") + self.aramis_status.setTitle("Aramis") + self.aramis_status.style().polish(self.aramis_status) + + def reset_athos(self): + """ Reset Athos QGroupBox color + """ + self.athos_status.setObjectName("ATHOS") + self.athos_status.setTitle("Athos") + self.athos_status.style().polish(self.athos_status) + + def reset_porthos(self): + """ Reset Porthos QGroupBox color + """ + if self.porthos_status: + self.porthos_status.setObjectName("PORTHOS") + self.porthos_status.setTitle("Porthos") + self.porthos_status.style().polish(self.porthos_status) + + def reset_operation_mode(self): + """ Reset header colors to application operation mode + """ + self.change_operation_mode(user_mode=self.user_mode) + + def change_operation_mode(self, user_mode=UserMode.OPERATION): + """ Different operation modes have different color schemes + """ + self.header_wgt.setObjectName(user_mode.name) + self.header_wgt.setTitle(self.header_wgt.title().replace( + self.current_user_mode.name, user_mode.name)) + self.header_wgt.style().polish(self.header_wgt) + self.current_user_mode = user_mode + + #self.header_wgt.setStyleSheet("QGroupBox#OPERATION{background-color:#8b1a96; color:white;}" "QGroupBox::title#OPERATION{background-color:#8b1a96;} ") + + + def beamline_widget(self, beamline="Aramis"): + """ QGroupBox template for beamlines + """ + station = QGroupBox() + station.setObjectName(beamline.upper()) + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle(beamline) + laser = CAQLabel(self, pv_name=self.settings.data[beamline]["laser"]) + laser.setFixedHeight(self.widget_height) + freq = CAQLabel(self, pv_name=self.settings.data[beamline]["freq"], + show_units=True) + freq.setAlignment(Qt.AlignRight) + freq.setFixedHeight(self.widget_height) + freq.setFixedWidth(84) + beamstatus = CAQLabel( + self, pv_name=self.settings.data[beamline]["beamStatus"], + color_mode="alarm") + beamstatus.setFixedHeight(self.widget_height) + + grid_layout = QGridLayout() + grid_layout.addWidget(laser, 0, 0, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(freq, 0, 1, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(beamstatus, 1, 0, 1, 2, Qt.AlignCenter) + + if self.extended: + grid_layout.addWidget(QVLine(), 0, 2, 2, 1) + filtered_energy = CAQLabel( + self, pv_name=self.settings.data[beamline]["energy"], + show_units=True) + filtered_energy.setFixedHeight(self.widget_height) + charge = CAQLabel( + self, pv_name=self.settings.data[beamline]["charge"], + show_units=True, notify_freq_hz=2) + charge.setFixedHeight(self.widget_height) + charge.setFixedWidth(78) + photon_energy = CAQLabel( + self, pv_name=self.settings.data[beamline]["photonEnergy"], + show_units=False, suffix='\u00B5J') + photon_energy.setFixedHeight(self.widget_height) + photon_energy.setFixedWidth(66) #So aramis/Athos are the same + + grid_layout.addWidget(filtered_energy, 0, 3, 1, 2, Qt.AlignCenter) + grid_layout.addWidget(charge, 1, 3, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(photon_energy, 1, 4, 1, 1, Qt.AlignCenter) + + grid_layout.setVerticalSpacing(0) + grid_layout.setHorizontalSpacing(0) + grid_layout.setContentsMargins(0, 10, 0, 0) + #print(grid_layout.getContentsMargins()) + + station.setLayout(grid_layout) + self.station_height = laser.height() + freq.height() + self.extra_height + station.setFixedHeight(self.station_height) + self.station_width = laser.width() + freq.width() + 10 + if self.extended: + self.station_width += (charge.width() + photon_energy.width()) + station.setFixedWidth(self.station_width) + station.setAlignment(Qt.AlignCenter) + return station + + def aramis_widget(self): + """ QGroupBox encompassing main Aramis parameters + """ + self.aramis_status = self.beamline_widget(beamline="Aramis") + return self.aramis_status + + def athos_widget(self): + """ QGroupBox encompassing main Athos parameters + """ + self.athos_status = self.beamline_widget(beamline="Athos") + return self.athos_status + + def porthos_widget(self): + """ QGroupBox encompassing main Porthos parameters + """ + #porthos = self.beamline_widget(beamline="Porthos") + station = QGroupBox() + station.setObjectName("Porthos".upper()) + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle("Porthos") + grid_layout = QGridLayout() + text = "Honest and extrovert!" \ + if random.randint(1,10) > 9 else "Arriving 2029" + qlabel = QLabel(text) + qlabel.setFont(self.font_pts10) + qlabel.setAlignment(Qt.AlignCenter) + grid_layout.addWidget(qlabel, 0, 0) + station.setLayout(grid_layout) + station.setFixedWidth(self.station_width) + station.setFixedHeight(self.station_height) + self.porthos_status = station + return self.porthos_status + + def status_widget(self): + """ QGroupBox encompassing machine status info + """ + station = QGroupBox() + station.setObjectName("MACHINE") + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle("Status") + date = CAQLabel(self, pv_name=self.settings.data["OpMsg"]["pvDate1"]) + date.setFixedHeight(self.widget_height) + eventno = CAQLabel(self, pv_name=self.settings.data["OpMsg"]["pvEventNo"], + notify_freq_hz=10) + eventno.setFixedHeight(self.widget_height) + eventno.setAlignment(Qt.AlignCenter) + message = CAQLabel( + self, pv_name=self.settings.data["OpMsg"]["pvMsg1"]) + message.setFixedHeight(self.widget_height) + message.setFixedWidth(eventno.width() + date.width() + 2) + + grid_layout = QGridLayout() + grid_layout.addWidget(date, 0, 0, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(eventno, 0, 1, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(message, 1, 0, 1, 2, Qt.AlignCenter) + grid_layout.setVerticalSpacing(0) + grid_layout.setHorizontalSpacing(0) + grid_layout.setContentsMargins(0, 10, 0, 0) + + station.setLayout(grid_layout) + station.setFixedHeight(eventno.height() + date.height() + + self.extra_height) + station.setFixedWidth(eventno.width() + date.width() + 10) + self.machine_status = station + return self.machine_status + + def operator_group_header(self): + return self.radio_target_beamline() + + def radio_target_beamline(self): + widget = QWidget() + layout = QGridLayout() + layout.setContentsMargins(0, 0, 0, 0) + self.setLayout(layout) + target_list = ["Aramis", "Athos"] + try: + if self.settings.data["showPorthos"]: + target_list.append("Porthos") + except KeyError as error: + print("KeyError in guiheader.py, def radio_target_beamline:", error) + + + color_list = [self.aramis_color, self.athos_color, self.porthos_color] + + self.radiobutton = [QRadioButton("Aramis"), QRadioButton("Athos"), + QRadioButton("Porthos")] + width_list = [70, 64, 84] + #width_list = [80, 74, 92] #pts 11 + layout.addWidget(QHLine(), 0, 0, 1, 3) + + for i, (radio, target, color, width) in enumerate( + zip(self.radiobutton, target_list, color_list, width_list)): + #radio = QRadioButton(target) + radio.setFont(self.font_pts10) + radio.setStyleSheet("color : {0};".format(color)) + radio.target = target + radio.toggled.connect(self.on_target_clicked) + layout.addWidget(radio, 1, i) + radio.setFixedWidth(width) + + try: + target = self.settings.data["Parameters"]["undulator"]["data"]["value"] + except KeyError as error: + print("KeyError in guiheader.py, def radio_target_beamline:", error) + target = target_list[0] + try: + idx = target_list.index(target) + except ValueError as error: + print("ValueError in guiheader.py, def radio_target_beamline:", error) + idx = 0 + + self.radiobutton[idx].setChecked(True) + self.radiobutton[idx].toggled.emit(True) + + ''' + radiobutton = QRadioButton("Aramis") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.aramis_color)) + radiobutton.setChecked(True) + radiobutton.target = "Aramis" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 0) + + radiobutton = QRadioButton("Athos") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.athos_color)) + radiobutton.target = "Athos" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 1) + + radiobutton = QRadioButton("Porthos") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.porthos_color)) + radiobutton.target = "Porthos" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 2) + ''' + + layout.addWidget(QHLine(), 2, 0, 1, 3) + + widget.setLayout(layout) + + return widget + + def on_target_clicked(self): + radio_button = self.sender() + if radio_button.isChecked(): + print("Target is {0}".format(radio_button.target)) + self.set_target_beamline(radio_button.target) + radio_button.setText(radio_button.target.upper()) + self.timer.start(500) + self.timer_count = 0 + #print (self.parent.input_parameters['undulator']) + self.parent.input_parameters['undulator'] = radio_button.target + print (self.parent.input_parameters['undulator']) + + for radio in self.radiobutton: + if not radio.isChecked(): + radio.setText(radio.target) + diff --git a/guiheader.py~ b/guiheader.py~ new file mode 100644 index 0000000..eaf81e4 --- /dev/null +++ b/guiheader.py~ @@ -0,0 +1,438 @@ +""" Gui header for SwissFEL +""" +from datetime import datetime +import random +import time + +from qtpy.QtCore import Qt, QTimer +from qtpy.QtGui import QFont, QIntValidator +from qtpy.QtWidgets import (QApplication, QFrame, QGridLayout, QGroupBox, + QHBoxLayout, QLabel, QLineEdit, QMessageBox, + QPushButton, QRadioButton, QSizePolicy, QSpacerItem, + QSpinBox, QTabWidget, QToolButton, QVBoxLayout, + QWidget) +from caqtwidgets.pvwidgets import (CAQDoubleSpinBox, CAQLabel, CAQLineEdit, + CAQMenu, CAQMessageButton, CAQSpinBox, + CAQTableWidget, CAQTextEntry, QHLine, QVLine, + QResultsWidget) + +from pyqtacc.bdbase.enumkind import MsgSeverity, UserMode + + + +class GUIHeader(QWidget): + """ GUI Header Class + """ + def __init__(self, parent, user_mode=UserMode.OPERATION, extended=True): + super(GUIHeader, self).__init__() + self.parent = parent + self.appname = parent.appname + self.title = parent.title + self.settings = parent.settings + self.user_mode = user_mode + self.current_user_mode = user_mode + self.extended = extended + self.cafe = parent.cafe + self.cyca = parent.cyca + + self.input_parameters = parent.input_parameters + self.input_labels = parent.input_labels + self.expert_parameters = parent.expert_parameters + self.expert_labels = parent.expert_labels + + self.aramis_status = None + self.athos_status = None + self.porthos_status = None + + self.font_gui = QFont("sans serif") + self.font_gui.setPointSize(11) + self.font_pts10 = QFont("sans serif") + self.font_pts10.setPointSize(10) + self.widget_height = self.settings.data["StyleGuide"]["widgetHeight"] + self.extra_height = self.settings.data["StyleGuide"]["extraGroupHeight"] + self.aramis_color = self.settings.data["Aramis"]["color"] + self.athos_color = self.settings.data["Athos"]["color"] + self.porthos_color = self.settings.data["Porthos"]["color"] + + beamline = ["Aramis", "Athos", "Porthos"] + pvlist = [] + for item in beamline: + if item not in self.settings.data: + continue + try: + pvlist.append(self.settings.data[item]["laser"]) + pvlist.append(self.settings.data[item]["freq"]) + pvlist.append(self.settings.data[item]["beamStatus"]) + pvlist.append(self.settings.data[item]["energy"]) + pvlist.append(self.settings.data[item]["charge"]) + pvlist.append(self.settings.data[item]["photonEnergy"]) + except KeyError as error: + print("KeyError in guiheader.py __init__", error) + + for key, pv in self.settings.data["OpMsg"].items(): + pvlist.append(pv) + + print(datetime.now()) + self.cafe.openPrepare() + self.cafe.open(pvlist) + self.cafe.openNowAndWait(0.4) + print(datetime.now()) + self.cafe.printDisconnected() + + + self.station_width = 200 #default + self.station_height = 100 + self.hor_layout = QHBoxLayout() + self.hor_layout.addWidget(self.status_widget()) + self.hor_layout.addWidget(self.aramis_widget()) + self.hor_layout.addWidget(self.athos_widget()) + yr_diff = abs(2030 - datetime.now().year) + show_porthos = False + try: + if self.settings.data["showPorthos"]: + show_porthos = True + else: + if random.randint(1, 10) > yr_diff: + show_porthos = True + except KeyError as error: + print("KeyError in guiheader.py initialization:", error) + if random.randint(1, 10) > yr_diff: + show_porthos = True + if show_porthos: + self.hor_layout.addWidget(self.porthos_widget()) + self.hor_layout.setSpacing(10) + #self.header_layout.addItem(QSpacerItem(0, 20)) + self.hor_layout.setAlignment(Qt.AlignLeft) + self.hor_layout.setContentsMargins(5, 0, 5, 0) #default 11 pixels + #self.top_widget = QLabel("SwissFEL") + + #self.top_layout = QVBoxLayout() + #self.top_layout.addWidget(self.top_widget) + #self.top_layout.addLayout(self.hor_layout) + + self.header_wgt = QGroupBox() + self.header_wgt.setObjectName(self.user_mode.name) + self.header_wgt.setLayout(self.hor_layout) + self.header_wgt.setFixedHeight(110) + title = "SwissFEL {0}".format(self.user_mode.name) + if self.title: + title += ": {0}".format(self.title) + self.header_wgt.setTitle(title) + + self.target_beamline = None + + #self.set_target_beamline("Athos", reset=False) + #QApplication.processEvents() + + self.timer = QTimer() + self.timer.timeout.connect(self.blink_target_beamline) + self.timer.start(500) + self.timer_count = 0 + + def blink_target_beamline(self): + self.timer_count += 1 + if self.timer_count < 2: + return + if self.timer_count % 2 == 0: + self.reset_beamline() + else: + self.set_target_beamline(target=self.target_beamline, reset=False) + if self.timer_count > 4: + self.timer.stop() + QApplication.processEvents() + + def set_target_beamline(self, target, reset = True): + """ Select beamline target and modify color scheme accordinly + """ + if not target: + return + if target == "Aramis": + self.aramis_status.setObjectName("TARGET") + self.aramis_status.setTitle("Target: Aramis") + self.aramis_status.style().polish(self.aramis_status) + elif target == "Athos": + self.athos_status.setObjectName("TARGET") + self.athos_status.setTitle("Target: Athos") + self.athos_status.style().polish(self.athos_status) + elif target == "Porthos" and self.porthos_status: + if self.porthos_status: + self.porthos_status.setObjectName("TARGET") + self.porthos_status.setTitle("Target: Porthos") + self.porthos_status.style().polish(self.porthos_status) + + if reset: + self.reset_beamline() + self.target_beamline = target + + def reset_beamline(self): + """ Reset QGroupBox for previous target to original colors + """ + if self.target_beamline == "Aramis": + self.reset_aramis() + elif self.target_beamline == "Athos": + self.reset_athos() + elif self.target_beamline == "Porthos": + self.reset_porthos() + + def reset_aramis(self): + """ Reset Aramis QGroupBox color + """ + self.aramis_status.setObjectName("ARAMIS") + self.aramis_status.setTitle("Aramis") + self.aramis_status.style().polish(self.aramis_status) + + def reset_athos(self): + """ Reset Athos QGroupBox color + """ + self.athos_status.setObjectName("ATHOS") + self.athos_status.setTitle("Athos") + self.athos_status.style().polish(self.athos_status) + + def reset_porthos(self): + """ Reset Porthos QGroupBox color + """ + if self.porthos_status: + self.porthos_status.setObjectName("PORTHOS") + self.porthos_status.setTitle("Porthos") + self.porthos_status.style().polish(self.porthos_status) + + def reset_operation_mode(self): + """ Reset header colors to application operation mode + """ + self.change_operation_mode(user_mode=self.user_mode) + + def change_operation_mode(self, user_mode=UserMode.OPERATION): + """ Different operation modes have different color schemes + """ + self.header_wgt.setObjectName(user_mode.name) + self.header_wgt.setTitle(self.header_wgt.title().replace( + self.current_user_mode.name, user_mode.name)) + self.header_wgt.style().polish(self.header_wgt) + self.current_user_mode = user_mode + + #self.header_wgt.setStyleSheet("QGroupBox#OPERATION{background-color:#8b1a96; color:white;}" "QGroupBox::title#OPERATION{background-color:#8b1a96;} ") + + + def beamline_widget(self, beamline="Aramis"): + """ QGroupBox template for beamlines + """ + station = QGroupBox() + station.setObjectName(beamline.upper()) + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle(beamline) + laser = CAQLabel(self, pv_name=self.settings.data[beamline]["laser"]) + laser.setFixedHeight(self.widget_height) + freq = CAQLabel(self, pv_name=self.settings.data[beamline]["freq"], + show_units=True) + freq.setAlignment(Qt.AlignRight) + freq.setFixedHeight(self.widget_height) + freq.setFixedWidth(84) + beamstatus = CAQLabel( + self, pv_name=self.settings.data[beamline]["beamStatus"], + color_mode="alarm") + beamstatus.setFixedHeight(self.widget_height) + + grid_layout = QGridLayout() + grid_layout.addWidget(laser, 0, 0, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(freq, 0, 1, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(beamstatus, 1, 0, 1, 2, Qt.AlignCenter) + + if self.extended: + grid_layout.addWidget(QVLine(), 0, 2, 2, 1) + filtered_energy = CAQLabel( + self, pv_name=self.settings.data[beamline]["energy"], + show_units=True) + filtered_energy.setFixedHeight(self.widget_height) + charge = CAQLabel( + self, pv_name=self.settings.data[beamline]["charge"], + show_units=True, notify_freq_hz=2) + charge.setFixedHeight(self.widget_height) + charge.setFixedWidth(78) + photon_energy = CAQLabel( + self, pv_name=self.settings.data[beamline]["photonEnergy"], + show_units=False, suffix='\u00B5J') + photon_energy.setFixedHeight(self.widget_height) + photon_energy.setFixedWidth(66) #So aramis/Athos are the same + + grid_layout.addWidget(filtered_energy, 0, 3, 1, 2, Qt.AlignCenter) + grid_layout.addWidget(charge, 1, 3, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(photon_energy, 1, 4, 1, 1, Qt.AlignCenter) + + grid_layout.setVerticalSpacing(0) + grid_layout.setHorizontalSpacing(0) + grid_layout.setContentsMargins(0, 10, 0, 0) + #print(grid_layout.getContentsMargins()) + + station.setLayout(grid_layout) + self.station_height = laser.height() + freq.height() + self.extra_height + station.setFixedHeight(self.station_height) + self.station_width = laser.width() + freq.width() + 10 + if self.extended: + self.station_width += (charge.width() + photon_energy.width()) + station.setFixedWidth(self.station_width) + station.setAlignment(Qt.AlignCenter) + return station + + def aramis_widget(self): + """ QGroupBox encompassing main Aramis parameters + """ + self.aramis_status = self.beamline_widget(beamline="Aramis") + return self.aramis_status + + def athos_widget(self): + """ QGroupBox encompassing main Athos parameters + """ + self.athos_status = self.beamline_widget(beamline="Athos") + return self.athos_status + + def porthos_widget(self): + """ QGroupBox encompassing main Porthos parameters + """ + #porthos = self.beamline_widget(beamline="Porthos") + station = QGroupBox() + station.setObjectName("Porthos".upper()) + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle("Porthos") + grid_layout = QGridLayout() + text = "Honest and extrovert!" \ + if random.randint(1,10) > 9 else "Arriving 2029" + qlabel = QLabel(text) + qlabel.setFont(self.font_pts10) + qlabel.setAlignment(Qt.AlignCenter) + grid_layout.addWidget(qlabel, 0, 0) + station.setLayout(grid_layout) + station.setFixedWidth(self.station_width) + station.setFixedHeight(self.station_height) + self.porthos_status = station + return self.porthos_status + + def status_widget(self): + """ QGroupBox encompassing machine status info + """ + station = QGroupBox() + station.setObjectName("MACHINE") + station.setAlignment(Qt.AlignHCenter | Qt.AlignTop) + station.setFlat(False) + station.setTitle("Status") + date = CAQLabel(self, pv_name=self.settings.data["OpMsg"]["pvDate1"]) + date.setFixedHeight(self.widget_height) + eventno = CAQLabel(self, pv_name=self.settings.data["OpMsg"]["pvEventNo"], + notify_freq_hz=10) + eventno.setFixedHeight(self.widget_height) + eventno.setAlignment(Qt.AlignCenter) + message = CAQLabel( + self, pv_name=self.settings.data["OpMsg"]["pvMsg1"]) + message.setFixedHeight(self.widget_height) + message.setFixedWidth(eventno.width() + date.width() + 2) + + grid_layout = QGridLayout() + grid_layout.addWidget(date, 0, 0, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(eventno, 0, 1, 1, 1, Qt.AlignCenter) + grid_layout.addWidget(message, 1, 0, 1, 2, Qt.AlignCenter) + grid_layout.setVerticalSpacing(0) + grid_layout.setHorizontalSpacing(0) + grid_layout.setContentsMargins(0, 10, 0, 0) + + station.setLayout(grid_layout) + station.setFixedHeight(eventno.height() + date.height() + + self.extra_height) + station.setFixedWidth(eventno.width() + date.width() + 10) + self.machine_status = station + return self.machine_status + + def operator_group_header(self): + return self.radio_target_beamline() + + def radio_target_beamline(self): + widget = QWidget() + layout = QGridLayout() + layout.setContentsMargins(0, 0, 0, 0) + self.setLayout(layout) + target_list = ["Aramis", "Athos"] + try: + if self.settings.data["showPorthos"]: + target_list.append("Porthos") + except KeyError as error: + print("KeyError in guiheader.py, def radio_target_beamline:", error) + + + color_list = [self.aramis_color, self.athos_color, self.porthos_color] + + self.radiobutton = [QRadioButton("Aramis"), QRadioButton("Athos"), + QRadioButton("Porthos")] + width_list = [80, 74, 92] + + layout.addWidget(QHLine(), 0, 0, 1, 3) + + for i, (radio, target, color, width) in enumerate( + zip(self.radiobutton, target_list, color_list, width_list)): + #radio = QRadioButton(target) + radio.setFont(self.font_gui) + radio.setStyleSheet("color : {0};".format(color)) + radio.target = target + radio.toggled.connect(self.on_target_clicked) + layout.addWidget(radio, 1, i) + radio.setFixedWidth(width) + + try: + target = self.settings.data["Parameters"]["undulator"]["data"]["value"] + except KeyError as error: + print("KeyError in guiheader.py, def radio_target_beamline:", error) + target = target_list[0] + try: + idx = target_list.index(target) + except ValueError as error: + print("ValueError in guiheader.py, def radio_target_beamline:", error) + idx = 0 + + self.radiobutton[idx].setChecked(True) + self.radiobutton[idx].toggled.emit(True) + + ''' + radiobutton = QRadioButton("Aramis") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.aramis_color)) + radiobutton.setChecked(True) + radiobutton.target = "Aramis" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 0) + + radiobutton = QRadioButton("Athos") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.athos_color)) + radiobutton.target = "Athos" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 1) + + radiobutton = QRadioButton("Porthos") + radiobutton.setFont(self.font_gui) + radiobutton.setStyleSheet("color : {0};".format(self.porthos_color)) + radiobutton.target = "Porthos" + radiobutton.toggled.connect(self.on_target_clicked) + layout.addWidget(radiobutton, 0, 2) + ''' + + layout.addWidget(QHLine(), 2, 0, 1, 3) + + widget.setLayout(layout) + + return widget + + def on_target_clicked(self): + radio_button = self.sender() + if radio_button.isChecked(): + print("Target is {0}".format(radio_button.target)) + self.set_target_beamline(radio_button.target) + radio_button.setText(radio_button.target.upper()) + self.timer.start(500) + self.timer_count = 0 + #print (self.parent.input_parameters['undulator']) + self.parent.input_parameters['undulator'] = radio_button.target + print (self.parent.input_parameters['undulator']) + + for radio in self.radiobutton: + if not radio.isChecked(): + radio.setText(radio.target) + diff --git a/mainwindow.py b/mainwindow.py new file mode 100644 index 0000000..a40c7a6 --- /dev/null +++ b/mainwindow.py @@ -0,0 +1,62 @@ +import inspect +import os + +# Third-party modules +from qtpy.QtCore import (PYQT_VERSION_STR, Signal, Slot, QFile, QFileInfo, + QIODevice, QMutex, QSettings, QSize, Qt, QTimer, + qVersion) +from qtpy.QtCore import __version__ as QT_VERSION_STR +from qtpy.QtGui import (QColor, QKeySequence, QFont, QIcon, QPainter, QPalette, + QPixmap) +from qtpy.QtPrintSupport import QPrinter, QPrintDialog +from qtpy.QtWidgets import (QAbstractItemView, QAction, QActionGroup, + QApplication, QButtonGroup, QComboBox, QDialog, + QDockWidget, QDoubleSpinBox, QFileDialog, QFrame, + QGridLayout, QGroupBox, QHBoxLayout, QLabel, + QLayout, QLineEdit, QListWidget, QMainWindow, QMenu, + QMenuBar, QMessageBox, QPlainTextEdit, QProgressBar, + QPushButton, QScrollArea, QSizePolicy, QSlider, + QSpinBox, QSplashScreen, QStyle, QStyleOptionSlider, + QToolButton, QVBoxLayout, QWidget) + +from pyqtacc.bdbase.base import BaseWindow +from pyqtacc.bdbase.enumkind import MsgSeverity, UserMode +from pyqtacc.bdbase.guiframe import GUIFrame +from pyqtacc.sf.guiheader import GUIHeader + +_pymodule = os.path.basename(__file__) +_appversion = "1.0.0" + +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 MainWindow(BaseWindow): + + def __init__(self, parent=None, pymodule=_pymodule, appversion="", + title="", user_mode=UserMode.OPERATION): + super(MainWindow, self).__init__(parent, pymodule, appversion, title) + self.appname, appext = pymodule.split(".") + self.title = title + self.gui_frame = GUIFrame(self, self.appname) + self.show_log_message = self.gui_frame.show_log_message + self.gui_header = GUIHeader(self, user_mode) + self.mainwindow = QWidget() + self.mainwindow_layout = QVBoxLayout() + #self.mainwindow_layout.addLayout(self.gui_header.top_layout) + self.mainwindow_layout.addWidget(self.gui_header.header_wgt) + self.mainwindow_layout.addWidget(self.gui_frame.central_tab_widget) + self.mainwindow.setLayout(self.mainwindow_layout) + self.mainwindow.setMinimumHeight(400) + self.mainwindow.setMinimumWidth(1100) + + self.setCentralWidget(self.mainwindow) + self.show_log_message(MsgSeverity.INFO, _pymodule, _line(), + "Application started") diff --git a/mainwindow.py~ b/mainwindow.py~ new file mode 100644 index 0000000..711bf2f --- /dev/null +++ b/mainwindow.py~ @@ -0,0 +1,62 @@ +import inspect +import os + +# Third-party modules +from qtpy.QtCore import (PYQT_VERSION_STR, Signal, Slot, QFile, QFileInfo, + QIODevice, QMutex, QSettings, QSize, Qt, QTimer, + qVersion) +from qtpy.QtCore import __version__ as QT_VERSION_STR +from qtpy.QtGui import (QColor, QKeySequence, QFont, QIcon, QPainter, QPalette, + QPixmap) +from qtpy.QtPrintSupport import QPrinter, QPrintDialog +from qtpy.QtWidgets import (QAbstractItemView, QAction, QActionGroup, + QApplication, QButtonGroup, QComboBox, QDialog, + QDockWidget, QDoubleSpinBox, QFileDialog, QFrame, + QGridLayout, QGroupBox, QHBoxLayout, QLabel, + QLayout, QLineEdit, QListWidget, QMainWindow, QMenu, + QMenuBar, QMessageBox, QPlainTextEdit, QProgressBar, + QPushButton, QScrollArea, QSizePolicy, QSlider, + QSpinBox, QSplashScreen, QStyle, QStyleOptionSlider, + QToolButton, QVBoxLayout, QWidget) + +from pyqtacc.bdbase.base import BaseWindow +from pyqtacc.bdbase.enumkind import MsgSeverity +from pyqtacc.bdbase.guiframe import GUIFrame +from pyqtacc.sf.guiheader import GUIHeader + +_pymodule = os.path.basename(__file__) +_appversion = "1.0.0" + +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 MainWindow(BaseWindow): + + def __init__(self, parent=None, pymodule=_pymodule, appversion="", title=""): + super(MainWindow, self).__init__(parent, pymodule, appversion, title) + + self.appname, appext = pymodule.split(".") + self.title = title + self.gui_frame = GUIFrame(self, self.appname) + self.show_log_message = self.gui_frame.show_log_message + self.gui_header = GUIHeader(self) + self.mainwindow = QWidget() + self.mainwindow_layout = QVBoxLayout() + #self.mainwindow_layout.addLayout(self.gui_header.top_layout) + self.mainwindow_layout.addWidget(self.gui_header.header_wgt) + self.mainwindow_layout.addWidget(self.gui_frame.central_tab_widget) + self.mainwindow.setLayout(self.mainwindow_layout) + self.mainwindow.setMinimumHeight(400) + self.mainwindow.setMinimumWidth(1100) + + self.setCentralWidget(self.mainwindow) + self.show_log_message(MsgSeverity.INFO, _pymodule, _line(), + "Application started") diff --git a/sf.json b/sf.json new file mode 100644 index 0000000..ba93ee7 --- /dev/null +++ b/sf.json @@ -0,0 +1,153 @@ +{ + "menuFlags":{ + "hasFile": 1, + "loadInitFile": 1, + "hasDaq": 1, + "hasH5" : 1, + "hasEpics" : 1 + }, + "Expt": { + "encoding": "UTF-8", + "beamline": "", + "exptColorBg": "blue", + "exptColorFg": "white", + "operator": "sfop" + }, + "ElogBooks": { + "SwissFEL+commissioning": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning/" + }, + "SwissFEL+commissioning+data": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning+data/" + }, + "SwissFEL+test": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+test", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+test/" + }, + "SwissFEL+test+data": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+test+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+test+data/" + } + }, + "Elog": { + "useELOGenv" : 0, + "host": "elog-gfa.psi.ch", + "book": "SwissFEL+commissioning+data", + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning+data/", + "category": ["Info","Measurement"], + "system" : ["","Beamdynamics","Controls", "Diagnostics", "Electric supply", "Insertion-devices", "Laser", + "Magnet Power Supplies", "Operation", "RF", "Safety", "Vacuum", "Water cooling", "Other", "Unknown"], + "domain" : ["","Injector","Linac1","Linac2","Linac3","Aramis","Aramis Beamlines","Athos","Athos Beamlines"], + "section" : [ [""], + ["","SINEG01", "SINBD01", "SINSB01", "SINSB02", "SINLH01", "SINLH02", "SINLH03", "SINSB03", "SINSB04", "SINSB05", "SINXB01", "SINBC01", "SINBC02", "SINDI01", "SINDI02"], + ["","S10CB01", "S10CB02", "S10DI01", "S10BD01", "S10CB03", "S10CB04", "S10CB05", "S10CB06", "S10CB08", "S10CB09", "S10BC01", "S10BC02", "S10MA01"], + ["","S20CB01", "S20CB02", "S20CB03", "S20CB04", "S20SY01", "S20SY02", "S20SY03"], + ["","S30CB01", "S30CB02", "S20CB03", "S30CB04", "S30CB05", "S30CB06", "S30CB07", "S30CB08", "S30CB09", "S30CB10", "S30CB11", "S30CB12", "S30CB13", "S30CB14", "S30CB15", "S30CB16"], + ["","SARCL01", "SARCL02", "SARMA01", "SARMA02", "SARUN01", "SARUN02", "SARUN03", "SARUN04", "SARUN05", "SARUN06", "SARUN07", "SARUN08", "SARUN09", "SARUN10", "SARUN11", "SARUN12", + "SARUN13", "SARUN14", "SARUN15", "SARUN16", "SARUN17", "SARUN18", "SARUN19", "SARUN20", "SARBD01", "SARBD02"], + ["","SARFE10 (Gas detector)", "SAROP11 (ESA / ALVRA)", "SAROP21 (ESB / Bernina)", "SAROP31 (ESC)"], + ["","SATSY01", "SATSY02", "SATSY03", "SATCL01", "SATDI01", "SATCB01", "SATCB02", "SATMA01", "SATUN01", "SATUN02", "SATUN03", "SATUN04", "SATUN05", "SATUN06", "SATUN07", "SATUN08", + "SATUN09", "SATUN10", "SATDI04", "SATUN11", "SATUN12", "SATUN13", "SATUN14", "SATUN15", "SATUN16", "SATUN17", "SATUN18", "SATUN19", "SATUN20", "SATUN21", "SATUN22", "SATBD01", "SATBD02"], + ["","SATFE10", "SATOP1"] + ] + }, + "stdlog": { + "destination": "/afs/psi.ch/intranet/Controls/tmp/bdbase/stdlog/" + }, + "screenshot": { + "destination": "/afs/psi.ch/intranet/Controls/tmp/bdbase/screenshot/" + }, + "url": { + "archiver" : "https://ui-data-api.psi.ch/prepare?channel=sf-archiverappliance/", + "databuffer": "https://ui-data-api.psi.ch/prepare?channel=sf-databuffer/" + }, + "OpMsg":{ + "pvDate1" :"SF-OP:CR-MSG:OP-DATE1", + "pvMsg1" :"SF-OP:CR-MSG:OP-MSG1", + "pvBeamOK":"SFTEST-CVME-TI3-EVR0:BUNCH-1-OK" + }, + "BS":{ + "pvFreqSel":"SWISSFEL-STATUS:Bunch-1-Freq-Sel", + "pvFreqRB" :"SWISSFEL-STATUS:Bunch-1-Appl-Freq-RB", + "modulo": 10, + "offset": 0, + "timeoutMS":1000 + }, + "Aramis":{ + "laser":"SWISSFEL-STATUS:Bunch-1-Las-Appl-RB", + "pvFreqRB":"SIN-TIMAST-TMA:Bunch-1-Appl-Freq-RB", + "beamStatus":"SOP-BEAMSTATUS-AR", + "energy" : "SARBD02-DBPM040:ENERGY-OP", + "charge": "SINEG01-DICT215:B1_CHARGE-OP", + "photonEnergy": "SARFE10-PBPG050:PHOTON-ENERGY-PER-PULSE-AVG" + }, + "Athos":{ + "laser":"SWISSFEL-STATUS:Bunch-2-Las-Appl-RB", + "pvFreqRB":"SIN-TIMAST-TMA:Bunch-2-Appl-Freq-RB", + "beamStatus":"SOP-BEAMSTATUS-AT", + "energy" : "SATBD02-DBPM040:ENERGY-OP", + "charge": "SINEG01-DICT215:B2_CHARGE-OP", + "photonEnergy": "SATFE10-PEPG046:PHOTON-ENERGY-PER-PULSE-AVG" + }, + "Update":{ + "freq": [0.5, 1, 2, 5, 10], + "defaultIdx": 1 + }, + "DAQ":{ + "caWaitSec": 0.09 + }, + "MsgSeverity": { + "fatal": "#ee0011", + "error": "#990033", + "warn": "#cc6600", + "info": "#0040ff", + "debug": "#11aaee" + }, + "StyleGuide":{ + "fgAlarmInvalid": "#ffffff", + "fgAlarmMajor": "#ff0000", + "fgAlarmMinor": "#fbfb04", + "fgAlarmNoAlarm": "#00cd00", + "fgNormalText": "#000000", + "fgCurveHor": "#2a63e4", + "fgCurveVer": "#8b1a96", + "fgCurveLong": "#cd6100", + "bgTitleOperation": "#dadada", + "bgTitleExpert": "#646464", + "bgTitleSimulation":"#8b1a96", + "bgMain": "#ececec", + "bgReadbackAlarm": "#c8c8c8", + "bgReadback" : "#ffffe0", + "bgPVSetBeam": "#d4db9d", + "bgPVSet": "#a0a0a0", + "bgButtonWindow": "#b79d5c", + "bgGroupContainers":"#e1e1e1", + "bgErrorLogFile" : "#f0f0f8", + "aramis_color": "#00b7eb", + "athos_color": "#2e5894", + "aramis_qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00b7eb , stop: 1 #ffffff)", + "athos_qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2e5894 , stop: 1 #ffffff)" + }, + "h5": { + "groups":["General/Created","General/Author","General/Process","General/UID","General/Filepath", + "Machine/Charge", "Machine/Laser","Machine/RepetitionRate","Machine/BeamDestination","Machine/Energy", + "Method/Method","Method/Sensors","Method/Actuators","Method/TimeRecordLength","Method/Background", + "Data"] + }, + "h5Machine": { + "charge": "SINEG01-DICT215:B1_CHARGE_AVERAGE-OP", + "laser": "SLG-LGEN:WHICH_LASER", + "repRate": "SIN-TIMAST-TMA:Beam-Appl-Freq-RB", + "beamDest": "SF:MODE_AR", + "energy": "SF:ENERGY_AR" + }, + "h5Data": { + "dataSet": ["timestamp2","data2", "pulse_id2", "timestamp_offset2"] + }, + "test":{ + "test": 2 + } +} diff --git a/sf.json~ b/sf.json~ new file mode 100644 index 0000000..1b0523d --- /dev/null +++ b/sf.json~ @@ -0,0 +1,150 @@ +{ + "menuFlags":{ + "hasFile": 1, + "loadInitFile": 1, + "hasDaq": 1, + "hasH5" : 1, + "hasEpics" : 1 + }, + "Expt": { + "encoding": "UTF-8", + "beamline": "", + "exptColorBg": "blue", + "exptColorFg": "white", + "operator": "sfop" + }, + "ElogBooks": { + "SwissFEL+commissioning": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning/" + }, + "SwissFEL+commissioning+data": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning+data/" + }, + "SwissFEL+test": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+test", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+test/" + }, + "SwissFEL+test+data": { + "url": "https://elog-gfa.psi.ch:443/SwissFEL+test+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+test+data/" + } + }, + "Elog": { + "useELOGenv" : 0, + "host": "elog-gfa.psi.ch", + "book": "SwissFEL+commissioning+data", + "url": "https://elog-gfa.psi.ch:443/SwissFEL+commissioning+data", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/SwissFEL+commissioning+data/", + "category": ["Info","Measurement"], + "system" : ["","Beamdynamics","Controls", "Diagnostics", "Electric supply", "Insertion-devices", "Laser", + "Magnet Power Supplies", "Operation", "RF", "Safety", "Vacuum", "Water cooling", "Other", "Unknown"], + "domain" : ["","Injector","Linac1","Linac2","Linac3","Aramis","Aramis Beamlines","Athos","Athos Beamlines"], + "section" : [ [""], + ["","SINEG01", "SINBD01", "SINSB01", "SINSB02", "SINLH01", "SINLH02", "SINLH03", "SINSB03", "SINSB04", "SINSB05", "SINXB01", "SINBC01", "SINBC02", "SINDI01", "SINDI02"], + ["","S10CB01", "S10CB02", "S10DI01", "S10BD01", "S10CB03", "S10CB04", "S10CB05", "S10CB06", "S10CB08", "S10CB09", "S10BC01", "S10BC02", "S10MA01"], + ["","S20CB01", "S20CB02", "S20CB03", "S20CB04", "S20SY01", "S20SY02", "S20SY03"], + ["","S30CB01", "S30CB02", "S20CB03", "S30CB04", "S30CB05", "S30CB06", "S30CB07", "S30CB08", "S30CB09", "S30CB10", "S30CB11", "S30CB12", "S30CB13", "S30CB14", "S30CB15", "S30CB16"], + ["","SARCL01", "SARCL02", "SARMA01", "SARMA02", "SARUN01", "SARUN02", "SARUN03", "SARUN04", "SARUN05", "SARUN06", "SARUN07", "SARUN08", "SARUN09", "SARUN10", "SARUN11", "SARUN12", + "SARUN13", "SARUN14", "SARUN15", "SARUN16", "SARUN17", "SARUN18", "SARUN19", "SARUN20", "SARBD01", "SARBD02"], + ["","SARFE10 (Gas detector)", "SAROP11 (ESA / ALVRA)", "SAROP21 (ESB / Bernina)", "SAROP31 (ESC)"], + ["","SATSY01", "SATSY02", "SATSY03", "SATCL01", "SATDI01", "SATCB01", "SATCB02", "SATMA01", "SATUN01", "SATUN02", "SATUN03", "SATUN04", "SATUN05", "SATUN06", "SATUN07", "SATUN08", + "SATUN09", "SATUN10", "SATDI04", "SATUN11", "SATUN12", "SATUN13", "SATUN14", "SATUN15", "SATUN16", "SATUN17", "SATUN18", "SATUN19", "SATUN20", "SATUN21", "SATUN22", "SATBD01", "SATBD02"], + ["","SATFE10", "SATOP1"] + ] + }, + "stdlog": { + "destination": "/afs/psi.ch/intranet/Controls/tmp/bdbase/stdlog/" + }, + "screenshot": { + "destination": "/afs/psi.ch/intranet/Controls/tmp/bdbase/screenshot/" + }, + "url": { + "archiver" : "https://ui-data-api.psi.ch/prepare?channel=sf-archiverappliance/", + "databuffer": "https://ui-data-api.psi.ch/prepare?channel=sf-databuffer/" + }, + "OpMsg":{ + "pvDate1" :"SF-OP:CR-MSG:OP-DATE1", + "pvMsg1" :"SF-OP:CR-MSG:OP-MSG1", + "pvBeamOK":"SFTEST-CVME-TI3-EVR0:BUNCH-1-OK" + }, + "BS":{ + "pvFreqSel":"SWISSFEL-STATUS:Bunch-1-Freq-Sel", + "pvFreqRB" :"SWISSFEL-STATUS:Bunch-1-Appl-Freq-RB", + "modulo": 10, + "offset": 0, + "timeoutMS":1000 + }, + "Aramis":{ + "laser":"SWISSFEL-STATUS:Bunch-1-Las-Appl-RB", + "pvFreqRB":"SIN-TIMAST-TMA:Bunch-1-Appl-Freq-RB", + "beamStatus":"SOP-BEAMSTATUS-AR", + "energy" : "SARBD02-DBPM040:ENERGY-OP", + "charge": "SINEG01-DICT215:B1_CHARGE-OP", + "photonEnergy": "SARFE10-PBPG050:PHOTON-ENERGY-PER-PULSE-AVG" + }, + "Athos":{ + "laser":"SWISSFEL-STATUS:Bunch-2-Las-Appl-RB", + "pvFreqRB":"SIN-TIMAST-TMA:Bunch-2-Appl-Freq-RB", + "beamStatus":"SOP-BEAMSTATUS-AT", + "energy" : "SATBD02-DBPM040:ENERGY-OP", + "charge": "SINEG01-DICT215:B2_CHARGE-OP", + "photonEnergy": "SATFE10-PEPG046:PHOTON-ENERGY-PER-PULSE-AVG" + }, + "Update":{ + "freq": [0.5, 1, 2, 5, 10], + "defaultIdx": 1 + }, + "DAQ":{ + "caWaitSec": 0.09 + }, + "MsgSeverity": { + "fatal": "#ee0011", + "error": "#990033", + "warn": "#cc6600", + "info": "#0040ff", + "debug": "#11aaee" + }, + "StyleGuide":{ + "fgAlarmInvalid": "#ffffff", + "fgAlarmMajor": "#ff0000", + "fgAlarmMinor": "#fbfb04", + "fgAlarmNoAlarm": "#00cd00", + "fgNormalText": "#000000", + "fgCurveHor": "#2a63e4", + "fgCurveVer": "#8b1a96", + "fgCurveLong": "#cd6100", + "bgTitleOperation": "#dadada", + "bgTitleExpert": "#646464", + "bgTitleSimulation":"#8b1a96", + "bgMain": "#ececec", + "bgReadbackAlarm": "#c8c8c8", + "bgReadback" : "#ffffe0", + "bgPVSetBeam": "#d4db9d", + "bgPVSet": "#a0a0a0", + "bgButtonWindow": "#b79d5c", + "bgGroupContainers":"#e1e1e1", + "bgErrorLogFile" : "#f0f0f8", + "aramis_color": "#00b7eb", + "athos_color": "#2e5894", + "aramis_qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #00b7eb , stop: 1 #ffffff)", + "athos_qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #2e5894 , stop: 1 #ffffff)" + }, + "h5": { + "groups":["General/Created","General/Author","General/Process","General/UID","General/Filepath", + "Machine/Charge", "Machine/Laser","Machine/RepetitionRate","Machine/BeamDestination","Machine/Energy", + "Method/Method","Method/Sensors","Method/Actuators","Method/TimeRecordLength","Method/Background", + "Data"] + }, + "h5Machine": { + "charge": "SINEG01-DICT215:B1_CHARGE_AVERAGE-OP", + "laser": "SLG-LGEN:WHICH_LASER", + "repRate": "SIN-TIMAST-TMA:Beam-Appl-Freq-RB", + "beamDest": "SF:MODE_AR", + "energy": "SF:ENERGY_AR" + }, + "h5Data": { + "dataSet": ["timestamp","data", "pulse_id", "timestamp_offset"] + } +}