From d53bf7b918e58c0381a4cff4feaba7d51eae3efd Mon Sep 17 00:00:00 2001 From: Zhixu Ni Date: Tue, 6 Aug 2019 23:16:42 +0200 Subject: [PATCH 01/11] Add docstring for cmd_lipidhunter Update requirements.txt and travis settings --- .travis.yml | 13 ++++++++---- ConfigurationFiles/3-Specific_ions.xlsx | Bin 7330 -> 12863 bytes cmd_lipidhunter.py | 18 +++++++++------- requirements.txt | 26 ++++++------------------ 4 files changed, 26 insertions(+), 31 deletions(-) diff --git a/.travis.yml b/.travis.yml index 498b4b7..b08f1d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,8 +20,9 @@ matrix: - conda info -a - conda config --add channels conda-forge - conda config --set channel_priority strict - - conda env create -f conda_env_linux.yml + - conda create -c conda-forge -n envlipidhunter python=3.6.7 - source activate envlipidhunter + - pip install -r requirements.txt - conda env export > env.yml - ls - cat env.yml @@ -29,6 +30,10 @@ matrix: - travis_wait pytest --cov=./ after_success: - travis_wait codecov + - conda install -c conda-forge pyside=1.2.4 + - conda env export > env.yml + - ls + - cat env.yml - os: osx sudo: required @@ -44,10 +49,10 @@ matrix: - conda info -a - conda config --add channels conda-forge - conda config --set channel_priority strict - - conda env create -f conda_env_mac.yml + - conda create -c conda-forge -n envlipidhunter python=3.6.7 - source activate envlipidhunter - ls - - pip install cython pandas matplotlib natsort numba numpy numexpr scipy six pymzml codecov pytest pytest-cov xlwt xlrd openpyxl + - pip install -r requirements.txt - conda env export > env.yml - ls - cat env.yml @@ -76,7 +81,7 @@ matrix: - source activate base - conda create -c conda-forge -n envlipidhunter python=3.6.7 - source activate envlipidhunter - - pip install cython pandas matplotlib natsort numba numpy numexpr scipy six pymzml codecov pytest pytest-cov xlwt xlrd openpyxl + - pip install -r requirements.txt - conda env export > env.yml - conda list - echo $PATH diff --git a/ConfigurationFiles/3-Specific_ions.xlsx b/ConfigurationFiles/3-Specific_ions.xlsx index f56a9d92ce9950c3af66492066e42ba5445e98fb..766a647450140dda11e78ad0f5f07a42ce47f61a 100644 GIT binary patch literal 12863 zcmeHt1AARt*Y<8~v$1Wnabq<`W81cEJ85j&W@EcaV>fP+Zy&txIZw~|e!=^!Yh7#a zeXTX_Irm)S9&<=u3KR?t00Dpk002Y)kN6QH_jdq*A2qMpfN=&nhMy@>I)J>_6b&WPhwDlzOLQ! ziEph3OLm_(51qM$hiR;!a?`oFUL0Lli|erd+E^k@d0~-2qhDZebo)X4D|*nVV7uo^ zjbk{!@2uK8`A^0CSmeP}NOt;^dkV(B@7o1k)C+O3qx6h;`E8FWpw6a_DxB?fe)9Ow z#7ZmW$}QNQ+iQ;#U}88NU>v!{RTYMjN#YotZr)>i^F}gvL2$6oe#Z=AcpyAyioJ5{ z45D;+7urzz&PMx=(mhP86yPqo-nl;s|8s%=AmF1pO6JGxRlr7h4M7}x+krY12sS6& zXst01lG|Q2Jx_y6IK)O$7DJqt1DiLE0~q}`aPB7{Dc{~e0rLMrS=7&6Mj$}SZUGqy z3#6=$y^*B@1O0E;|5Ek;FhBqH*DK;>q(GUFf-n5vh$cFD)~JbREg3`)Wei{5F{Qoe za-_w6X?wXB6LidL!gtTCcFA^2yEU#Wa4kUca7IZMh4#-ho@-a>lX_`sfkaNQ7mGR- z@AD(JEITQ`Wr?ER&s)Cb53ktG52Po1^Tl%ds50o!*Q#a4sg`7qrSU@&v5ZVBX&*0m z>%IIW>)@0)6psUFKL10mMPg~m(H;f2MFqM{gCP&#PV_s3IC@P>{rq7JA&>uF-12aFxeh{bBw45Rt? zOtpLlQ>tG%P^LEPo`9?HPs&JNH_4EJ0sucD002bb6RwsFE;jZS`ZhKezwK~elojOG z7?Hel8s3l|`A8AWBuPNbGgO2@f_?p1m4&Q#*)e1@R}f@^9xiw&Wbzyl;qn)wy`~N> z&b#Vkz&!=ZLSG1VKyMaII70=+k6&qxfZWWp0|6{evoONELlwz~1E13fcg zuT0+w1Zr@HwA`Qh_P{ZaQsiD1h zY`HoqPq(NUP6GsKF8z=jBn|2V@$##ljwdB`a1wPiR*wHjiD1HE;UqYhW9~d9nfzMf z8R1wmZuw^TEmHylI-#P$}hI<566@A z+03l>S=|#Mt&K=7mP7ty8`TMmI2^wxB?|U#$ib^F>p+03DdeWB`Lnf;Zp_c+#!d-> zXA+<7=%FiEPLcpd@-)5-#sD5v5kC5hMUJsB9Mg8nRQyv{|oYBIe}>>)q_|fl|}B2kTolEG%1^PKKpu ziOHhCBvwB1DiKyQSn=g@(F)OFhu(5#TTjDLWqxTQjsuFYYkDjB_mTL#72)i{mQk~N zbs<-fBt7nWqz3^zzf@D{R`MP<{patX8Yd2g8ThPYzE&SD{jU_ZS2mFdR-2)-Nx$>r_pQcHX?tuXAq9LZf$2XanI>ZRDvBCl!T*zxuaTM@POM)-b{i*>7P~N`+o#SML9h_DL;cnNOwSO<&Phs z%|_$={y<5F9a2z4Eb^muHkj3XiqVPL++iATOh$ckykXDxDe%*2rGGSTZ*4U9=`E}oVr|(zuH_->Mlb6F_E&FTE_v`h?!{pbl zNy*H3PP;E2h&4NSR_xnzqwubF@NO?%J9w_2Lgdya580}Z^VenYn4Gf|x-^r^_3v4o zULRgwwRa=QU~=>kxOvb*QaQz?+bMfbT%c7QVZ=|9!m#GKWJ;vm zHToXQ=SA!EL}k^POJtqBoWJXIi*Ec3UxXJUBmc1?kh|dQ`uJt8s-kWfzT=((*>HTO z80OXOa?56+fh*T4wbmpFbR17SE+J|lr3}4huhl3Ou z-_Y%&-m5B11VSIF_QHZxZ94Z`%l893PngGXzE|_LS10Q#Rq%-#&vJ#N>f))GUGtrg zslD$S*wZ z^lI%5--hdcQi6AdRMD4IB@vc#YqAeoR0U0RVlDPuke@ z^IG7BGewf=H){_McKyY(vo)(5Yfate4VN{c_OrY-j1{X0YfVqn3;-3RagSvP3rX+T zEaFenP=auAWU2Q=Xzgaavfn5r5*F)oF;f-nKqf~r{c^)vO$bem@max=cXuYi(sRK< zxuy~Zsc46HG9_y!O9ei8jtd|uxV+C-M^|8WE`;^x(|RG~H;(Kma4KPAG$Bk?hVZZ0 z5fr9XiQ}TB9N?L%87y-Q4_K-J%h5~n(^X*;sXun>U5<+93{$)bz~D$aAR7A~DLFw6 z+FM~Ro}!GHcH{4dJGr8d{`1jRh3o;Y91g6$j3{`a2dCZcIAmE_kqiGi+(8W8IKfYs zoozrLwXz#H$F79IA~->awG!Yk2|_hI3s5q~d(ql*P}OYHXnrP2nIV|`ER@o~QNEam zicoD8xZ;M$6FtHWrdv)^MMY?8dQy*Z3xdU#!+v0&6?e9e`D-Fti$ypI08I5 z4-*Gvve<s7dwN^MOUdi zQJXW6Pw^Og7=U_xwKx(v`cYwsFGTRui!P(K_PcO542U_h51dt4G#GJ4O*YND><00T zZ0g;u%KH0o4RYrbsM&#e!&hgfpq#&WUMDrIM zP+~MxT<{~gEpa=$VZCafqH&M>`*HDdWiCY36LXKC3R5K1p*lCDCBGnB;@ib;=jO}> zlTKp8IT=iZLRGSg_DPKN9oCh6sItshjJT#0L`9W6d6XUtW%^9(i%J{UW~Kuj^eNnP zIGOongw}`elWJOIYSscwiqH?Ji$4Fut^Ghw{Bbu zZX}-*PA`RAf{4E4J(usMeQF#9;AD8X&0ZTAn18;bMeg6+(Wg)kQ7T<%zvZiMeE3MMu)M|q$^Ac+k>uDNyT^n#tPrL7mJst z&tAYL)G&b!SD1p0ou_I*dpxoO8*p@kju~`<4?jrNi6$)DSOJ=f<>~Lcj+*ussepm3 z!?=AI6h{J8{=<-rxXZWq$D@CQ{^uC6WaKMw&}f**%)1JKV8p)rmuv?*S(+2_+sM4#6oZC|Ljz=Rocy|b^3G<5 zIH)N-x=&htqP=M!4RWzC3$Wm#P%B_uK(Kk$sv{8FIITDfwi|Y+(L#v${ltuz!cj2A zWS4MUex@cVJWx{ebjDFNSTzKyKm_nr`k5BU=!?(sF7XU>P@ZMlN!Ci~G8z(mV@%Z! zIATuGP3h5d*Yfw7DMSzAA3pbWZ;YEu&LV`zP>_~2!M1|F1BVL+Ys7_sY=oGDH%C2% z<&=(LxO@w7zs*7+mK$3|nd{?)p6{$b2giBKH^~ZwCl6il+12Ps6XOKiQOO&HUy0i9h^xa}P9x=Vb^RF)g8!nfKcuITs-b0uAP zkyCbIE2_c=J{n^L+AO}-oxPLpj38?1f(sMZqW6sY1<9sryza;X%!KULdn6;}#Z+6# z>4xU#@px65JT9P&}Ema<# zirS;F0}Ibd*Wn5M@INx%{?)(g#YF0og#`LngukV7fA_B(O^vLK7=FM0?pmFyPe$Ny zpmk$DeSmXt`N{SzhHP{Dt7XClsbN+kZe!D_f(i?BdR=#V6}@$zStj zMlPq4&L#U;a8j~*%84gNA{#+lKf==flv>O2wnw%ag&JN4eH5|GOD2%uTBF7ogbI#p z=`rT?+aiw~7Vjg;!5GHH3)oD>peanrDC^YC$@f?q6^;$2Ri3fkzWA>gB1;yL+k?iFFvzY;7Mul8tA3|N& zI`@saRa)0mZN}mHsMma!5Gp{!qfiI5L~Ho=eJfsBOwdxUl21)A0bJX*C~UPL6~9)0NS1N2$;nbKnvQ1wlGNE} z`Q{%M@*)!UEy46bjpi<`tLTP(hta5;Z~=my@l;~|7 zJNv1-RyY!`yj?hSe~FKISGp$b$2n4UKMkb3}^$TzH^7% zz8CC#!;vKQiD=jzAjfst& zzbgi181mMa$M+%|lG>d6nM&?i(FiizY#{ptdl7R~OW=o$@$KCbCs9!9CMoV1=bqZO zG~PD#!@4?~d}m!?*q-Ltgm=w%lSm2{{=9m@P%v_nE)iXv!k(Mq}vq?pDw|t;5rAjQryIFk7ypcAteP@q8S7uwBT-3#?-% z5|XiGO`(mV)%@KQ@k2UWD(!kA3Eek4@(&cut1;7X8p1{!J(=Osw@R)o*5nL4vHpWdnFhDPE zNb88Kf|*Jab5CF?O?xM=&%i<$|^x)I+TPC0B@6l6g(c z{7)^;*b>>+4=#Gi*qC)8B8l8u39@4lOmV3mi34;xbUsP&tTVXzRy3-$mo@DaNs6mh0e{|W^9W!0(2%qIjj3(iZkax~cHO%f~3#*!#k)t8Nl3Pjd%{!sz zO)Uex>y+EzAXpf4fH3=RQZz_?Jnxur6vDFyUw$n-Uq@YN{US?eUu8kxih#1s%Se|q!7QWRA=@8bU$3y%z(NZJCpXXjVC5vn$#+#n@nIxuLc>Xb_Czx4;c0BW zW5F2G#gEtB)`zoL@lamKCWVCZX%=TBkzF@pJwZJRYO8~bg6_?m$`W!za+xmiyZ~JtULC6si(mE5E zjXO`fU0N%ib{EKmSX0R-8X7xaCt8~N#GGy z7p&z^IA9v>n>C@#$&9=U)Jq_fBza1jab9v?2x$y-_o=)Ly8!p*?M-jMT-HC+8@Ku1 zgLJ?gGY2rm0sqJL>)_~SY2@%*PNP9Z+h&dt&Fkat2Q}}nnT9f^<)o zJnDig!g5M3ONXgci*~8#R~|}}hayx;`4-i9mKj^M$|%teyTJ@j6U82{ zk($nSq|tA>!9_tOjvGuBmq>Gp{Jri82T5Ww#R^ABqiOyc9drF0f;Q5S&8Jyqbvnsc z{@GNBX8vPon1T&L2;8F1R9pvh+gwy9Kr25ZSoL(t*2GZE)JX_r?)5veC0Qxb>g$-*CS}Z%sLR&biF9L}_6%Bjk8B@Jr0SlrG zsxi|?;i;T@BYxPqJ-p&M7{3G{wZ}+J*C1%zIcBHMt&3P$V(7ibhVE(9vbH8aIyjZ_ zt=COh1~UBGRapELju{LLUn|tWo$1Q~oG653%|ry)D%CrQq{? zPHe8&ogQLMvrobak+3H+qU34@M40_cIQJG#uv;`%bWo)u=CVr~3Oi*Um&=IUlo+VH zQ*5&b-;tfSBB2739anhH*O5?G5c#rmIDayw599Y1$yXfo=XY`Kez@K&KP;_@ehqD^ zT;8zW4^OjiLCFm4xUJl_AX^cv%|-kmievS_A-+*+QNrM?nzWz9qO{#J(WAW8LCHZ7 zG0>A&T2rb{k*M-TU zVbxlr^-`1ss6UsR|_vL!rSf7io_TgZ2FRCoz%)q)^ z=n+V?a#gP_4zp|SViE=otI{=6a1f&y@`L&2{&dx^7K$+1E-f8twRA>2j*>xV1!Fhp zk~pg4ec43C{n+SLH&9h5O4XF;EMvtL;Ag`oItbUWZGd)h<3M%Y&qMG%)%JhYjA=6@!`4Z z<1DwITv_FVMs1-fI`4*Y9f69&OKM%UYjh+{x4|I&Q@3n^H+n*$L}ij!Ol=BhQlo3j zk0(r{RedN|XIFoX+&VcR`#wS{6Dgl4L8J+BB(WiH<4ztEk4_<*@I^Qtu!euddUj1} zkE>c(k)Q17LAhoSQ~XquM^}xEj%T%Xh>7%;1y$Jc_-vOR5xjjsj|ArB{>W1Vn;^a>(84X(EO03X2gs+bh$q}7>yLS{?! z?qn9{p;Z#Yj9oa@33mNM;NCCF=y|f9l+k=*ToPTK6-l$;YO$8 zThe1c$Jz}((e1NwB3=uK$;X3|a?pcW?H8pj6EOxA%JOlU zZe`;xUuqE*M-;I!T0x*H7ik1*VO>ln{VZ&!@eUH13gE+Rmw?wao8IEm~xmB zS*{`)o3ar9#hJJ4vTn~OcJ2d^6#t|Rj}^02FYt~KaI+%$gEqgFX8z2!|52;?E9d@u zr6w?@H@uG#P4pi0RoK-dVKE3!_!9?li}C@e{?jVNT1xCa+KWd$u2IkazU|k2_KauV zQXFH1INJF(kf1#SOw*c6k5#&E!CKDabu?%?-dMdk`mS_PSy{=j;aD|v*xDck(ig0L z?}3%tXz0>d{_iUiVQ!40j}bW26=mjD*E*0546=aVBKUIe_>1>IBP z*IxrAxMFqr^ToMFM9;2$^#xB{?y@bs5WtG8CdO~>{?%|;QzjQA{8o0N1OO=hSOHt0 z#c(vT|77Io_?ziq_~kbfy}p_CY3f(WegUMRZmUl??xiu)0o#Hwg_yk=B^-RJx58!#)HEFkqnU1|EIfB`jbX|)yN|B}Q zX5r$csBJ(hYj{xGS-)&tEXYjW5((twHX9=^fA*$al1gtB@Q&$Pb~AlrBGE!`;3CHg z&O3D5%l(%72}BkF?f?Y@9OWErH{9SM2^4o*ps!}ZB0(Z-xO^kSKfhzrT;d)4esE5- zXZrOI5%j}|;1Xbd=eW^2fB1nJDhgp>|FO_Q^BVd!SUZST$+KB5GMtWN5L2$O;roH? zO!8CV5BL1X(sHQ^HED&bYCVqHH?vGqW>2&L_#A>q47!D=Ox($oTw;SR6_f4x#BdH+2bZtm6DRI?h23nG z)8e^w(%BXxed^h^6Jv?!dzpH1`=fL#ctjl&(K-_58>#$#x3OR-1-T*;KKp;wf-GwA z@rD`!uTMPBeUbjyp0euStUJ7^xq|G{u5Gh~$lmb=<};DK)mKuhB%^{WpA9XWH1r zVBw8Cph*FL@}=69AR!Jjt2hurtl>k4JTG*h8f?*Gb$c*o`USos{z5snf2tJR>w5ALeP*G^0aaXGa z*tOSF&(+GSGm9*WKm91!rL(KaawhRXnIFzk_>%CwZ@;n17bb(Xws7Es68VCUmYLsn#kh z=-G731B$eI>{_EQnviu`3t`w#KfUGskxvNwj4{7w={+c@g|hGmSK-_w-XJH^Zx%}d zpX)rO=g$~jP2g+Eo<>*Dn3|M4*VHd1ry{~tSA4zXqVL+2?6b?F*znI&g_?&*DBV!z zNm5TQS6c!#q8i@!DoTU5A>KVmqE$l>)vM~Wj;0B82wP{w3!g%M`QkJ5BNz{m7r)LJ z7Gk@}6SI-hL4R*=yO}x&9SD06+DL-2UO(_peh49hyP}Vog5r(tp2Ob|D(&mC7P45@n^(>ynK%L zf}G`P$}Pd_p)_?~)(c~}uR=3}u$oihs5@=19+^I=!?y7nf4l!7fiwBxc#KP-Fm0RZ z5(0`d5jBp*JG9rj-MP4D2I2-+)qf6)RVl#j`T?nvlBkq9(tKFV7B65Hiz`4rA%0N} z@sz!pCrF-+-MI`w9u1s?6?ISTlXY&)G*)~8d%p8N8G@r*eZr%KA-%X})}{@P*|PW0>XjBuG-N={jX*J#zM)@YlY=zeK+S zI}Ly7GW=EeKU=8&5(NM_fuZjIzoF_^oL~ED{z9^V``=0Yqs!)3lwYeyf1!+{|7$Jj zSAbvhUw;8e;{6WrS2pZd(O*OSzeMv1{}BB(;Qtlj*J$T2gcXus*Wh1cpI-rg4Icgi zTqFG*@R!ixUqgvsLI2Zp{RIuKln{`Hp<8n3?oN?zq`T7rq+yV5P`W{+rKD52@SX2oJ>GM^ zwf~s;?caXayZ5u!dfpX4d003+C?q5#C}ukZWvJhT`0>A|ExVyJ$kv73!@=3c#KFOa z&C|}7?deW+f}%|i0PXGZ5ByhGeX@wA(fp8Taqy38=zf*2pL=-|XB!^;*+}$IKnI_b zKF^(X$XtBmj`0;jSacRr9nmRJntz5>u7M}@tOG&*GJBuP>gMW&1cjWghUqQTSJQ>e z?3Hvq`XgGuG(o4YrlTtzIwDJkbuSvdILuaRSW<=h7c01{x;l9(s=g2}M80q+ z&ETowsoUvmdV#8(8%=7*o6u+LEDU1Vx2?p`vZA$loz9C&(B=JtV{xH(x8Nss%T3}d zpwYPi5}!Qx;ec6#uQnXeRwiUd*!wlT2VtV?h3_pg9t2555|z;zpEYELp{fIqnYCZ3 zq^DP@_RR!oq>ui$b6G@rqJ0_)l$ohOAWwzaYPeqv2(#8p2VUDaUr~{(b_0+3$jM8w zhgQ5CX`m!ZCE-J4Lz_f;0}F$dj5ij!_p~bxBCB{%9m^dxP+*Ddbo=_KSlCvFMy}gz zB%{L-(t8Ly*T@!pM?uJH%`l&jl6!6eJY zxe;E@>QDLJb^XFqh=X;i`#!7LLi?{Q|+mt72FgRY|OT3y7SE=roNJHW$yCtZJ+TWGP3VJzB2@1b86Kr&AZ+L9n zIvbb4L!HN6XkWdEhA>~eG{DRz?^INZ$S*{2g~SpcX!^*bw^P{yz)@WW^4X+nBqEt+ z8g!nuV43Gdy+;msHA$T|`g5JA97#5(28WpFmsiW(fO3gg*|i!InT2uxzXE9qYF7mj z779uZ=br+J@Lz%SL@q9tAdssI`(HmCPr=lur|7c8j{`Xd1NS;`pucm0e5_3tW;H?m zYWt%~Gpm-!b=vtdtg=f<_qXsektMf0G-Nn}VaaeJZXrJcUx{`$UvC{72zpIOrEe~5 zsgGvuNm^9;W}7LePKk=H{p8A08fF@wb;_`~b-vX|oicp?)9ECGz;L*FcBYqbaCl^| zvEq_q`^>pvrmZ<^%O^XXA+vqH@7;~A@Ysl7{)XF+LIc6n*o{vfPKk;ns1%VdwwsxX zb(2xP7wuCzGlb7wiM2}Zws;p(rz)csdno$Ml8WB3`H#$%EM@YuHh4A0<(`MU|G7N( zsq)heMalYiPk%QKhX7xb3mD7Yuc=o)H1ZlfV{aTe67GxYvnhg=wM%Tz{mYDJNcpVc`c^UaMj+=9aw>;i!U6uO|^goLu(SPDISmQ z^qkCa3f)D*9YuiX9ziy-@8O3vbCZSkp8LVRnNVbXod*YrwEnxv#A#xK7pWQ@cg#9k zOR(rmW{_E;{l?3dsE3ZM45$MfA)Z6wduyv2XuHujTutPOqO*n8FDk|hcZE?nP&eZ| z_8Qp?w&_AMyhPVoA+yB;E$8N(*C%Wtv&EvTdT*;o;+^)wL|1biH>qkSJP;1r)1P0Q z>-1{)x~Xh}lM2YKV)o5d-Bwq(nfG3W{2YgSztV%6an*Qa+sJJ5=BCy_==J-osGF!m zqp0g}B&X8C0V4Fc*4M+>AY$s-ha>fR?r6WvF`NGYLl)o%@Kowf5I|OT34Xj4UMW|m0CPr`N)O;J*){p(8d3MS7cuxYUVm;13aNRXCYI?jS~yoD0zaCW zfVm4Lw;Cf58#K^I#;yAtK&~OPU<|+pm3B4%fbfUag$TjDCo~%HNhNXxE}z9>EjqJe zEJ2;Iy}@%qW%c-xvOz$m=ZcyPeqYq{9c_UX=z%&XBTPlBUX`UhKk`Dt%Z0GjhY_gV z#zq#7)=xqhZd&OOr26c}c$4jW2#UUBhmI920kdX*sq&40M5qhl7epyu1I-jtdeScz zwsdU3X=>5ZhGwJQX6DiJh%BUCWBpgjIb56kVbI<{JD>OgqER4uTz?6o8|!2UVIJZ| zb7d7N0d`fLWlTj32|~yLfY1o>qEY(OEB?{W^>AMTMK+Z=7%4Oa&MZkqwyNbMk>c>$ z?S#qww_RdXy~dVQ(m!`9-H1+F{sGjzcmqcf ztKbda?)9$%rBRFxD*^pQ#$n0PDbSWNqKIv|of_gLYik!8PBta#kAggP*Zw@p#|%8^x2A>~vz} z97~>`$Mm3Ob(GgWz^SiOs8I`rL%V;E6O*#U0dJ`EHGHX>kih)QRb(KmM2{Ym;k^TC zgTJF5s<`v>leVp!sf8?Sx+es9x8+Ick)P|Oj7M$i_bdaiujGfUdRf3RFN zaPnDIzC3wNfH~B(ji9{H*4rQ(Sy!jk;2*I1Vm75@%&qydKg{x@yH;@tuFYjfnNR(= z;fGIp*(;fRd^Almqfv8w-`Ps<+RGyO%ST6wPQHzR7jD6Js&0G-^!wCD2IhKu+>mjP zOD03B<3do$Vas$=y+;_)j8n}#LnE!*YVgBs-SAa}2#c>GmczcM;_Q&QDbjGoVwYYn z#@N;V#n{M_B&2n4Zht#Ahe#RnY1`Da*6K*)Dmxv#fpvG8g!# zTnh77F7>~KT8!F~^CAGt?^w(89HYbWIUo&<$1^c~mA+``gDto=lEtftPE7E})q7A@ z$&|=BbP;6tU}0rrYpf+@m5Y$MK2nDtEe(-rE);l|=I0}W$hEDrS@A`cIeY=0rA-H- zms2lbrb{904YnO+>NQ`#;|1q!yO)sw@t!x73nW@ycG#hP@79FUmKQ|{E;n?^*AA-z zJcQ(rsBYFw+|(k3l7&MLCCo3$ai>(L6vuy`=h-|dxf!)7$aYNU3b>HFt32V%p@>zK zTi{@BsTYgUygjG8!w^uF)|cDHC#A|l+z{EqM2bn41r06;lEY^m9DCXb_UhU7MrjUi zvGM5+r{xR0uEbWsyZK1n<_^RZ{s1|dJ1%p{ae z8JZJ{pHACvPQ_?+6gfzB37EE5IwL@Ody4C)E=gr8K*T7z7fd<(#y#dE+m5w^7&Sv; z4<%CfGlKE!i2@<8YGTGwz>sX@s2BrfDcv?%O!z|F)s$t%XvqYnZdjo>p*=$gX5ooh zy!})%eX4Du*KLyP7LedvUhwBLbU)fF;1OH>lFMl04(aBi)9Lf-JCEu6*SM92PkzIl z5vP9#4F%=+n1}!OVix`HV%F8m7W7vYd#Ek$kO?4!9BXNJfW~xiLXvt+sY0cCK=4jTE_SSNFDvrVqXbK*zXH+AR3bLe5m3EZfM& zI#3P-6H97HMK4*zletJcQRF?zJ5Gu#7(0eIG{v|8M4kHOr`a2W`~&cb((SzpqOvWF z@so-P0(E$Vbd#=3Wn4}xEozkAM!O$0u<_-B)4*vcUy4EkSw-k|mwZuzirc;CcNvDqTHp*+*=%J+m4I(F z)(TH7rbJLs5w`@b%dQAWzqF2GG0a}so*%B4@}deS)5`r!rg+r~_=zot=wcrDnLR;O zyGDjjOwCZeI0v>wE55jV!yh{vS=}p12P|Q*+b++B12I_|CAX!D$4Yj3yK6_(iKh}_ zj0oAmtb&)w{i<$dB3`$g9GMzRr4mWdI(f-a&g!Byv1h8V7o+pjaB^(dK(SRRmrYBP z@BBUIVrB)%nz)R`3g1bhpcjR&6GX-t$i_IN9n=H^hS%cPyf~^}|151sIoLuOm$9f| zG<)#u!vcN;y4e6~P`AxRI#_|I*sNoHv zta@sf#NGE08H;Rtfh~LA)60wUi55F`iX)*Jwvag*b7!m%5~Hg=`;^;%U*;4XQyUzR z=cTJ<(+bkX=A86A77yCdQ=%P9J-)}JqDxnVAC+>Mj`wdA_rQk=YrX*wR!i=_NI#Yv zZVSQ3I#o0^gh3W}>Tem1_HF@Yz&T zEY*+Xk-fAu+}4(DXGfEBgt2y7j{!O7gqZ29O9nxr3NuqPPqV;xn!fa}3D)m0#Fo`!KVD_C$fgD$t=@)b?M@9x}i+ik)7577> zphEO*f%kBw9F}DWXPeKxHD0QM2xnpyzX&1}b2ua9)6-SglFx(ewNUb{Z4ZECd5kEp zEa?YpOP0kb@;PXw?IaI}%^A+-2KD1FUA;fr6^+RkxOi^hH5hxLb<|Og)j`3( z|A?YCC$Tz-9=6^qrS|5&IQM-|-!~Hex|IXiu#Lr4U#hK+{iGP-bR9a;dX)%1@;s`S z*zHPEH3Sbe z-(63gT^_0)tjWiGHSnU9s=1&%#v8!j5=f_cmlz@b^DyLwz5T3DyLS#ysC_rb{7d@Y%(*Ad6*fU zy;U`@8frs;#)?r3c~Q5LvHz_@z8SqE%HE)2vAj9iw18%GKrN{w-dkM#U=Yy`8)+>s?- z$H4X6U4Km!b2je*Q8PbmPXlmvrG_SemXs}R)Wd%Lxl91WmQJEV0Mr$2&|K&MXND=g z<3u;-p`PRX5a)Uvrp7lD8NJ7vuj0y~>hM`}wuWGAOdHBfQR{OSaG*_{Txvrls# zrqz|==S|!m-;<#hvic~k9}TtikD-F~yP=F79iQx!9j~nXNGpBEzL89e4T}B1^b&4d zB&Q6xu;6A5DyOErd$q4hD@_c6^@pQlpFZ6#`1=Y8>5)-^aDAmy&}r~J@#|0SV%sl1 zU1X>e70*o~V3G-l)9X3)7^;QGe-?X>(zO#yinZ}}vI^sinSJD86xZ8L+GpvP+|h+9 z-|?n5J82-Gs$u|*CwgnF1?3HmeeAVi8OFDrj{DVIlXc|PkSI-RBqeqb1#oedA8TY% z1obCYA&;DitmMI{MR4jGe!ZQx%Uablp^Z|nYwacpA1woPw5?EfpbU|V?Fm0ok3CW_)|+F$ z$U&`S{;fbPxk*?Y=`u+H8dC@2%9FTud#kk^H#zY@%W_?(I-KKCK3u(WdYdT=W~8$0 z>V;-T9Ry9m;=^`xX ze>wK%3X(#ts^3xfjYK#AkzorEl6~nZ4jcV|(ys&ujN<@WC@gQpzqf0E+uEFrFA}2= zV?2PO=DGgrM=4z)vKx;%ay_aea{mx->H%l*1F!zsD@&hU;jblOA1Hc_TI1Rw0S`_) zj9W}+4y%G1a3^U)yev?BvdIMq1dQ00Yw)IBQXQYx6z;Q z4+j8xMIW)BhI_&v8U_#Q*EHz&X~@$w=-=hP&xZcg^LsP+X?F5Uh#z-;)bsx)DSvAC zy##t{8vhd0$M=5J@E=>qe`@(XA$}^CehK(73;tWn{}xYwF8)17c*>c7$ bool: + """ To run LipidHunter from command line, please generate one configuration file by GUI mode and use it as a template. You can load each time one configuration file only. - :param argv: -i + Args: + argv (str): -i + + Returns: + is_successful(bool): Return True if the run finished with no error message """ is_successful = False diff --git a/requirements.txt b/requirements.txt index 7d97534..898f735 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,31 +1,17 @@ -ca-certificates>=2019.3.9 -certifi>=2019.3.9 codecov>=2.0.15 coverage>=4.5.3 -cython>=0.29.12 -idna>=2.8 -llvmlite>=0.29.0 +cython==0.29.13 matplotlib>=3.1.1 natsort>=6.0.0 -numba>=0.45.0 -numexpr>=2.6.9 -numpy>=1.16.4 +numba==0.45.1 +numpy==1.17.0 openpyxl>=2.6.2 -packaging>=19.0 pandas==0.25.0 plotly>=4.0.0 -pymzml==2.2.5 -pyparsing>=2.4.0 -pyside==1.2.4 -python>=3.6.7 +pymzml==2.4.0 pytest>=5.0.1 pytest-cov>=2.7.1 -python-dateutil>=2.8.0 -pytz>=2019.1 -regex>=2019.6.8 -requests>=2.22.0 -scipy.=1.3.0 -six>=1.12.0 -urllib3>=1.25.3 +scipy>=1.3.0 +six==1.12.0 xlrd>=1.2.0 xlwt>=1.3.0 \ No newline at end of file From c72ee3727960e6397f37799f2399d33752697acd Mon Sep 17 00:00:00 2001 From: Zhixu Ni Date: Tue, 6 Aug 2019 23:53:23 +0200 Subject: [PATCH 02/11] Add docstring for LipidComposer --- LibLipidHunter/LipidComposer.py | 49 ++++++++++++++++++++++++++++++--- conda_env_linux.yml | 48 -------------------------------- conda_env_mac.yml | 11 -------- conda_env_win.yml | 10 ------- 4 files changed, 45 insertions(+), 73 deletions(-) delete mode 100644 conda_env_linux.yml delete mode 100644 conda_env_mac.yml delete mode 100755 conda_env_win.yml diff --git a/LibLipidHunter/LipidComposer.py b/LibLipidHunter/LipidComposer.py index 05b5fc2..dc1596c 100644 --- a/LibLipidHunter/LipidComposer.py +++ b/LibLipidHunter/LipidComposer.py @@ -18,9 +18,9 @@ # Developer Georgia Angelidou georgia.angelidou@uni-leipzig.de import itertools +from typing import List import pandas as pd -from natsort import natsorted, ns from LibLipidHunter.LipidNomenclature import NameParserFA from LibLipidHunter.AbbrElemCalc import ElemCalc @@ -28,8 +28,17 @@ class LipidComposer: + """ + Lipid composer is designed to generate all possible combinations of given lipid class based on the + FA white list from user settings. and calculate all information required for MS/MS identification + including elemental composition, m/z of precursor and fragments ion under selected charge status + as fragment or from neutral losses. + """ def __init__(self): + """ + Default parameters for the elemental compositions + """ pa_hg_elem = {'C': 0, 'H': 3, 'O': 4, 'P': 1, 'N': 0} pc_hg_elem = {'C': 5, 'H': 14, 'O': 4, 'P': 1, 'N': 1} pe_hg_elem = {'C': 2, 'H': 8, 'O': 4, 'P': 1, 'N': 1} @@ -59,7 +68,16 @@ def __init__(self): 'K': [38.9637069, 0.932581]} @staticmethod - def calc_fa_df(lipid_class, fa_df): + def calc_fa_df(lipid_class: str, fa_df: pd.DataFrame) -> List[List[str]]: + """ + Read list of FA abbreviations from FA white list for lipid enumeration later + Args: + lipid_class(str): lipid class abbreviation + fa_df(pd.DataFrame): FA white list in pd.DataFrame + + Returns: + sn_units_lst(List[List[str]]): list of FA for each FA position + """ sn_units_lst = [] @@ -121,7 +139,18 @@ def calc_fa_df(lipid_class, fa_df): return sn_units_lst - def calc_fa_query(self, lipid_class, fa_whitelist, ms2_ppm=100): + def calc_fa_query(self, lipid_class: str, fa_whitelist: str, ms2_ppm: int = 100) -> pd.DataFrame: + """ + Prepare all query strings for the MS/MS identification + build all pandas query code in advance to save the time during identification + Args: + lipid_class(str): Lipid class abbreviation + fa_whitelist(str): the ile path to FA white list + ms2_ppm(int): ppm at MS/MS level, set default to 100 for some qTOF instrument + + Returns (pd.DataFrame): The calculated information including m/z and query code in DataFrame + + """ usr_fa_df = pd.read_excel(fa_whitelist) usr_fa_df = usr_fa_df.fillna(value='F') @@ -273,7 +302,19 @@ def calc_fa_query(self, lipid_class, fa_whitelist, ms2_ppm=100): pass return usr_fa_df - def gen_all_comb(self, lipid_class, usr_fa_df, position=False): + def gen_all_comb(self, lipid_class: str, usr_fa_df: pd.DataFrame, position: bool = False) -> dict: + + """ + Generate all possible FA combination of selected lipid class in discrete form without mirrored duplicates + + Args: + lipid_class(str): Lipid class abbreviation + usr_fa_df(pd.DataFrame): FA white list in DataFrame + position(bool): set as False by default to consider discrete form without position specific isomers + + Returns(dict): all combinations stored in dict + + """ fa_units_lst = self.calc_fa_df(lipid_class, usr_fa_df) diff --git a/conda_env_linux.yml b/conda_env_linux.yml deleted file mode 100644 index 26a8d95..0000000 --- a/conda_env_linux.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: envlipidhunter -channels: - - conda-forge - - defaults -dependencies: - - ca-certificates - - certifi - - cython - - mkl - - mkl_fft - - mkl_random - - openssl - - pip - - plotly - - pyopenssl - - pyqt - - pyside=1.2.* - - python=3.6.* - - setuptools - - pip: - - codecov==2.0.15 - - coverage==4.5.3 - - cython==0.29.12 - - idna==2.8 - - llvmlite==0.29.0 - - matplotlib==3.1.1 - - natsort==6.0.0 - - numba==0.45.0 - - numexpr==2.6.9 - - numpy==1.16.4 - - openpyxl==2.6.2 - - packaging==19.0 - - pandas==0.25.0 - - plotly==4.0.0 - - py==1.8.0 - - pymzml==2.2.5 - - pyparsing==2.4.0 - - pytest==5.0.1 - - pytest-cov==2.7.1 - - python-dateutil==2.8.0 - - pytz==2019.1 - - regex==2019.6.8 - - requests==2.22.0 - - scipy==1.3.0 - - six==1.12.0 - - urllib3==1.25.3 - - xlrd==1.2.0 - - xlwt==1.3.0 \ No newline at end of file diff --git a/conda_env_mac.yml b/conda_env_mac.yml deleted file mode 100644 index 6162a4a..0000000 --- a/conda_env_mac.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: envlipidhunter -channels: - - conda-forge - - defaults -dependencies: - - ca-certificates - - certifi=2019.6.16 - - pip=19.2.1 - - python=3.6.7 - - setuptools - - wheel \ No newline at end of file diff --git a/conda_env_win.yml b/conda_env_win.yml deleted file mode 100755 index ae40de8..0000000 --- a/conda_env_win.yml +++ /dev/null @@ -1,10 +0,0 @@ -name: envlipidhunter -channels: - - conda-forge - - defaults -dependencies: - - certifi - - pip=19.2.1 - - python=3.6.7 - - setuptools - - wheel From 7144ea44a95e3f7faa22b37c18b68e333d3bd761 Mon Sep 17 00:00:00 2001 From: Zhixu Ni Date: Fri, 9 Aug 2019 14:22:40 +0200 Subject: [PATCH 03/11] add Todo for SP --- LibLipidHunter/LipidComposer.py | 76 ++++++++++----------------------- test/test_LipidComposer.py | 3 ++ 2 files changed, 25 insertions(+), 54 deletions(-) diff --git a/LibLipidHunter/LipidComposer.py b/LibLipidHunter/LipidComposer.py index dc1596c..0a4abaf 100644 --- a/LibLipidHunter/LipidComposer.py +++ b/LibLipidHunter/LipidComposer.py @@ -47,6 +47,7 @@ def __init__(self): pip_hg_elem = {'C': 6, 'H': 14, 'O': 12, 'P': 2, 'N': 0} ps_hg_elem = {'C': 3, 'H': 8, 'O': 6, 'P': 1, 'N': 1} tg_hg_elem = {'C': 0, 'H': 0, 'O': 0, 'P': 0, 'N': 0} + # Todo: add SM corresponding HG sections around here self.lipid_hg_lst = ['PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'PIP', 'TG'] @@ -226,11 +227,12 @@ def calc_fa_query(self, lipid_class: str, fa_whitelist: str, ms2_ppm: int = 100) # the element here is with no Hydroxyl on fa1 and fa2, here a [M-H]- is already considered lyso_base_mz = elem_calc.get_exactmass(lyso_base_elem_dct) + 1.0078250321 + 15.9949146221 - + # Todo: SM section if lipid_class in ['PC', 'SM']: lyso_base_mz -= (12.0 + 2 * 1.0078250321) # LPC loss one -CH3 from HG (one H already remove above) for _lyso_ion in list(lyso_type_dct.keys()): + if lipid_class in ['PC', 'SM']: if lyso_type_dct[_lyso_ion] == 'EXACTMASS': @@ -279,6 +281,7 @@ def calc_fa_query(self, lipid_class: str, fa_whitelist: str, ms2_ppm: int = 100) ms2_ppm) usr_fa_df['%s_Q' % _mg_ion] = (usr_fa_df['%s_MZ_LOW' % _mg_ion].astype(str) + ' <= mz <= ' + usr_fa_df[ '%s_MZ_HIGH' % _mg_ion].astype(str)) + elif lipid_class in ['DG']: mg_type_dct = {'[MG-H2O+H]+': 'EXACTMASS'} mg_base_elem_dct = self.lipid_hg_elem_dct[lipid_class] @@ -298,7 +301,7 @@ def calc_fa_query(self, lipid_class: str, fa_whitelist: str, ms2_ppm: int = 100) usr_fa_df['%s_Q' % _mg_ion] = (usr_fa_df['%s_MZ_LOW' % _mg_ion].astype(str) + ' <= mz <= ' + usr_fa_df[ '%s_MZ_HIGH' % _mg_ion].astype(str)) else: - # TODO (georgia.angelidou@uni-leipzig.de): SM + # Todo: SM section like above pass return usr_fa_df @@ -336,50 +339,11 @@ def gen_all_comb(self, lipid_class: str, usr_fa_df: pd.DataFrame, position: bool fa_comb_lst = [] fa_df_header_lst = [] - # fa_comb_lite_lst = [] - # # sn_comb_rm_lst = [] - # - # print('fa_comb_lst count', len(fa_comb_lst)) - # - # if position is False: - # for _comb in fa_comb_lst: - # # _rev_comb = tuple(sorted(list(_comb))) - # _rev_comb = tuple(natsorted(list(_comb))) - # if _comb not in fa_comb_lite_lst and _rev_comb not in fa_comb_lite_lst: - # fa_comb_lite_lst.append(_comb) - # else: - # pass - # # sn_comb_rm_lst.append(_comb) - # # sn_comb_rm_lst.append(_rev_comb) - # else: - # fa_comb_lite_lst = fa_comb_lst - # - # print('unique fa_comb_lite_lst count', len(fa_comb_lite_lst)) - # - # lipid_comb_dct = {} - # - # if lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'DG'] and len(fa_comb_lite_lst) > 0: - # for _comb_lite in fa_comb_lite_lst: - # _lipid_abbr = '{lt}({fa1}_{fa2})'.format(lt=lipid_class, fa1=_comb_lite[0].strip('FA'), - # fa2=_comb_lite[1].strip('FA')) - # lipid_comb_dct[_lipid_abbr] = {'CLASS': lipid_class, 'FA1': _comb_lite[0], 'FA2': _comb_lite[1], - # 'DISCRETE_ABBR': _lipid_abbr} - # elif lipid_class in ['TG'] and len(fa_comb_lite_lst) > 0: - # for _comb_lite in fa_comb_lite_lst: - # _lipid_abbr = '{pl}({fa1}_{fa2}_{fa3})'.format(pl=lipid_class, fa1=_comb_lite[0].strip('FA'), - # fa2=_comb_lite[1].strip('FA'), - # fa3=_comb_lite[2].strip('FA')) - # - # lipid_comb_dct[_lipid_abbr] = {'CLASS': lipid_class, 'FA1': _comb_lite[0], 'FA2': _comb_lite[1], - # 'FA3': _comb_lite[2], 'DISCRETE_ABBR': _lipid_abbr} - # else: - # # TODO (georgia.angelidou@uni-leipzig.de): SM posible composition - # pass - fa_combo_df = pd.DataFrame(data=fa_comb_lst, columns=fa_df_header_lst) fa_combo_df['CLASS'] = lipid_class + # Todo: check SM section below: if lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'DG', 'SM']: fa_combo_link_df = fa_combo_df.copy() @@ -541,7 +505,6 @@ def calc_fragments(lipid_dct, charge='', ms2_ppm=100): if m_class in ['PA', 'PE', 'PG', 'PI', 'PS', 'PIP', 'PL']: lyso_str = 'L' + m_class - # create the abbreviation name for the Lyso fragments eg. LPE(18:0)-H]-_ABBR # without the loss of water lipid_dct['[LPL(FA1)-H]-_ABBR'] = '[%s(%s)-H]-' % (lyso_str, fa1_abbr) @@ -556,7 +519,8 @@ def calc_fragments(lipid_dct, charge='', ms2_ppm=100): lipid_dct['[LPL(FA1)-H2O-H]-_MZ'] = round(m_exactmass - fa2_exactmass - h_exactmass, 6) lipid_dct['[LPL(FA2)-H2O-H]-_MZ'] = round(m_exactmass - fa1_exactmass - h_exactmass, 6) - elif m_class in ['PC']: + # Todo: Add SM section here and check + elif m_class in ['PC', 'SM']: lyso_str = 'L' + m_class # The abbr. here is not exactly correct due to the compatibility issues with ranks core calc functions @@ -781,7 +745,17 @@ def calc_fragments(lipid_dct, charge='', ms2_ppm=100): return lipid_dct - def compose_lipid(self, param_dct, ms2_ppm=100): + def compose_lipid(self, param_dct: dict, ms2_ppm: int = 100) -> pd.DataFrame: + """ + Main function to generate the combination of lipids. + Control all functions above. + Args: + param_dct (dict): parameter load from GUI or config file + ms2_ppm (int): The MS/MS tolerance for the calculation of MS/MS query window + + Returns: + + """ lipid_class = param_dct['lipid_class'] lipid_charge = param_dct['charge_mode'] @@ -797,6 +771,7 @@ def compose_lipid(self, param_dct, ms2_ppm=100): usr_fa_df.columns = usr_fa_df.columns.str.upper() + # Todo: check SM section below: if lipid_class in ['PL', 'PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'SM']: if lipid_class in tmp_columns: pass @@ -855,7 +830,7 @@ def compose_lipid(self, param_dct, ms2_ppm=100): _fa2_abbr = '' _fa2_info_dct = {} - # TODO (georgia.angelidou@uni-leipzig.de): SM, Cer + # Todo: add and check SM, Cer below if lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'DG']: _lipid_dct['M_DB'] = _fa1_info_dct['DB'] + _fa2_info_dct['DB'] # TODO(georgia.angelidou@uni-leipzig.de): not important (just keep in mind for future correction) @@ -902,8 +877,8 @@ def compose_lipid(self, param_dct, ms2_ppm=100): c=(_fa1_info_dct['C'] + _fa2_info_dct['C'] + _fa3_info_dct['C']), db=lipid_comb_dct[_lipid]['M_DB']) + # Todo: check SM section below: elif lipid_class in ['SM']: - # TODO(georgia.angelidou@uni-leipzi.de): sphingomyelin support lipid_bulk_str = '{sm}({c}:{db})'.format(sm=lipid_class, c=_fa1_info_dct['C'] + _fa2_info_dct['C'], db=lipid_comb_dct[_lipid]['M_DB']) @@ -935,10 +910,3 @@ def compose_lipid(self, param_dct, ms2_ppm=100): lipid_master_df.reset_index(drop=True, inplace=True) return lipid_master_df - - -if __name__ == '__main__': - - from test.test_LipidComposer import TestCaseLipidComposer - - TestCaseLipidComposer() diff --git a/test/test_LipidComposer.py b/test/test_LipidComposer.py index 62e9b15..3089cae 100644 --- a/test/test_LipidComposer.py +++ b/test/test_LipidComposer.py @@ -65,6 +65,7 @@ def setUp(self): 'charge_mode': '[M+NH4]+', 'exact_position': 'FALSE'} self.tg_param_dct = {'fa_whitelist': self.fa_lst_file, 'lipid_class': 'TG', 'charge_mode': '[M+NH4]+', 'exact_position': 'FALSE'} + # Todo: add SM parameters here if not os.path.isdir(r'test/results/LipidComposer'): os.makedirs(r'test/results/LipidComposer') @@ -117,6 +118,8 @@ def test_pe(self): is_sucessful = self.get_lipidmaster(self.pe_param_dct) assert is_sucessful is True + # Todo: add SM test function here + def test_dg(self): is_sucessful = self.get_lipidmaster(self.tg_param_dct) assert is_sucessful is True From 80e50a2dca43dbff6c57fe2a7d91d9f8f0599b04 Mon Sep 17 00:00:00 2001 From: Zhixu Ni Date: Tue, 13 Aug 2019 18:26:53 +0200 Subject: [PATCH 04/11] Apply code style black, fix Bruker file reader. Fixed: - Fixed issues to read mzML from Bruker files --- LibLipidHunter/AbbrElemCalc.py | 618 ++++--- LibLipidHunter/HuntManager.py | 123 +- LibLipidHunter/Hunter_Core.py | 1427 ++++++++++----- LibLipidHunter/IsotopeHunter.py | 533 ++++-- LibLipidHunter/LipidComposer.py | 1341 +++++++++------ LibLipidHunter/LipidHunter_Main.py | 1188 ++++++++----- LibLipidHunter/LipidHunter_UI.py | 2480 +++++++++++++++++++++++---- LibLipidHunter/LipidHunter_rcc.py | 12 +- LibLipidHunter/LipidNomenclature.py | 125 +- LibLipidHunter/LogPageCreator.py | 547 ++++-- LibLipidHunter/OutputFilter.py | 212 ++- LibLipidHunter/PanelPlotter.py | 1744 +++++++++++++------ LibLipidHunter/ParallelFunc.py | 50 +- LibLipidHunter/PrecursorHunter.py | 375 ++-- LibLipidHunter/ScoreHunter.py | 1280 +++++++++----- LibLipidHunter/SpectraReader.py | 403 +++-- LipidHunter.py | 2 +- cmd_lipidhunter.py | 117 +- test/test_HuntManager.py | 14 +- test/test_LipidComposer.py | 107 +- test/test_LipidNomenclature.py | 37 +- test/test_cmd_lipidhunter.py | 105 +- 22 files changed, 8919 insertions(+), 3921 deletions(-) diff --git a/LibLipidHunter/AbbrElemCalc.py b/LibLipidHunter/AbbrElemCalc.py index 8e1f134..21a4330 100644 --- a/LibLipidHunter/AbbrElemCalc.py +++ b/LibLipidHunter/AbbrElemCalc.py @@ -23,58 +23,85 @@ class ElemCalc: def __init__(self): - pa_hg_elem = {'C': 0, 'H': 3, 'O': 4, 'P': 1, 'N': 0} - pc_hg_elem = {'C': 5, 'H': 14, 'O': 4, 'P': 1, 'N': 1} - pe_hg_elem = {'C': 2, 'H': 8, 'O': 4, 'P': 1, 'N': 1} - pg_hg_elem = {'C': 3, 'H': 9, 'O': 6, 'P': 1, 'N': 0} - pi_hg_elem = {'C': 6, 'H': 13, 'O': 9, 'P': 1, 'N': 0} - pip_hg_elem = {'C': 6, 'H': 14, 'O': 12, 'P': 2, 'N': 0} - ps_hg_elem = {'C': 3, 'H': 8, 'O': 6, 'P': 1, 'N': 1} - tg_hg_elem = {'C': 0, 'H': 0, 'O': 0, 'P': 0, 'N': 0} - fa_hg_elem = {'C': 0, 'H': 0, 'O': 0, 'P': 0, 'N': 0} - - self.lipid_hg_elem_dct = {'PA': pa_hg_elem, 'PC': pc_hg_elem, 'PE': pe_hg_elem, 'PG': pg_hg_elem, - 'PI': pi_hg_elem, 'PS': ps_hg_elem, 'PIP': pip_hg_elem, - 'LPA': pa_hg_elem, 'LPC': pc_hg_elem, 'LPE': pe_hg_elem, 'LPG': pg_hg_elem, - 'LPI': pi_hg_elem, 'LPS': ps_hg_elem, 'LPIP': pip_hg_elem, - 'TG': tg_hg_elem,'FA': fa_hg_elem, 'DG': tg_hg_elem} - - self.glycerol_bone_elem_dct = {'C': 3, 'H': 2} - self.link_o_elem_dct = {'O': -1, 'H': 2} - self.link_p_elem_dct = {'O': -1} - - self.periodic_table_dct = {'H': [(1.0078250321, 0.999885), (2.0141017780, 0.0001157)], - 'D': [(2.0141017780, 0.0001157)], - 'C': [(12.0, 0.9893), (13.0033548378, 0.0107)], - 'N': [(14.0030740052, 0.99632), (15.0001088984, 0.00368)], - 'O': [(15.9949146221, 0.99757), (16.99913150, 0.00038), (17.9991604, 0.00205)], - 'Na': [(22.98976967, 1.0)], - 'P': [(30.97376151, 1.0)], - 'S': [(31.97207069, 0.9493), (32.97145850, 0.0076), - (33.96786683, 0.0429), (35.96708088, 0.0002)], - 'K': [(38.9637069, 0.932581), (39.96399867, 0.000117), (40.96182597, 0.067302)], - } + pa_hg_elem = {"C": 0, "H": 3, "O": 4, "P": 1, "N": 0} + pc_hg_elem = {"C": 5, "H": 14, "O": 4, "P": 1, "N": 1} + pe_hg_elem = {"C": 2, "H": 8, "O": 4, "P": 1, "N": 1} + pg_hg_elem = {"C": 3, "H": 9, "O": 6, "P": 1, "N": 0} + pi_hg_elem = {"C": 6, "H": 13, "O": 9, "P": 1, "N": 0} + pip_hg_elem = {"C": 6, "H": 14, "O": 12, "P": 2, "N": 0} + ps_hg_elem = {"C": 3, "H": 8, "O": 6, "P": 1, "N": 1} + tg_hg_elem = {"C": 0, "H": 0, "O": 0, "P": 0, "N": 0} + fa_hg_elem = {"C": 0, "H": 0, "O": 0, "P": 0, "N": 0} + + self.lipid_hg_elem_dct = { + "PA": pa_hg_elem, + "PC": pc_hg_elem, + "PE": pe_hg_elem, + "PG": pg_hg_elem, + "PI": pi_hg_elem, + "PS": ps_hg_elem, + "PIP": pip_hg_elem, + "LPA": pa_hg_elem, + "LPC": pc_hg_elem, + "LPE": pe_hg_elem, + "LPG": pg_hg_elem, + "LPI": pi_hg_elem, + "LPS": ps_hg_elem, + "LPIP": pip_hg_elem, + "TG": tg_hg_elem, + "FA": fa_hg_elem, + "DG": tg_hg_elem, + } + + self.glycerol_bone_elem_dct = {"C": 3, "H": 2} + self.link_o_elem_dct = {"O": -1, "H": 2} + self.link_p_elem_dct = {"O": -1} + + self.periodic_table_dct = { + "H": [(1.0078250321, 0.999885), (2.0141017780, 0.0001157)], + "D": [(2.0141017780, 0.0001157)], + "C": [(12.0, 0.9893), (13.0033548378, 0.0107)], + "N": [(14.0030740052, 0.99632), (15.0001088984, 0.00368)], + "O": [ + (15.9949146221, 0.99757), + (16.99913150, 0.00038), + (17.9991604, 0.00205), + ], + "Na": [(22.98976967, 1.0)], + "P": [(30.97376151, 1.0)], + "S": [ + (31.97207069, 0.9493), + (32.97145850, 0.0076), + (33.96786683, 0.0429), + (35.96708088, 0.0002), + ], + "K": [ + (38.9637069, 0.932581), + (39.96399867, 0.000117), + (40.96182597, 0.067302), + ], + } @staticmethod def decode_abbr(abbr): - pl_checker = re.compile(r'(P[ACEGSI])([(])(.*)([)])') - lpl_checker = re.compile(r'(LP[ACEGSI])([(])(.*)([)])') - pip_checker = re.compile(r'(PIP)([(])(.*)([)])') - tg_checker = re.compile(r'(TG)([(])(.*)([)])') - dg_checker = re.compile(r'(DG)([(])(.*)([)])') - fa_checker = re.compile(r'(FA)(\d{1,2})([:])(\d{1,2})') - fa_short_checker = re.compile(r'(\d{1,2})([:])(\d{1,2})') - fa_o_checker = re.compile(r'(O-)(\d{1,2})([:])(\d)') - fa_p_checker = re.compile(r'(P-)(\d{1,2})([:])(\d)') + pl_checker = re.compile(r"(P[ACEGSI])([(])(.*)([)])") + lpl_checker = re.compile(r"(LP[ACEGSI])([(])(.*)([)])") + pip_checker = re.compile(r"(PIP)([(])(.*)([)])") + tg_checker = re.compile(r"(TG)([(])(.*)([)])") + dg_checker = re.compile(r"(DG)([(])(.*)([)])") + fa_checker = re.compile(r"(FA)(\d{1,2})([:])(\d{1,2})") + fa_short_checker = re.compile(r"(\d{1,2})([:])(\d{1,2})") + fa_o_checker = re.compile(r"(O-)(\d{1,2})([:])(\d)") + fa_p_checker = re.compile(r"(P-)(\d{1,2})([:])(\d)") # Check PL Type - _pl_typ = '' - bulk_fa_typ = '' - bulk_fa_linker = '' + _pl_typ = "" + bulk_fa_typ = "" + bulk_fa_linker = "" bulk_fa_c = 0 bulk_fa_db = 0 - lyso_fa_linker_dct = {'fa1': '', 'fa2': ''} + lyso_fa_linker_dct = {"fa1": "", "fa2": ""} # TODO(georgia.angelidou@uni-leipzig.de): consideration to put se elif statement if pl_checker.match(abbr): @@ -108,49 +135,49 @@ def decode_abbr(abbr): bulk_fa_typ = dg_typ_lst[2] if fa_checker.match(abbr): # print('FA') - _pl_typ = 'FA' + _pl_typ = "FA" bulk_fa_typ = abbr fa_chk = fa_checker.match(abbr) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[1] bulk_fa_db = bulk_fa_lst[3] - bulk_fa_linker = 'A-' - lyso_fa_linker_dct = {'A': ''} + bulk_fa_linker = "A-" + lyso_fa_linker_dct = {"A": ""} if fa_short_checker.match(abbr): # print('FA') - _pl_typ = 'FA' + _pl_typ = "FA" bulk_fa_typ = abbr fa_chk = fa_checker.match(abbr) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[0] bulk_fa_db = bulk_fa_lst[2] - bulk_fa_linker = 'A-' - lyso_fa_linker_dct = {'A': ''} + bulk_fa_linker = "A-" + lyso_fa_linker_dct = {"A": ""} if fa_o_checker.match(abbr): # print('FA') - _pl_typ = 'FA' + _pl_typ = "FA" bulk_fa_typ = abbr fa_chk = fa_o_checker.match(abbr) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[1] bulk_fa_db = bulk_fa_lst[3] - bulk_fa_linker = 'O-' - lyso_fa_linker_dct = {'O': ''} + bulk_fa_linker = "O-" + lyso_fa_linker_dct = {"O": ""} if fa_p_checker.match(abbr): # print('FA') - _pl_typ = 'FA' + _pl_typ = "FA" bulk_fa_typ = abbr fa_chk = fa_p_checker.match(abbr) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[1] bulk_fa_db = bulk_fa_lst[3] - bulk_fa_linker = 'P-' - lyso_fa_linker_dct = {'P': ''} + bulk_fa_linker = "P-" + lyso_fa_linker_dct = {"P": ""} - if _pl_typ in ['PL', 'PA', 'PC', 'PE', 'PG', 'PI', 'PIP', 'PS']: + if _pl_typ in ["PL", "PA", "PC", "PE", "PG", "PI", "PIP", "PS"]: if fa_short_checker.match(bulk_fa_typ): - bulk_fa_linker = 'A-A-' - lyso_fa_linker_dct = {'A': ''} + bulk_fa_linker = "A-A-" + lyso_fa_linker_dct = {"A": ""} fa_chk = fa_short_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[0] @@ -163,83 +190,105 @@ def decode_abbr(abbr): # bulk_fa_c = bulk_fa_lst[0] # bulk_fa_db = bulk_fa_lst[2] elif fa_o_checker.match(bulk_fa_typ): - bulk_fa_linker = 'O-A-' - lyso_fa_linker_dct = {'O': '', 'A': 'O-'} # link of the other sn after NL of this sn + bulk_fa_linker = "O-A-" + lyso_fa_linker_dct = { + "O": "", + "A": "O-", + } # link of the other sn after NL of this sn fa_chk = fa_o_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[1] bulk_fa_db = bulk_fa_lst[3] elif fa_p_checker.match(bulk_fa_typ): - bulk_fa_linker = 'P-A-' - lyso_fa_linker_dct = {'P': '', 'A': 'P-'} # link of the other sn after NL of this sn + bulk_fa_linker = "P-A-" + lyso_fa_linker_dct = { + "P": "", + "A": "P-", + } # link of the other sn after NL of this sn fa_chk = fa_p_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[1] bulk_fa_db = bulk_fa_lst[3] - elif _pl_typ in ['LPL', 'LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPIP', 'LPS']: + elif _pl_typ in ["LPL", "LPA", "LPC", "LPE", "LPG", "LPI", "LPIP", "LPS"]: if fa_short_checker.match(bulk_fa_typ): - bulk_fa_linker = 'A-' - lyso_fa_linker_dct = {'A': ''} + bulk_fa_linker = "A-" + lyso_fa_linker_dct = {"A": ""} fa_chk = fa_short_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[0] bulk_fa_db = bulk_fa_lst[2] elif fa_o_checker.match(bulk_fa_typ): - bulk_fa_linker = 'O-' - lyso_fa_linker_dct = {'O': ''} # link of the other sn after NL of this sn + bulk_fa_linker = "O-" + lyso_fa_linker_dct = { + "O": "" + } # link of the other sn after NL of this sn fa_chk = fa_o_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[1] bulk_fa_db = bulk_fa_lst[3] elif fa_p_checker.match(bulk_fa_typ): - bulk_fa_linker = 'P-' - lyso_fa_linker_dct = {'P': ''} # link of the other sn after NL of this sn + bulk_fa_linker = "P-" + lyso_fa_linker_dct = { + "P": "" + } # link of the other sn after NL of this sn fa_chk = fa_p_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[1] bulk_fa_db = bulk_fa_lst[3] - elif _pl_typ in ['TG']: + elif _pl_typ in ["TG"]: if fa_short_checker.match(bulk_fa_typ): - bulk_fa_linker = 'A-A-A-' - lyso_fa_linker_dct = {'A': ''} + bulk_fa_linker = "A-A-A-" + lyso_fa_linker_dct = {"A": ""} fa_chk = fa_short_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[0] bulk_fa_db = bulk_fa_lst[2] elif fa_o_checker.match(bulk_fa_typ): - bulk_fa_linker = 'O-A-A-' - lyso_fa_linker_dct = {'O': '', 'A': 'O-'} # link of the other sn after NL of this sn + bulk_fa_linker = "O-A-A-" + lyso_fa_linker_dct = { + "O": "", + "A": "O-", + } # link of the other sn after NL of this sn fa_chk = fa_o_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[1] bulk_fa_db = bulk_fa_lst[3] elif fa_p_checker.match(bulk_fa_typ): - bulk_fa_linker = 'P-A-A-' - lyso_fa_linker_dct = {'P': '', 'A': 'P-'} # link of the other sn after NL of this sn + bulk_fa_linker = "P-A-A-" + lyso_fa_linker_dct = { + "P": "", + "A": "P-", + } # link of the other sn after NL of this sn fa_chk = fa_p_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[1] bulk_fa_db = bulk_fa_lst[3] - elif _pl_typ in ['DG']: + elif _pl_typ in ["DG"]: if fa_short_checker.match(bulk_fa_typ): - bulk_fa_linker = 'A-A-' - lyso_fa_linker_dct = {'A': ''} + bulk_fa_linker = "A-A-" + lyso_fa_linker_dct = {"A": ""} fa_chk = fa_short_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[0] bulk_fa_db = bulk_fa_lst[2] elif fa_o_checker.match(bulk_fa_typ): - bulk_fa_linker = 'O-A-' - lyso_fa_linker_dct = {'O': '', 'A': 'O-'} # link of the other sn after NL of this sn + bulk_fa_linker = "O-A-" + lyso_fa_linker_dct = { + "O": "", + "A": "O-", + } # link of the other sn after NL of this sn fa_chk = fa_o_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[1] bulk_fa_db = bulk_fa_lst[3] elif fa_p_checker.match(bulk_fa_typ): - bulk_fa_linker = 'P-A-' - lyso_fa_linker_dct = {'P': '', 'A': 'P-'} # link of the other sn after NL of this sn + bulk_fa_linker = "P-A-" + lyso_fa_linker_dct = { + "P": "", + "A": "P-", + } # link of the other sn after NL of this sn fa_chk = fa_p_checker.match(bulk_fa_typ) bulk_fa_lst = fa_chk.groups() bulk_fa_c = bulk_fa_lst[1] @@ -248,8 +297,13 @@ def decode_abbr(abbr): bulk_fa_c = int(bulk_fa_c) bulk_fa_db = int(bulk_fa_db) - lipid_info_dct = {'TYPE': _pl_typ, 'LINK': bulk_fa_linker, 'C': bulk_fa_c, 'DB': bulk_fa_db, - 'LYSO_LINK': lyso_fa_linker_dct} + lipid_info_dct = { + "TYPE": _pl_typ, + "LINK": bulk_fa_linker, + "C": bulk_fa_c, + "DB": bulk_fa_db, + "LYSO_LINK": lyso_fa_linker_dct, + } return lipid_info_dct @@ -257,164 +311,196 @@ def get_neutral_elem(self, abbr): usr_lipid_info_dct = self.decode_abbr(abbr) - lipid_type = usr_lipid_info_dct['TYPE'] + lipid_type = usr_lipid_info_dct["TYPE"] if lipid_type in list(self.lipid_hg_elem_dct.keys()): - if lipid_type in ['FA']: + if lipid_type in ["FA"]: # print(abbr) - tmp_lipid_elem_dct = {'C': usr_lipid_info_dct['C'], 'O': 2, - 'H': (usr_lipid_info_dct['C'] * 2 - usr_lipid_info_dct['DB'] * 2)} - if usr_lipid_info_dct['LINK'] == '': + tmp_lipid_elem_dct = { + "C": usr_lipid_info_dct["C"], + "O": 2, + "H": (usr_lipid_info_dct["C"] * 2 - usr_lipid_info_dct["DB"] * 2), + } + if usr_lipid_info_dct["LINK"] == "": pass - elif usr_lipid_info_dct['LINK'] == 'O-': - tmp_lipid_elem_dct['O'] += -1 - tmp_lipid_elem_dct['H'] += 2 - elif usr_lipid_info_dct['LINK'] == 'P-': - tmp_lipid_elem_dct['O'] += -1 + elif usr_lipid_info_dct["LINK"] == "O-": + tmp_lipid_elem_dct["O"] += -1 + tmp_lipid_elem_dct["H"] += 2 + elif usr_lipid_info_dct["LINK"] == "P-": + tmp_lipid_elem_dct["O"] += -1 else: pass return tmp_lipid_elem_dct - if lipid_type in ['PA', 'PC', 'PE', 'PG', 'PI', 'PIP', 'PS']: - tmp_lipid_elem_dct = self.lipid_hg_elem_dct[usr_lipid_info_dct['TYPE']].copy() - tmp_lipid_elem_dct['O'] += 4 - tmp_lipid_elem_dct['C'] += self.glycerol_bone_elem_dct['C'] + usr_lipid_info_dct['C'] - tmp_lipid_elem_dct['H'] += (self.glycerol_bone_elem_dct['H'] + usr_lipid_info_dct['C'] * 2 - - usr_lipid_info_dct['DB'] * 2) # DBE = DB + 2xC=O from FA - if usr_lipid_info_dct['LINK'] == 'O-A-': - tmp_lipid_elem_dct['O'] += -1 - tmp_lipid_elem_dct['H'] += 2 - elif usr_lipid_info_dct['LINK'] == 'P-A-': - tmp_lipid_elem_dct['O'] += -1 + if lipid_type in ["PA", "PC", "PE", "PG", "PI", "PIP", "PS"]: + tmp_lipid_elem_dct = self.lipid_hg_elem_dct[ + usr_lipid_info_dct["TYPE"] + ].copy() + tmp_lipid_elem_dct["O"] += 4 + tmp_lipid_elem_dct["C"] += ( + self.glycerol_bone_elem_dct["C"] + usr_lipid_info_dct["C"] + ) + tmp_lipid_elem_dct["H"] += ( + self.glycerol_bone_elem_dct["H"] + + usr_lipid_info_dct["C"] * 2 + - usr_lipid_info_dct["DB"] * 2 + ) # DBE = DB + 2xC=O from FA + if usr_lipid_info_dct["LINK"] == "O-A-": + tmp_lipid_elem_dct["O"] += -1 + tmp_lipid_elem_dct["H"] += 2 + elif usr_lipid_info_dct["LINK"] == "P-A-": + tmp_lipid_elem_dct["O"] += -1 else: pass return tmp_lipid_elem_dct - elif lipid_type in ['LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPIP', 'LPS']: - tmp_lipid_elem_dct = self.lipid_hg_elem_dct[usr_lipid_info_dct['TYPE']].copy() - tmp_lipid_elem_dct['O'] += 3 - tmp_lipid_elem_dct['C'] += self.glycerol_bone_elem_dct['C'] + usr_lipid_info_dct['C'] - tmp_lipid_elem_dct['H'] += (self.glycerol_bone_elem_dct['H'] + 2 + usr_lipid_info_dct['C'] * 2 - - usr_lipid_info_dct['DB'] * 2) # DBE = DB + 2xC=O from FA - - if usr_lipid_info_dct['LINK'] == 'O-': - tmp_lipid_elem_dct['O'] += -1 - tmp_lipid_elem_dct['H'] += 2 - elif usr_lipid_info_dct['LINK'] == 'P-': - tmp_lipid_elem_dct['O'] += -1 + elif lipid_type in ["LPA", "LPC", "LPE", "LPG", "LPI", "LPIP", "LPS"]: + tmp_lipid_elem_dct = self.lipid_hg_elem_dct[ + usr_lipid_info_dct["TYPE"] + ].copy() + tmp_lipid_elem_dct["O"] += 3 + tmp_lipid_elem_dct["C"] += ( + self.glycerol_bone_elem_dct["C"] + usr_lipid_info_dct["C"] + ) + tmp_lipid_elem_dct["H"] += ( + self.glycerol_bone_elem_dct["H"] + + 2 + + usr_lipid_info_dct["C"] * 2 + - usr_lipid_info_dct["DB"] * 2 + ) # DBE = DB + 2xC=O from FA + + if usr_lipid_info_dct["LINK"] == "O-": + tmp_lipid_elem_dct["O"] += -1 + tmp_lipid_elem_dct["H"] += 2 + elif usr_lipid_info_dct["LINK"] == "P-": + tmp_lipid_elem_dct["O"] += -1 else: pass return tmp_lipid_elem_dct - elif lipid_type in ['TG']: - tmp_lipid_elem_dct = self.lipid_hg_elem_dct[usr_lipid_info_dct['TYPE']].copy() - tmp_lipid_elem_dct['O'] += 6 - tmp_lipid_elem_dct['C'] += self.glycerol_bone_elem_dct['C'] + usr_lipid_info_dct['C'] - tmp_lipid_elem_dct['H'] += (self.glycerol_bone_elem_dct['H'] + usr_lipid_info_dct['C'] * 2 - - usr_lipid_info_dct['DB'] * 2) # DBE = DB + 2xC=O from FA - if usr_lipid_info_dct['LINK'] == 'O-A-A-': - tmp_lipid_elem_dct['O'] += -1 - tmp_lipid_elem_dct['H'] += 2 - elif usr_lipid_info_dct['LINK'] == 'P-A-A-': - tmp_lipid_elem_dct['O'] += -1 + elif lipid_type in ["TG"]: + tmp_lipid_elem_dct = self.lipid_hg_elem_dct[ + usr_lipid_info_dct["TYPE"] + ].copy() + tmp_lipid_elem_dct["O"] += 6 + tmp_lipid_elem_dct["C"] += ( + self.glycerol_bone_elem_dct["C"] + usr_lipid_info_dct["C"] + ) + tmp_lipid_elem_dct["H"] += ( + self.glycerol_bone_elem_dct["H"] + + usr_lipid_info_dct["C"] * 2 + - usr_lipid_info_dct["DB"] * 2 + ) # DBE = DB + 2xC=O from FA + if usr_lipid_info_dct["LINK"] == "O-A-A-": + tmp_lipid_elem_dct["O"] += -1 + tmp_lipid_elem_dct["H"] += 2 + elif usr_lipid_info_dct["LINK"] == "P-A-A-": + tmp_lipid_elem_dct["O"] += -1 else: pass return tmp_lipid_elem_dct - elif lipid_type in ['DG']: - tmp_lipid_elem_dct = self.lipid_hg_elem_dct[usr_lipid_info_dct['TYPE']].copy() - tmp_lipid_elem_dct['O'] += 5 - tmp_lipid_elem_dct['C'] += self.glycerol_bone_elem_dct['C'] + usr_lipid_info_dct['C'] - tmp_lipid_elem_dct['H'] += ( - self.glycerol_bone_elem_dct['H'] + usr_lipid_info_dct['C'] * 2 - usr_lipid_info_dct[ - 'DB'] * 2 + 2) + elif lipid_type in ["DG"]: + tmp_lipid_elem_dct = self.lipid_hg_elem_dct[ + usr_lipid_info_dct["TYPE"] + ].copy() + tmp_lipid_elem_dct["O"] += 5 + tmp_lipid_elem_dct["C"] += ( + self.glycerol_bone_elem_dct["C"] + usr_lipid_info_dct["C"] + ) + tmp_lipid_elem_dct["H"] += ( + self.glycerol_bone_elem_dct["H"] + + usr_lipid_info_dct["C"] * 2 + - usr_lipid_info_dct["DB"] * 2 + + 2 + ) return tmp_lipid_elem_dct else: - return {'C': 0, 'H': 0, 'O': 0, 'P': 0} + return {"C": 0, "H": 0, "O": 0, "P": 0} else: - return {'C': 0, 'H': 0, 'O': 0, 'P': 0} + return {"C": 0, "H": 0, "O": 0, "P": 0} - def get_charged_elem(self, abbr, charge='[M-H]-'): + def get_charged_elem(self, abbr, charge="[M-H]-"): lipid_elem_dct = self.get_neutral_elem(abbr) - if charge == '[M-H]-': - lipid_elem_dct['H'] += -1 - elif charge == '[M+HCOO]-' or charge == '[M+FA-H]-': - lipid_elem_dct['H'] += 1 - lipid_elem_dct['C'] += 1 - lipid_elem_dct['O'] += 2 - elif charge == '[M+CH3COO]-': - lipid_elem_dct['H'] += 3 - lipid_elem_dct['C'] += 2 - lipid_elem_dct['O'] += 2 - elif charge == '[M+OAc]-': - lipid_elem_dct['H'] += 3 - lipid_elem_dct['C'] += 2 - lipid_elem_dct['O'] += 2 - elif charge == '[M+H]+': - lipid_elem_dct['H'] += 1 - elif charge == '[M+NH4]+': - if 'N' in list(lipid_elem_dct.keys()): - lipid_elem_dct['N'] += 1 + if charge == "[M-H]-": + lipid_elem_dct["H"] += -1 + elif charge == "[M+HCOO]-" or charge == "[M+FA-H]-": + lipid_elem_dct["H"] += 1 + lipid_elem_dct["C"] += 1 + lipid_elem_dct["O"] += 2 + elif charge == "[M+CH3COO]-": + lipid_elem_dct["H"] += 3 + lipid_elem_dct["C"] += 2 + lipid_elem_dct["O"] += 2 + elif charge == "[M+OAc]-": + lipid_elem_dct["H"] += 3 + lipid_elem_dct["C"] += 2 + lipid_elem_dct["O"] += 2 + elif charge == "[M+H]+": + lipid_elem_dct["H"] += 1 + elif charge == "[M+NH4]+": + if "N" in list(lipid_elem_dct.keys()): + lipid_elem_dct["N"] += 1 else: - lipid_elem_dct['N'] = 1 - lipid_elem_dct['H'] += 4 - elif charge == '[M+Na]+': - lipid_elem_dct['Na'] = 1 + lipid_elem_dct["N"] = 1 + lipid_elem_dct["H"] += 4 + elif charge == "[M+Na]+": + lipid_elem_dct["Na"] = 1 return lipid_elem_dct - def get_formula(self, abbr, charge=''): + def get_formula(self, abbr, charge=""): - if charge in ['neutral', 'Neutral', '', None]: + if charge in ["neutral", "Neutral", "", None]: elem_dct = self.get_neutral_elem(abbr) else: elem_dct = self.get_charged_elem(abbr, charge=charge) - formula_str = 'C{c}H{h}'.format(c=elem_dct['C'], h=elem_dct['H']) - - if 'N' in list(elem_dct.keys()): - if elem_dct['N'] == 1: - formula_str += 'N' - elif elem_dct['N'] > 1: - formula_str += 'N%i' % elem_dct['N'] - - if 'O' in list(elem_dct.keys()): - if elem_dct['O'] == 1: - formula_str += 'O' - elif elem_dct['O'] > 1: - formula_str += 'O%i' % elem_dct['O'] - - if 'P' in list(elem_dct.keys()): - if elem_dct['P'] == 1: - formula_str += 'P' - elif elem_dct['P'] > 1: - formula_str += 'P%i' % elem_dct['P'] - - if 'Na' in list(elem_dct.keys()): - if elem_dct['Na'] == 1: - formula_str += 'Na' - elif elem_dct['Na'] > 1: - formula_str += 'Na%i' % elem_dct['Na'] - - if 'K' in list(elem_dct.keys()): - if elem_dct['K'] == 1: - formula_str += 'K' - elif elem_dct['K'] > 1: - formula_str += 'K%i' % elem_dct['K'] - - if charge in ['neutral', 'Neutral', '', None]: + formula_str = "C{c}H{h}".format(c=elem_dct["C"], h=elem_dct["H"]) + + if "N" in list(elem_dct.keys()): + if elem_dct["N"] == 1: + formula_str += "N" + elif elem_dct["N"] > 1: + formula_str += "N%i" % elem_dct["N"] + + if "O" in list(elem_dct.keys()): + if elem_dct["O"] == 1: + formula_str += "O" + elif elem_dct["O"] > 1: + formula_str += "O%i" % elem_dct["O"] + + if "P" in list(elem_dct.keys()): + if elem_dct["P"] == 1: + formula_str += "P" + elif elem_dct["P"] > 1: + formula_str += "P%i" % elem_dct["P"] + + if "Na" in list(elem_dct.keys()): + if elem_dct["Na"] == 1: + formula_str += "Na" + elif elem_dct["Na"] > 1: + formula_str += "Na%i" % elem_dct["Na"] + + if "K" in list(elem_dct.keys()): + if elem_dct["K"] == 1: + formula_str += "K" + elif elem_dct["K"] > 1: + formula_str += "K%i" % elem_dct["K"] + + if charge in ["neutral", "Neutral", "", None]: pass - elif charge in ['[M-H]-', '[M+HCOO]-']: - formula_str += '-' - elif charge in ['[M+H]+', '[M+NH4]+', '[M+Na]+']: - formula_str += '+' + elif charge in ["[M-H]-", "[M+HCOO]-"]: + formula_str += "-" + elif charge in ["[M+H]+", "[M+NH4]+", "[M+Na]+"]: + formula_str += "+" # print ('lets see if you manage to get out from this one') return formula_str, elem_dct @@ -430,37 +516,57 @@ def get_exactmass(self, elem_dct): # Current step is working for TG # This is needed to understand if the precursors is true [M+H]+ or [M+Na]+ (given the users option) def get_NH3_pos_mode(self, charge, mz_pr, amm_elem_dct): - mz_NH3_pr_H = '' # The corespond mz of [M+NH4]+ if the given precursor corresponds to the [M+H]+ - mz_NH3_pr_Na = '' # The corespond mz of [M+NH4]+ if the given precursor corresponds to the [M+Na]+ - if charge in ['[M+H]+']: + mz_NH3_pr_H = ( + "" + ) # The corespond mz of [M+NH4]+ if the given precursor corresponds to the [M+H]+ + mz_NH3_pr_Na = ( + "" + ) # The corespond mz of [M+NH4]+ if the given precursor corresponds to the [M+Na]+ + if charge in ["[M+H]+"]: # Problem need to calculate the theoritical one and not according to the experimental identification # mz_NH3_pr_H = mz_pr - self.periodic_table_dct['H'][0][0] + (4 * self.periodic_table_dct['H'][0][0]) + \ # self.periodic_table_dct['N'][0][0] - mz_NH3_pr_H = amm_elem_dct['C'] * self.periodic_table_dct['C'][0][0] + amm_elem_dct['H'] * \ - self.periodic_table_dct['H'][0][0] + amm_elem_dct['O'] * self.periodic_table_dct['O'][0][0] + \ - self.periodic_table_dct['N'][0][0] + mz_NH3_pr_H = ( + amm_elem_dct["C"] * self.periodic_table_dct["C"][0][0] + + amm_elem_dct["H"] * self.periodic_table_dct["H"][0][0] + + amm_elem_dct["O"] * self.periodic_table_dct["O"][0][0] + + self.periodic_table_dct["N"][0][0] + ) # If this precursor corresponds to the [M+Na]+ then to calculate the bulk identification which it will be different from the above # We do the following calculations # First remove the charge and the atoms which form the glycerol bond (Na, C3, H5) # C3H5Na = 64.028895 - mz_pr_Na = mz_pr - self.periodic_table_dct['Na'][0][0] - (self.periodic_table_dct['C'][0][0] * 3) - ( - self.periodic_table_dct['H'][0][0] * 5) + mz_pr_Na = ( + mz_pr + - self.periodic_table_dct["Na"][0][0] + - (self.periodic_table_dct["C"][0][0] * 3) + - (self.periodic_table_dct["H"][0][0] * 5) + ) # Second Step: For TG Remove the 6O and the first C from the 3 FA and the last C with the 3 H from each # O = 15.994915, C = 12, CH3 = 15.023475 # 6O, 3xC, 3xCH3 => C6H9O6 = 177.039915 - mz_pr_Na = mz_pr_Na - (self.periodic_table_dct['O'][0][0] * 6) - ( - self.periodic_table_dct['C'][0][0] * 6) - (self.periodic_table_dct['H'][0][0] * 9) + mz_pr_Na = ( + mz_pr_Na + - (self.periodic_table_dct["O"][0][0] * 6) + - (self.periodic_table_dct["C"][0][0] * 6) + - (self.periodic_table_dct["H"][0][0] * 9) + ) mz_pr_Na = int(mz_pr_Na) db_count_Na = 0 - while (mz_pr_Na % 14 > 1): + while mz_pr_Na % 14 > 1: db_count_Na = db_count_Na + 1 mz_pr_Na = mz_pr_Na - 26 c_count_Na = int(mz_pr_Na / 14) + 6 + db_count_Na * 2 - tg_abbt_bulk_Na = 'TG(' + str(c_count_Na) + ':' + str(db_count_Na) + ')' - _mz_Na_formula, _mz_Na_elemdct = self.get_formula(tg_abbt_bulk_Na, '[M+Na]+') - mz_NH3_pr_Na = _mz_Na_elemdct['C'] * self.periodic_table_dct['C'][0][0] + ( - (_mz_Na_elemdct['H'] + 4) * self.periodic_table_dct['H'][0][0]) + _mz_Na_elemdct['O'] * \ - self.periodic_table_dct['O'][0][0] + self.periodic_table_dct['N'][0][0] + tg_abbt_bulk_Na = "TG(" + str(c_count_Na) + ":" + str(db_count_Na) + ")" + _mz_Na_formula, _mz_Na_elemdct = self.get_formula( + tg_abbt_bulk_Na, "[M+Na]+" + ) + mz_NH3_pr_Na = ( + _mz_Na_elemdct["C"] * self.periodic_table_dct["C"][0][0] + + ((_mz_Na_elemdct["H"] + 4) * self.periodic_table_dct["H"][0][0]) + + _mz_Na_elemdct["O"] * self.periodic_table_dct["O"][0][0] + + self.periodic_table_dct["N"][0][0] + ) # Third step: the rest of the elements correspond to the CH2 * x and if DB to the (CHx2) * y (For 1DB == 2xCH) # CH2 = 14.015650, CH = 13.007825 # Need to create a loop and make all the numbers integers @@ -471,47 +577,75 @@ def get_NH3_pos_mode(self, charge, mz_pr, amm_elem_dct): # TODO(georgia.angelidou@uni-leipzig.de): _mz_H_formula is used before ref, fix here! # Temp add - mz_NH4_H_form = 'C' + str(amm_elem_dct['C']) + 'H' + str(amm_elem_dct['H']) + 'O6N' + mz_NH4_H_form = ( + "C" + str(amm_elem_dct["C"]) + "H" + str(amm_elem_dct["H"]) + "O6N" + ) # mz_NH4_Na_form = _mz_H_formula - mz_NH4_Na_form = 'C' + str(_mz_Na_elemdct['C']) + 'H' + str((_mz_Na_elemdct['H'] + 3)) + 'O6N' - - elif charge in ['[M+Na]+']: - mz_NH3_pr_Na = amm_elem_dct['C'] * self.periodic_table_dct['C'][0][0] + amm_elem_dct['H'] * \ - self.periodic_table_dct['H'][0][0] + amm_elem_dct['O'] * self.periodic_table_dct['O'][0][0] + \ - self.periodic_table_dct['N'][0][0] - print (mz_pr) - C5H3= self.periodic_table_dct['H'][0][0] * 6 + self.periodic_table_dct['C'][0][0] *3 - rest_sampl = self.periodic_table_dct['O'][0][0] *6 + self.periodic_table_dct['H'][0][0] *9 + self.periodic_table_dct['C'][0][0] * 6 + mz_NH4_Na_form = ( + "C" + + str(_mz_Na_elemdct["C"]) + + "H" + + str((_mz_Na_elemdct["H"] + 3)) + + "O6N" + ) + + elif charge in ["[M+Na]+"]: + mz_NH3_pr_Na = ( + amm_elem_dct["C"] * self.periodic_table_dct["C"][0][0] + + amm_elem_dct["H"] * self.periodic_table_dct["H"][0][0] + + amm_elem_dct["O"] * self.periodic_table_dct["O"][0][0] + + self.periodic_table_dct["N"][0][0] + ) + print(mz_pr) + C5H3 = ( + self.periodic_table_dct["H"][0][0] * 6 + + self.periodic_table_dct["C"][0][0] * 3 + ) + rest_sampl = ( + self.periodic_table_dct["O"][0][0] * 6 + + self.periodic_table_dct["H"][0][0] * 9 + + self.periodic_table_dct["C"][0][0] * 6 + ) mz_pr_H = mz_pr - C5H3 - rest_sampl mz_pr_H = int(mz_pr_H) db_count_H = 0 - while (mz_pr_H % 14 > 1): + while mz_pr_H % 14 > 1: db_count_H = db_count_H + 1 mz_pr_H = mz_pr_H - 26 c_count_H = int(mz_pr_H / 14) + 6 + db_count_H * 2 - tg_abbt_bulk_H = 'TG(' + str(c_count_H) + ':' + str(db_count_H) + ')' - _mz_H_formula, _mz_H_elemdct = self.get_formula(tg_abbt_bulk_H, '[M+H]+') - mz_NH3_pr_H = _mz_H_elemdct['C'] * self.periodic_table_dct['C'][0][0] + (_mz_H_elemdct['H'] + 3) * \ - self.periodic_table_dct['H'][0][0] + _mz_H_elemdct['O'] * self.periodic_table_dct['O'][0][0] + self.periodic_table_dct['N'][0][0] - mz_NH4_Na_form = 'C' + str(amm_elem_dct['C']) + 'H' + str(amm_elem_dct['H']) + 'O6N' - mz_NH4_H_form = 'C' + str(_mz_H_elemdct['C']) + 'H' + str((_mz_H_elemdct['H'] + 3)) + 'O6N' - - + tg_abbt_bulk_H = "TG(" + str(c_count_H) + ":" + str(db_count_H) + ")" + _mz_H_formula, _mz_H_elemdct = self.get_formula(tg_abbt_bulk_H, "[M+H]+") + mz_NH3_pr_H = ( + _mz_H_elemdct["C"] * self.periodic_table_dct["C"][0][0] + + (_mz_H_elemdct["H"] + 3) * self.periodic_table_dct["H"][0][0] + + _mz_H_elemdct["O"] * self.periodic_table_dct["O"][0][0] + + self.periodic_table_dct["N"][0][0] + ) + mz_NH4_Na_form = ( + "C" + str(amm_elem_dct["C"]) + "H" + str(amm_elem_dct["H"]) + "O6N" + ) + mz_NH4_H_form = ( + "C" + + str(_mz_H_elemdct["C"]) + + "H" + + str((_mz_H_elemdct["H"] + 3)) + + "O6N" + ) return (mz_NH3_pr_H, mz_NH4_H_form, mz_NH3_pr_Na, mz_NH4_Na_form) -if __name__ == '__main__': +if __name__ == "__main__": usr_bulk_abbr_lst = [ # 'TG(P-48:2)', # 'PC(O-36:3)', # 'PC(P-36:3)', # 'PC(36:3)', - 'LPC(20:3)' + "LPC(20:3)" ] - charge_lst = ['[M+NH4]+', '[M-H]-', '[M+HCOO]-', '[M+OAc]-'] + charge_lst = ["[M+NH4]+", "[M-H]-", "[M+HCOO]-", "[M+OAc]-"] # usr_bulk_abbr_lst = ['PC(36:3)', 'PC(O-36:3)', 'PC(P-36:3)'] # charge_lst = ['', '[M-H]-', '[M+HCOO]-', '[M+OAc]-'] @@ -519,7 +653,9 @@ def get_NH3_pos_mode(self, charge, mz_pr, amm_elem_dct): for usr_abbr in usr_bulk_abbr_lst: for _charge in charge_lst: - usr_formula, usr_elem_dct = abbr2formula.get_formula(usr_abbr, charge=_charge) + usr_formula, usr_elem_dct = abbr2formula.get_formula( + usr_abbr, charge=_charge + ) print((usr_abbr, _charge)) print(usr_elem_dct) print(usr_formula) diff --git a/LibLipidHunter/HuntManager.py b/LibLipidHunter/HuntManager.py index 895f07f..6eb7860 100644 --- a/LibLipidHunter/HuntManager.py +++ b/LibLipidHunter/HuntManager.py @@ -31,14 +31,14 @@ def save_hunt(results_pickle_dct, hunt_save_path): - for key in ['lipid_info_img_lst', 'param_dct', 'output_df', 'final_output_df']: + for key in ["lipid_info_img_lst", "param_dct", "output_df", "final_output_df"]: if key in list(results_pickle_dct.keys()): pass else: - print('Key %s is missing' % key) + print("Key %s is missing" % key) raise KeyError - with open(hunt_save_path, 'wb') as results_pickle: + with open(hunt_save_path, "wb") as results_pickle: pickle.dump(results_pickle_dct, results_pickle) @@ -47,32 +47,34 @@ def recover_hunt(hunter_data): hunt_pickle_dct = pickle.load(hunter_data) print(list(hunt_pickle_dct.keys())) - param_dct = hunt_pickle_dct['param_dct'] - output_df = hunt_pickle_dct['output_df'] - lipid_info_img_lst = hunt_pickle_dct['lipid_info_img_lst'] - final_output_df = hunt_pickle_dct['final_output_df'] - - usr_vendor = param_dct['vendor'] - output_folder = param_dct['img_output_folder_str'] - output_sum_xlsx = param_dct['xlsx_output_path_str'] - usr_ms1_ppm = param_dct['ms_ppm'] - usr_ms2_ppm = param_dct['ms2_ppm'] + param_dct = hunt_pickle_dct["param_dct"] + output_df = hunt_pickle_dct["output_df"] + lipid_info_img_lst = hunt_pickle_dct["lipid_info_img_lst"] + final_output_df = hunt_pickle_dct["final_output_df"] + + usr_vendor = param_dct["vendor"] + output_folder = param_dct["img_output_folder_str"] + output_sum_xlsx = param_dct["xlsx_output_path_str"] + usr_ms1_ppm = param_dct["ms_ppm"] + usr_ms2_ppm = param_dct["ms2_ppm"] usr_ms1_precision = usr_ms1_ppm * 1e-6 - hunter_start_time_str = param_dct['hunter_start_time'] - usr_core_num = param_dct['core_number'] - usr_dpi = param_dct['img_dpi'] - usr_img_type = param_dct['img_type'] + hunter_start_time_str = param_dct["hunter_start_time"] + usr_core_num = param_dct["core_number"] + usr_dpi = param_dct["img_dpi"] + usr_img_type = param_dct["img_type"] output_sum_xlsx_directory = os.path.dirname(output_sum_xlsx) if not os.path.exists(output_sum_xlsx_directory): os.makedirs(output_sum_xlsx_directory) try: final_output_df.to_excel(output_sum_xlsx, index=False) - print('[OUTPUT] ==> Prepare to save output as: ', output_sum_xlsx) + print("[OUTPUT] ==> Prepare to save output as: ", output_sum_xlsx) except IOError: - final_output_df.to_excel('%s-%i%s' % (output_sum_xlsx[:-5], int(time.time()), '.xlsx'), index=False) + final_output_df.to_excel( + "%s-%i%s" % (output_sum_xlsx[:-5], int(time.time()), ".xlsx"), index=False + ) print(output_sum_xlsx) - print('[OUTPUT] ==> File saved ...') + print("[OUTPUT] ==> File saved ...") if lipid_info_img_lst: gen_html_report(param_dct, output_df, lipid_info_img_lst) @@ -80,31 +82,31 @@ def recover_hunt(hunter_data): def gen_html_report(param_dct, output_df, lipid_info_img_lst): - usr_vendor = param_dct['vendor'] - output_folder = param_dct['img_output_folder_str'] - usr_ms1_ppm = param_dct['ms_ppm'] - usr_ms2_ppm = param_dct['ms2_ppm'] + usr_vendor = param_dct["vendor"] + output_folder = param_dct["img_output_folder_str"] + usr_ms1_ppm = param_dct["ms_ppm"] + usr_ms2_ppm = param_dct["ms2_ppm"] usr_ms1_precision = usr_ms1_ppm * 1e-6 usr_ms2_precision = usr_ms2_ppm * 1e-6 - usr_core_num = param_dct['core_number'] - usr_dpi = param_dct['img_dpi'] - usr_img_type = param_dct['img_type'] - hunter_start_time_str = param_dct['hunter_start_time'] + usr_core_num = param_dct["core_number"] + usr_dpi = param_dct["img_dpi"] + usr_img_type = param_dct["img_type"] + hunter_start_time_str = param_dct["hunter_start_time"] # keep stay in current working directory current_path = os.getcwd() if os.path.isdir(output_folder): os.chdir(output_folder) - if os.path.isdir('LipidHunter_Results_Figures_%s' % hunter_start_time_str): - print('[INFO] --> Output folder existed...') + if os.path.isdir("LipidHunter_Results_Figures_%s" % hunter_start_time_str): + print("[INFO] --> Output folder existed...") else: - os.mkdir('LipidHunter_Results_Figures_%s' % hunter_start_time_str) - print('[INFO] --> Output folder created...') + os.mkdir("LipidHunter_Results_Figures_%s" % hunter_start_time_str) + print("[INFO] --> Output folder created...") else: os.mkdir(output_folder) os.chdir(output_folder) - os.mkdir('LipidHunter_Results_Figures_%s' % hunter_start_time_str) - print('[INFO] --> Output folder created...') + os.mkdir("LipidHunter_Results_Figures_%s" % hunter_start_time_str) + print("[INFO] --> Output folder created...") os.chdir(current_path) # generate html files @@ -112,13 +114,19 @@ def gen_html_report(param_dct, output_df, lipid_info_img_lst): log_pager.add_all_info(output_df) log_pager.close_page() # del log_pager - print('[STATUS] >>> start to generate images: image count %i' % len(lipid_info_img_lst)) + print( + "[STATUS] >>> start to generate images: image count %i" + % len(lipid_info_img_lst) + ) if usr_core_num > 1: parallel_pool = Pool(usr_core_num) img_num = len(lipid_info_img_lst) img_sub_len = int(math.ceil(img_num / usr_core_num)) - img_sub_key_lst = [lipid_info_img_lst[k: k + img_sub_len] for k in range(0, img_num, img_sub_len)] + img_sub_key_lst = [ + lipid_info_img_lst[k : k + img_sub_len] + for k in range(0, img_num, img_sub_len) + ] worker_count = 1 for img_sub_lst in img_sub_key_lst: @@ -132,14 +140,25 @@ def gen_html_report(param_dct, output_df, lipid_info_img_lst): # 'usr_ms1_precision': usr_ms1_precision, 'worker_count': worker_count} if len(img_sub_lst) > 0: - print('[STATUS] >>> Core #%i ==> Generating output images ... image count: %i' - % (worker_count, len(img_sub_lst))) - if 'debug_mode' in list(param_dct.keys()): - if param_dct['debug_mode'] == 'ON': + print( + "[STATUS] >>> Core #%i ==> Generating output images ... image count: %i" + % (worker_count, len(img_sub_lst)) + ) + if "debug_mode" in list(param_dct.keys()): + if param_dct["debug_mode"] == "ON": for img_param_dct in img_sub_lst: - print(img_param_dct['save_img_as']) - parallel_pool.apply_async(gen_plot, args=(img_sub_lst, worker_count, usr_img_type, - usr_dpi, usr_vendor, usr_ms1_precision)) + print(img_param_dct["save_img_as"]) + parallel_pool.apply_async( + gen_plot, + args=( + img_sub_lst, + worker_count, + usr_img_type, + usr_dpi, + usr_vendor, + usr_ms1_precision, + ), + ) worker_count += 1 # del img_sub_key_lst # del img_sub_lst @@ -148,18 +167,26 @@ def gen_html_report(param_dct, output_df, lipid_info_img_lst): else: worker_count = 1 - print('[INFO] --> Using single core mode...') - if isinstance(lipid_info_img_lst, tuple) or isinstance(lipid_info_img_lst, list): + print("[INFO] --> Using single core mode...") + if isinstance(lipid_info_img_lst, tuple) or isinstance( + lipid_info_img_lst, list + ): if None in lipid_info_img_lst: lipid_info_img_lst = [x for x in lipid_info_img_lst if x is not None] else: pass if len(lipid_info_img_lst) > 0: - gen_plot(lipid_info_img_lst, worker_count, usr_img_type, usr_dpi, - usr_vendor, usr_ms1_precision) + gen_plot( + lipid_info_img_lst, + worker_count, + usr_img_type, + usr_dpi, + usr_vendor, + usr_ms1_precision, + ) -if __name__ == '__main__': +if __name__ == "__main__": from test.test_HuntManager import test_recover_hunt diff --git a/LibLipidHunter/Hunter_Core.py b/LibLipidHunter/Hunter_Core.py index 2aa6750..7d70722 100644 --- a/LibLipidHunter/Hunter_Core.py +++ b/LibLipidHunter/Hunter_Core.py @@ -42,7 +42,7 @@ from LibLipidHunter.HuntManager import gen_html_report -def save_output(output_path: str, output_df: pd.DataFrame, output_name: str = 'output'): +def save_output(output_path: str, output_df: pd.DataFrame, output_name: str = "output"): """ function to save output in a safer way with few checks. @@ -57,33 +57,45 @@ def save_output(output_path: str, output_df: pd.DataFrame, output_name: str = 'o if not os.path.exists(output_directory): os.makedirs(output_directory) - if output_path.endswith('.xlsx'): + if output_path.endswith(".xlsx"): try: output_df.to_excel(output_path, index=False) - print(f'[OUTPUT] ==> Prepare to save {output_name} as: ', output_path) + print(f"[OUTPUT] ==> Prepare to save {output_name} as: ", output_path) except IOError: - output_df.to_excel('{0}-{1}{2}'.format(output_path[:-5], int(time.time()), '.xlsx'), index=False) + output_df.to_excel( + "{0}-{1}{2}".format(output_path[:-5], int(time.time()), ".xlsx"), + index=False, + ) print(output_path) - elif output_path.endswith('.csv'): + elif output_path.endswith(".csv"): try: output_df.to_csv(output_path, index=False) - print(f'[OUTPUT] ==> Prepare to save {output_name} as: ', output_path) + print(f"[OUTPUT] ==> Prepare to save {output_name} as: ", output_path) except IOError: - output_df.to_csv('{0}-{1}{2}'.format(output_path[:-5], int(time.time()), '.csv'), index=False) + output_df.to_csv( + "{0}-{1}{2}".format(output_path[:-5], int(time.time()), ".csv"), + index=False, + ) print(output_path) else: try: - output_df.to_excel(f'{output_path}.xlsx', index=False) - print(f'[OUTPUT] ==> Prepare to save {output_name} as: ', f'{output_path}.xlsx') + output_df.to_excel(f"{output_path}.xlsx", index=False) + print( + f"[OUTPUT] ==> Prepare to save {output_name} as: ", + f"{output_path}.xlsx", + ) except IOError: - output_df.to_excel('{0}-{1}{2}'.format(output_path[:-5], int(time.time()), '.xlsx'), index=False) + output_df.to_excel( + "{0}-{1}{2}".format(output_path[:-5], int(time.time()), ".xlsx"), + index=False, + ) print(output_path) - print('[OUTPUT] ==> {output_name} saved ...') + print("[OUTPUT] ==> {output_name} saved ...") -def huntlipids(param_dct: dict, error_lst: list, - save_fig: bool = True, save_session: bool = False) \ - -> Tuple[Union[float, bool], list, Union[pd.DataFrame, bool]]: +def huntlipids( + param_dct: dict, error_lst: list, save_fig: bool = True, save_session: bool = False +) -> Tuple[Union[float, bool], list, Union[pd.DataFrame, bool]]: """ This is the core workflow of lipidhunter. The cmd_lipidhunter and LipidHunter GUI transfer the parsed Lipidhunter configurations as param_dct. @@ -119,34 +131,34 @@ def huntlipids(param_dct: dict, error_lst: list, """ - print('[INFO] --> Hunter Core Start...') + print("[INFO] --> Hunter Core Start...") # initialization of all parameters start_time = time.clock() lipidcomposer = LipidComposer() - usr_lipid_class = param_dct['lipid_class'] - usr_charge = param_dct['charge_mode'] - usr_vendor = param_dct['vendor'] - usr_fa_xlsx = param_dct['fawhitelist_path_str'] - usr_mzml = param_dct['mzml_path_str'] - output_folder = param_dct['img_output_folder_str'] - output_sum_xlsx = param_dct['xlsx_output_path_str'] + usr_lipid_class = param_dct["lipid_class"] + usr_charge = param_dct["charge_mode"] + usr_vendor = param_dct["vendor"] + usr_fa_xlsx = param_dct["fawhitelist_path_str"] + usr_mzml = param_dct["mzml_path_str"] + output_folder = param_dct["img_output_folder_str"] + output_sum_xlsx = param_dct["xlsx_output_path_str"] - key_frag_cfg = param_dct['lipid_specific_cfg'] - score_cfg = param_dct['score_cfg'] + key_frag_cfg = param_dct["lipid_specific_cfg"] + score_cfg = param_dct["score_cfg"] - usr_rt_range = [param_dct['rt_start'], param_dct['rt_end']] + usr_rt_range = [param_dct["rt_start"], param_dct["rt_end"]] # usr_pr_mz_range = [param_dct['mz_start'], param_dct['mz_end']] - mz_start = param_dct['mz_start'] - mz_end = param_dct['mz_end'] - usr_dda_top = param_dct['dda_top'] - usr_ms1_threshold = param_dct['ms_th'] - usr_ms1_max = param_dct['ms_max'] - usr_ms2_threshold = param_dct['ms2_th'] - usr_ms1_ppm = param_dct['ms_ppm'] - usr_ms2_ppm = param_dct['ms2_ppm'] + mz_start = param_dct["mz_start"] + mz_end = param_dct["mz_end"] + usr_dda_top = param_dct["dda_top"] + usr_ms1_threshold = param_dct["ms_th"] + usr_ms1_max = param_dct["ms_max"] + usr_ms2_threshold = param_dct["ms2_th"] + usr_ms1_ppm = param_dct["ms_ppm"] + usr_ms2_ppm = param_dct["ms2_ppm"] usr_ms1_precision = usr_ms1_ppm * 1e-6 usr_ms2_precision = usr_ms2_ppm * 1e-6 # usr_rank_score_filter = param_dct['rank_score_filter'] @@ -155,71 +167,90 @@ def huntlipids(param_dct: dict, error_lst: list, # usr_ms2_info_th = param_dct['ms2_infopeak_threshold'] # usr_rank_mode = param_dct['rank_score'] # usr_fast_isotope = param_dct['fast_isotope'] - if 'xic_ppm' in list(param_dct.keys()): - usr_xic_ppm = int(param_dct['xic_ppm']) + if "xic_ppm" in list(param_dct.keys()): + usr_xic_ppm = int(param_dct["xic_ppm"]) else: usr_xic_ppm = usr_ms1_ppm # parameters from settings tab - usr_core_num = param_dct['core_number'] - usr_max_ram = param_dct['max_ram'] + usr_core_num = param_dct["core_number"] + usr_max_ram = param_dct["max_ram"] # usr_dpi = param_dct['img_dpi'] # usr_img_type = param_dct['img_type'] - hunter_start_time_str = param_dct['hunter_start_time'] + hunter_start_time_str = param_dct["hunter_start_time"] try: - if param_dct['debug_mode'] == 'ON': + if param_dct["debug_mode"] == "ON": save_session = True else: pass except (KeyError, AttributeError): - print('Debug mode == off') + print("Debug mode == off") # Check platform for multiprocessing settings if platform == "linux" or platform == "linux2": # linux if usr_core_num > 1: - os_typ = 'linux_multi' - print('[INFO] --> LipidHunter Running on >>> Linux with multiprocessing mode ...') + os_typ = "linux_multi" + print( + "[INFO] --> LipidHunter Running on >>> Linux with multiprocessing mode ..." + ) else: - os_typ = 'linux_single' - print('[INFO] --> LipidHunter Running on >>> Linux with single core mode ...') + os_typ = "linux_single" + print( + "[INFO] --> LipidHunter Running on >>> Linux with single core mode ..." + ) elif platform == "win32": # Windows - os_typ = 'windows' - print('[INFO] --> LipidHunter Running on >>> Windows ...') + os_typ = "windows" + print("[INFO] --> LipidHunter Running on >>> Windows ...") elif platform == "darwin": # macOS if usr_core_num > 1: - os_typ = 'linux_multi' - print('[INFO] --> LipidHunter Running on >>> macOS with multiprocessing mode ...') + os_typ = "linux_multi" + print( + "[INFO] --> LipidHunter Running on >>> macOS with multiprocessing mode ..." + ) else: - os_typ = 'linux_single' - print('[INFO] --> LipidHunter Running on >>> macOS with single core mode ...') + os_typ = "linux_single" + print( + "[INFO] --> LipidHunter Running on >>> macOS with single core mode ..." + ) else: usr_core_num = 1 - param_dct['core_number'] = 1 - os_typ = 'linux_single' - print('[INFO] --> LipidHunter Running on >>> unoptimized system ... %s' % platform) - print('[WARNING] !!! Force to use single core mode !!') - - print('[INFO] --> Start to process >>>') - print('[INFO] --> Lipid class: %s >>>' % usr_lipid_class) - - composer_param_dct = {'fa_whitelist': usr_fa_xlsx, 'lipid_class': usr_lipid_class, - 'charge_mode': usr_charge, 'exact_position': 'FALSE'} - - existed_lipid_master_path = '' # reserved to load existing lipid master table for later development + param_dct["core_number"] = 1 + os_typ = "linux_single" + print( + "[INFO] --> LipidHunter Running on >>> unoptimized system ... %s" % platform + ) + print("[WARNING] !!! Force to use single core mode !!") + + print("[INFO] --> Start to process >>>") + print("[INFO] --> Lipid class: %s >>>" % usr_lipid_class) + + composer_param_dct = { + "fa_whitelist": usr_fa_xlsx, + "lipid_class": usr_lipid_class, + "charge_mode": usr_charge, + "exact_position": "FALSE", + } + + existed_lipid_master_path = ( + "" + ) # reserved to load existing lipid master table for later development use_existed_lipid_master = False # reserved to re-use lipid master table save_lipid_master_table = False - if 'debug_mode' in list(param_dct.keys()): - if param_dct['debug_mode'] == 'ON': - if 'lipid_master_table' in list(param_dct.keys()): - existed_lipid_master_path = param_dct['lipid_master_table'] + if "debug_mode" in list(param_dct.keys()): + if param_dct["debug_mode"] == "ON": + if "lipid_master_table" in list(param_dct.keys()): + existed_lipid_master_path = param_dct["lipid_master_table"] if os.path.isfile(existed_lipid_master_path): use_existed_lipid_master = True else: - print('[ERROR] !!! Failed to load existed Lipid Master table: %s', existed_lipid_master_path) + print( + "[ERROR] !!! Failed to load existed Lipid Master table: %s", + existed_lipid_master_path, + ) else: save_lipid_master_table = True @@ -230,22 +261,34 @@ def huntlipids(param_dct: dict, error_lst: list, if use_existed_lipid_master is False: try: - print('[INFO] --> Start to generate Lipid Master Table ...') + print("[INFO] --> Start to generate Lipid Master Table ...") t_lm_0 = time.time() - usr_lipid_master_df = lipidcomposer.compose_lipid(param_dct=composer_param_dct, ms2_ppm=usr_ms2_ppm) - print('[INFO] --> Lipid Master Table generated >>> in %.2f sec' % (time.time() - t_lm_0)) + usr_lipid_master_df = lipidcomposer.compose_lipid( + param_dct=composer_param_dct, ms2_ppm=usr_ms2_ppm + ) + print( + "[INFO] --> Lipid Master Table generated >>> in %.2f sec" + % (time.time() - t_lm_0) + ) except Exception as e: - print('[ERROR] !!! Failed to predict Lipid structures...', e) + print("[ERROR] !!! Failed to predict Lipid structures...", e) error_lst.append(e) - error_lst.append('[ERROR] !!! Some files missing...') - error_lst.append('... ... Please check your settings in the configuration file ...') + error_lst.append("[ERROR] !!! Some files missing...") + error_lst.append( + "... ... Please check your settings in the configuration file ..." + ) return False, error_lst, False else: try: - print('[INFO] --> Try to use existed Lipid Master table: %s' % existed_lipid_master_path) + print( + "[INFO] --> Try to use existed Lipid Master table: %s" + % existed_lipid_master_path + ) usr_lipid_master_df = pd.read_csv(existed_lipid_master_path) - print('[INFO] --> Lipid Master table loaded >>>', usr_lipid_master_df.shape[0]) + print( + "[INFO] --> Lipid Master table loaded >>>", usr_lipid_master_df.shape[0] + ) except Exception as e: print(e) error_lst.append(e) @@ -256,73 +299,103 @@ def huntlipids(param_dct: dict, error_lst: list, if not usr_lipid_master_df.empty: pass else: - print('[ERROR] !!! Failed to generate LipidMaster Table...') - error_lst.append('[ERROR] !!! Failed to generate LipidMaster Table...') - error_lst.append('... ... Please check if Lipid Class and FA are marked in FA whitelist...') + print("[ERROR] !!! Failed to generate LipidMaster Table...") + error_lst.append("[ERROR] !!! Failed to generate LipidMaster Table...") + error_lst.append( + "... ... Please check if Lipid Class and FA are marked in FA whitelist..." + ) return False, error_lst, False else: - print('[ERROR] !!! Failed to generate LipidMaster Table...') - error_lst.append('[ERROR] !!! Failed to generate LipidMaster Table...') - error_lst.append('... ... Please check if Lipid Class and FA are marked in FA whitelist...') + print("[ERROR] !!! Failed to generate LipidMaster Table...") + error_lst.append("[ERROR] !!! Failed to generate LipidMaster Table...") + error_lst.append( + "... ... Please check if Lipid Class and FA are marked in FA whitelist..." + ) return False, error_lst, False if save_lipid_master_table is True: - log_master_name = 'Lipid_Master_%s.csv' % hunter_start_time_str + log_master_name = "Lipid_Master_%s.csv" % hunter_start_time_str log_master_name = os.path.join(output_folder, log_master_name) - print('[OUTPUT] ==> Lipid Master table Saved as: ', log_master_name) - save_output(log_master_name, usr_lipid_master_df, output_name='Lipid Master table') + print("[OUTPUT] ==> Lipid Master table Saved as: ", log_master_name) + save_output( + log_master_name, usr_lipid_master_df, output_name="Lipid Master table" + ) else: pass # for TG has the fragment of neutral loss of the FA and the fragments for the MG - usr_fa_df = lipidcomposer.calc_fa_query(usr_lipid_class, usr_fa_xlsx, ms2_ppm=usr_ms2_ppm) + usr_fa_df = lipidcomposer.calc_fa_query( + usr_lipid_class, usr_fa_xlsx, ms2_ppm=usr_ms2_ppm + ) # del lipidcomposer if usr_fa_df is False: - print('[ERROR] !!! Failed to generate FA info table ...\n') - error_lst.append('[ERROR] !!! Failed to generate FA info table ...\n') + print("[ERROR] !!! Failed to generate FA info table ...\n") + error_lst.append("[ERROR] !!! Failed to generate FA info table ...\n") return False, error_lst, False - lipid_info_df = usr_lipid_master_df # make a copy to avoid pandas warning when modify it later + lipid_info_df = ( + usr_lipid_master_df + ) # make a copy to avoid pandas warning when modify it later # cut lib info to the user defined m/z range # TODO (georgia.angelidou@uni-leipzig.de): support for the sphingomyelins and ceramides - pos_charge_lst = ['[M+H]+', '[M+Na]+', '[M+NH4]+'] - neg_charge_lst = ['[M-H]-', '[M+HCOO]-', '[M+CH3COO]-'] + pos_charge_lst = ["[M+H]+", "[M+Na]+", "[M+NH4]+"] + neg_charge_lst = ["[M-H]-", "[M+HCOO]-", "[M+CH3COO]-"] if usr_charge in neg_charge_lst: - if usr_lipid_class in ['PC', 'LPC']: - if usr_charge == '[M+HCOO]-': - lipid_info_df = lipid_info_df[(mz_start <= lipid_info_df['[M+HCOO]-_MZ']) - & (lipid_info_df['[M+HCOO]-_MZ'] <= mz_end)] - elif usr_charge == '[M+CH3COO]-': - lipid_info_df = lipid_info_df[(mz_start <= lipid_info_df['[M+CH3COO]-_MZ']) - & (lipid_info_df['[M+CH3COO]-_MZ'] <= mz_end)] + if usr_lipid_class in ["PC", "LPC"]: + if usr_charge == "[M+HCOO]-": + lipid_info_df = lipid_info_df[ + (mz_start <= lipid_info_df["[M+HCOO]-_MZ"]) + & (lipid_info_df["[M+HCOO]-_MZ"] <= mz_end) + ] + elif usr_charge == "[M+CH3COO]-": + lipid_info_df = lipid_info_df[ + (mz_start <= lipid_info_df["[M+CH3COO]-_MZ"]) + & (lipid_info_df["[M+CH3COO]-_MZ"] <= mz_end) + ] else: - error_lst.append('PC charge not supported. User input charge = %s. ' - 'LipidHunter support [M+HCOO]- and [M+CH3COO]-.' % usr_charge) + error_lst.append( + "PC charge not supported. User input charge = %s. " + "LipidHunter support [M+HCOO]- and [M+CH3COO]-." % usr_charge + ) else: lipid_info_df = lipid_info_df[ - (mz_start <= lipid_info_df['[M-H]-_MZ']) & (lipid_info_df['[M-H]-_MZ'] <= mz_end)] + (mz_start <= lipid_info_df["[M-H]-_MZ"]) + & (lipid_info_df["[M-H]-_MZ"] <= mz_end) + ] elif usr_charge in pos_charge_lst: - if usr_lipid_class == 'TG': - if usr_charge == '[M+NH4]+': + if usr_lipid_class == "TG": + if usr_charge == "[M+NH4]+": lipid_info_df = lipid_info_df[ - (mz_start <= lipid_info_df['[M+NH4]+_MZ']) & (lipid_info_df['[M+NH4]+_MZ'] <= mz_end)] - elif usr_charge == '[M+H]+': + (mz_start <= lipid_info_df["[M+NH4]+_MZ"]) + & (lipid_info_df["[M+NH4]+_MZ"] <= mz_end) + ] + elif usr_charge == "[M+H]+": lipid_info_df = lipid_info_df[ - (mz_start <= lipid_info_df['[M+H]+_MZ']) & (lipid_info_df['[M+H]+_MZ'] <= mz_end)] - elif usr_charge == '[M+Na]+': + (mz_start <= lipid_info_df["[M+H]+_MZ"]) + & (lipid_info_df["[M+H]+_MZ"] <= mz_end) + ] + elif usr_charge == "[M+Na]+": lipid_info_df = lipid_info_df[ - (mz_start <= lipid_info_df['[M+Na]+_MZ']) & (lipid_info_df['[M+Na]+_MZ'] <= mz_end)] - if usr_lipid_class == 'DG': - if usr_charge == '[M+NH4]+': + (mz_start <= lipid_info_df["[M+Na]+_MZ"]) + & (lipid_info_df["[M+Na]+_MZ"] <= mz_end) + ] + if usr_lipid_class == "DG": + if usr_charge == "[M+NH4]+": lipid_info_df = lipid_info_df[ - (mz_start <= lipid_info_df['[M+NH4]+_MZ']) & (lipid_info_df['[M+NH4]+_MZ'] <= mz_end)] - elif usr_charge == '[M+H]+': + (mz_start <= lipid_info_df["[M+NH4]+_MZ"]) + & (lipid_info_df["[M+NH4]+_MZ"] <= mz_end) + ] + elif usr_charge == "[M+H]+": lipid_info_df = lipid_info_df[ - (mz_start <= lipid_info_df['[M+H]+_MZ']) & (lipid_info_df['[M+H]+_MZ'] <= mz_end)] + (mz_start <= lipid_info_df["[M+H]+_MZ"]) + & (lipid_info_df["[M+H]+_MZ"] <= mz_end) + ] else: - error_lst.append('Lipid class or charge NOT supported. User input lipid class = %s, charge = %s. ' - % (usr_lipid_class, usr_charge)) + error_lst.append( + "Lipid class or charge NOT supported. User input lipid class = %s, charge = %s. " + % (usr_lipid_class, usr_charge) + ) # TODO(zhixu.ni@uni-leipzig.de): Add more error to the error_lst. @@ -330,48 +403,71 @@ def huntlipids(param_dct: dict, error_lst: list, output_df = pd.DataFrame() - print('[INFO] --> Start to process data ...') - print('[INFO] --> Lipid class: %s' % usr_lipid_class) + print("[INFO] --> Start to process data ...") + print("[INFO] --> Lipid class: %s" % usr_lipid_class) # generate the Weight factor df - usr_weight_df = pd.read_excel(score_cfg, index_col='Type') + usr_weight_df = pd.read_excel(score_cfg, index_col="Type") - print('[INFO] --> Start to parse mzML') + print("[INFO] --> Start to parse mzML") # Preparation finished. # Lipid identification workflow start. # Extract all spectra from mzML to pandas DataFrame - usr_scan_info_df, usr_spectra_pl, ms1_xic_df = extract_mzml(usr_mzml, usr_rt_range, dda_top=usr_dda_top, - ms1_threshold=usr_ms1_threshold, - ms2_threshold=usr_ms2_threshold, - ms1_precision=usr_ms1_precision, - ms2_precision=usr_ms2_precision, - vendor=usr_vendor, ms1_max=usr_ms1_max) - - print('[INFO] --> MS1_XIC_df.shape', ms1_xic_df.shape) + usr_scan_info_df, usr_spectra_pl, ms1_xic_df = extract_mzml( + usr_mzml, + usr_rt_range, + dda_top=usr_dda_top, + ms1_threshold=usr_ms1_threshold, + ms2_threshold=usr_ms2_threshold, + ms1_precision=usr_ms1_precision, + ms2_precision=usr_ms2_precision, + vendor=usr_vendor, + ms1_max=usr_ms1_max, + ) + + print("[INFO] --> MS1_XIC_df.shape", ms1_xic_df.shape) # Find all possible precursor according to lipid master table - ms1_obs_pr_df = pr_hunter.get_matched_pr(usr_scan_info_df, usr_spectra_pl, ms1_max=usr_ms1_max, - core_num=usr_core_num, max_ram=usr_max_ram) + ms1_obs_pr_df = pr_hunter.get_matched_pr( + usr_scan_info_df, + usr_spectra_pl, + ms1_max=usr_ms1_max, + core_num=usr_core_num, + max_ram=usr_max_ram, + ) if ms1_obs_pr_df is False: - print('[WARNING] !!! NO suitable precursor --> Check settings!!\n') - error_lst.append('[WARNING] !! NO suitable precursor --> Check settings!!\n') + print("[WARNING] !!! NO suitable precursor --> Check settings!!\n") + error_lst.append("[WARNING] !! NO suitable precursor --> Check settings!!\n") return False, error_lst, False - print('[INFO] --> ms1 precursor matched') + print("[INFO] --> ms1 precursor matched") # Remove bad precursors, keep the matched scans by DDA_rank and scan number # Build unique str identifier for each scan with scan_number00dda_rank use numpy.int64 to avoid large scan_number # The unique identifier is important to index scans - usr_scan_info_df['scan_checker'] = (usr_scan_info_df['scan_number'].astype(int64).astype(str).str. - cat(usr_scan_info_df['DDA_rank'].astype(int64).astype(str), sep='_')) - ms1_obs_pr_df['scan_checker'] = (ms1_obs_pr_df['scan_number'].astype(int64).astype(str).str. - cat(ms1_obs_pr_df['DDA_rank'].astype(int64).astype(str).astype(str), sep='_')) - - checked_info_df = ms1_obs_pr_df[ms1_obs_pr_df['scan_checker'].isin(usr_scan_info_df['scan_checker'] - .tolist())].copy() - checked_info_df.sort_values(by=['scan_checker', 'Lib_mz'], ascending=[True, True], inplace=True) + usr_scan_info_df["scan_checker"] = ( + usr_scan_info_df["scan_number"] + .astype(int64) + .astype(str) + .str.cat(usr_scan_info_df["DDA_rank"].astype(int64).astype(str), sep="_") + ) + ms1_obs_pr_df["scan_checker"] = ( + ms1_obs_pr_df["scan_number"] + .astype(int64) + .astype(str) + .str.cat( + ms1_obs_pr_df["DDA_rank"].astype(int64).astype(str).astype(str), sep="_" + ) + ) + + checked_info_df = ms1_obs_pr_df[ + ms1_obs_pr_df["scan_checker"].isin(usr_scan_info_df["scan_checker"].tolist()) + ].copy() + checked_info_df.sort_values( + by=["scan_checker", "Lib_mz"], ascending=[True, True], inplace=True + ) # # reserved for further debug_mode options # if 'debug_mode' in list(param_dct.keys()): @@ -381,34 +477,43 @@ def huntlipids(param_dct: dict, error_lst: list, # checked_info_df.to_csv(os.path.join(output_folder, 'checked_info_df.csv')) if checked_info_df.empty: - print('[ERROR] !!! No identification in pre-match steps !!') - error_lst.append('!! No identification in pre-match steps !!\n') + print("[ERROR] !!! No identification in pre-match steps !!") + error_lst.append("!! No identification in pre-match steps !!\n") return False, error_lst, False else: - print('[INFO] --> features identified in the pre-match: ', checked_info_df.shape[0]) + print( + "[INFO] --> features identified in the pre-match: ", + checked_info_df.shape[0], + ) - ms1_xic_mz_lst = sorted(set(ms1_obs_pr_df['MS1_XIC_mz'].values.tolist())) - print('ms1_xic_mz_lst', len(ms1_xic_mz_lst)) + ms1_xic_mz_lst = sorted(set(ms1_obs_pr_df["MS1_XIC_mz"].values.tolist())) + print("ms1_xic_mz_lst", len(ms1_xic_mz_lst)) print(ms1_xic_mz_lst) - print('[INFO] --> Start to extract XIC') + print("[INFO] --> Start to extract XIC") # Distribute task according to core numbers if len(ms1_xic_mz_lst) >= 3 * usr_core_num: sub_len = int(math.ceil(len(ms1_xic_mz_lst) / usr_core_num)) - core_key_list = [ms1_xic_mz_lst[k: k + sub_len] for k in range(0, len(ms1_xic_mz_lst), sub_len)] + core_key_list = [ + ms1_xic_mz_lst[k : k + sub_len] + for k in range(0, len(ms1_xic_mz_lst), sub_len) + ] else: core_key_list = [ms1_xic_mz_lst] # Start multiprocessing to get XIC according to precursor m/z found above - print('[STATUS] >>> Start multiprocessing to get XIC ==> ==> ==> Number of Cores: %i' % usr_core_num) + print( + "[STATUS] >>> Start multiprocessing to get XIC ==> ==> ==> Number of Cores: %i" + % usr_core_num + ) xic_dct = {} if usr_core_num > 1: xic_results_lst = [] - if os_typ == 'windows': + if os_typ == "windows": parallel_pool = Pool(usr_core_num) - queue = '' + queue = "" worker_count = 1 for core_list in core_key_list: if isinstance(core_list, tuple) or isinstance(core_list, list): @@ -416,11 +521,16 @@ def huntlipids(param_dct: dict, error_lst: list, core_list = [x for x in core_list if x is not None] else: pass - print('[STATUS] >>> Core #%i ==> ...... processing ......' % worker_count) + print( + "[STATUS] >>> Core #%i ==> ...... processing ......" + % worker_count + ) print(core_list) # TODO (georgia.angelidou@uni-leipzig.de): maybe can be combine or stay like this???? - xic_result = parallel_pool.apply_async(get_xic_from_pl, args=(core_list, ms1_xic_df, usr_xic_ppm, - os_typ, queue)) + xic_result = parallel_pool.apply_async( + get_xic_from_pl, + args=(core_list, ms1_xic_df, usr_xic_ppm, os_typ, queue), + ) worker_count += 1 xic_results_lst.append(xic_result) @@ -448,10 +558,15 @@ def huntlipids(param_dct: dict, error_lst: list, core_list = [x for x in core_list if x is not None] else: pass - print('[STATUS] >>> Core #%i ==> ...... processing ......' % worker_count) + print( + "[STATUS] >>> Core #%i ==> ...... processing ......" + % worker_count + ) print(core_list) - job = multiprocessing.Process(target=get_xic_from_pl, args=(core_list, ms1_xic_df, usr_xic_ppm, - os_typ, queue)) + job = multiprocessing.Process( + target=get_xic_from_pl, + args=(core_list, ms1_xic_df, usr_xic_ppm, os_typ, queue), + ) worker_count += 1 jobs.append(job) job.start() @@ -471,8 +586,8 @@ def huntlipids(param_dct: dict, error_lst: list, pass del xic_results_lst else: - print('[INFO] --> Using single core mode...') - queue = '' + print("[INFO] --> Using single core mode...") + queue = "" worker_count = 1 for core_list in core_key_list: if isinstance(core_list, tuple) or isinstance(core_list, list): @@ -480,9 +595,14 @@ def huntlipids(param_dct: dict, error_lst: list, core_list = [x for x in core_list if x is not None] else: pass - print('[STATUS] >>> Core #1 Part %i ==> ...... processing ......' % worker_count) + print( + "[STATUS] >>> Core #1 Part %i ==> ...... processing ......" + % worker_count + ) print(core_list) - sub_xic_dct = get_xic_from_pl(core_list, ms1_xic_df, usr_xic_ppm, os_typ, queue) + sub_xic_dct = get_xic_from_pl( + core_list, ms1_xic_df, usr_xic_ppm, os_typ, queue + ) worker_count += 1 if len(list(sub_xic_dct.keys())) > 0: @@ -490,13 +610,13 @@ def huntlipids(param_dct: dict, error_lst: list, del ms1_xic_df if len(list(xic_dct.keys())) == 0: - print('[ERROR] !!! No precursor for XIC found !!') - error_lst.append('!! No precursor for XIC found !!\n') + print("[ERROR] !!! No precursor for XIC found !!") + error_lst.append("!! No precursor for XIC found !!\n") return False, error_lst, False else: - print('[INFO] --> Number of XIC extracted: %i' % len(list(xic_dct.keys()))) + print("[INFO] --> Number of XIC extracted: %i" % len(list(xic_dct.keys()))) - print('[STATUS] >>> Start to Hunt for Lipids !!') + print("[STATUS] >>> Start to Hunt for Lipids !!") # All XIC extracted # Start to process further identification and scoring # Stat to use get_spec_info to match MS2 to precursor and XIC with multiprocessing @@ -507,14 +627,16 @@ def huntlipids(param_dct: dict, error_lst: list, lipid_spec_info_dct = {} spec_part_key_lst = [] split_seg = 1 - lipid_all_scan_num = checked_info_df['scan_checker'].nunique() + lipid_all_scan_num = checked_info_df["scan_checker"].nunique() # Checked_info_df may become very large for TG in Thermo files, need to be divided for Multiprocessing - checked_info_df_groups = checked_info_df.groupby(['Formula', 'scan_checker']) + checked_info_df_groups = checked_info_df.groupby(["Formula", "scan_checker"]) checked_info_key_lst = list(checked_info_df_groups.groups.keys()) checked_info_key_num = len(checked_info_key_lst) - print('[INFO] --> Total number of spectra features: %i | Number of proposed Formula: %i' - % (lipid_all_scan_num, checked_info_key_num)) + print( + "[INFO] --> Total number of spectra features: %i | Number of proposed Formula: %i" + % (lipid_all_scan_num, checked_info_key_num) + ) if lipid_all_scan_num > (usr_core_num * 100): @@ -526,43 +648,60 @@ def huntlipids(param_dct: dict, error_lst: list, else: split_seg = 2 - spec_part_len = int(math.ceil(lipid_all_scan_num / split_seg)) # Number of scan in each part + spec_part_len = int( + math.ceil(lipid_all_scan_num / split_seg) + ) # Number of scan in each part if spec_part_len > 200: spec_part_len = 200 - spec_part_lst = [list(checked_info_df['scan_checker'].unique())[k: k + spec_part_len] - for k in range(0, lipid_all_scan_num, spec_part_len)] + spec_part_lst = [ + list(checked_info_df["scan_checker"].unique())[k : k + spec_part_len] + for k in range(0, lipid_all_scan_num, spec_part_len) + ] for part_lst in spec_part_lst: if None in part_lst: part_lst = [x for x in part_lst if x is not None] spec_sub_len = int(math.ceil(len(part_lst) / usr_core_num)) - scan_sub_lst = [part_lst[k: k + spec_sub_len] for k in range(0, len(part_lst), spec_sub_len)] + scan_sub_lst = [ + part_lst[k : k + spec_sub_len] + for k in range(0, len(part_lst), spec_sub_len) + ] for scan_lst in scan_sub_lst: - _tmp_lipid_info_df = checked_info_df[checked_info_df['scan_checker'].isin(scan_lst)] - _tmp_info_groups = _tmp_lipid_info_df.groupby(['Formula', 'scan_checker']) + _tmp_lipid_info_df = checked_info_df[ + checked_info_df["scan_checker"].isin(scan_lst) + ] + _tmp_info_groups = _tmp_lipid_info_df.groupby( + ["Formula", "scan_checker"] + ) _tmp_group_key_lst = list(_tmp_info_groups.groups.keys()) _tmp_group_key_num = len(_tmp_group_key_lst) # chk_info_df_lst.append([_tmp_lipid_info_df, _tmp_info_groups]) - spec_sub_key_lst = [_tmp_group_key_lst[k: k + spec_sub_len] - for k in range(0, _tmp_group_key_num, spec_sub_len)] + spec_sub_key_lst = [ + _tmp_group_key_lst[k : k + spec_sub_len] + for k in range(0, _tmp_group_key_num, spec_sub_len) + ] spec_part_key_lst.append((spec_sub_key_lst, _tmp_info_groups)) print( - '[INFO] --> Distributed tasks into %i parts with max %i features ...' % (len(spec_part_lst), spec_part_len)) + "[INFO] --> Distributed tasks into %i parts with max %i features ..." + % (len(spec_part_lst), spec_part_len) + ) else: spec_sub_len = int(math.ceil(checked_info_key_num / usr_core_num)) - spec_sub_key_lst = [checked_info_key_lst[k: k + spec_sub_len] for k in - range(0, checked_info_key_num, spec_sub_len)] + spec_sub_key_lst = [ + checked_info_key_lst[k : k + spec_sub_len] + for k in range(0, checked_info_key_num, spec_sub_len) + ] spec_part_key_lst.append((spec_sub_key_lst, checked_info_df_groups)) del checked_info_df_groups if usr_core_num > 1: part_tot = len(spec_part_key_lst) part_counter = 1 - queue = '' + queue = "" for spec_sub_lst in spec_part_key_lst: @@ -570,16 +709,20 @@ def huntlipids(param_dct: dict, error_lst: list, sub_info_groups = spec_sub_lst[1] if part_tot == 1: - print('[STATUS] >>> Start multiprocessing to get Spectra info ==> Max Number of Cores: %i' - % usr_core_num) + print( + "[STATUS] >>> Start multiprocessing to get Spectra info ==> Max Number of Cores: %i" + % usr_core_num + ) else: - print('[STATUS] >>> Start multiprocessing to get Spectra info ==> Part %i / %i ' - '--> Max Number of Cores: %i' - % (part_counter, part_tot, usr_core_num)) + print( + "[STATUS] >>> Start multiprocessing to get Spectra info ==> Part %i / %i " + "--> Max Number of Cores: %i" + % (part_counter, part_tot, usr_core_num) + ) spec_results_lst = [] - if os_typ == 'windows': + if os_typ == "windows": parallel_pool = Pool(usr_core_num) # usr_queue = '' worker_count = 1 @@ -589,9 +732,20 @@ def huntlipids(param_dct: dict, error_lst: list, _sub_lst = [x for x in _sub_lst if x is not None] else: pass - print('[STATUS] >>> Core #%i ==> ...... processing ......' % worker_count) - spec_result = parallel_pool.apply_async(get_spec_info, args=(_sub_lst, sub_info_groups, - usr_scan_info_df, os_typ, queue)) + print( + "[STATUS] >>> Core #%i ==> ...... processing ......" + % worker_count + ) + spec_result = parallel_pool.apply_async( + get_spec_info, + args=( + _sub_lst, + sub_info_groups, + usr_scan_info_df, + os_typ, + queue, + ), + ) worker_count += 1 if worker_count > usr_core_num: worker_count = 1 @@ -610,9 +764,20 @@ def huntlipids(param_dct: dict, error_lst: list, _sub_lst = [x for x in _sub_lst if x is not None] else: pass - print('[STATUS] >>> Core #%i ==> ...... processing ......' % worker_count) - job = multiprocessing.Process(target=get_spec_info, args=(_sub_lst, sub_info_groups, - usr_scan_info_df, os_typ, queue_spec)) + print( + "[STATUS] >>> Core #%i ==> ...... processing ......" + % worker_count + ) + job = multiprocessing.Process( + target=get_spec_info, + args=( + _sub_lst, + sub_info_groups, + usr_scan_info_df, + os_typ, + queue_spec, + ), + ) worker_count += 1 jobs.append(job) job.start() @@ -623,31 +788,37 @@ def huntlipids(param_dct: dict, error_lst: list, # Merge multiprocessing results for spec_result in spec_results_lst: - if os_typ == 'windows': + if os_typ == "windows": try: sub_spec_dct = spec_result.get() # print(sub_spec_dct) if len(list(sub_spec_dct.keys())) > 0: lipid_spec_info_dct.update(sub_spec_dct) except (KeyError, SystemError, ValueError): - print('[ValueError] !!! must supply a tuple to get_group with multiple grouping keys ...') + print( + "[ValueError] !!! must supply a tuple to get_group with multiple grouping keys ..." + ) else: # for linux try: if len(list(spec_result.keys())) > 0: lipid_spec_info_dct.update(spec_result) except (KeyError, SystemError, ValueError): - print('[ValueError] !!! must supply a tuple to get_group with multiple grouping keys ...') + print( + "[ValueError] !!! must supply a tuple to get_group with multiple grouping keys ..." + ) # del spec_result # del spec_results_lst if part_tot == 1: - print('[STATUS] >>> multiprocessing results merged') + print("[STATUS] >>> multiprocessing results merged") else: - print('[STATUS] >>> multiprocessing results merged ==> Part %i / %i ' - % (part_counter, part_tot)) + print( + "[STATUS] >>> multiprocessing results merged ==> Part %i / %i " + % (part_counter, part_tot) + ) part_counter += 1 else: - print('[INFO] --> Using single core mode...') - queue = '' + print("[INFO] --> Using single core mode...") + queue = "" worker_count = 1 for spec_sub_lst in spec_part_key_lst: spec_sub_key_lst = spec_sub_lst[0] @@ -662,8 +833,13 @@ def huntlipids(param_dct: dict, error_lst: list, _sub_lst3 = _sub_lst3 + (_sub_lst,) _sub_lst = _sub_lst3 - print('[STATUS] >>> Core #%i ==> ...... processing ......' % worker_count) - sub_spec_dct = get_spec_info(_sub_lst, sub_info_groups, usr_scan_info_df, os_typ, queue) + print( + "[STATUS] >>> Core #%i ==> ...... processing ......" + % worker_count + ) + sub_spec_dct = get_spec_info( + _sub_lst, sub_info_groups, usr_scan_info_df, os_typ, queue + ) if len(list(sub_spec_dct.keys())) > 0: lipid_spec_info_dct.update(sub_spec_dct) @@ -671,7 +847,7 @@ def huntlipids(param_dct: dict, error_lst: list, else: pass - print('lipid_spec_info_dct', len(list(lipid_spec_info_dct.keys()))) + print("lipid_spec_info_dct", len(list(lipid_spec_info_dct.keys()))) # Single process ONLY. usr_spectra_pl is too big in RAM --> RAM leaking during copy lipid_spec_dct = {} @@ -685,14 +861,23 @@ def huntlipids(param_dct: dict, error_lst: list, for _spec_group_key in spec_info_key_lst: _spec_info_dct = lipid_spec_info_dct[_spec_group_key] - _usr_ms2_pr_mz = _spec_info_dct['MS2_PR_mz'] - _usr_ms2_dda_rank = _spec_info_dct['DDA_rank'] - _usr_ms2_scan_id = _spec_info_dct['scan_number'] - _usr_mz_lib = _spec_info_dct['Lib_mz'] - - usr_spec_info_dct = get_spectra(_usr_ms2_pr_mz, _usr_mz_lib, _usr_ms2_dda_rank, _usr_ms2_scan_id, - ms1_xic_mz_lst, usr_scan_info_df, usr_spectra_pl, - dda_top=usr_dda_top, ms1_precision=usr_ms1_precision, vendor=usr_vendor) + _usr_ms2_pr_mz = _spec_info_dct["MS2_PR_mz"] + _usr_ms2_dda_rank = _spec_info_dct["DDA_rank"] + _usr_ms2_scan_id = _spec_info_dct["scan_number"] + _usr_mz_lib = _spec_info_dct["Lib_mz"] + + usr_spec_info_dct = get_spectra( + _usr_ms2_pr_mz, + _usr_mz_lib, + _usr_ms2_dda_rank, + _usr_ms2_scan_id, + ms1_xic_mz_lst, + usr_scan_info_df, + usr_spectra_pl, + dda_top=usr_dda_top, + ms1_precision=usr_ms1_precision, + vendor=usr_vendor, + ) lipid_spec_dct[_spec_group_key] = usr_spec_info_dct found_spec_key_lst = list(lipid_spec_dct.keys()) @@ -703,90 +888,159 @@ def huntlipids(param_dct: dict, error_lst: list, # Parse specific peak info # Lipid class specific triggers - pl_class_lst = ['PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'PIP'] - lpl_class_lst = ['LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPS', 'LPIP'] - pl_neg_chg_lst = ['[M-H]-', '[M+HCOO]-', '[M+CH3COO]-'] - tg_class_lst = ['TG', 'DG'] - tg_pos_chg_lst = ['[M+NH4]+', '[M+H]+', '[M+Na]+'] + pl_class_lst = ["PA", "PC", "PE", "PG", "PI", "PS", "PIP"] + lpl_class_lst = ["LPA", "LPC", "LPE", "LPG", "LPI", "LPS", "LPIP"] + pl_neg_chg_lst = ["[M-H]-", "[M+HCOO]-", "[M+CH3COO]-"] + tg_class_lst = ["TG", "DG"] + tg_pos_chg_lst = ["[M+NH4]+", "[M+H]+", "[M+Na]+"] # Todo(zhixu.ni@uni-leipzig.de): Other classes such as SM, Cer and CL here. if usr_lipid_class in pl_class_lst and usr_charge in pl_neg_chg_lst: - charge_mode = 'NEG' + charge_mode = "NEG" usr_key_frag_df = pd.read_excel(key_frag_cfg) - usr_key_frag_df = usr_key_frag_df.query('EXACTMASS > 0') + usr_key_frag_df = usr_key_frag_df.query("EXACTMASS > 0") # get the information from the following columns - usr_key_frag_df = usr_key_frag_df[['CLASS', 'TYPE', 'EXACTMASS', 'PR_CHARGE', 'LABEL', 'CHARGE_MODE']] + usr_key_frag_df = usr_key_frag_df[ + ["CLASS", "TYPE", "EXACTMASS", "PR_CHARGE", "LABEL", "CHARGE_MODE"] + ] # find key peaks for the target PL class - target_frag_df = usr_key_frag_df.query(r'CLASS == "%s" and TYPE == "FRAG" and PR_CHARGE == "%s"' - % (usr_lipid_class, usr_charge)) - target_nl_df = usr_key_frag_df.query(r'CLASS == "%s" and TYPE == "NL" and PR_CHARGE == "%s"' - % (usr_lipid_class, usr_charge)) + target_frag_df = usr_key_frag_df.query( + r'CLASS == "%s" and TYPE == "FRAG" and PR_CHARGE == "%s"' + % (usr_lipid_class, usr_charge) + ) + target_nl_df = usr_key_frag_df.query( + r'CLASS == "%s" and TYPE == "NL" and PR_CHARGE == "%s"' + % (usr_lipid_class, usr_charge) + ) # add precursor to the list - target_pr_df = pd.DataFrame(data={'CLASS': usr_lipid_class, 'TYPE': 'NL', 'EXACTMASS': 0.0, - 'PR_CHARGE': usr_charge, 'LABEL': 'PR', 'CHARGE_MODE': 'NEG'}, index=['PR']) + target_pr_df = pd.DataFrame( + data={ + "CLASS": usr_lipid_class, + "TYPE": "NL", + "EXACTMASS": 0.0, + "PR_CHARGE": usr_charge, + "LABEL": "PR", + "CHARGE_MODE": "NEG", + }, + index=["PR"], + ) target_nl_df = target_nl_df.append(target_pr_df) target_nl_df.reset_index(drop=True, inplace=True) # extract info for other classes - other_frag_df = usr_key_frag_df.query('CLASS != "%s" and TYPE == "FRAG" and CHARGE_MODE == "%s"' - % (usr_lipid_class, charge_mode)) - other_nl_df = usr_key_frag_df.query('CLASS != "%s" and TYPE == "NL" and CHARGE_MODE == "%s"' - % (usr_lipid_class, charge_mode)) - key_frag_dct = {'target_frag_df': target_frag_df, 'target_nl_df': target_nl_df, - 'other_frag_df': other_frag_df, 'other_nl_df': other_nl_df} + other_frag_df = usr_key_frag_df.query( + 'CLASS != "%s" and TYPE == "FRAG" and CHARGE_MODE == "%s"' + % (usr_lipid_class, charge_mode) + ) + other_nl_df = usr_key_frag_df.query( + 'CLASS != "%s" and TYPE == "NL" and CHARGE_MODE == "%s"' + % (usr_lipid_class, charge_mode) + ) + key_frag_dct = { + "target_frag_df": target_frag_df, + "target_nl_df": target_nl_df, + "other_frag_df": other_frag_df, + "other_nl_df": other_nl_df, + } elif usr_lipid_class in lpl_class_lst and usr_charge in pl_neg_chg_lst: - charge_mode = 'NEG' + charge_mode = "NEG" usr_key_frag_df = pd.read_excel(key_frag_cfg) - usr_key_frag_df = usr_key_frag_df.query('EXACTMASS > 0') + usr_key_frag_df = usr_key_frag_df.query("EXACTMASS > 0") # get the information from the following columns - usr_key_frag_df = usr_key_frag_df[['CLASS', 'TYPE', 'EXACTMASS', 'PR_CHARGE', 'LABEL', 'CHARGE_MODE']] + usr_key_frag_df = usr_key_frag_df[ + ["CLASS", "TYPE", "EXACTMASS", "PR_CHARGE", "LABEL", "CHARGE_MODE"] + ] # find key peaks for the target PL class - target_frag_df = usr_key_frag_df.query(r'CLASS == "%s" and TYPE == "FRAG" and PR_CHARGE == "%s"' - % (usr_lipid_class[1:], usr_charge)) - target_nl_df = usr_key_frag_df.query(r'CLASS == "%s" and TYPE == "NL" and PR_CHARGE == "%s"' - % (usr_lipid_class[1:], usr_charge)) + target_frag_df = usr_key_frag_df.query( + r'CLASS == "%s" and TYPE == "FRAG" and PR_CHARGE == "%s"' + % (usr_lipid_class[1:], usr_charge) + ) + target_nl_df = usr_key_frag_df.query( + r'CLASS == "%s" and TYPE == "NL" and PR_CHARGE == "%s"' + % (usr_lipid_class[1:], usr_charge) + ) # add precursor to the list - target_pr_df = pd.DataFrame(data={'CLASS': usr_lipid_class, 'TYPE': 'NL', 'EXACTMASS': 0.0, - 'PR_CHARGE': usr_charge, 'LABEL': 'PR', 'CHARGE_MODE': 'NEG'}, index=['PR']) + target_pr_df = pd.DataFrame( + data={ + "CLASS": usr_lipid_class, + "TYPE": "NL", + "EXACTMASS": 0.0, + "PR_CHARGE": usr_charge, + "LABEL": "PR", + "CHARGE_MODE": "NEG", + }, + index=["PR"], + ) target_nl_df = target_nl_df.append(target_pr_df) target_nl_df.reset_index(drop=True, inplace=True) # extract info for other classes - other_frag_df = usr_key_frag_df.query('CLASS != "%s" and TYPE == "FRAG" and CHARGE_MODE == "%s"' - % (usr_lipid_class[1:], charge_mode)) - other_nl_df = usr_key_frag_df.query('CLASS != "%s" and TYPE == "NL" and CHARGE_MODE == "%s"' - % (usr_lipid_class[1:], charge_mode)) - key_frag_dct = {'target_frag_df': target_frag_df, 'target_nl_df': target_nl_df, - 'other_frag_df': other_frag_df, 'other_nl_df': other_nl_df} + other_frag_df = usr_key_frag_df.query( + 'CLASS != "%s" and TYPE == "FRAG" and CHARGE_MODE == "%s"' + % (usr_lipid_class[1:], charge_mode) + ) + other_nl_df = usr_key_frag_df.query( + 'CLASS != "%s" and TYPE == "NL" and CHARGE_MODE == "%s"' + % (usr_lipid_class[1:], charge_mode) + ) + key_frag_dct = { + "target_frag_df": target_frag_df, + "target_nl_df": target_nl_df, + "other_frag_df": other_frag_df, + "other_nl_df": other_nl_df, + } elif usr_lipid_class in tg_class_lst and usr_charge in tg_pos_chg_lst: - charge_mode = 'POS' + charge_mode = "POS" usr_key_frag_df = pd.read_excel(key_frag_cfg) - usr_key_frag_df = usr_key_frag_df.query('EXACTMASS > 0') + usr_key_frag_df = usr_key_frag_df.query("EXACTMASS > 0") # get the information from the following columns - usr_key_frag_df = usr_key_frag_df[['CLASS', 'TYPE', 'EXACTMASS', 'PR_CHARGE', 'LABEL', 'CHARGE_MODE']] + usr_key_frag_df = usr_key_frag_df[ + ["CLASS", "TYPE", "EXACTMASS", "PR_CHARGE", "LABEL", "CHARGE_MODE"] + ] # find key peaks for the target PL class - target_frag_df = usr_key_frag_df.query(r'CLASS == "%s" and TYPE == "FRAG" and PR_CHARGE == "%s"' - % (usr_lipid_class, usr_charge)) - target_nl_df = usr_key_frag_df.query(r'CLASS == "%s" and TYPE == "NL" and PR_CHARGE == "%s"' - % (usr_lipid_class, usr_charge)) + target_frag_df = usr_key_frag_df.query( + r'CLASS == "%s" and TYPE == "FRAG" and PR_CHARGE == "%s"' + % (usr_lipid_class, usr_charge) + ) + target_nl_df = usr_key_frag_df.query( + r'CLASS == "%s" and TYPE == "NL" and PR_CHARGE == "%s"' + % (usr_lipid_class, usr_charge) + ) # add precursor to the list - target_pr_df = pd.DataFrame(data={'CLASS': usr_lipid_class, 'TYPE': 'NL', 'EXACTMASS': 0.0, - 'PR_CHARGE': usr_charge, 'LABEL': 'PR', 'CHARGE_MODE': 'NEG'}, index=['PR']) + target_pr_df = pd.DataFrame( + data={ + "CLASS": usr_lipid_class, + "TYPE": "NL", + "EXACTMASS": 0.0, + "PR_CHARGE": usr_charge, + "LABEL": "PR", + "CHARGE_MODE": "NEG", + }, + index=["PR"], + ) target_nl_df = target_nl_df.append(target_pr_df) target_nl_df.reset_index(drop=True, inplace=True) # extract info for other classes - other_frag_df = usr_key_frag_df.query('CLASS != "%s" and TYPE == "FRAG" and CHARGE_MODE == "%s"' - % (usr_lipid_class, charge_mode)) - other_nl_df = usr_key_frag_df.query('CLASS != "%s" and TYPE == "NL" and CHARGE_MODE == "%s"' - % (usr_lipid_class, charge_mode)) - key_frag_dct = {'target_frag_df': target_frag_df, 'target_nl_df': target_nl_df, - 'other_frag_df': other_frag_df, 'other_nl_df': other_nl_df} + other_frag_df = usr_key_frag_df.query( + 'CLASS != "%s" and TYPE == "FRAG" and CHARGE_MODE == "%s"' + % (usr_lipid_class, charge_mode) + ) + other_nl_df = usr_key_frag_df.query( + 'CLASS != "%s" and TYPE == "NL" and CHARGE_MODE == "%s"' + % (usr_lipid_class, charge_mode) + ) + key_frag_dct = { + "target_frag_df": target_frag_df, + "target_nl_df": target_nl_df, + "other_frag_df": other_frag_df, + "other_nl_df": other_nl_df, + } else: key_frag_dct = {} - print('[INFO] --> Key FRAG Dict Generated ...') + print("[INFO] --> Key FRAG Dict Generated ...") # Start to get rank score using get_lipid_info with multiprocessing @@ -800,55 +1054,83 @@ def huntlipids(param_dct: dict, error_lst: list, # Problem with the 1 Core run. Temporary solution if usr_core_num * 24 < spec_key_num <= usr_core_num * 48 and usr_core_num != 1: split_seg = 2 - elif usr_core_num * 48 < spec_key_num <= usr_core_num * 96 and usr_core_num != 1: + elif ( + usr_core_num * 48 < spec_key_num <= usr_core_num * 96 and usr_core_num != 1 + ): split_seg = 3 elif usr_core_num * 96 < spec_key_num and usr_core_num != 1: split_seg = 4 else: split_seg = 1 lipid_part_len = int(math.ceil(spec_key_num / split_seg)) - lipid_part_lst = [found_spec_key_lst[k: k + lipid_part_len] for k in range(0, spec_key_num, - lipid_part_len)] - print('[INFO] --> lipid_part_number: ', len(lipid_part_lst), ' lipid_part_len:', lipid_part_len) + lipid_part_lst = [ + found_spec_key_lst[k : k + lipid_part_len] + for k in range(0, spec_key_num, lipid_part_len) + ] + print( + "[INFO] --> lipid_part_number: ", + len(lipid_part_lst), + " lipid_part_len:", + lipid_part_len, + ) for part_lst in lipid_part_lst: if None in part_lst: part_lst = [x for x in part_lst if x is not None] lipid_sub_len = int(math.ceil(len(part_lst) / usr_core_num)) # print('lipid_sub_len', lipid_sub_len) - pre_lipid_sub_key_lst = [part_lst[k: k + lipid_sub_len] for k in range(0, len(part_lst), lipid_sub_len)] + pre_lipid_sub_key_lst = [ + part_lst[k : k + lipid_sub_len] + for k in range(0, len(part_lst), lipid_sub_len) + ] lipid_sub_key_lst = [] for _core_key_lst in pre_lipid_sub_key_lst: - _core_key_df = pd.DataFrame(_core_key_lst, columns=['Formula', 'scan_checker']) - _core_scan_lst = _core_key_df['scan_checker'].tolist() - _core_chk_info_df = checked_info_df[checked_info_df['scan_checker'].isin(_core_scan_lst)] - _core_chk_groups = _core_chk_info_df.groupby(['Formula', 'scan_checker']) - - lipid_sub_key_lst.append((_core_key_lst, _core_chk_info_df, _core_chk_groups)) + _core_key_df = pd.DataFrame( + _core_key_lst, columns=["Formula", "scan_checker"] + ) + _core_scan_lst = _core_key_df["scan_checker"].tolist() + _core_chk_info_df = checked_info_df[ + checked_info_df["scan_checker"].isin(_core_scan_lst) + ] + _core_chk_groups = _core_chk_info_df.groupby( + ["Formula", "scan_checker"] + ) + + lipid_sub_key_lst.append( + (_core_key_lst, _core_chk_info_df, _core_chk_groups) + ) lipid_part_key_lst.append(lipid_sub_key_lst) else: lipid_sub_len = int(math.ceil(spec_key_num / usr_core_num)) - pre_lipid_sub_key_lst = [found_spec_key_lst[k: k + lipid_sub_len] for k in - range(0, spec_key_num, lipid_sub_len)] + pre_lipid_sub_key_lst = [ + found_spec_key_lst[k : k + lipid_sub_len] + for k in range(0, spec_key_num, lipid_sub_len) + ] lipid_sub_key_lst = [] for _core_key_lst in pre_lipid_sub_key_lst: - _core_key_df = pd.DataFrame(_core_key_lst, columns=['Formula', 'scan_checker']) - _core_scan_lst = _core_key_df['scan_checker'].tolist() - _core_chk_info_df = checked_info_df[checked_info_df['scan_checker'].isin(_core_scan_lst)] - _core_chk_groups = _core_chk_info_df.groupby(['Formula', 'scan_checker']) + _core_key_df = pd.DataFrame( + _core_key_lst, columns=["Formula", "scan_checker"] + ) + _core_scan_lst = _core_key_df["scan_checker"].tolist() + _core_chk_info_df = checked_info_df[ + checked_info_df["scan_checker"].isin(_core_scan_lst) + ] + _core_chk_groups = _core_chk_info_df.groupby(["Formula", "scan_checker"]) # TODO (georgia.angelidou@uni-leipzig.de): unnecesary decleration of new parameter # It can directly be save in the destination parameter: # lipid_part_key_lst.append((_core_key_lst, _core_chk_info_df, _core_chk_groups)) - lipid_sub_key_lst.append((_core_key_lst, _core_chk_info_df, _core_chk_groups)) + lipid_sub_key_lst.append( + (_core_key_lst, _core_chk_info_df, _core_chk_groups) + ) lipid_part_key_lst.append(lipid_sub_key_lst) part_tot = len(lipid_part_key_lst) part_counter = 1 - queue = '' + queue = "" if usr_core_num > 1: @@ -857,27 +1139,44 @@ def huntlipids(param_dct: dict, error_lst: list, lipid_info_results_lst = [] if part_tot == 1: - print('[STATUS] >>> Start multiprocessing to get Score ==> Max Number of Cores: %i' % usr_core_num) + print( + "[STATUS] >>> Start multiprocessing to get Score ==> Max Number of Cores: %i" + % usr_core_num + ) try: worker_feature_count = len(lipid_sub_key_lst[0][0]) - print('[STATUS] >>> Start multiprocessing to get Score ==> Max Number of Cores: %i | ' - 'x%i Features each' - % (usr_core_num, worker_feature_count)) + print( + "[STATUS] >>> Start multiprocessing to get Score ==> Max Number of Cores: %i | " + "x%i Features each" % (usr_core_num, worker_feature_count) + ) except Exception as _e: - print('[STATUS] >>> Start multiprocessing to get Score ==> Max Number of Cores: %i' % usr_core_num) - print('[Exception] Can not get the number of features distributed to each core...', _e) + print( + "[STATUS] >>> Start multiprocessing to get Score ==> Max Number of Cores: %i" + % usr_core_num + ) + print( + "[Exception] Can not get the number of features distributed to each core...", + _e, + ) else: try: worker_feature_count = len(lipid_sub_key_lst[0][0]) - print('[STATUS] >>> Start multiprocessing to get Score ==> Part %i / %i ' - '--> Max Number of Cores: %i | x%i Features each' - % (part_counter, part_tot, usr_core_num, worker_feature_count)) + print( + "[STATUS] >>> Start multiprocessing to get Score ==> Part %i / %i " + "--> Max Number of Cores: %i | x%i Features each" + % (part_counter, part_tot, usr_core_num, worker_feature_count) + ) except Exception as _e: - print('[STATUS] >>> Start multiprocessing to get Score ==> Part %i / %i --> Max Number of Cores: %i' - % (part_counter, part_tot, usr_core_num)) - print('[Exception] ... Can not get the number of features distributed to each core...', _e) - - if os_typ == 'windows': + print( + "[STATUS] >>> Start multiprocessing to get Score ==> Part %i / %i --> Max Number of Cores: %i" + % (part_counter, part_tot, usr_core_num) + ) + print( + "[Exception] ... Can not get the number of features distributed to each core...", + _e, + ) + + if os_typ == "windows": parallel_pool = Pool(usr_core_num) worker_count = 1 @@ -892,20 +1191,40 @@ def huntlipids(param_dct: dict, error_lst: list, lipid_sub_lst = [x for x in lipid_sub_lst if x is not None] else: pass - if isinstance(lipid_sub_lst[0], tuple) or isinstance(lipid_sub_lst[0], list): - lipid_sub_dct = {k: lipid_spec_dct[k] for k in lipid_sub_lst} + if isinstance(lipid_sub_lst[0], tuple) or isinstance( + lipid_sub_lst[0], list + ): + lipid_sub_dct = { + k: lipid_spec_dct[k] for k in lipid_sub_lst + } else: - lipid_sub_dct = {lipid_sub_lst: lipid_spec_dct[lipid_sub_lst]} + lipid_sub_dct = { + lipid_sub_lst: lipid_spec_dct[lipid_sub_lst] + } lipid_sub_lst = tuple([lipid_sub_lst]) - print('[STATUS] >>> Core #%i ==> ...... processing ......' % worker_count) + print( + "[STATUS] >>> Core #%i ==> ...... processing ......" + % worker_count + ) if len(list(lipid_sub_dct.keys())) > 0: - lipid_info_result = parallel_pool.apply_async(get_lipid_info, - args=(param_dct, usr_fa_df, _chk_info_df, - _chk_info_gp, lipid_sub_lst, - usr_weight_df, key_frag_dct, - lipid_sub_dct, xic_dct, - worker_count, - save_fig, os_typ, queue)) + lipid_info_result = parallel_pool.apply_async( + get_lipid_info, + args=( + param_dct, + usr_fa_df, + _chk_info_df, + _chk_info_gp, + lipid_sub_lst, + usr_weight_df, + key_frag_dct, + lipid_sub_dct, + xic_dct, + worker_count, + save_fig, + os_typ, + queue, + ), + ) lipid_info_results_lst.append(lipid_info_result) worker_count += 1 @@ -927,19 +1246,39 @@ def huntlipids(param_dct: dict, error_lst: list, lipid_sub_lst = [x for x in lipid_sub_lst if x is not None] else: pass - if isinstance(lipid_sub_lst[0], tuple) or isinstance(lipid_sub_lst[0], list): - lipid_sub_dct = {k: lipid_spec_dct[k] for k in lipid_sub_lst} + if isinstance(lipid_sub_lst[0], tuple) or isinstance( + lipid_sub_lst[0], list + ): + lipid_sub_dct = { + k: lipid_spec_dct[k] for k in lipid_sub_lst + } else: - lipid_sub_dct = {lipid_sub_lst: lipid_spec_dct[lipid_sub_lst]} + lipid_sub_dct = { + lipid_sub_lst: lipid_spec_dct[lipid_sub_lst] + } lipid_sub_lst = tuple([lipid_sub_lst]) - print('[STATUS] >>> Core #%i ==> ...... processing ......' % worker_count) - job = multiprocessing.Process(target=get_lipid_info, args=(param_dct, usr_fa_df, - _chk_info_df, - _chk_info_gp, lipid_sub_lst, - usr_weight_df, key_frag_dct, - lipid_sub_dct, xic_dct, - worker_count, - save_fig, os_typ, queue)) + print( + "[STATUS] >>> Core #%i ==> ...... processing ......" + % worker_count + ) + job = multiprocessing.Process( + target=get_lipid_info, + args=( + param_dct, + usr_fa_df, + _chk_info_df, + _chk_info_gp, + lipid_sub_lst, + usr_weight_df, + key_frag_dct, + lipid_sub_dct, + xic_dct, + worker_count, + save_fig, + os_typ, + queue, + ), + ) worker_count += 1 jobs.append(job) @@ -954,7 +1293,7 @@ def huntlipids(param_dct: dict, error_lst: list, # TODO (georgia.angelidou@uni-leipzig.de): # need to change the following part. The differnt sections can be combine - if os_typ == 'windows': + if os_typ == "windows": try: tmp_lipid_info = lipid_info_result.get() # TODO (georgia.angelidou@uni-leipzig.de): can be avoided @@ -967,9 +1306,9 @@ def huntlipids(param_dct: dict, error_lst: list, # output_df = output_df.append(tmp_lipid_info[0]) # lipid_info_img_lst.extend(tmp_lipid_info[1]) except (KeyError, SystemError, ValueError, TypeError): - tmp_lipid_info_df = 'error' + tmp_lipid_info_df = "error" tmp_lipid_img_lst = [] - print('[ERROR] !!! This segment receive no Lipid identified.') + print("[ERROR] !!! This segment receive no Lipid identified.") else: # for linux try: tmp_lipid_info_df = lipid_info_result[0] @@ -982,9 +1321,9 @@ def huntlipids(param_dct: dict, error_lst: list, # lipid_info_img_lst.extend(lipid_info_result[1]) except (KeyError, SystemError, ValueError, TypeError): - tmp_lipid_info_df = 'error' + tmp_lipid_info_df = "error" tmp_lipid_img_lst = [] - print('[ERROR] !!! This segment receive no Lipid identified.') + print("[ERROR] !!! This segment receive no Lipid identified.") # TODO (georgia.angelidou@uni-leipzig.de): # when new section are activate all the below if/else statement cant go away @@ -996,14 +1335,16 @@ def huntlipids(param_dct: dict, error_lst: list, output_df = output_df.append(tmp_lipid_info_df) lipid_info_img_lst.extend(tmp_lipid_img_lst) if part_tot == 1: - print('[STATUS] >>> multiprocessing results merged') + print("[STATUS] >>> multiprocessing results merged") else: - print('[STATUS] >>> multiprocessing results merged ==> Part %i / %i ' - % (part_counter, part_tot)) + print( + "[STATUS] >>> multiprocessing results merged ==> Part %i / %i " + % (part_counter, part_tot) + ) part_counter += 1 else: - print('[INFO] --> Using single core mode...') + print("[INFO] --> Using single core mode...") for lipid_sub_key_lst in lipid_part_key_lst: for lipid_sub in lipid_sub_key_lst: if isinstance(lipid_sub, tuple) or isinstance(lipid_sub, list): @@ -1013,9 +1354,18 @@ def huntlipids(param_dct: dict, error_lst: list, _chk_info_gp = lipid_sub[2] worker_count = 1 - lipid_info_results_lst = get_lipid_info(param_dct, usr_fa_df, _chk_info_df, - _chk_info_gp, found_spec_key_lst, usr_weight_df, - key_frag_dct, lipid_spec_dct, xic_dct, worker_count) + lipid_info_results_lst = get_lipid_info( + param_dct, + usr_fa_df, + _chk_info_df, + _chk_info_gp, + found_spec_key_lst, + usr_weight_df, + key_frag_dct, + lipid_spec_dct, + xic_dct, + worker_count, + ) # TODO (georgia.angelidou@uni-leipzig.de): unnecessary declaration of values can be avoided tmp_lipid_info_df = lipid_info_results_lst[0] @@ -1026,65 +1376,160 @@ def huntlipids(param_dct: dict, error_lst: list, lipid_info_img_lst = tmp_lipid_img_lst # TODO (georgia.angelidou@uni-leipzig.de): code can change as below - print('[OUTPUT] ==> Generate the output table') + print("[OUTPUT] ==> Generate the output table") if isinstance(output_df, pd.DataFrame): - print('[INFO] --> Total number of records', output_df.shape[0]) + print("[INFO] --> Total number of records", output_df.shape[0]) if not output_df.empty: try: - output_df = output_df.sort_values(by=['Lib_mz', 'Bulk_identification', 'MS2_scan_time', 'RANK_SCORE'], - ascending=[True, True, True, False]) + output_df = output_df.sort_values( + by=["Lib_mz", "Bulk_identification", "MS2_scan_time", "RANK_SCORE"], + ascending=[True, True, True, False], + ) except KeyError: pass output_df.reset_index(drop=True, inplace=True) output_df.index += 1 - output_df.drop_duplicates(keep='first', inplace=True) + output_df.drop_duplicates(keep="first", inplace=True) output_header_lst = output_df.columns.values.tolist() # TODO (georgia.angeldou@uni-leipzig.de): Add the info for the DG - if usr_lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PIP', 'PS']: - output_list = ['FA1_[FA-H]-_i', 'FA2_[FA-H]-_i', '[LPL(FA1)-H]-_i', '[LPL(FA2)-H]-_i', - '[LPL(FA1)-H2O-H]-_i', '[LPL(FA2)-H2O-H]-_i'] - output_round_dct = {r'MS1_obs_mz': 4, r'Lib_mz': 4, 'ppm': 2, 'MS2_scan_time': 3, - 'i_fa1': 2, 'i_fa2': 2, 'i_[M-H]-fa1': 2, 'i_[M-H]-fa2': 2, - 'i_[M-H]-fa1-H2O': 2, 'i_[M-H]-fa2-H2O': 2 - } - - elif usr_lipid_class in ['LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPIP', 'LPS']: - output_list = ['FA1_[FA-H]-_i'] - output_round_dct = {r'MS1_obs_mz': 4, r'Lib_mz': 4, 'ppm': 2, 'MS2_scan_time': 3, - 'i_fa1': 2, 'i_fa2': 2, 'i_[M-H]-fa1': 2, 'i_[M-H]-fa2': 2, - 'i_[M-H]-fa1-H2O': 2, 'i_[M-H]-fa2-H2O': 2 - } - - elif usr_lipid_class in ['TG'] and usr_charge in ['[M+NH4]+', '[M+H]+']: - output_list = ['FA1_[FA-H2O+H]+_i', 'FA2_[FA-H2O+H]+_i', 'FA3_[FA-H2O+H]+_i', '[MG(FA1)-H2O+H]+_i', - '[MG(FA2)-H2O+H]+_i', '[MG(FA3)-H2O+H]+_i', '[M-(FA1)+H]+_i', '[M-(FA2)+H]+_i', - '[M-(FA3)+H]+_i'] - output_round_dct = {r'MS1_obs_mz': 4, r'Lib_mz': 4, 'ppm': 2, 'MS2_scan_time': 3, - 'i_fa1': 2, 'i_fa2': 2, 'i_fa3': 2, 'i_[M+H]-fa1': 2, 'i_[M+H]-fa2': 2, - 'i_[M+H]-fa3': 2, 'i_[MG(fa1)+H]-H2O': 2, 'i_[MG(fa2)+H]-H2O': 2, - 'i_[MG(fa3)+H]-H2O': 2} - elif usr_lipid_class in ['TG'] and usr_charge in ['[M+Na]+']: + if usr_lipid_class in ["PA", "PC", "PE", "PG", "PI", "PIP", "PS"]: + output_list = [ + "FA1_[FA-H]-_i", + "FA2_[FA-H]-_i", + "[LPL(FA1)-H]-_i", + "[LPL(FA2)-H]-_i", + "[LPL(FA1)-H2O-H]-_i", + "[LPL(FA2)-H2O-H]-_i", + ] + output_round_dct = { + r"MS1_obs_mz": 4, + r"Lib_mz": 4, + "ppm": 2, + "MS2_scan_time": 3, + "i_fa1": 2, + "i_fa2": 2, + "i_[M-H]-fa1": 2, + "i_[M-H]-fa2": 2, + "i_[M-H]-fa1-H2O": 2, + "i_[M-H]-fa2-H2O": 2, + } + + elif usr_lipid_class in ["LPA", "LPC", "LPE", "LPG", "LPI", "LPIP", "LPS"]: + output_list = ["FA1_[FA-H]-_i"] + output_round_dct = { + r"MS1_obs_mz": 4, + r"Lib_mz": 4, + "ppm": 2, + "MS2_scan_time": 3, + "i_fa1": 2, + "i_fa2": 2, + "i_[M-H]-fa1": 2, + "i_[M-H]-fa2": 2, + "i_[M-H]-fa1-H2O": 2, + "i_[M-H]-fa2-H2O": 2, + } + + elif usr_lipid_class in ["TG"] and usr_charge in ["[M+NH4]+", "[M+H]+"]: + output_list = [ + "FA1_[FA-H2O+H]+_i", + "FA2_[FA-H2O+H]+_i", + "FA3_[FA-H2O+H]+_i", + "[MG(FA1)-H2O+H]+_i", + "[MG(FA2)-H2O+H]+_i", + "[MG(FA3)-H2O+H]+_i", + "[M-(FA1)+H]+_i", + "[M-(FA2)+H]+_i", + "[M-(FA3)+H]+_i", + ] + output_round_dct = { + r"MS1_obs_mz": 4, + r"Lib_mz": 4, + "ppm": 2, + "MS2_scan_time": 3, + "i_fa1": 2, + "i_fa2": 2, + "i_fa3": 2, + "i_[M+H]-fa1": 2, + "i_[M+H]-fa2": 2, + "i_[M+H]-fa3": 2, + "i_[MG(fa1)+H]-H2O": 2, + "i_[MG(fa2)+H]-H2O": 2, + "i_[MG(fa3)+H]-H2O": 2, + } + elif usr_lipid_class in ["TG"] and usr_charge in ["[M+Na]+"]: # TODO (georgia.angelidou@uni-leipzig.de): check why this can cause some problems with [MGSN1-H2O+H]+ - output_list = ['FA1_[FA-H2O+H]+_i', 'FA2_[FA-H2O+H]+_i', 'FA3_[FA-H2O+H]+_i', '[MG(FA1)-H2O+H]+_i', - '[MG(FA2)-H2O+H]+_i', '[MG(FA3)-H2O+H]+_i', '[M-(FA1)+Na]+_i', '[M-(FA2)+Na]+_i', - '[M-(FA3)+Na]+_i', '[M-(FA1-H+Na)+N]+_i', '[M-(FA2-H+Na)+H]+_i'] - output_round_dct = {r'MS1_obs_mz': 4, r'lib_mz': 4, 'ppm': 2, 'MS2_scan_time': 3, 'i_fa1': 2, 'i_fa2': 2, - 'i_fa3': 2, 'i_[M+Na]-fa1': 2, 'i_[M+Na]-fa2': 2, 'i_[M+Na]-fa3': 2, - 'i_[M+H]-fa1-H+Na': 2, 'i_[M+H]-fa2-H+Na': 2, 'i_[M+H]-fa3-H+Na': 2} - elif usr_lipid_class in ['DG'] and usr_charge in ['[M+H]+', '[M+NH4]+', '[M+Na]+']: - output_list = ['FA1_[FA-H2O+H]+_i', 'FA2_[FA-H2O+H]+_i', '[MG(FA1)-H2O+H]+_i', - '[MG(FA2)-H2O+H]+_i'] - output_round_dct = {r'MS1_obs_mz': 4, r'Lib_mz': 4, 'ppm': 2, 'MS2_scan_time': 3, 'i_fa1': 2, 'i_fa2': 2, - 'i_[MG(fa1)+H]-H2O': 2, 'i_[MG(fa2)+H]-H2O': 2} + output_list = [ + "FA1_[FA-H2O+H]+_i", + "FA2_[FA-H2O+H]+_i", + "FA3_[FA-H2O+H]+_i", + "[MG(FA1)-H2O+H]+_i", + "[MG(FA2)-H2O+H]+_i", + "[MG(FA3)-H2O+H]+_i", + "[M-(FA1)+Na]+_i", + "[M-(FA2)+Na]+_i", + "[M-(FA3)+Na]+_i", + "[M-(FA1-H+Na)+N]+_i", + "[M-(FA2-H+Na)+H]+_i", + ] + output_round_dct = { + r"MS1_obs_mz": 4, + r"lib_mz": 4, + "ppm": 2, + "MS2_scan_time": 3, + "i_fa1": 2, + "i_fa2": 2, + "i_fa3": 2, + "i_[M+Na]-fa1": 2, + "i_[M+Na]-fa2": 2, + "i_[M+Na]-fa3": 2, + "i_[M+H]-fa1-H+Na": 2, + "i_[M+H]-fa2-H+Na": 2, + "i_[M+H]-fa3-H+Na": 2, + } + elif usr_lipid_class in ["DG"] and usr_charge in [ + "[M+H]+", + "[M+NH4]+", + "[M+Na]+", + ]: + output_list = [ + "FA1_[FA-H2O+H]+_i", + "FA2_[FA-H2O+H]+_i", + "[MG(FA1)-H2O+H]+_i", + "[MG(FA2)-H2O+H]+_i", + ] + output_round_dct = { + r"MS1_obs_mz": 4, + r"Lib_mz": 4, + "ppm": 2, + "MS2_scan_time": 3, + "i_fa1": 2, + "i_fa2": 2, + "i_[MG(fa1)+H]-H2O": 2, + "i_[MG(fa2)+H]-H2O": 2, + } else: - output_list = ['FA1_[FA-H]-_i', 'FA2_[FA-H]-_i', '[LPL(FA1)-H]-_i', '[LPL(FA2)-H]-_i', - '[LPL(FA1)-H2O-H]-_i', '[LPL(FA2)-H2O-H]-_i'] - output_round_dct = {r'MS1_obs_mz': 4, r'Lib_mz': 4, 'ppm': 2, 'MS2_scan_time': 3, - 'i_fa1': 2, 'i_fa2': 2, 'i_[M-H]-fa1': 2, 'i_[M-H]-fa2': 2, - 'i_[M-H]-fa1-H2O': 2, 'i_[M-H]-fa2-H2O': 2 - } + output_list = [ + "FA1_[FA-H]-_i", + "FA2_[FA-H]-_i", + "[LPL(FA1)-H]-_i", + "[LPL(FA2)-H]-_i", + "[LPL(FA1)-H2O-H]-_i", + "[LPL(FA2)-H2O-H]-_i", + ] + output_round_dct = { + r"MS1_obs_mz": 4, + r"Lib_mz": 4, + "ppm": 2, + "MS2_scan_time": 3, + "i_fa1": 2, + "i_fa2": 2, + "i_[M-H]-fa1": 2, + "i_[M-H]-fa2": 2, + "i_[M-H]-fa1-H2O": 2, + "i_[M-H]-fa2-H2O": 2, + } for _i_check in output_list: if _i_check not in output_header_lst: output_df[_i_check] = 0.0 @@ -1094,79 +1539,191 @@ def huntlipids(param_dct: dict, error_lst: list, output_round_dct[_t] = 2 output_df = output_df.round(output_round_dct) - output_df.rename(columns={'OBS_RESIDUES': '#Observed_FA'}, - inplace=True) - if usr_lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PIP', 'PS']: - output_short_lst = ['Proposed_structures', 'DISCRETE_ABBR', 'Formula_neutral', 'Formula_ion', 'Charge', - 'Lib_mz', 'ppm', 'ISOTOPE_SCORE', 'RANK_SCORE', - 'MS1_obs_mz', 'MS1_obs_i', r'MS2_PR_mz', 'MS2_scan_time', - 'DDA#', 'Scan#', '#Observed_FA', '#Specific_peaks', '#Unspecific_peaks', - 'FA1_[FA-H]-_i', 'FA2_[FA-H]-_i', - '[LPL(FA1)-H]-_i', '[LPL(FA2)-H]-_i', - '[LPL(FA1)-H2O-H]-_i', '[LPL(FA2)-H2O-H]-_i' - ] - elif usr_lipid_class in ['LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPIP', 'LPS']: - output_short_lst = ['Proposed_structures', 'DISCRETE_ABBR', 'Formula_neutral', 'Formula_ion', 'Charge', - 'Lib_mz', 'ppm', 'ISOTOPE_SCORE', 'RANK_SCORE', - 'MS1_obs_mz', 'MS1_obs_i', r'MS2_PR_mz', 'MS2_scan_time', - 'DDA#', 'Scan#', '#Observed_FA', '#Specific_peaks', '#Unspecific_peaks', - 'FA1_[FA-H]-_i', - ] - elif usr_lipid_class in ['TG'] and usr_charge in ['[M+H]+', '[M+NH4]+']: - output_short_lst = ['Proposed_structures', 'DISCRETE_ABBR', 'Formula_neutral', 'Formula_ion', 'Charge', - 'Lib_mz', 'ppm', 'ISOTOPE_SCORE', 'RANK_SCORE', - 'MS1_obs_mz', 'MS1_obs_i', r'MS2_PR_mz', 'MS2_scan_time', - 'DDA#', 'Scan#', '#Observed_FA', - '[M-(FA1)+H]+_i', '[M-(FA2)+H]+_i', '[M-(FA3)+H]+_i', - '[MG(FA1)-H2O+H]+_i', '[MG(FA2)-H2O+H]+_i', '[MG(FA3)-H2O+H]+_i', - 'FA1_[FA-H2O+H]+_i', 'FA2_[FA-H2O+H]+_i', 'FA3_[FA-H2O+H]+_i', - ] - elif usr_lipid_class in ['TG'] and usr_charge in ['[M+Na]+']: - output_short_lst = ['Proposed_structures', 'DISCRETE_ABBR', 'Formula_neutral', 'Formula_ion', 'Charge', - 'Lib_mz', 'ppm', 'ISOTOPE_SCORE', 'RANK_SCORE', - 'MS1_obs_mz', 'MS1_obs_i', r'MS2_PR_mz', 'MS2_scan_time', - 'DDA#', 'Scan#', '#Observed_FA', - '[M-(FA1)+Na]+_i', '[M-(FA2)+Na]+_i', '[M-(FA3)+Na]+_i', - '[MG(FA1)-H2O+H]+_i', '[MG(FA2)-H2O+H]+_i', '[MG(FA3)-H2O+H]+_i', - 'FA1_[FA-H2O+H]+_i', 'FA2_[FA-H2O+H]+_i', 'FA3_[FA-H2O+H]+_i' - ] - elif usr_lipid_class in ['DG'] and usr_charge in ['[M+H]+', '[M+NH4]+', '[M+Na]+']: - output_short_lst = ['Proposed_structures', 'DISCRETE_ABBR', 'Formula_neutral', 'Formula_ion', 'Charge', - 'Lib_mz', 'ppm', 'ISOTOPE_SCORE', 'RANK_SCORE', - 'MS1_obs_mz', 'MS1_obs_i', r'MS2_PR_mz', 'MS2_scan_time', - 'DDA#', 'Scan#', '#Observed_FA', - '[MG(FA1)-H2O+H]+_i', '[MG(FA2)-H2O+H]+_i', - 'FA1_[FA-H2O+H]+_i', 'FA2_[FA-H2O+H]+_i', - ] + output_df.rename(columns={"OBS_RESIDUES": "#Observed_FA"}, inplace=True) + if usr_lipid_class in ["PA", "PC", "PE", "PG", "PI", "PIP", "PS"]: + output_short_lst = [ + "Proposed_structures", + "DISCRETE_ABBR", + "Formula_neutral", + "Formula_ion", + "Charge", + "Lib_mz", + "ppm", + "ISOTOPE_SCORE", + "RANK_SCORE", + "MS1_obs_mz", + "MS1_obs_i", + r"MS2_PR_mz", + "MS2_scan_time", + "DDA#", + "Scan#", + "#Observed_FA", + "#Specific_peaks", + "#Unspecific_peaks", + "FA1_[FA-H]-_i", + "FA2_[FA-H]-_i", + "[LPL(FA1)-H]-_i", + "[LPL(FA2)-H]-_i", + "[LPL(FA1)-H2O-H]-_i", + "[LPL(FA2)-H2O-H]-_i", + ] + elif usr_lipid_class in ["LPA", "LPC", "LPE", "LPG", "LPI", "LPIP", "LPS"]: + output_short_lst = [ + "Proposed_structures", + "DISCRETE_ABBR", + "Formula_neutral", + "Formula_ion", + "Charge", + "Lib_mz", + "ppm", + "ISOTOPE_SCORE", + "RANK_SCORE", + "MS1_obs_mz", + "MS1_obs_i", + r"MS2_PR_mz", + "MS2_scan_time", + "DDA#", + "Scan#", + "#Observed_FA", + "#Specific_peaks", + "#Unspecific_peaks", + "FA1_[FA-H]-_i", + ] + elif usr_lipid_class in ["TG"] and usr_charge in ["[M+H]+", "[M+NH4]+"]: + output_short_lst = [ + "Proposed_structures", + "DISCRETE_ABBR", + "Formula_neutral", + "Formula_ion", + "Charge", + "Lib_mz", + "ppm", + "ISOTOPE_SCORE", + "RANK_SCORE", + "MS1_obs_mz", + "MS1_obs_i", + r"MS2_PR_mz", + "MS2_scan_time", + "DDA#", + "Scan#", + "#Observed_FA", + "[M-(FA1)+H]+_i", + "[M-(FA2)+H]+_i", + "[M-(FA3)+H]+_i", + "[MG(FA1)-H2O+H]+_i", + "[MG(FA2)-H2O+H]+_i", + "[MG(FA3)-H2O+H]+_i", + "FA1_[FA-H2O+H]+_i", + "FA2_[FA-H2O+H]+_i", + "FA3_[FA-H2O+H]+_i", + ] + elif usr_lipid_class in ["TG"] and usr_charge in ["[M+Na]+"]: + output_short_lst = [ + "Proposed_structures", + "DISCRETE_ABBR", + "Formula_neutral", + "Formula_ion", + "Charge", + "Lib_mz", + "ppm", + "ISOTOPE_SCORE", + "RANK_SCORE", + "MS1_obs_mz", + "MS1_obs_i", + r"MS2_PR_mz", + "MS2_scan_time", + "DDA#", + "Scan#", + "#Observed_FA", + "[M-(FA1)+Na]+_i", + "[M-(FA2)+Na]+_i", + "[M-(FA3)+Na]+_i", + "[MG(FA1)-H2O+H]+_i", + "[MG(FA2)-H2O+H]+_i", + "[MG(FA3)-H2O+H]+_i", + "FA1_[FA-H2O+H]+_i", + "FA2_[FA-H2O+H]+_i", + "FA3_[FA-H2O+H]+_i", + ] + elif usr_lipid_class in ["DG"] and usr_charge in [ + "[M+H]+", + "[M+NH4]+", + "[M+Na]+", + ]: + output_short_lst = [ + "Proposed_structures", + "DISCRETE_ABBR", + "Formula_neutral", + "Formula_ion", + "Charge", + "Lib_mz", + "ppm", + "ISOTOPE_SCORE", + "RANK_SCORE", + "MS1_obs_mz", + "MS1_obs_i", + r"MS2_PR_mz", + "MS2_scan_time", + "DDA#", + "Scan#", + "#Observed_FA", + "[MG(FA1)-H2O+H]+_i", + "[MG(FA2)-H2O+H]+_i", + "FA1_[FA-H2O+H]+_i", + "FA2_[FA-H2O+H]+_i", + ] else: - output_short_lst = ['Proposed_structures', 'DISCRETE_ABBR', 'Formula_neutral', 'Formula_ion', 'Charge', - 'Lib_mz', 'ppm', 'ISOTOPE_SCORE', 'RANK_SCORE', - 'MS1_obs_mz', 'MS1_obs_i', r'MS2_PR_mz', 'MS2_scan_time', - 'DDA#', 'Scan#', '#Observed_FA', - ] + output_short_lst = [ + "Proposed_structures", + "DISCRETE_ABBR", + "Formula_neutral", + "Formula_ion", + "Charge", + "Lib_mz", + "ppm", + "ISOTOPE_SCORE", + "RANK_SCORE", + "MS1_obs_mz", + "MS1_obs_i", + r"MS2_PR_mz", + "MS2_scan_time", + "DDA#", + "Scan#", + "#Observed_FA", + ] # Make copy of selected list of columns from output_df to avoid pandas warnings final_output_df = output_df[output_short_lst] - final_output_df = final_output_df.sort_values(by=['MS1_obs_mz', 'MS2_scan_time', 'RANK_SCORE'], - ascending=[True, True, False]) + final_output_df = final_output_df.sort_values( + by=["MS1_obs_mz", "MS2_scan_time", "RANK_SCORE"], + ascending=[True, True, False], + ) final_output_df = final_output_df.reset_index(drop=True) final_output_df.index += 1 save_output(output_sum_xlsx, final_output_df) else: - error_lst.append('[Warning] NO Lipid identified in this file.\n!! Please check your settings !!') + error_lst.append( + "[Warning] NO Lipid identified in this file.\n!! Please check your settings !!" + ) tot_run_time = time.clock() - start_time - print('[WARNING] !!! This file got no Lipid identified.') - print('[STATUS] >>> Identification finished in %s sec <<<' % tot_run_time) + print("[WARNING] !!! This file got no Lipid identified.") + print("[STATUS] >>> Identification finished in %s sec <<<" % tot_run_time) return tot_run_time, error_lst, output_df # Reserved for the development to re-use the session if save_session is True: - hunt_save_path = os.path.join(output_folder, 'HunterData_%s.hunt' % hunter_start_time_str) - results_pickle_dct = {'param_dct': param_dct, 'output_df': output_df, - 'final_output_df': final_output_df, 'lipid_info_img_lst': lipid_info_img_lst} + hunt_save_path = os.path.join( + output_folder, "HunterData_%s.hunt" % hunter_start_time_str + ) + results_pickle_dct = { + "param_dct": param_dct, + "output_df": output_df, + "final_output_df": final_output_df, + "lipid_info_img_lst": lipid_info_img_lst, + } save_hunt(results_pickle_dct, hunt_save_path) - print('Hunter session saved as:', hunt_save_path) + print("Hunter session saved as:", hunt_save_path) else: pass @@ -1174,10 +1731,10 @@ def huntlipids(param_dct: dict, error_lst: list, if save_fig is True: gen_html_report(param_dct, output_df, lipid_info_img_lst) else: - print('[WARNING] !!! User skip image generation !!!!!!') - print('Time', time.clock(), start_time) + print("[WARNING] !!! User skip image generation !!!!!!") + print("Time", time.clock(), start_time) tot_run_time = time.clock() - start_time - print('[STATUS] >>> >>> >>> FINISHED in %s sec <<< <<< <<<' % tot_run_time) + print("[STATUS] >>> >>> >>> FINISHED in %s sec <<< <<< <<<" % tot_run_time) return tot_run_time, error_lst, output_df diff --git a/LibLipidHunter/IsotopeHunter.py b/LibLipidHunter/IsotopeHunter.py index 47bdd3c..efc0107 100644 --- a/LibLipidHunter/IsotopeHunter.py +++ b/LibLipidHunter/IsotopeHunter.py @@ -27,29 +27,42 @@ class IsotopeHunter(object): def __init__(self): # iupac '97 - self.periodic_table_dct = {'H': [(1.0078250321, 0.999885), (2.0141017780, 0.0001157)], - 'D': [(2.0141017780, 0.0001157)], - 'C': [(12.0, 0.9893), (13.0033548378, 0.0107)], - 'N': [(14.0030740052, 0.99632), (15.0001088984, 0.00368)], - 'O': [(15.9949146221, 0.99757), (16.99913150, 0.00038), (17.9991604, 0.00205)], - 'Na': [(22.98976967, 1.0)], - 'P': [(30.97376151, 1.0)], - 'S': [(31.97207069, 0.9493), (32.97145850, 0.0076), - (33.96786683, 0.0429), (35.96708088, 0.0002)], - 'K': [(38.9637069, 0.932581), (39.96399867, 0.000117), (40.96182597, 0.067302)], - } + self.periodic_table_dct = { + "H": [(1.0078250321, 0.999885), (2.0141017780, 0.0001157)], + "D": [(2.0141017780, 0.0001157)], + "C": [(12.0, 0.9893), (13.0033548378, 0.0107)], + "N": [(14.0030740052, 0.99632), (15.0001088984, 0.00368)], + "O": [ + (15.9949146221, 0.99757), + (16.99913150, 0.00038), + (17.9991604, 0.00205), + ], + "Na": [(22.98976967, 1.0)], + "P": [(30.97376151, 1.0)], + "S": [ + (31.97207069, 0.9493), + (32.97145850, 0.0076), + (33.96786683, 0.0429), + (35.96708088, 0.0002), + ], + "K": [ + (38.9637069, 0.932581), + (39.96399867, 0.000117), + (40.96182597, 0.067302), + ], + } def get_elements(self, formula): elem_dct = {} elem_key_lst = list(self.periodic_table_dct.keys()) - tmp_formula = formula.strip('+') - tmp_formula = tmp_formula.strip('-') + tmp_formula = formula.strip("+") + tmp_formula = tmp_formula.strip("-") - elem_lst = re.findall('[A-Z][a-z]*[0-9]*', formula) + elem_lst = re.findall("[A-Z][a-z]*[0-9]*", formula) for _e in range(0, len(elem_lst)): - _elem = re.findall('[A-Z][a-z]*', elem_lst[_e]) - _elem_count = re.findall('[0-9]+', elem_lst[_e]) + _elem = re.findall("[A-Z][a-z]*", elem_lst[_e]) + _elem_count = re.findall("[0-9]+", elem_lst[_e]) if len(_elem_count) == 0: _elem_count = 1 else: @@ -80,7 +93,7 @@ def get_isotope_mz(self, elem_dct, only_c=False, isotope_number=2): mono_mz = self.get_mono_mz(elem_dct) # consider C only - c_count = elem_dct['C'] + c_count = elem_dct["C"] delta_13c = 1.0033548378 ration_13c12c = 0.011 @@ -92,50 +105,60 @@ def get_isotope_mz(self, elem_dct, only_c=False, isotope_number=2): # calc distribution by selected algorithms if only_c is True: # consider C only --> binomial expansion 3x faster - isotope_pattern = stats.binom.pmf(list(range(0, isotope_number + 1)), c_count, ration_13c12c) + isotope_pattern = stats.binom.pmf( + list(range(0, isotope_number + 1)), c_count, ration_13c12c + ) else: try: # consider more elements --> binomial/polynomial and McLaurin expansion [doi:10.1038/nmeth.3393] - h_count = elem_dct['H'] - o_count = elem_dct['O'] + h_count = elem_dct["H"] + o_count = elem_dct["O"] c_ploy = Polynomial((0.9893, 0.0107)) h_ploy = Polynomial((0.999885, 0.0001157)) o_ploy = Polynomial((0.99757, 0.00038, 0.00205)) - isotope_pattern_calc = c_ploy ** c_count * h_ploy ** h_count * o_ploy ** o_count + isotope_pattern_calc = ( + c_ploy ** c_count * h_ploy ** h_count * o_ploy ** o_count + ) - if 'N' in list(elem_dct.keys()): - n_count = elem_dct['N'] + if "N" in list(elem_dct.keys()): + n_count = elem_dct["N"] if n_count > 0: n_ploy = Polynomial((0.99632, 0.00368)) isotope_pattern_calc *= n_ploy - if 'S' in list(elem_dct.keys()): - s_count = elem_dct['S'] + if "S" in list(elem_dct.keys()): + s_count = elem_dct["S"] if s_count > 0: s_ploy = Polynomial((0.9493, 0.0076, 0.0429, 0.0002)) isotope_pattern_calc *= s_ploy - if 'K' in list(elem_dct.keys()): - k_count = elem_dct['K'] + if "K" in list(elem_dct.keys()): + k_count = elem_dct["K"] if k_count > 0: k_ploy = Polynomial((0.932581, 0.000117, 0.067302)) isotope_pattern_calc *= k_ploy - isotope_pattern = list(isotope_pattern_calc.coef)[:isotope_number + 1] + isotope_pattern = list(isotope_pattern_calc.coef)[: isotope_number + 1] except ValueError: # print(_e) - print('[INFO] --> Too large to use full elements for isotope pattern ... ' - 'use 13C only mode for this compound...') + print( + "[INFO] --> Too large to use full elements for isotope pattern ... " + "use 13C only mode for this compound..." + ) # consider C only --> binomial expansion 3x faster - isotope_pattern = stats.binom.pmf(list(range(0, isotope_number + 1)), c_count, ration_13c12c) + isotope_pattern = stats.binom.pmf( + list(range(0, isotope_number + 1)), c_count, ration_13c12c + ) m0_i = isotope_pattern[0] isotope_pattern = [x / m0_i for x in isotope_pattern] - isotope_distribution_df = pd.DataFrame(data={'mz': isotope_mz_lst, 'ratio': isotope_pattern}) - isotope_distribution_df = isotope_distribution_df.round({'ratio': 2}) + isotope_distribution_df = pd.DataFrame( + data={"mz": isotope_mz_lst, "ratio": isotope_pattern} + ) + isotope_distribution_df = isotope_distribution_df.round({"ratio": 2}) return isotope_distribution_df @@ -153,14 +176,18 @@ def peak_top_checker(ms1_pr_mz, spec_df, core_count=1, ms1_precision=50e-6): top_precision = min(ms1_precision * 2, 500e-6) pr_delta = ms1_pr_mz * ms1_precision - ms_pr_df = spec_df.query('%f <= mz <= %f' % (ms1_pr_mz - pr_delta, ms1_pr_mz + pr_delta)) + ms_pr_df = spec_df.query( + "%f <= mz <= %f" % (ms1_pr_mz - pr_delta, ms1_pr_mz + pr_delta) + ) if not ms_pr_df.empty: - _i_df = ms_pr_df.sort_values(by='i', ascending=False) - pr_obs_i = _i_df['i'].values.tolist()[0] - pr_obs_mz = _i_df['mz'].values.tolist()[0] + _i_df = ms_pr_df.sort_values(by="i", ascending=False) + pr_obs_i = _i_df["i"].values.tolist()[0] + pr_obs_mz = _i_df["mz"].values.tolist()[0] top_delta = pr_obs_mz * top_precision - peak_top_df = spec_df.query('%f <= mz <= %f' % (ms1_pr_mz - top_delta, ms1_pr_mz + top_delta)) - top_obs_i = max(peak_top_df['i'].values.tolist()) + peak_top_df = spec_df.query( + "%f <= mz <= %f" % (ms1_pr_mz - top_delta, ms1_pr_mz + top_delta) + ) + top_obs_i = max(peak_top_df["i"].values.tolist()) else: pr_obs_i = 0 pr_obs_mz = 0 @@ -173,13 +200,25 @@ def peak_top_checker(ms1_pr_mz, spec_df, core_count=1, ms1_precision=50e-6): # '[PASSED]MS1 PR m/z {pr} is peak top in +/- {delta} m/z, PR i {obs_i}, max i {max_i}' # .format(pr=pr_obs_mz, delta=top_delta, obs_i=pr_obs_i, max_i=top_obs_i)) else: - print(core_count, - '[Warning] MS1 PR m/z {pr} is not peak top in +/- {delta} m/z, PR i {obs_i}, max i {max_i}' - .format(pr=pr_obs_mz, delta=top_delta, obs_i=pr_obs_i, max_i=top_obs_i)) + print( + core_count, + "[Warning] MS1 PR m/z {pr} is not peak top in +/- {delta} m/z, PR i {obs_i}, max i {max_i}".format( + pr=pr_obs_mz, delta=top_delta, obs_i=pr_obs_i, max_i=top_obs_i + ), + ) return peak_top, top_obs_i - def calc_isotope_score(self, isotope_pattern_df, spec_df, ms1_precision, ms1_pr_i, - core_count=1, deconv=[], mode='m', score_filter=75): + def calc_isotope_score( + self, + isotope_pattern_df, + spec_df, + ms1_precision, + ms1_pr_i, + core_count=1, + deconv=[], + mode="m", + score_filter=75, + ): isotope_checker_dct = {} isotope_score_delta = 0 @@ -200,32 +239,34 @@ def calc_isotope_score(self, isotope_pattern_df, spec_df, ms1_precision, ms1_pr_ _base_i = 0 # [M+0] has _i == 0 - _mz = _se['mz'] - _ratio = _se['ratio'] + _mz = _se["mz"] + _ratio = _se["ratio"] _mz_delta = _mz * ms1_precision - _i_df = spec_df.query('%f <= mz <= %f' % (_mz - _mz_delta, _mz + _mz_delta)) + _i_df = spec_df.query( + "%f <= mz <= %f" % (_mz - _mz_delta, _mz + _mz_delta) + ) if _i < 2: theo_i = ms1_pr_i * _ratio + _base_i else: theo_i = ms1_pr_i * _ratio - _i_info_dct = {'theo_mz': _mz, 'theo_i': theo_i, 'theo_ratio': _ratio} + _i_info_dct = {"theo_mz": _mz, "theo_i": theo_i, "theo_ratio": _ratio} if not _i_df.empty: - _i_df = _i_df.sort_values(by='i', ascending=False).head(1) - _i_max = _i_df['i'].max() - _mz_max = _i_df['mz'].max() - _i_info_dct['obs_i'] = _i_max - _i_info_dct['obs_mz'] = _mz_max + _i_df = _i_df.sort_values(by="i", ascending=False).head(1) + _i_max = _i_df["i"].max() + _mz_max = _i_df["mz"].max() + _i_info_dct["obs_i"] = _i_max + _i_info_dct["obs_mz"] = _mz_max else: _i_max = 0.0 - _i_info_dct['obs_i'] = 0 - _i_info_dct['obs_mz'] = 0 + _i_info_dct["obs_i"] = 0 + _i_info_dct["obs_mz"] = 0 theo_i_lst.append(theo_i) _i_r = _i_max / ms1_pr_i - _i_info_dct['obs_ratio'] = _i_r + _i_info_dct["obs_ratio"] = _i_r isotope_checker_dct[_i] = _i_info_dct if _i > 0: @@ -242,38 +283,70 @@ def calc_isotope_score(self, isotope_pattern_df, spec_df, ms1_precision, ms1_pr_ isotope_m1_score = 100 * (1 - isotope_m1_score_delta) try: - theo_pr_mz = isotope_checker_dct[0]['theo_mz'] - obs_pr_mz = isotope_checker_dct[0]['obs_mz'] - obs_pr_i = isotope_checker_dct[0]['obs_i'] + theo_pr_mz = isotope_checker_dct[0]["theo_mz"] + obs_pr_mz = isotope_checker_dct[0]["obs_mz"] + obs_pr_i = isotope_checker_dct[0]["obs_i"] except Exception as _e: - if mode == 'm': - print(core_count, '[Exception] !!! Cannot get Theoretical or observed PR m/z ...', _e) + if mode == "m": + print( + core_count, + "[Exception] !!! Cannot get Theoretical or observed PR m/z ...", + _e, + ) else: - print(core_count, '[Exception] !!! M+2 is NOT potential M+0 of M+2H ...', _e) + print( + core_count, + "[Exception] !!! M+2 is NOT potential M+0 of M+2H ...", + _e, + ) theo_pr_mz = 0 obs_pr_mz = 0 obs_pr_i = 0 - if mode == 'm': + if mode == "m": if score_filter > 0: - peak_top, top_obs_i = self.peak_top_checker(theo_pr_mz, spec_df, - core_count=core_count, ms1_precision=ms1_precision) + peak_top, top_obs_i = self.peak_top_checker( + theo_pr_mz, + spec_df, + core_count=core_count, + ms1_precision=ms1_precision, + ) if peak_top is True: - isotope_calc_dct = {'isotope_checker_dct': isotope_checker_dct, 'isotope_score': isotope_score, - 'isotope_m1_score': isotope_m1_score, 'theo_i_lst': theo_i_lst, - 'obs_pr_mz': obs_pr_mz, 'obs_pr_i': obs_pr_i} + isotope_calc_dct = { + "isotope_checker_dct": isotope_checker_dct, + "isotope_score": isotope_score, + "isotope_m1_score": isotope_m1_score, + "theo_i_lst": theo_i_lst, + "obs_pr_mz": obs_pr_mz, + "obs_pr_i": obs_pr_i, + } else: - isotope_calc_dct = {'isotope_checker_dct': {}, 'isotope_score': 0, - 'isotope_m1_score': 0, 'theo_i_lst': [], - 'obs_pr_mz': 0, 'obs_pr_i': 0} + isotope_calc_dct = { + "isotope_checker_dct": {}, + "isotope_score": 0, + "isotope_m1_score": 0, + "theo_i_lst": [], + "obs_pr_mz": 0, + "obs_pr_i": 0, + } else: - isotope_calc_dct = {'isotope_checker_dct': isotope_checker_dct, 'isotope_score': isotope_score, - 'isotope_m1_score': isotope_m1_score, 'theo_i_lst': theo_i_lst, - 'obs_pr_mz': obs_pr_mz, 'obs_pr_i': obs_pr_i} + isotope_calc_dct = { + "isotope_checker_dct": isotope_checker_dct, + "isotope_score": isotope_score, + "isotope_m1_score": isotope_m1_score, + "theo_i_lst": theo_i_lst, + "obs_pr_mz": obs_pr_mz, + "obs_pr_i": obs_pr_i, + } else: - isotope_calc_dct = {'isotope_checker_dct': isotope_checker_dct, 'isotope_score': isotope_score, - 'isotope_m1_score': isotope_m1_score, 'theo_i_lst': theo_i_lst, - 'obs_pr_mz': obs_pr_mz, 'obs_pr_i': obs_pr_i} + isotope_calc_dct = { + "isotope_checker_dct": isotope_checker_dct, + "isotope_score": isotope_score, + "isotope_m1_score": isotope_m1_score, + "theo_i_lst": theo_i_lst, + "obs_pr_mz": obs_pr_mz, + "obs_pr_i": obs_pr_i, + } # print('mode', mode) # print(isotope_calc_dct) @@ -295,31 +368,46 @@ def get_deconvolution(self, spec_df, mz_delta, base_i, elem_dct={}, only_c=False base_m2_i = 0 base_m3_i = 0 - m_pre1_isotope_pattern_df = self.get_isotope_mz(elem_dct, only_c=only_c, isotope_number=3) - m_pre1_mz = m_pre1_isotope_pattern_df.at[0, 'mz'] - pre_i_df = spec_df.query('%f <= mz <= %f' % - (m_pre1_mz - mz_delta, m_pre1_mz + mz_delta)) + m_pre1_isotope_pattern_df = self.get_isotope_mz( + elem_dct, only_c=only_c, isotope_number=3 + ) + m_pre1_mz = m_pre1_isotope_pattern_df.at[0, "mz"] + pre_i_df = spec_df.query( + "%f <= mz <= %f" % (m_pre1_mz - mz_delta, m_pre1_mz + mz_delta) + ) if not pre_i_df.empty: - max_m_pre1_i = pre_i_df['i'].max() + max_m_pre1_i = pre_i_df["i"].max() max_m_pre1_i -= base_i if max_m_pre1_i > 0: - base_m1_i += max_m_pre1_i * m_pre1_isotope_pattern_df.at[1, 'ratio'] - base_m2_i += max_m_pre1_i * m_pre1_isotope_pattern_df.at[2, 'ratio'] - base_m3_i += max_m_pre1_i * m_pre1_isotope_pattern_df.at[3, 'ratio'] + base_m1_i += max_m_pre1_i * m_pre1_isotope_pattern_df.at[1, "ratio"] + base_m2_i += max_m_pre1_i * m_pre1_isotope_pattern_df.at[2, "ratio"] + base_m3_i += max_m_pre1_i * m_pre1_isotope_pattern_df.at[3, "ratio"] return base_m1_i, base_m2_i, base_m3_i - def get_isotope_score(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_count, - ms1_precision=50e-6, only_c=False, score_filter=75, decon=True, exp_mode='LC-MS', - isotope_number=2, pattern_tolerance=5): + def get_isotope_score( + self, + ms1_pr_mz, + ms1_pr_i, + formula, + spec_df, + core_count, + ms1_precision=50e-6, + only_c=False, + score_filter=75, + decon=True, + exp_mode="LC-MS", + isotope_number=2, + pattern_tolerance=5, + ): mz_delta = ms1_pr_mz * ms1_precision delta_13c = 1.0033548378 obs_pr_mz = 0 obs_pr_i = 0 - if exp_mode == 'Shotgun': + if exp_mode == "Shotgun": pseudo_pr_check = 0 else: pseudo_pr_check = 1 @@ -327,16 +415,22 @@ def get_isotope_score(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_count, if decon is True: deconv_elem_dct = self.get_elements(formula) # M-2 - deconv_elem_dct['H'] += -2 + deconv_elem_dct["H"] += -2 base_i = 0 - pre2_base_m1_i, pre2_base_m2_i, pre2_base_m3_i = self.get_deconvolution(spec_df, mz_delta, base_i, - deconv_elem_dct, only_c=only_c) + pre2_base_m1_i, pre2_base_m2_i, pre2_base_m3_i = self.get_deconvolution( + spec_df, mz_delta, base_i, deconv_elem_dct, only_c=only_c + ) # M+0 # m0_base_abs = pre2_base_m2_i + pre1_base_m1_i m0_base_abs = pre2_base_m2_i - base_m1_i, base_m2_i, base_m3_i = self.get_deconvolution(spec_df, mz_delta, m0_base_abs, - self.get_elements(formula), only_c=only_c) + base_m1_i, base_m2_i, base_m3_i = self.get_deconvolution( + spec_df, + mz_delta, + m0_base_abs, + self.get_elements(formula), + only_c=only_c, + ) # M+1 m1_base_abs = pre2_base_m3_i @@ -357,12 +451,19 @@ def get_isotope_score(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_count, deconv_lst = [m0_base_abs, m1_base_abs, m2_base_abs, m3_base_abs] - i_df = spec_df.query('%f <= mz <= %f' % (ms1_pr_mz - delta_13c - mz_delta, ms1_pr_mz - delta_13c + mz_delta)) + i_df = spec_df.query( + "%f <= mz <= %f" + % (ms1_pr_mz - delta_13c - mz_delta, ms1_pr_mz - delta_13c + mz_delta) + ) if not i_df.empty: - max_pre_m_i = i_df['i'].max() - peak_top, top_obs_i = self.peak_top_checker(ms1_pr_mz - delta_13c, spec_df, - core_count=core_count, ms1_precision=ms1_precision) + max_pre_m_i = i_df["i"].max() + peak_top, top_obs_i = self.peak_top_checker( + ms1_pr_mz - delta_13c, + spec_df, + core_count=core_count, + ms1_precision=ms1_precision, + ) if peak_top is True: pass else: @@ -374,50 +475,75 @@ def get_isotope_score(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_count, if ms1_pr_i > max_pre_m_i or pseudo_pr_check == 0: elem_dct = self.get_elements(formula) mono_mz = self.get_mono_mz(elem_dct) - pr_range_top, range_top_obs_i = self.peak_top_checker(ms1_pr_mz, spec_df, core_count=core_count, - ms1_precision=ms1_precision * 2.5) + pr_range_top, range_top_obs_i = self.peak_top_checker( + ms1_pr_mz, + spec_df, + core_count=core_count, + ms1_precision=ms1_precision * 2.5, + ) if pr_range_top and abs((ms1_pr_mz - mono_mz)) <= ms1_precision * ms1_pr_mz: isotope_pattern_df = self.get_isotope_mz(elem_dct, only_c=only_c) # print(isotope_pattern_df) ms1_pr_i -= m0_base_abs m0_deconv_lst = [m0_base_abs, m1_base_abs, m2_base_abs] - isotope_calc_dct = self.calc_isotope_score(isotope_pattern_df, spec_df, ms1_precision, ms1_pr_i, - core_count=core_count, deconv=m0_deconv_lst, mode='m', - score_filter=score_filter) - - isotope_checker_dct = isotope_calc_dct['isotope_checker_dct'] - isotope_score = isotope_calc_dct['isotope_score'] - isotope_m1_score = isotope_calc_dct['isotope_m1_score'] + isotope_calc_dct = self.calc_isotope_score( + isotope_pattern_df, + spec_df, + ms1_precision, + ms1_pr_i, + core_count=core_count, + deconv=m0_deconv_lst, + mode="m", + score_filter=score_filter, + ) + + isotope_checker_dct = isotope_calc_dct["isotope_checker_dct"] + isotope_score = isotope_calc_dct["isotope_score"] + isotope_m1_score = isotope_calc_dct["isotope_m1_score"] # m2_i = isotope_calc_dct['m2_i'] m2_checker_dct = {} m2_score = 0 - obs_pr_mz = isotope_calc_dct['obs_pr_mz'] - obs_pr_i = isotope_calc_dct['obs_pr_i'] + obs_pr_mz = isotope_calc_dct["obs_pr_mz"] + obs_pr_i = isotope_calc_dct["obs_pr_i"] if isotope_score <= score_filter <= isotope_m1_score: - print(core_count, '[INFO] --> check if M+2 is potential M+0 of M+2H ...') + print( + core_count, + "[INFO] --> check if M+2 is potential M+0 of M+2H ...", + ) # check if M+2 is potential M+0 of M+2H # M+H2 elements - m2_elem_dct = self.get_elements(formula + 'H2') - m2_isotope_pattern_df = self.get_isotope_mz(m2_elem_dct, only_c=only_c) + m2_elem_dct = self.get_elements(formula + "H2") + m2_isotope_pattern_df = self.get_isotope_mz( + m2_elem_dct, only_c=only_c + ) # get exact M+2 pr i, especially for ppm < 10 m2_mz_df = m2_isotope_pattern_df.head(1) - m2_mz = m2_mz_df['mz'].tolist()[0] - m2_i_df = spec_df.query('%f <= mz <= %f' % (m2_mz * (1 - ms1_precision), - m2_mz * (1 + ms1_precision))) - m2_i = m2_i_df['i'].max() + m2_mz = m2_mz_df["mz"].tolist()[0] + m2_i_df = spec_df.query( + "%f <= mz <= %f" + % (m2_mz * (1 - ms1_precision), m2_mz * (1 + ms1_precision)) + ) + m2_i = m2_i_df["i"].max() m2_i -= m2_base_abs m2_deconv_lst = [m2_base_abs, m3_base_abs, 0] - m2_calc_dct = self.calc_isotope_score(m2_isotope_pattern_df, spec_df, ms1_precision, m2_i, - core_count=core_count, deconv=m2_deconv_lst, mode='m+2', - score_filter=score_filter) - - m2_checker_dct = m2_calc_dct['isotope_checker_dct'] + m2_calc_dct = self.calc_isotope_score( + m2_isotope_pattern_df, + spec_df, + ms1_precision, + m2_i, + core_count=core_count, + deconv=m2_deconv_lst, + mode="m+2", + score_filter=score_filter, + ) + + m2_checker_dct = m2_calc_dct["isotope_checker_dct"] # use M+1 only - m2_score = m2_calc_dct['isotope_m1_score'] + m2_score = m2_calc_dct["isotope_m1_score"] # m2_m2i = m2_calc_dct['m2_i'] if m2_score > 0: @@ -428,60 +554,94 @@ def get_isotope_score(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_count, if 2 in list(m2_checker_dct.keys()): del m2_checker_dct[2] - if m2_score >= max(score_filter * 0.75, 60): # set lower filter for M+2H - print(core_count, '[INFO] --> M+2 ~ M+4 has isotope score for [M+H2]: %.1f' % m2_score) + if m2_score >= max( + score_filter * 0.75, 60 + ): # set lower filter for M+2H + print( + core_count, + "[INFO] --> M+2 ~ M+4 has isotope score for [M+H2]: %.1f" + % m2_score, + ) isotope_score = isotope_m1_score - del isotope_checker_dct[2]['obs_i'] - del isotope_checker_dct[2]['obs_mz'] + del isotope_checker_dct[2]["obs_i"] + del isotope_checker_dct[2]["obs_mz"] else: - print(core_count, '[WARNING] !!! M+2 ~ M+4 has isotope score for [M+H2]: %.1f' % m2_score) + print( + core_count, + "[WARNING] !!! M+2 ~ M+4 has isotope score for [M+H2]: %.1f" + % m2_score, + ) isotope_score = isotope_m1_score m2_checker_dct = {} m2_score = 0 - del isotope_checker_dct[2]['obs_i'] - del isotope_checker_dct[2]['obs_mz'] + del isotope_checker_dct[2]["obs_i"] + del isotope_checker_dct[2]["obs_mz"] else: - print(core_count, '[WARNING] !!! MS1 PR m/z not fit to Formula check bulk identification !!!') + print( + core_count, + "[WARNING] !!! MS1 PR m/z not fit to Formula check bulk identification !!!", + ) isotope_score = 0 isotope_checker_dct = {} m2_checker_dct = {} m2_score = 0 else: - print(core_count, '[WARNING] !!! MS1 PR is an isotope !!!') + print(core_count, "[WARNING] !!! MS1 PR is an isotope !!!") isotope_score = 0 isotope_checker_dct = {} m2_checker_dct = {} m2_score = 0 - isotope_score_info_dct = {'isotope_score': isotope_score, 'isotope_checker_dct': isotope_checker_dct, - 'm2_score': m2_score, 'm2_checker_dct': m2_checker_dct, - 'deconv_lst': deconv_lst, 'obs_pr_mz': obs_pr_mz, 'obs_pr_i': obs_pr_i} + isotope_score_info_dct = { + "isotope_score": isotope_score, + "isotope_checker_dct": isotope_checker_dct, + "m2_score": m2_score, + "m2_checker_dct": m2_checker_dct, + "deconv_lst": deconv_lst, + "obs_pr_mz": obs_pr_mz, + "obs_pr_i": obs_pr_i, + } return isotope_score_info_dct - def get_isotope_fragments(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_count, - ms1_precision=50e-6, only_c=False, - decon=True, exp_mode='LC-MS'): + def get_isotope_fragments( + self, + ms1_pr_mz, + ms1_pr_i, + formula, + spec_df, + core_count, + ms1_precision=50e-6, + only_c=False, + decon=True, + exp_mode="LC-MS", + ): # TODO (georgia.angelidou@uni-leipzig.de): Need to check the reason why we do not get any output mz_delta = ms1_pr_mz * ms1_precision delta_13c = 1.0033548378 - if exp_mode == 'Shotgun': + if exp_mode == "Shotgun": pseudo_pr_check = 0 else: pseudo_pr_check = 1 if decon is True: deconv_elem_dct = self.get_elements(formula) - deconv_elem_dct['H'] += -2 + deconv_elem_dct["H"] += -2 base_i = 0 - pre2_base_m1_i, pre2_base_m2_i, pre2_base_m3_i = self.get_deconvolution(spec_df, mz_delta, base_i, - deconv_elem_dct, only_c=only_c) + pre2_base_m1_i, pre2_base_m2_i, pre2_base_m3_i = self.get_deconvolution( + spec_df, mz_delta, base_i, deconv_elem_dct, only_c=only_c + ) m0_base_abs = pre2_base_m2_i - base_m1_i, base_m2_i, base_m3_i = self.get_deconvolution(spec_df, mz_delta, m0_base_abs, - self.get_elements(formula), only_c=only_c) + base_m1_i, base_m2_i, base_m3_i = self.get_deconvolution( + spec_df, + mz_delta, + m0_base_abs, + self.get_elements(formula), + only_c=only_c, + ) m1_base_abs = pre2_base_m3_i @@ -491,9 +651,12 @@ def get_isotope_fragments(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_coun # M+3 m3_base_abs = base_m3_i - print(core_count, '[INFO] --> Deconvolution_i_abs_corrections: ' - '[M+0] %.1f, [M+1] %.1f, [M+2] %.1f, [M+3] %.1f' - % (m0_base_abs, m1_base_abs, m2_base_abs, m3_base_abs)) + print( + core_count, + "[INFO] --> Deconvolution_i_abs_corrections: " + "[M+0] %.1f, [M+1] %.1f, [M+2] %.1f, [M+3] %.1f" + % (m0_base_abs, m1_base_abs, m2_base_abs, m3_base_abs), + ) deconv_lst = [m0_base_abs, m1_base_abs, m2_base_abs, m3_base_abs] else: @@ -504,10 +667,13 @@ def get_isotope_fragments(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_coun deconv_lst = [m0_base_abs, m1_base_abs, m2_base_abs, m3_base_abs] - i_df = spec_df.query('%f <= mz <= %f' % (ms1_pr_mz - delta_13c - mz_delta, ms1_pr_mz - delta_13c + mz_delta)) + i_df = spec_df.query( + "%f <= mz <= %f" + % (ms1_pr_mz - delta_13c - mz_delta, ms1_pr_mz - delta_13c + mz_delta) + ) isotope_flag = 0 if not i_df.empty: - max_pre_m_i = i_df['i'].max() + max_pre_m_i = i_df["i"].max() if ms1_pr_i > max_pre_m_i or pseudo_pr_check == 0: elem_dct = self.get_elements(formula) @@ -515,34 +681,52 @@ def get_isotope_fragments(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_coun if abs((ms1_pr_mz - mono_mz)) <= ms1_precision * ms1_pr_mz: isotope_flag = 0 else: - print('[WARNING] !!! MS1 PR m/z not fit to Formula check bulk identification !!!') + print( + "[WARNING] !!! MS1 PR m/z not fit to Formula check bulk identification !!!" + ) else: - print('[WARNING] !!! MS1 PR is an isotope !!!') + print("[WARNING] !!! MS1 PR is an isotope !!!") isotope_flag = 1 else: pass return isotope_flag - def get_isotope_fragments_sec(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_count, ms1_precision=50e-6, - only_c=False, decon=True, exp_mode='LC-MS'): + def get_isotope_fragments_sec( + self, + ms1_pr_mz, + ms1_pr_i, + formula, + spec_df, + core_count, + ms1_precision=50e-6, + only_c=False, + decon=True, + exp_mode="LC-MS", + ): mz_delta = ms1_pr_mz * ms1_precision delta_13c = 1.0033548378 - if exp_mode == 'Shotgun': + if exp_mode == "Shotgun": pseudo_pr_check = 0 else: pseudo_pr_check = 1 if decon is True: deconv_elem_dct = self.get_elements(formula) - deconv_elem_dct['H'] += -2 + deconv_elem_dct["H"] += -2 base_i = 0 - pre2_base_m1_i, pre2_base_m2_i, pre2_base_m3_i = self.get_deconvolution(spec_df, mz_delta, base_i, - deconv_elem_dct, only_c=only_c) + pre2_base_m1_i, pre2_base_m2_i, pre2_base_m3_i = self.get_deconvolution( + spec_df, mz_delta, base_i, deconv_elem_dct, only_c=only_c + ) m0_base_abs = pre2_base_m2_i - base_m1_i, base_m2_i, base_m3_i = self.get_deconvolution(spec_df, mz_delta, m0_base_abs, - self.get_elements(formula), only_c=only_c) + base_m1_i, base_m2_i, base_m3_i = self.get_deconvolution( + spec_df, + mz_delta, + m0_base_abs, + self.get_elements(formula), + only_c=only_c, + ) m1_base_abs = pre2_base_m3_i @@ -552,9 +736,12 @@ def get_isotope_fragments_sec(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_ # M+3 m3_base_abs = base_m3_i - print(core_count, '[INFO] --> Deconvolution_i_abs_corrections: ' - '[M+0] %.1f, [M+1] %.1f, [M+2] %.1f, [M+3] %.1f' - % (m0_base_abs, m1_base_abs, m2_base_abs, m3_base_abs)) + print( + core_count, + "[INFO] --> Deconvolution_i_abs_corrections: " + "[M+0] %.1f, [M+1] %.1f, [M+2] %.1f, [M+3] %.1f" + % (m0_base_abs, m1_base_abs, m2_base_abs, m3_base_abs), + ) deconv_lst = [m0_base_abs, m1_base_abs, m2_base_abs, m3_base_abs] else: @@ -565,10 +752,13 @@ def get_isotope_fragments_sec(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_ deconv_lst = [m0_base_abs, m1_base_abs, m2_base_abs, m3_base_abs] - i_df = spec_df.query('%f <= mz <= %f' % (ms1_pr_mz - delta_13c - mz_delta, ms1_pr_mz - delta_13c + mz_delta)) + i_df = spec_df.query( + "%f <= mz <= %f" + % (ms1_pr_mz - delta_13c - mz_delta, ms1_pr_mz - delta_13c + mz_delta) + ) isotope_flag = 0 if not i_df.empty: - max_pre_m_i = i_df['i'].max() + max_pre_m_i = i_df["i"].max() if ms1_pr_i > max_pre_m_i or pseudo_pr_check == 0: elem_dct = self.get_elements(formula) @@ -576,16 +766,19 @@ def get_isotope_fragments_sec(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_ if abs((ms1_pr_mz - mono_mz)) <= ms1_precision * ms1_pr_mz: isotope_flag = 0 else: - print(core_count, '[WARNING] !!! MS1 PR m/z not fit to Formula check bulk identification !!!') + print( + core_count, + "[WARNING] !!! MS1 PR m/z not fit to Formula check bulk identification !!!", + ) else: - print(core_count, '[WARNING] !!! MS1 PR is an isotope !!!') + print(core_count, "[WARNING] !!! MS1 PR is an isotope !!!") isotope_flag = 1 else: pass return isotope_flag -if __name__ == '__main__': +if __name__ == "__main__": # f = 'C39H67NO8P' # PE(34:5) # f_lst = [f, f + 'K', f + 'Na', f + 'NH4', f + 'S', f + 'D'] # usr_spec_df = pd.DataFrame() @@ -597,7 +790,7 @@ def get_isotope_fragments_sec(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_ # print(isotope_pattern_dct) # f = 'C41H71NO7P' # PE - f = 'C51H92O6Na' + f = "C51H92O6Na" # f_lst = [f, f + 'H+'] f_lst = [f] usr_spec_df = pd.DataFrame() @@ -605,9 +798,11 @@ def get_isotope_fragments_sec(self, ms1_pr_mz, ms1_pr_i, formula, spec_df, core_ for _f in f_lst: print(_f) isotope_pattern_dct = iso_hunter.get_elements(_f) - isotope_distribute = iso_hunter.get_isotope_mz(isotope_pattern_dct, only_c=False) + isotope_distribute = iso_hunter.get_isotope_mz( + isotope_pattern_dct, only_c=False + ) print(isotope_distribute) isotope_distribute = iso_hunter.get_isotope_mz(isotope_pattern_dct, only_c=True) isotope_distribute = isotope_distribute.head(3) print(isotope_distribute) - print(isotope_distribute.at[0, 'mz']) + print(isotope_distribute.at[0, "mz"]) diff --git a/LibLipidHunter/LipidComposer.py b/LibLipidHunter/LipidComposer.py index 0a4abaf..24bd6f4 100644 --- a/LibLipidHunter/LipidComposer.py +++ b/LibLipidHunter/LipidComposer.py @@ -39,34 +39,44 @@ def __init__(self): """ Default parameters for the elemental compositions """ - pa_hg_elem = {'C': 0, 'H': 3, 'O': 4, 'P': 1, 'N': 0} - pc_hg_elem = {'C': 5, 'H': 14, 'O': 4, 'P': 1, 'N': 1} - pe_hg_elem = {'C': 2, 'H': 8, 'O': 4, 'P': 1, 'N': 1} - pg_hg_elem = {'C': 3, 'H': 9, 'O': 6, 'P': 1, 'N': 0} - pi_hg_elem = {'C': 6, 'H': 13, 'O': 9, 'P': 1, 'N': 0} - pip_hg_elem = {'C': 6, 'H': 14, 'O': 12, 'P': 2, 'N': 0} - ps_hg_elem = {'C': 3, 'H': 8, 'O': 6, 'P': 1, 'N': 1} - tg_hg_elem = {'C': 0, 'H': 0, 'O': 0, 'P': 0, 'N': 0} + pa_hg_elem = {"C": 0, "H": 3, "O": 4, "P": 1, "N": 0} + pc_hg_elem = {"C": 5, "H": 14, "O": 4, "P": 1, "N": 1} + pe_hg_elem = {"C": 2, "H": 8, "O": 4, "P": 1, "N": 1} + pg_hg_elem = {"C": 3, "H": 9, "O": 6, "P": 1, "N": 0} + pi_hg_elem = {"C": 6, "H": 13, "O": 9, "P": 1, "N": 0} + pip_hg_elem = {"C": 6, "H": 14, "O": 12, "P": 2, "N": 0} + ps_hg_elem = {"C": 3, "H": 8, "O": 6, "P": 1, "N": 1} + tg_hg_elem = {"C": 0, "H": 0, "O": 0, "P": 0, "N": 0} # Todo: add SM corresponding HG sections around here - self.lipid_hg_lst = ['PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'PIP', 'TG'] - - self.lipid_hg_elem_dct = {'PA': pa_hg_elem, 'PC': pc_hg_elem, 'PE': pe_hg_elem, 'PG': pg_hg_elem, - 'PI': pi_hg_elem, 'PS': ps_hg_elem, 'PIP': pip_hg_elem, 'TG': tg_hg_elem, - 'DG': tg_hg_elem} - - self.glycerol_bone_elem_dct = {'C': 3, 'H': 2} - self.link_o_elem_dct = {'O': -1, 'H': 2} - self.link_p_elem_dct = {'O': -1} - self.elem_dct = {'H': [1.0078250321, 0.999885], - 'D': [2.0141017780, 0.0001157], - 'C': [12.0, 0.9893], - 'N': [14.0030740052, 0.99632], - 'O': [15.9949146221, 0.99757], - 'Na': [22.98976967, 1.0], - 'P': [30.97376151, 1.0], - 'S': [31.97207069, 0.9493], - 'K': [38.9637069, 0.932581]} + self.lipid_hg_lst = ["PA", "PC", "PE", "PG", "PI", "PS", "PIP", "TG"] + + self.lipid_hg_elem_dct = { + "PA": pa_hg_elem, + "PC": pc_hg_elem, + "PE": pe_hg_elem, + "PG": pg_hg_elem, + "PI": pi_hg_elem, + "PS": ps_hg_elem, + "PIP": pip_hg_elem, + "TG": tg_hg_elem, + "DG": tg_hg_elem, + } + + self.glycerol_bone_elem_dct = {"C": 3, "H": 2} + self.link_o_elem_dct = {"O": -1, "H": 2} + self.link_p_elem_dct = {"O": -1} + self.elem_dct = { + "H": [1.0078250321, 0.999885], + "D": [2.0141017780, 0.0001157], + "C": [12.0, 0.9893], + "N": [14.0030740052, 0.99632], + "O": [15.9949146221, 0.99757], + "Na": [22.98976967, 1.0], + "P": [30.97376151, 1.0], + "S": [31.97207069, 0.9493], + "K": [38.9637069, 0.932581], + } @staticmethod def calc_fa_df(lipid_class: str, fa_df: pd.DataFrame) -> List[List[str]]: @@ -84,63 +94,65 @@ def calc_fa_df(lipid_class: str, fa_df: pd.DataFrame) -> List[List[str]]: header_lst = fa_df.columns.values.tolist() - if lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PS']: - if 'PL' in header_lst and 'FATTYACID' in header_lst: + if lipid_class in ["PA", "PC", "PE", "PG", "PI", "PS"]: + if "PL" in header_lst and "FATTYACID" in header_lst: pl_fa1_df = fa_df.query('PL == "T" and FA1 == "T"') pl_fa2_df = fa_df.query('PL == "T" and FA2 == "T"') - pl_fa1_lst = pl_fa1_df['FATTYACID'].tolist() - pl_fa2_lst = pl_fa2_df['FATTYACID'].tolist() + pl_fa1_lst = pl_fa1_df["FATTYACID"].tolist() + pl_fa2_lst = pl_fa2_df["FATTYACID"].tolist() sn_units_lst = [pl_fa1_lst, pl_fa2_lst] - elif lipid_class in ['LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPS']: - if 'LPL' in header_lst and 'FATTYACID' in header_lst: + elif lipid_class in ["LPA", "LPC", "LPE", "LPG", "LPI", "LPS"]: + if "LPL" in header_lst and "FATTYACID" in header_lst: pl_fa1_df = fa_df.query('LPL == "T" and FA1 == "T"') - pl_fa1_lst = pl_fa1_df['FATTYACID'].tolist() - sn_units_lst = [pl_fa1_lst, ['']] - elif 'PL' in header_lst and 'FATTYACID' in header_lst: + pl_fa1_lst = pl_fa1_df["FATTYACID"].tolist() + sn_units_lst = [pl_fa1_lst, [""]] + elif "PL" in header_lst and "FATTYACID" in header_lst: pl_fa1_df = fa_df.query('PL == "T" and FA1 == "T"') - pl_fa1_lst = pl_fa1_df['FATTYACID'].tolist() - sn_units_lst = [pl_fa1_lst, ['']] + pl_fa1_lst = pl_fa1_df["FATTYACID"].tolist() + sn_units_lst = [pl_fa1_lst, [""]] - elif lipid_class in ['TG']: - if 'TG' in header_lst and 'FATTYACID' in header_lst: + elif lipid_class in ["TG"]: + if "TG" in header_lst and "FATTYACID" in header_lst: tg_fa1_df = fa_df.query('TG == "T" and FA1 == "T"') tg_fa2_df = fa_df.query('TG == "T" and FA2 == "T"') tg_fa3_df = fa_df.query('TG == "T" and FA3 == "T"') - tg_fa1_lst = tg_fa1_df['FATTYACID'].tolist() - tg_fa2_lst = tg_fa2_df['FATTYACID'].tolist() - tg_fa3_lst = tg_fa3_df['FATTYACID'].tolist() + tg_fa1_lst = tg_fa1_df["FATTYACID"].tolist() + tg_fa2_lst = tg_fa2_df["FATTYACID"].tolist() + tg_fa3_lst = tg_fa3_df["FATTYACID"].tolist() sn_units_lst = [tg_fa1_lst, tg_fa2_lst, tg_fa3_lst] - elif lipid_class in ['DG']: - if 'DG' in header_lst and 'FATTYACID' in header_lst: + elif lipid_class in ["DG"]: + if "DG" in header_lst and "FATTYACID" in header_lst: dg_fa1_df = fa_df.query('TG == "T" and FA1 == "T"') dg_fa2_df = fa_df.query('TG == "T" and FA2 == "T"') - dg_fa1_lst = dg_fa1_df['FATTYACID'].tolist() - dg_fa2_lst = dg_fa2_df['FATTYACID'].tolist() + dg_fa1_lst = dg_fa1_df["FATTYACID"].tolist() + dg_fa2_lst = dg_fa2_df["FATTYACID"].tolist() sn_units_lst = [dg_fa1_lst, dg_fa2_lst] - elif lipid_class in ['CL']: - if 'CL' in header_lst and 'FATTYACID' in header_lst: + elif lipid_class in ["CL"]: + if "CL" in header_lst and "FATTYACID" in header_lst: cl_fa1_df = fa_df.query('CL == "T" and FA1 == "T"') cl_fa2_df = fa_df.query('CL == "T" and FA2 == "T"') cl_fa3_df = fa_df.query('CL == "T" and FA3 == "T"') cl_fa4_df = fa_df.query('CL == "T" and FA4 == "T"') - cl_fa1_lst = cl_fa1_df['FATTYACID'].tolist() - cl_fa2_lst = cl_fa2_df['FATTYACID'].tolist() - cl_fa3_lst = cl_fa3_df['FATTYACID'].tolist() - cl_fa4_lst = cl_fa4_df['FATTYACID'].tolist() + cl_fa1_lst = cl_fa1_df["FATTYACID"].tolist() + cl_fa2_lst = cl_fa2_df["FATTYACID"].tolist() + cl_fa3_lst = cl_fa3_df["FATTYACID"].tolist() + cl_fa4_lst = cl_fa4_df["FATTYACID"].tolist() sn_units_lst = [cl_fa1_lst, cl_fa2_lst, cl_fa3_lst, cl_fa4_lst] return sn_units_lst - def calc_fa_query(self, lipid_class: str, fa_whitelist: str, ms2_ppm: int = 100) -> pd.DataFrame: + def calc_fa_query( + self, lipid_class: str, fa_whitelist: str, ms2_ppm: int = 100 + ) -> pd.DataFrame: """ Prepare all query strings for the MS/MS identification build all pandas query code in advance to save the time during identification @@ -154,25 +166,25 @@ def calc_fa_query(self, lipid_class: str, fa_whitelist: str, ms2_ppm: int = 100) """ usr_fa_df = pd.read_excel(fa_whitelist) - usr_fa_df = usr_fa_df.fillna(value='F') + usr_fa_df = usr_fa_df.fillna(value="F") tmp_columns = usr_fa_df.columns.tolist() usr_fa_df.columns = usr_fa_df.columns.str.upper() - if lipid_class in ['PL', 'PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'SM']: + if lipid_class in ["PL", "PA", "PC", "PE", "PG", "PI", "PS", "SM"]: if lipid_class in tmp_columns: pass - elif 'PL' in tmp_columns: + elif "PL" in tmp_columns: pass else: return False - elif lipid_class in ['LPL', 'LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPS']: + elif lipid_class in ["LPL", "LPA", "LPC", "LPE", "LPG", "LPI", "LPS"]: if lipid_class in tmp_columns: pass - elif 'LPL' in tmp_columns or 'PL' in tmp_columns: + elif "LPL" in tmp_columns or "PL" in tmp_columns: pass else: return False - elif lipid_class in ['TG', 'DG']: + elif lipid_class in ["TG", "DG"]: if lipid_class in tmp_columns: pass else: @@ -180,7 +192,9 @@ def calc_fa_query(self, lipid_class: str, fa_whitelist: str, ms2_ppm: int = 100) else: return False - sn_units_lst = self.calc_fa_df(lipid_class, usr_fa_df) # Return a list with list of the FA for each sn position + sn_units_lst = self.calc_fa_df( + lipid_class, usr_fa_df + ) # Return a list with list of the FA for each sn position fa_abbr_lst = [] # For PL lem(sn_units_lst) = 2 and for TG len(sn_units_lst) = 3 for _s in sn_units_lst: @@ -192,33 +206,50 @@ def calc_fa_query(self, lipid_class: str, fa_whitelist: str, ms2_ppm: int = 100) usr_fa_dct = {} for _fa_abbr in fa_abbr_lst: if _fa_abbr: - _fa_info_dct = abbr_parser.get_fa_info(_fa_abbr) # Calculate all the information for each FA - _lipid_formula, _lipid_elem_dct = elem_calc.get_formula(_fa_abbr) # get the elemental composition of FA + _fa_info_dct = abbr_parser.get_fa_info( + _fa_abbr + ) # Calculate all the information for each FA + _lipid_formula, _lipid_elem_dct = elem_calc.get_formula( + _fa_abbr + ) # get the elemental composition of FA # add the Abbr, formula and the exact mass in the dictionary - _fa_info_dct['ABBR'] = _fa_abbr - _fa_info_dct['FORMULA'] = _lipid_formula - _fa_info_dct['EXACTMASS'] = elem_calc.get_exactmass(_lipid_elem_dct) # Calc. the exact mass for each FA + _fa_info_dct["ABBR"] = _fa_abbr + _fa_info_dct["FORMULA"] = _lipid_formula + _fa_info_dct["EXACTMASS"] = elem_calc.get_exactmass( + _lipid_elem_dct + ) # Calc. the exact mass for each FA usr_fa_dct[_fa_abbr] = _fa_info_dct - usr_fa_df = pd.DataFrame(usr_fa_dct).T.copy() # put all the info for the FA in a dataframe + usr_fa_df = pd.DataFrame( + usr_fa_dct + ).T.copy() # put all the info for the FA in a dataframe # usr_fa_df.is_copy = False # create the queries for the FA fragments and MG - for _fa_ion in ['[FA-H]-', '[FA-H2O-H]-', '[FA-H2O+H]+']: - usr_fa_df['%s_MZ_LOW' % _fa_ion] = ppm_window_para(usr_fa_df['%s_MZ' % _fa_ion].values.tolist(), - ms2_ppm * -1) - usr_fa_df['%s_MZ_HIGH' % _fa_ion] = ppm_window_para(usr_fa_df['%s_MZ' % _fa_ion].values.tolist(), ms2_ppm) - usr_fa_df['%s_Q' % _fa_ion] = (usr_fa_df['%s_MZ_LOW' % _fa_ion].astype(str) + ' <= mz <= ' - + usr_fa_df['%s_MZ_HIGH' % _fa_ion].astype(str)) + for _fa_ion in ["[FA-H]-", "[FA-H2O-H]-", "[FA-H2O+H]+"]: + usr_fa_df["%s_MZ_LOW" % _fa_ion] = ppm_window_para( + usr_fa_df["%s_MZ" % _fa_ion].values.tolist(), ms2_ppm * -1 + ) + usr_fa_df["%s_MZ_HIGH" % _fa_ion] = ppm_window_para( + usr_fa_df["%s_MZ" % _fa_ion].values.tolist(), ms2_ppm + ) + usr_fa_df["%s_Q" % _fa_ion] = ( + usr_fa_df["%s_MZ_LOW" % _fa_ion].astype(str) + + " <= mz <= " + + usr_fa_df["%s_MZ_HIGH" % _fa_ion].astype(str) + ) # More specific fragments for PL - if lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'PIP']: + if lipid_class in ["PA", "PC", "PE", "PG", "PI", "PS", "PIP"]: # there alreadz the backbone of the stucture eg. for PE C5H10NO4P # for the [LPE(16:0)-H]- missing the exact mass of the FA # for the [LPE(16:0)-H2O-H]- we have the loss of water which already calculated in the structure # thats why addition of the FA but without of the water - lyso_type_dct = {'[L%s-H]-' % lipid_class: 'EXACTMASS', '[L%s-H2O-H]-' % lipid_class: '[FA-H2O]_MZ'} + lyso_type_dct = { + "[L%s-H]-" % lipid_class: "EXACTMASS", + "[L%s-H2O-H]-" % lipid_class: "[FA-H2O]_MZ", + } # backbone creation for the different PL lyso_base_elem_dct = self.lipid_hg_elem_dct[lipid_class] @@ -226,86 +257,147 @@ def calc_fa_query(self, lipid_class: str, fa_whitelist: str, ms2_ppm: int = 100) lyso_base_elem_dct[_e] += self.glycerol_bone_elem_dct[_e] # the element here is with no Hydroxyl on fa1 and fa2, here a [M-H]- is already considered - lyso_base_mz = elem_calc.get_exactmass(lyso_base_elem_dct) + 1.0078250321 + 15.9949146221 + lyso_base_mz = ( + elem_calc.get_exactmass(lyso_base_elem_dct) + + 1.0078250321 + + 15.9949146221 + ) # Todo: SM section - if lipid_class in ['PC', 'SM']: - lyso_base_mz -= (12.0 + 2 * 1.0078250321) # LPC loss one -CH3 from HG (one H already remove above) + if lipid_class in ["PC", "SM"]: + lyso_base_mz -= ( + 12.0 + 2 * 1.0078250321 + ) # LPC loss one -CH3 from HG (one H already remove above) for _lyso_ion in list(lyso_type_dct.keys()): - if lipid_class in ['PC', 'SM']: - - if lyso_type_dct[_lyso_ion] == 'EXACTMASS': - usr_fa_df['%s_ABBR' % _lyso_ion] = ('[L' + lipid_class + '(' + usr_fa_df['ABBR'].str.strip('FA') - + ')-CH3]-') - elif lyso_type_dct[_lyso_ion] == '[FA-H2O]_MZ': - usr_fa_df['%s_ABBR' % _lyso_ion] = ('[L' + lipid_class + '(' + usr_fa_df['ABBR'].str.strip('FA') - + ')-H2O-CH3]-') + if lipid_class in ["PC", "SM"]: + + if lyso_type_dct[_lyso_ion] == "EXACTMASS": + usr_fa_df["%s_ABBR" % _lyso_ion] = ( + "[L" + + lipid_class + + "(" + + usr_fa_df["ABBR"].str.strip("FA") + + ")-CH3]-" + ) + elif lyso_type_dct[_lyso_ion] == "[FA-H2O]_MZ": + usr_fa_df["%s_ABBR" % _lyso_ion] = ( + "[L" + + lipid_class + + "(" + + usr_fa_df["ABBR"].str.strip("FA") + + ")-H2O-CH3]-" + ) else: - usr_fa_df['%s_ABBR' % _lyso_ion] = 'ERROR' + usr_fa_df["%s_ABBR" % _lyso_ion] = "ERROR" else: - if lyso_type_dct[_lyso_ion] == 'EXACTMASS': - usr_fa_df['%s_ABBR' % _lyso_ion] = ('[L' + lipid_class + '(' + usr_fa_df['ABBR'].str.strip('FA') - + ')-H]-') - elif lyso_type_dct[_lyso_ion] == '[FA-H2O]_MZ': - usr_fa_df['%s_ABBR' % _lyso_ion] = ('[L' + lipid_class + '(' + usr_fa_df['ABBR'].str.strip('FA') - + ')-H2O-H]-') + if lyso_type_dct[_lyso_ion] == "EXACTMASS": + usr_fa_df["%s_ABBR" % _lyso_ion] = ( + "[L" + + lipid_class + + "(" + + usr_fa_df["ABBR"].str.strip("FA") + + ")-H]-" + ) + elif lyso_type_dct[_lyso_ion] == "[FA-H2O]_MZ": + usr_fa_df["%s_ABBR" % _lyso_ion] = ( + "[L" + + lipid_class + + "(" + + usr_fa_df["ABBR"].str.strip("FA") + + ")-H2O-H]-" + ) else: - usr_fa_df['%s_ABBR' % _lyso_ion] = 'ERROR' - - usr_fa_df['%s_MZ' % _lyso_ion] = lyso_base_mz + usr_fa_df[lyso_type_dct[_lyso_ion]] - usr_fa_df['%s_MZ_LOW' % _lyso_ion] = ppm_window_para(usr_fa_df['%s_MZ' % _lyso_ion].values.tolist(), - ms2_ppm * -1) - usr_fa_df['%s_MZ_HIGH' % _lyso_ion] = ppm_window_para(usr_fa_df['%s_MZ' % _lyso_ion].values.tolist(), - ms2_ppm) - usr_fa_df['%s_Q' % _lyso_ion] = (usr_fa_df['%s_MZ_LOW' % _lyso_ion].astype(str) + ' <= mz <= ' - + usr_fa_df['%s_MZ_HIGH' % _lyso_ion].astype(str)) - elif lipid_class in ['TG']: + usr_fa_df["%s_ABBR" % _lyso_ion] = "ERROR" + + usr_fa_df["%s_MZ" % _lyso_ion] = ( + lyso_base_mz + usr_fa_df[lyso_type_dct[_lyso_ion]] + ) + usr_fa_df["%s_MZ_LOW" % _lyso_ion] = ppm_window_para( + usr_fa_df["%s_MZ" % _lyso_ion].values.tolist(), ms2_ppm * -1 + ) + usr_fa_df["%s_MZ_HIGH" % _lyso_ion] = ppm_window_para( + usr_fa_df["%s_MZ" % _lyso_ion].values.tolist(), ms2_ppm + ) + usr_fa_df["%s_Q" % _lyso_ion] = ( + usr_fa_df["%s_MZ_LOW" % _lyso_ion].astype(str) + + " <= mz <= " + + usr_fa_df["%s_MZ_HIGH" % _lyso_ion].astype(str) + ) + elif lipid_class in ["TG"]: # Cannot calculate the theoritical m/z values of the DG fragments sinc we calculate the loss of a FA # and we dont know the cobination of the remaining 2 # TODO(georgia.angelidou@uni-leipzig.de): create the section for theuniue fragments when there is TG - mg_type_dct = {'[MG-H2O+H]+': 'EXACTMASS'} + mg_type_dct = {"[MG-H2O+H]+": "EXACTMASS"} mg_base_elem_dct = self.lipid_hg_elem_dct[lipid_class] for _e in self.glycerol_bone_elem_dct.keys(): mg_base_elem_dct[_e] += self.glycerol_bone_elem_dct[_e] # Calculate the rest of monoglycerol after the neutral loss of 2 FA in protonated form (one without Water) - mg_base_elem_dct = elem_calc.get_exactmass(mg_base_elem_dct) + 15.9949146221 + (3 * 1.0078250321) + mg_base_elem_dct = ( + elem_calc.get_exactmass(mg_base_elem_dct) + + 15.9949146221 + + (3 * 1.0078250321) + ) for _mg_ion in mg_type_dct.keys(): - usr_fa_df['%s_ABBR' % _mg_ion] = ('[MG(' + usr_fa_df['ABBR'].str.strip('FA') + ')-H2O+H]+') - usr_fa_df['%s_MZ' % _mg_ion] = mg_base_elem_dct + usr_fa_df[mg_type_dct[_mg_ion]] - usr_fa_df['%s_MZ_LOW' % _mg_ion] = ppm_window_para(usr_fa_df['%s_MZ' % _mg_ion].values.tolist(), - ms2_ppm * -1) - usr_fa_df['%s_MZ_HIGH' % _mg_ion] = ppm_window_para(usr_fa_df['%s_MZ' % _mg_ion].values.tolist(), - ms2_ppm) - usr_fa_df['%s_Q' % _mg_ion] = (usr_fa_df['%s_MZ_LOW' % _mg_ion].astype(str) + ' <= mz <= ' + usr_fa_df[ - '%s_MZ_HIGH' % _mg_ion].astype(str)) - - elif lipid_class in ['DG']: - mg_type_dct = {'[MG-H2O+H]+': 'EXACTMASS'} + usr_fa_df["%s_ABBR" % _mg_ion] = ( + "[MG(" + usr_fa_df["ABBR"].str.strip("FA") + ")-H2O+H]+" + ) + usr_fa_df["%s_MZ" % _mg_ion] = ( + mg_base_elem_dct + usr_fa_df[mg_type_dct[_mg_ion]] + ) + usr_fa_df["%s_MZ_LOW" % _mg_ion] = ppm_window_para( + usr_fa_df["%s_MZ" % _mg_ion].values.tolist(), ms2_ppm * -1 + ) + usr_fa_df["%s_MZ_HIGH" % _mg_ion] = ppm_window_para( + usr_fa_df["%s_MZ" % _mg_ion].values.tolist(), ms2_ppm + ) + usr_fa_df["%s_Q" % _mg_ion] = ( + usr_fa_df["%s_MZ_LOW" % _mg_ion].astype(str) + + " <= mz <= " + + usr_fa_df["%s_MZ_HIGH" % _mg_ion].astype(str) + ) + + elif lipid_class in ["DG"]: + mg_type_dct = {"[MG-H2O+H]+": "EXACTMASS"} mg_base_elem_dct = self.lipid_hg_elem_dct[lipid_class] for _e in self.glycerol_bone_elem_dct.keys(): mg_base_elem_dct[_e] += self.glycerol_bone_elem_dct[_e] # Calculate the rest of monoglycerol after the neutral loss of 2 FA in protonated form (one without Water) - mg_base_elem_dct = elem_calc.get_exactmass(mg_base_elem_dct) + 15.9949146221 + (3 * 1.0078250321) + mg_base_elem_dct = ( + elem_calc.get_exactmass(mg_base_elem_dct) + + 15.9949146221 + + (3 * 1.0078250321) + ) for _mg_ion in mg_type_dct.keys(): - usr_fa_df['%s_ABBR' % _mg_ion] = ('[MG(' + usr_fa_df['ABBR'].str.strip('FA') + ')-H2O+H]+') - usr_fa_df['%s_MZ' % _mg_ion] = mg_base_elem_dct + usr_fa_df[mg_type_dct[_mg_ion]] - usr_fa_df['%s_MZ_LOW' % _mg_ion] = ppm_window_para(usr_fa_df['%s_MZ' % _mg_ion].values.tolist(), - ms2_ppm * -1) - usr_fa_df['%s_MZ_HIGH' % _mg_ion] = ppm_window_para(usr_fa_df['%s_MZ' % _mg_ion].values.tolist(), - ms2_ppm) - usr_fa_df['%s_Q' % _mg_ion] = (usr_fa_df['%s_MZ_LOW' % _mg_ion].astype(str) + ' <= mz <= ' + usr_fa_df[ - '%s_MZ_HIGH' % _mg_ion].astype(str)) + usr_fa_df["%s_ABBR" % _mg_ion] = ( + "[MG(" + usr_fa_df["ABBR"].str.strip("FA") + ")-H2O+H]+" + ) + usr_fa_df["%s_MZ" % _mg_ion] = ( + mg_base_elem_dct + usr_fa_df[mg_type_dct[_mg_ion]] + ) + usr_fa_df["%s_MZ_LOW" % _mg_ion] = ppm_window_para( + usr_fa_df["%s_MZ" % _mg_ion].values.tolist(), ms2_ppm * -1 + ) + usr_fa_df["%s_MZ_HIGH" % _mg_ion] = ppm_window_para( + usr_fa_df["%s_MZ" % _mg_ion].values.tolist(), ms2_ppm + ) + usr_fa_df["%s_Q" % _mg_ion] = ( + usr_fa_df["%s_MZ_LOW" % _mg_ion].astype(str) + + " <= mz <= " + + usr_fa_df["%s_MZ_HIGH" % _mg_ion].astype(str) + ) else: # Todo: SM section like above pass return usr_fa_df - def gen_all_comb(self, lipid_class: str, usr_fa_df: pd.DataFrame, position: bool = False) -> dict: + def gen_all_comb( + self, lipid_class: str, usr_fa_df: pd.DataFrame, position: bool = False + ) -> dict: """ Generate all possible FA combination of selected lipid class in discrete form without mirrored duplicates @@ -321,57 +413,81 @@ def gen_all_comb(self, lipid_class: str, usr_fa_df: pd.DataFrame, position: bool fa_units_lst = self.calc_fa_df(lipid_class, usr_fa_df) - if lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'DG', 'SM'] and len(fa_units_lst) == 2: + if ( + lipid_class in ["PA", "PC", "PE", "PG", "PI", "PS", "DG", "SM"] + and len(fa_units_lst) == 2 + ): fa_comb_lst = list(itertools.product(fa_units_lst[0], fa_units_lst[1])) - fa_df_header_lst = ['FA1', 'FA2'] + fa_df_header_lst = ["FA1", "FA2"] # lipid_template = '{}' - elif lipid_class in ['LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPS'] and len(fa_units_lst) == 2: + elif ( + lipid_class in ["LPA", "LPC", "LPE", "LPG", "LPI", "LPS"] + and len(fa_units_lst) == 2 + ): fa_comb_lst = list(itertools.product(fa_units_lst[0], fa_units_lst[1])) - fa_df_header_lst = ['FA1', 'FA2'] + fa_df_header_lst = ["FA1", "FA2"] # lipid_template = '{}' - elif lipid_class == 'TG' and len(fa_units_lst) == 3: - fa_comb_lst = list(itertools.product(fa_units_lst[0], fa_units_lst[1], fa_units_lst[2])) - fa_df_header_lst = ['FA1', 'FA2', 'FA3'] - elif lipid_class == 'CL' and len(fa_units_lst) == 4: - fa_comb_lst = list(itertools.product(fa_units_lst[0], fa_units_lst[1], fa_units_lst[2], fa_units_lst[3])) - fa_df_header_lst = ['FA1', 'FA2', 'FA3', 'FA4'] + elif lipid_class == "TG" and len(fa_units_lst) == 3: + fa_comb_lst = list( + itertools.product(fa_units_lst[0], fa_units_lst[1], fa_units_lst[2]) + ) + fa_df_header_lst = ["FA1", "FA2", "FA3"] + elif lipid_class == "CL" and len(fa_units_lst) == 4: + fa_comb_lst = list( + itertools.product( + fa_units_lst[0], fa_units_lst[1], fa_units_lst[2], fa_units_lst[3] + ) + ) + fa_df_header_lst = ["FA1", "FA2", "FA3", "FA4"] else: fa_comb_lst = [] fa_df_header_lst = [] fa_combo_df = pd.DataFrame(data=fa_comb_lst, columns=fa_df_header_lst) - fa_combo_df['CLASS'] = lipid_class + fa_combo_df["CLASS"] = lipid_class # Todo: check SM section below: - if lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'DG', 'SM']: + if lipid_class in ["PA", "PC", "PE", "PG", "PI", "PS", "DG", "SM"]: fa_combo_link_df = fa_combo_df.copy() # fa_combo_link_df.is_copy = False - fa_combo_link_df['LINK'] = fa_combo_link_df['FA1'].str[0:2] - fa_link_df = fa_combo_link_df[fa_combo_link_df['LINK'] == 'FA'].copy() + fa_combo_link_df["LINK"] = fa_combo_link_df["FA1"].str[0:2] + fa_link_df = fa_combo_link_df[fa_combo_link_df["LINK"] == "FA"].copy() # fa_link_df.is_copy = False - fa_link_df.drop(['LINK', 'CLASS'], axis=1, inplace=True) + fa_link_df.drop(["LINK", "CLASS"], axis=1, inplace=True) # fa_link_df.values.argsort(kind='mergesort') # fa_link_df.drop(columns=['CLASS'], inplace=True) - fa_link_df.values.sort(kind='mergesort') # safe sort by numpy - fa_link_df['CLASS'] = lipid_class - fa_link_df['DISCRETE_ABBR'] = (fa_link_df['CLASS'] + '(' + - fa_link_df['FA1'].str.strip('FA') + '_' + - fa_link_df['FA2'].str.strip('FA') + ')') - fa_link_df.sort_values(by='DISCRETE_ABBR', inplace=True) - - if lipid_class in ['PC', 'PE']: - op_link_df = fa_combo_link_df[(fa_combo_link_df['LINK'] == 'O-') - | (fa_combo_link_df['LINK'] == 'P-')].copy() + fa_link_df.values.sort(kind="mergesort") # safe sort by numpy + fa_link_df["CLASS"] = lipid_class + fa_link_df["DISCRETE_ABBR"] = ( + fa_link_df["CLASS"] + + "(" + + fa_link_df["FA1"].str.strip("FA") + + "_" + + fa_link_df["FA2"].str.strip("FA") + + ")" + ) + fa_link_df.sort_values(by="DISCRETE_ABBR", inplace=True) + + if lipid_class in ["PC", "PE"]: + op_link_df = fa_combo_link_df[ + (fa_combo_link_df["LINK"] == "O-") + | (fa_combo_link_df["LINK"] == "P-") + ].copy() if not op_link_df.empty: # op_link_df.is_copy = False - op_link_df.drop(['LINK'], axis=1, inplace=True) - op_link_df['DISCRETE_ABBR'] = (op_link_df['CLASS'] + '(' + - op_link_df['FA1'].str.strip('FA') + '_' + - op_link_df['FA2'].str.strip('FA') + ')') - op_link_df.sort_values(by='DISCRETE_ABBR', inplace=True) + op_link_df.drop(["LINK"], axis=1, inplace=True) + op_link_df["DISCRETE_ABBR"] = ( + op_link_df["CLASS"] + + "(" + + op_link_df["FA1"].str.strip("FA") + + "_" + + op_link_df["FA2"].str.strip("FA") + + ")" + ) + op_link_df.sort_values(by="DISCRETE_ABBR", inplace=True) fa_combo_df = fa_link_df.append(op_link_df) del op_link_df @@ -380,36 +496,46 @@ def gen_all_comb(self, lipid_class: str, usr_fa_df: pd.DataFrame, position: bool del fa_combo_link_df del fa_link_df - print('[INFO] --> Number of predicted lipids (exact position): ', fa_combo_df.shape[0]) + print( + "[INFO] --> Number of predicted lipids (exact position): ", + fa_combo_df.shape[0], + ) - elif lipid_class in ['LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPS']: + elif lipid_class in ["LPA", "LPC", "LPE", "LPG", "LPI", "LPS"]: fa_combo_link_df = fa_combo_df.copy() # fa_combo_link_df.is_copy = False - fa_combo_link_df['LINK'] = fa_combo_link_df['FA1'].str[0:2] - fa_link_df = fa_combo_link_df[fa_combo_link_df['LINK'] == 'FA'].copy() + fa_combo_link_df["LINK"] = fa_combo_link_df["FA1"].str[0:2] + fa_link_df = fa_combo_link_df[fa_combo_link_df["LINK"] == "FA"].copy() # fa_link_df.is_copy = False - fa_link_df.drop(['LINK', 'CLASS'], axis=1, inplace=True) + fa_link_df.drop(["LINK", "CLASS"], axis=1, inplace=True) # fa_link_df.values.argsort(kind='mergesort') # fa_link_df.drop(columns=['CLASS'], inplace=True) # fa_link_df.values.sort(kind='mergesort') # safe sort by numpy - fa_link_df['CLASS'] = lipid_class - - fa_link_df['DISCRETE_ABBR'] = (fa_link_df['CLASS'] + '(' + - fa_link_df['FA1'].str.strip('FA') + ')') - fa_link_df.sort_values(by='DISCRETE_ABBR', inplace=True) - - if lipid_class in ['LPC', 'LPE']: - op_link_df = fa_combo_link_df[(fa_combo_link_df['LINK'] == 'O-') - | (fa_combo_link_df['LINK'] == 'P-')].copy() + fa_link_df["CLASS"] = lipid_class + + fa_link_df["DISCRETE_ABBR"] = ( + fa_link_df["CLASS"] + "(" + fa_link_df["FA1"].str.strip("FA") + ")" + ) + fa_link_df.sort_values(by="DISCRETE_ABBR", inplace=True) + + if lipid_class in ["LPC", "LPE"]: + op_link_df = fa_combo_link_df[ + (fa_combo_link_df["LINK"] == "O-") + | (fa_combo_link_df["LINK"] == "P-") + ].copy() if not op_link_df.empty: # op_link_df.is_copy = False - op_link_df.drop(['LINK'], axis=1, inplace=True) - op_link_df['DISCRETE_ABBR'] = (op_link_df['CLASS'] + '(' + - op_link_df['FA1'].str.strip('FA') + ')') - op_link_df.sort_values(by='DISCRETE_ABBR', inplace=True) + op_link_df.drop(["LINK"], axis=1, inplace=True) + op_link_df["DISCRETE_ABBR"] = ( + op_link_df["CLASS"] + + "(" + + op_link_df["FA1"].str.strip("FA") + + ")" + ) + op_link_df.sort_values(by="DISCRETE_ABBR", inplace=True) fa_combo_df = fa_link_df.append(op_link_df) del op_link_df @@ -418,32 +544,48 @@ def gen_all_comb(self, lipid_class: str, usr_fa_df: pd.DataFrame, position: bool del fa_combo_link_df del fa_link_df - print('[INFO] --> Number of predicted lipids (exact position): ', fa_combo_df.shape[0]) + print( + "[INFO] --> Number of predicted lipids (exact position): ", + fa_combo_df.shape[0], + ) - elif lipid_class in ['TG']: + elif lipid_class in ["TG"]: fa_combo_link_df = fa_combo_df.copy() # fa_combo_link_df.is_copy = False - fa_combo_link_df['LINK'] = fa_combo_link_df['FA1'].str[0:2] - fa_link_df = fa_combo_link_df[fa_combo_link_df['LINK'] == 'FA'] + fa_combo_link_df["LINK"] = fa_combo_link_df["FA1"].str[0:2] + fa_link_df = fa_combo_link_df[fa_combo_link_df["LINK"] == "FA"] # fa_link_df.is_copy = False - fa_link_df.drop(['LINK'], axis=1, inplace=True) - fa_link_df.values.sort(kind='mergesort') # safe sort by numpy - fa_link_df['DISCRETE_ABBR'] = (fa_link_df['CLASS'] + '(' + - fa_link_df['FA1'].str.strip('FA') + '_' + - fa_link_df['FA2'].str.strip('FA') + '_' + - fa_link_df['FA3'].str.strip('FA') + ')') - fa_link_df.sort_values(by='DISCRETE_ABBR', inplace=True) - op_link_df = fa_combo_link_df[(fa_combo_link_df['LINK'] == 'O-') - | (fa_combo_link_df['LINK'] == 'P-')].copy() + fa_link_df.drop(["LINK"], axis=1, inplace=True) + fa_link_df.values.sort(kind="mergesort") # safe sort by numpy + fa_link_df["DISCRETE_ABBR"] = ( + fa_link_df["CLASS"] + + "(" + + fa_link_df["FA1"].str.strip("FA") + + "_" + + fa_link_df["FA2"].str.strip("FA") + + "_" + + fa_link_df["FA3"].str.strip("FA") + + ")" + ) + fa_link_df.sort_values(by="DISCRETE_ABBR", inplace=True) + op_link_df = fa_combo_link_df[ + (fa_combo_link_df["LINK"] == "O-") | (fa_combo_link_df["LINK"] == "P-") + ].copy() if not op_link_df.empty: # op_link_df.is_copy = False - op_link_df.drop(['LINK'], axis=1, inplace=True) - op_link_df['DISCRETE_ABBR'] = (op_link_df['CLASS'] + '(' + - op_link_df['FA1'].str.strip('FA') + '_' + - op_link_df['FA2'].str.strip('FA') + '_' + - op_link_df['FA3'].str.strip('FA') + ')') - op_link_df.sort_values(by='DISCRETE_ABBR', inplace=True) + op_link_df.drop(["LINK"], axis=1, inplace=True) + op_link_df["DISCRETE_ABBR"] = ( + op_link_df["CLASS"] + + "(" + + op_link_df["FA1"].str.strip("FA") + + "_" + + op_link_df["FA2"].str.strip("FA") + + "_" + + op_link_df["FA3"].str.strip("FA") + + ")" + ) + op_link_df.sort_values(by="DISCRETE_ABBR", inplace=True) fa_combo_df = fa_link_df.append(op_link_df) del op_link_df else: @@ -451,43 +593,64 @@ def gen_all_comb(self, lipid_class: str, usr_fa_df: pd.DataFrame, position: bool del fa_link_df del fa_combo_link_df - print('[INFO] --> Number of predicted lipids (exact position): ', fa_combo_df.shape[0]) - - elif lipid_class in ['CL']: - fa_combo_df.values.sort(kind='mergesort') # safe sort by numpy - print('[INFO] --> Number of predicted lipids (exact position): ', fa_combo_df.shape[0]) - fa_combo_df['DISCRETE_ABBR'] = (fa_combo_df['CLASS'] + '(' + - fa_combo_df['FA1'].str.strip('FA') + '_' + - fa_combo_df['FA2'].str.strip('FA') + '_' + - fa_combo_df['FA3'].str.strip('FA') + '_' + - fa_combo_df['FA4'].str.strip('FA') + ')') - fa_combo_df.sort_values(by='DISCRETE_ABBR', inplace=True) - print('[INFO] --> Number of predicted lipids (exact position): ', fa_combo_df.shape[0]) + print( + "[INFO] --> Number of predicted lipids (exact position): ", + fa_combo_df.shape[0], + ) + + elif lipid_class in ["CL"]: + fa_combo_df.values.sort(kind="mergesort") # safe sort by numpy + print( + "[INFO] --> Number of predicted lipids (exact position): ", + fa_combo_df.shape[0], + ) + fa_combo_df["DISCRETE_ABBR"] = ( + fa_combo_df["CLASS"] + + "(" + + fa_combo_df["FA1"].str.strip("FA") + + "_" + + fa_combo_df["FA2"].str.strip("FA") + + "_" + + fa_combo_df["FA3"].str.strip("FA") + + "_" + + fa_combo_df["FA4"].str.strip("FA") + + ")" + ) + fa_combo_df.sort_values(by="DISCRETE_ABBR", inplace=True) + print( + "[INFO] --> Number of predicted lipids (exact position): ", + fa_combo_df.shape[0], + ) else: - fa_combo_df['DISCRETE_ABBR'] = '' - print('[WARNING] !!! Number of predicted lipids (exact position): 0') + fa_combo_df["DISCRETE_ABBR"] = "" + print("[WARNING] !!! Number of predicted lipids (exact position): 0") if position is False: - print('[INFO] --> Use discrete form for identification ...') - fa_combo_lite_df = fa_combo_df.drop_duplicates(subset=['DISCRETE_ABBR'], keep='first').copy() - print('[INFO] --> Number of predicted lipids (discrete form): ', fa_combo_lite_df.shape[0]) + print("[INFO] --> Use discrete form for identification ...") + fa_combo_lite_df = fa_combo_df.drop_duplicates( + subset=["DISCRETE_ABBR"], keep="first" + ).copy() + print( + "[INFO] --> Number of predicted lipids (discrete form): ", + fa_combo_lite_df.shape[0], + ) else: fa_combo_lite_df = fa_combo_df.copy() # fa_combo_lite_df.is_copy = False - fa_combo_lite_df['idx'] = fa_combo_lite_df['DISCRETE_ABBR'] - fa_combo_lite_df.set_index('idx', drop=True, inplace=True) + fa_combo_lite_df["idx"] = fa_combo_lite_df["DISCRETE_ABBR"] + fa_combo_lite_df.set_index("idx", drop=True, inplace=True) - lipid_comb_dct = fa_combo_lite_df.to_dict(orient='index') + lipid_comb_dct = fa_combo_lite_df.to_dict(orient="index") return lipid_comb_dct @staticmethod - def calc_fragments(lipid_dct, charge='', ms2_ppm=100): + def calc_fragments(lipid_dct, charge="", ms2_ppm=100): # m_formula = lipid_dct['FORMULA'] - m_exactmass = lipid_dct['EXACTMASS'] - m_class = lipid_dct['CLASS'] + m_exactmass = lipid_dct["EXACTMASS"] + m_class = lipid_dct["CLASS"] h_exactmass = 1.0078250321 na_exactmass = 22.98976967 @@ -495,249 +658,405 @@ def calc_fragments(lipid_dct, charge='', ms2_ppm=100): ch3_exactmass = 12.0 + 3 * 1.0078250321 nl_water = 2 * 1.0078250321 + 15.9949146221 gly_mg_base_exactmass = 3 * 12.0 + 5 * 1.0078250321 + 15.9949146221 - fa1_abbr = lipid_dct['FA1'].strip('FA') - fa2_abbr = lipid_dct['FA2'].strip('FA') + fa1_abbr = lipid_dct["FA1"].strip("FA") + fa2_abbr = lipid_dct["FA2"].strip("FA") - fa1_exactmass = lipid_dct['FA1_EXACTMASS'] - if 'FA2_EXACTMASS' in list(lipid_dct.keys()): - fa2_exactmass = lipid_dct['FA2_EXACTMASS'] + fa1_exactmass = lipid_dct["FA1_EXACTMASS"] + if "FA2_EXACTMASS" in list(lipid_dct.keys()): + fa2_exactmass = lipid_dct["FA2_EXACTMASS"] - if m_class in ['PA', 'PE', 'PG', 'PI', 'PS', 'PIP', 'PL']: + if m_class in ["PA", "PE", "PG", "PI", "PS", "PIP", "PL"]: - lyso_str = 'L' + m_class + lyso_str = "L" + m_class # create the abbreviation name for the Lyso fragments eg. LPE(18:0)-H]-_ABBR # without the loss of water - lipid_dct['[LPL(FA1)-H]-_ABBR'] = '[%s(%s)-H]-' % (lyso_str, fa1_abbr) - lipid_dct['[LPL(FA2)-H]-_ABBR'] = '[%s(%s)-H]-' % (lyso_str, fa2_abbr) + lipid_dct["[LPL(FA1)-H]-_ABBR"] = "[%s(%s)-H]-" % (lyso_str, fa1_abbr) + lipid_dct["[LPL(FA2)-H]-_ABBR"] = "[%s(%s)-H]-" % (lyso_str, fa2_abbr) # with the loss of water - lipid_dct['[LPL(FA1)-H2O-H]-_ABBR'] = '[%s(%s)-H2O-H]-' % (lyso_str, fa1_abbr) - lipid_dct['[LPL(FA2)-H2O-H]-_ABBR'] = '[%s(%s)-H2O-H]-' % (lyso_str, fa2_abbr) + lipid_dct["[LPL(FA1)-H2O-H]-_ABBR"] = "[%s(%s)-H2O-H]-" % ( + lyso_str, + fa1_abbr, + ) + lipid_dct["[LPL(FA2)-H2O-H]-_ABBR"] = "[%s(%s)-H2O-H]-" % ( + lyso_str, + fa2_abbr, + ) # calculation of the exact mass for the different lyso fragments - lipid_dct['[LPL(FA1)-H]-_MZ'] = round(m_exactmass - (fa2_exactmass - nl_water) - h_exactmass, 6) - lipid_dct['[LPL(FA2)-H]-_MZ'] = round(m_exactmass - (fa1_exactmass - nl_water) - h_exactmass, 6) - lipid_dct['[LPL(FA1)-H2O-H]-_MZ'] = round(m_exactmass - fa2_exactmass - h_exactmass, 6) - lipid_dct['[LPL(FA2)-H2O-H]-_MZ'] = round(m_exactmass - fa1_exactmass - h_exactmass, 6) + lipid_dct["[LPL(FA1)-H]-_MZ"] = round( + m_exactmass - (fa2_exactmass - nl_water) - h_exactmass, 6 + ) + lipid_dct["[LPL(FA2)-H]-_MZ"] = round( + m_exactmass - (fa1_exactmass - nl_water) - h_exactmass, 6 + ) + lipid_dct["[LPL(FA1)-H2O-H]-_MZ"] = round( + m_exactmass - fa2_exactmass - h_exactmass, 6 + ) + lipid_dct["[LPL(FA2)-H2O-H]-_MZ"] = round( + m_exactmass - fa1_exactmass - h_exactmass, 6 + ) # Todo: Add SM section here and check - elif m_class in ['PC', 'SM']: + elif m_class in ["PC", "SM"]: - lyso_str = 'L' + m_class + lyso_str = "L" + m_class # The abbr. here is not exactly correct due to the compatibility issues with ranks core calc functions - lipid_dct['[LPL(FA1)-H]-_ABBR'] = '[%s(%s)-CH3]-' % (lyso_str, fa1_abbr) - lipid_dct['[LPL(FA2)-H]-_ABBR'] = '[%s(%s)-CH3]-' % (lyso_str, fa2_abbr) - lipid_dct['[LPL(FA1)-H2O-H]-_ABBR'] = '[%s(%s)-H2O-CH3]-' % (lyso_str, fa1_abbr) - lipid_dct['[LPL(FA2)-H2O-H]-_ABBR'] = '[%s(%s)-H2O-CH3]-' % (lyso_str, fa2_abbr) - - lipid_dct['[LPL(FA1)-H]-_MZ'] = round(m_exactmass - (fa2_exactmass - nl_water) - ch3_exactmass, 6) - lipid_dct['[LPL(FA2)-H]-_MZ'] = round(m_exactmass - (fa1_exactmass - nl_water) - ch3_exactmass, 6) - lipid_dct['[LPL(FA1)-H2O-H]-_MZ'] = round(m_exactmass - fa2_exactmass - ch3_exactmass, 6) - lipid_dct['[LPL(FA2)-H2O-H]-_MZ'] = round(m_exactmass - fa1_exactmass - ch3_exactmass, 6) - - elif m_class in ['LPA', 'LPE', 'LPG', 'LPI', 'LPS', 'LPIP', 'LPL']: + lipid_dct["[LPL(FA1)-H]-_ABBR"] = "[%s(%s)-CH3]-" % (lyso_str, fa1_abbr) + lipid_dct["[LPL(FA2)-H]-_ABBR"] = "[%s(%s)-CH3]-" % (lyso_str, fa2_abbr) + lipid_dct["[LPL(FA1)-H2O-H]-_ABBR"] = "[%s(%s)-H2O-CH3]-" % ( + lyso_str, + fa1_abbr, + ) + lipid_dct["[LPL(FA2)-H2O-H]-_ABBR"] = "[%s(%s)-H2O-CH3]-" % ( + lyso_str, + fa2_abbr, + ) + + lipid_dct["[LPL(FA1)-H]-_MZ"] = round( + m_exactmass - (fa2_exactmass - nl_water) - ch3_exactmass, 6 + ) + lipid_dct["[LPL(FA2)-H]-_MZ"] = round( + m_exactmass - (fa1_exactmass - nl_water) - ch3_exactmass, 6 + ) + lipid_dct["[LPL(FA1)-H2O-H]-_MZ"] = round( + m_exactmass - fa2_exactmass - ch3_exactmass, 6 + ) + lipid_dct["[LPL(FA2)-H2O-H]-_MZ"] = round( + m_exactmass - fa1_exactmass - ch3_exactmass, 6 + ) + + elif m_class in ["LPA", "LPE", "LPG", "LPI", "LPS", "LPIP", "LPL"]: pass - elif m_class in ['LPC']: + elif m_class in ["LPC"]: pass - elif m_class in ['TG']: + elif m_class in ["TG"]: # Here maybe should get the DG fragments # TODO(georgia.angelidou@uni-leipzig.de): create the section for theuniue fragments when there is TG # Missing the fragments for the sodium adduct # The different frgments for triacylglycerol names when neutral loss of the FA # Take the correspond information of the 3 FA - fa3_abbr = lipid_dct['FA3'].strip('FA') - fa3_exactmass = lipid_dct['FA3_EXACTMASS'] - dg_str = 'M' - if charge in ['[M+Na]+']: - fa1_Na_exactmass = lipid_dct['FA1_[FA-H+Na]_MZ'] - fa2_Na_exactmass = lipid_dct['FA2_[FA-H+Na]_MZ'] - fa3_Na_exactmass = lipid_dct['FA3_[FA-H+Na]_MZ'] - - lipid_dct['[M-(FA1)+Na]+_ABBR'] = '[%s-FA%s+Na]+' % (dg_str, fa1_abbr) - lipid_dct['[M-(FA2)+Na]+_ABBR'] = '[%s-FA%s+Na]+' % (dg_str, fa2_abbr) - lipid_dct['[M-(FA3)+Na]+_ABBR'] = '[%s-FA%s+Na]+' % (dg_str, fa3_abbr) - - lipid_dct['[M-(FA1-H+Na)+H]+_ABBR'] = '[%s-(FA%s-H+Na)+H]+' % (dg_str, fa1_abbr) - lipid_dct['[M-(FA2-H+Na)+H]+_ABBR'] = '[%s-(FA%s-H+Na)+H]+' % (dg_str, fa2_abbr) - lipid_dct['[M-(FA3-H+Na)+H]+_ABBR'] = '[%s-(FA%s-H+Na)+H]+' % (dg_str, fa3_abbr) - - lipid_dct['[M-(FA1)+Na]+_MZ'] = round(m_exactmass - fa1_exactmass + na_exactmass, 6) - lipid_dct['[M-(FA2)+Na]+_MZ'] = round(m_exactmass - fa2_exactmass + na_exactmass, 6) - lipid_dct['[M-(FA3)+Na]+_MZ'] = round(m_exactmass - fa3_exactmass + na_exactmass, 6) - - lipid_dct['[M-(FA1-H+Na)+H]+_MZ'] = round(m_exactmass - fa1_Na_exactmass + na_exactmass, 6) - lipid_dct['[M-(FA2-H+Na)+H]+_MZ'] = round(m_exactmass - fa2_Na_exactmass + na_exactmass, 6) - lipid_dct['[M-(FA3-H+Na)+H]+_MZ'] = round(m_exactmass - fa3_Na_exactmass + na_exactmass, 6) - - lipid_dct['[M-(FA1)+Na]+_MZ_LOW'] = ppm_window_para((m_exactmass - (fa1_exactmass) + na_exactmass), - ms2_ppm * -1) - lipid_dct['[M-(FA1)+Na]+_MZ_HIGH'] = ppm_window_para((m_exactmass - (fa1_exactmass) + na_exactmass), - ms2_ppm) - lipid_dct['[M-(FA1)+Na]+_Q'] = ( - lipid_dct['[M-(FA1)+Na]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA1)+Na]+_MZ_HIGH'].astype(str)) - - lipid_dct['[M-(FA2)+Na]+_MZ_LOW'] = ppm_window_para((m_exactmass - (fa2_exactmass) + na_exactmass), - ms2_ppm * -1) - lipid_dct['[M-(FA2)+Na]+_MZ_HIGH'] = ppm_window_para((m_exactmass - (fa2_exactmass) + na_exactmass), - ms2_ppm) - lipid_dct['[M-(FA2)+Na]+_Q'] = ( - lipid_dct['[M-(FA2)+Na]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA2)+Na]+_MZ_HIGH'].astype(str)) - - lipid_dct['[M-(FA3)+Na]+_MZ_LOW'] = ppm_window_para((m_exactmass - (fa3_exactmass) + na_exactmass), - ms2_ppm * -1) - lipid_dct['[M-(FA3)+Na]+_MZ_HIGH'] = ppm_window_para((m_exactmass - (fa3_exactmass) + na_exactmass), - ms2_ppm) - lipid_dct['[M-(FA3)+Na]+_Q'] = ( - lipid_dct['[M-(FA3)+Na]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA3)+Na]+_MZ_HIGH'].astype(str)) - - lipid_dct['[M-(FA1-H+Na)+H]+_MZ_LOW'] = ppm_window_para( - (m_exactmass - (fa1_Na_exactmass) + na_exactmass), ms2_ppm * -1) - lipid_dct['[M-(FA1-H+Na)+H]+_MZ_HIGH'] = ppm_window_para( - (m_exactmass - (fa1_Na_exactmass) + na_exactmass), ms2_ppm) - lipid_dct['[M-(FA1-H+Na)+H]+_Q'] = ( - lipid_dct['[M-(FA1-H+Na)+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA1-H+Na)+H]+_MZ_HIGH'].astype(str)) - - lipid_dct['[M-(FA2-H+Na)+H]+_MZ_LOW'] = ppm_window_para( - (m_exactmass - (fa2_Na_exactmass) + na_exactmass), ms2_ppm * -1) - lipid_dct['[M-(FA2-H+Na)+H]+_MZ_HIGH'] = ppm_window_para( - (m_exactmass - (fa2_Na_exactmass) + na_exactmass), ms2_ppm) - lipid_dct['[M-(FA2-H+Na)+H]+_Q'] = ( - lipid_dct['[M-(FA2-H+Na)+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA2-H+Na)+H]+_MZ_HIGH'].astype(str)) - - lipid_dct['[M-(FA3-H+Na)+H]+_MZ_LOW'] = ppm_window_para( - (m_exactmass - (fa3_Na_exactmass) + na_exactmass), ms2_ppm * -1) - lipid_dct['[M-(FA3-H+Na)+H]+_MZ_HIGH'] = ppm_window_para( - (m_exactmass - (fa3_Na_exactmass) + na_exactmass), ms2_ppm) - lipid_dct['[M-(FA3-H+Na)+H]+_Q'] = ( - lipid_dct['[M-(FA3-H+Na)+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA3-H+Na)+H]+_MZ_HIGH'].astype(str)) + fa3_abbr = lipid_dct["FA3"].strip("FA") + fa3_exactmass = lipid_dct["FA3_EXACTMASS"] + dg_str = "M" + if charge in ["[M+Na]+"]: + fa1_Na_exactmass = lipid_dct["FA1_[FA-H+Na]_MZ"] + fa2_Na_exactmass = lipid_dct["FA2_[FA-H+Na]_MZ"] + fa3_Na_exactmass = lipid_dct["FA3_[FA-H+Na]_MZ"] + + lipid_dct["[M-(FA1)+Na]+_ABBR"] = "[%s-FA%s+Na]+" % (dg_str, fa1_abbr) + lipid_dct["[M-(FA2)+Na]+_ABBR"] = "[%s-FA%s+Na]+" % (dg_str, fa2_abbr) + lipid_dct["[M-(FA3)+Na]+_ABBR"] = "[%s-FA%s+Na]+" % (dg_str, fa3_abbr) + + lipid_dct["[M-(FA1-H+Na)+H]+_ABBR"] = "[%s-(FA%s-H+Na)+H]+" % ( + dg_str, + fa1_abbr, + ) + lipid_dct["[M-(FA2-H+Na)+H]+_ABBR"] = "[%s-(FA%s-H+Na)+H]+" % ( + dg_str, + fa2_abbr, + ) + lipid_dct["[M-(FA3-H+Na)+H]+_ABBR"] = "[%s-(FA%s-H+Na)+H]+" % ( + dg_str, + fa3_abbr, + ) + + lipid_dct["[M-(FA1)+Na]+_MZ"] = round( + m_exactmass - fa1_exactmass + na_exactmass, 6 + ) + lipid_dct["[M-(FA2)+Na]+_MZ"] = round( + m_exactmass - fa2_exactmass + na_exactmass, 6 + ) + lipid_dct["[M-(FA3)+Na]+_MZ"] = round( + m_exactmass - fa3_exactmass + na_exactmass, 6 + ) + + lipid_dct["[M-(FA1-H+Na)+H]+_MZ"] = round( + m_exactmass - fa1_Na_exactmass + na_exactmass, 6 + ) + lipid_dct["[M-(FA2-H+Na)+H]+_MZ"] = round( + m_exactmass - fa2_Na_exactmass + na_exactmass, 6 + ) + lipid_dct["[M-(FA3-H+Na)+H]+_MZ"] = round( + m_exactmass - fa3_Na_exactmass + na_exactmass, 6 + ) + + lipid_dct["[M-(FA1)+Na]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - (fa1_exactmass) + na_exactmass), ms2_ppm * -1 + ) + lipid_dct["[M-(FA1)+Na]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - (fa1_exactmass) + na_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA1)+Na]+_Q"] = ( + lipid_dct["[M-(FA1)+Na]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA1)+Na]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[M-(FA2)+Na]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - (fa2_exactmass) + na_exactmass), ms2_ppm * -1 + ) + lipid_dct["[M-(FA2)+Na]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - (fa2_exactmass) + na_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA2)+Na]+_Q"] = ( + lipid_dct["[M-(FA2)+Na]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA2)+Na]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[M-(FA3)+Na]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - (fa3_exactmass) + na_exactmass), ms2_ppm * -1 + ) + lipid_dct["[M-(FA3)+Na]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - (fa3_exactmass) + na_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA3)+Na]+_Q"] = ( + lipid_dct["[M-(FA3)+Na]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA3)+Na]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[M-(FA1-H+Na)+H]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - (fa1_Na_exactmass) + na_exactmass), ms2_ppm * -1 + ) + lipid_dct["[M-(FA1-H+Na)+H]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - (fa1_Na_exactmass) + na_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA1-H+Na)+H]+_Q"] = ( + lipid_dct["[M-(FA1-H+Na)+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA1-H+Na)+H]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[M-(FA2-H+Na)+H]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - (fa2_Na_exactmass) + na_exactmass), ms2_ppm * -1 + ) + lipid_dct["[M-(FA2-H+Na)+H]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - (fa2_Na_exactmass) + na_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA2-H+Na)+H]+_Q"] = ( + lipid_dct["[M-(FA2-H+Na)+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA2-H+Na)+H]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[M-(FA3-H+Na)+H]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - (fa3_Na_exactmass) + na_exactmass), ms2_ppm * -1 + ) + lipid_dct["[M-(FA3-H+Na)+H]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - (fa3_Na_exactmass) + na_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA3-H+Na)+H]+_Q"] = ( + lipid_dct["[M-(FA3-H+Na)+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA3-H+Na)+H]+_MZ_HIGH"].astype(str) + ) else: # Neutral loss of a FA with a water - lipid_dct['[M-(FA1)+H]+_ABBR'] = '[%s-FA%s+H]+' % (dg_str, fa1_abbr) - lipid_dct['[M-(FA2)+H]+_ABBR'] = '[%s-FA%s+H]+' % (dg_str, fa2_abbr) - lipid_dct['[M-(FA3)+H]+_ABBR'] = '[%s-FA%s+H]+' % (dg_str, fa3_abbr) + lipid_dct["[M-(FA1)+H]+_ABBR"] = "[%s-FA%s+H]+" % (dg_str, fa1_abbr) + lipid_dct["[M-(FA2)+H]+_ABBR"] = "[%s-FA%s+H]+" % (dg_str, fa2_abbr) + lipid_dct["[M-(FA3)+H]+_ABBR"] = "[%s-FA%s+H]+" % (dg_str, fa3_abbr) # Neutral loss of a FA minus a water - lipid_dct['[M-(FA1-H2O)+H]+_ABBR'] = '[%s-(FA%s-H2O)+H]+' % (dg_str, fa1_abbr) - lipid_dct['[M-(FA2-H2O)+H]+_ABBR'] = '[%s-(FA%s-H2O)+H]+' % (dg_str, fa2_abbr) - lipid_dct['[M-(FA3-H2O)+H]+_ABBR'] = '[%s-(FA%s-H2O)+H]+' % (dg_str, fa3_abbr) - - lipid_dct['[M-(FA1)+H]+_MZ'] = round(m_exactmass - fa1_exactmass + h_exactmass, 6) - lipid_dct['[M-(FA2)+H]+_MZ'] = round(m_exactmass - fa2_exactmass + h_exactmass, 6) - lipid_dct['[M-(FA3)+H]+_MZ'] = round(m_exactmass - fa3_exactmass + h_exactmass, 6) - - lipid_dct['[M-(FA1-H2O)+H]+_MZ'] = round(m_exactmass - (fa1_exactmass - nl_water) + h_exactmass, 6) - lipid_dct['[M-(FA2-H2O)+H]+_MZ'] = round(m_exactmass - (fa2_exactmass - nl_water) + h_exactmass, 6) - lipid_dct['[M-(FA3-H2O)+H]+_MZ'] = round(m_exactmass - (fa3_exactmass - nl_water) + h_exactmass, 6) - - lipid_dct['[MG(FA1)-H2O+H]+_MZ_LOW'] = ppm_window_para((fa1_exactmass + gly_mg_base_exactmass), - ms2_ppm * -1) - lipid_dct['[MG(FA1)-H2O+H]+_MZ_HIGH'] = ppm_window_para((fa1_exactmass + gly_mg_base_exactmass), - ms2_ppm) - lipid_dct['[MG(FA1)-H2O+H]+_Q'] = ( - lipid_dct['[MG(FA1)-H2O+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + - lipid_dct['[MG(FA1)-H2O+H]+_MZ_HIGH'].astype(str)) - - lipid_dct['[MG(FA2)-H2O+H]+_MZ_LOW'] = ppm_window_para((fa2_exactmass + gly_mg_base_exactmass), - ms2_ppm * -1) - lipid_dct['[MG(FA2)-H2O+H]+_MZ_HIGH'] = ppm_window_para((fa2_exactmass + gly_mg_base_exactmass), - ms2_ppm) - lipid_dct['[MG(FA2)-H2O+H]+_Q'] = ( - lipid_dct['[MG(FA2)-H2O+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + - lipid_dct['[MG(FA2)-H2O+H]+_MZ_HIGH'].astype(str)) - - lipid_dct['[MG(FA3)-H2O+H]+_MZ_LOW'] = ppm_window_para((fa3_exactmass + gly_mg_base_exactmass), - ms2_ppm * -1) - lipid_dct['[MG(FA3)-H2O+H]+_MZ_HIGH'] = ppm_window_para((fa3_exactmass + gly_mg_base_exactmass), - ms2_ppm) - lipid_dct['[MG(FA3)-H2O+H]+_Q'] = ( - lipid_dct['[MG(FA3)-H2O+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + - lipid_dct['[MG(FA3)-H2O+H]+_MZ_HIGH'].astype(str)) - - lipid_dct['[M-(FA1)+H]+_MZ_LOW'] = ppm_window_para((m_exactmass - fa1_exactmass + h_exactmass), - ms2_ppm * -1) - lipid_dct['[M-(FA1)+H]+_MZ_HIGH'] = ppm_window_para((m_exactmass - fa1_exactmass + h_exactmass), - ms2_ppm) - lipid_dct['[M-(FA1)+H]+_Q'] = (lipid_dct['[M-(FA1)+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA1)+H]+_MZ_HIGH'].astype(str)) - - lipid_dct['[M-(FA2)+H]+_MZ_LOW'] = ppm_window_para((m_exactmass - fa2_exactmass + h_exactmass), - ms2_ppm * -1) - lipid_dct['[M-(FA2)+H]+_MZ_HIGH'] = ppm_window_para((m_exactmass - fa2_exactmass + h_exactmass), - ms2_ppm) - lipid_dct['[M-(FA2)+H]+_Q'] = (lipid_dct['[M-(FA2)+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA2)+H]+_MZ_HIGH'].astype(str)) - - lipid_dct['[M-(FA3)+H]+_MZ_LOW'] = ppm_window_para((m_exactmass - fa3_exactmass + h_exactmass), - ms2_ppm * -1) - lipid_dct['[M-(FA3)+H]+_MZ_HIGH'] = ppm_window_para((m_exactmass - fa3_exactmass + h_exactmass), - ms2_ppm) - lipid_dct['[M-(FA3)+H]+_Q'] = (lipid_dct['[M-(FA3)+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA3)+H]+_MZ_HIGH'].astype(str)) - - lipid_dct['[M-(FA1-H2O)+H]+_MZ_LOW'] = ppm_window_para( - (m_exactmass - (fa1_exactmass - nl_water) + h_exactmass), ms2_ppm * -1) - lipid_dct['[M-(FA1-H2O)+H]+_MZ_HIGH'] = ppm_window_para( - (m_exactmass - (fa1_exactmass - nl_water) + h_exactmass), ms2_ppm) - lipid_dct['[M-(FA1-H2O)+H]+_Q'] = ( - lipid_dct['[M-(FA1-H2O)+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA1-H2O)+H]+_MZ_HIGH'].astype(str)) - - lipid_dct['[M-(FA2-H2O)+H]+_MZ_LOW'] = ppm_window_para( - (m_exactmass - (fa2_exactmass - nl_water) + h_exactmass), ms2_ppm * -1) - lipid_dct['[M-(FA2-H2O)+H]+_MZ_HIGH'] = ppm_window_para( - (m_exactmass - (fa2_exactmass - nl_water) + h_exactmass), ms2_ppm) - lipid_dct['[M-(FA2-H2O)+H]+_Q'] = ( - lipid_dct['[M-(FA2-H2O)+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA2-H2O)+H]+_MZ_HIGH'].astype(str)) - - lipid_dct['[M-(FA3-H2O)+H]+_MZ_LOW'] = ppm_window_para( - (m_exactmass - (fa3_exactmass - nl_water) + h_exactmass), ms2_ppm * -1) - lipid_dct['[M-(FA3-H2O)+H]+_MZ_HIGH'] = ppm_window_para( - (m_exactmass - (fa3_exactmass - nl_water) + h_exactmass), ms2_ppm) - lipid_dct['[M-(FA3-H2O)+H]+_Q'] = ( - lipid_dct['[M-(FA3-H2O)+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + lipid_dct[ - '[M-(FA3-H2O)+H]+_MZ_HIGH'].astype(str)) + lipid_dct["[M-(FA1-H2O)+H]+_ABBR"] = "[%s-(FA%s-H2O)+H]+" % ( + dg_str, + fa1_abbr, + ) + lipid_dct["[M-(FA2-H2O)+H]+_ABBR"] = "[%s-(FA%s-H2O)+H]+" % ( + dg_str, + fa2_abbr, + ) + lipid_dct["[M-(FA3-H2O)+H]+_ABBR"] = "[%s-(FA%s-H2O)+H]+" % ( + dg_str, + fa3_abbr, + ) + + lipid_dct["[M-(FA1)+H]+_MZ"] = round( + m_exactmass - fa1_exactmass + h_exactmass, 6 + ) + lipid_dct["[M-(FA2)+H]+_MZ"] = round( + m_exactmass - fa2_exactmass + h_exactmass, 6 + ) + lipid_dct["[M-(FA3)+H]+_MZ"] = round( + m_exactmass - fa3_exactmass + h_exactmass, 6 + ) + + lipid_dct["[M-(FA1-H2O)+H]+_MZ"] = round( + m_exactmass - (fa1_exactmass - nl_water) + h_exactmass, 6 + ) + lipid_dct["[M-(FA2-H2O)+H]+_MZ"] = round( + m_exactmass - (fa2_exactmass - nl_water) + h_exactmass, 6 + ) + lipid_dct["[M-(FA3-H2O)+H]+_MZ"] = round( + m_exactmass - (fa3_exactmass - nl_water) + h_exactmass, 6 + ) + + lipid_dct["[MG(FA1)-H2O+H]+_MZ_LOW"] = ppm_window_para( + (fa1_exactmass + gly_mg_base_exactmass), ms2_ppm * -1 + ) + lipid_dct["[MG(FA1)-H2O+H]+_MZ_HIGH"] = ppm_window_para( + (fa1_exactmass + gly_mg_base_exactmass), ms2_ppm + ) + lipid_dct["[MG(FA1)-H2O+H]+_Q"] = ( + lipid_dct["[MG(FA1)-H2O+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[MG(FA1)-H2O+H]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[MG(FA2)-H2O+H]+_MZ_LOW"] = ppm_window_para( + (fa2_exactmass + gly_mg_base_exactmass), ms2_ppm * -1 + ) + lipid_dct["[MG(FA2)-H2O+H]+_MZ_HIGH"] = ppm_window_para( + (fa2_exactmass + gly_mg_base_exactmass), ms2_ppm + ) + lipid_dct["[MG(FA2)-H2O+H]+_Q"] = ( + lipid_dct["[MG(FA2)-H2O+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[MG(FA2)-H2O+H]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[MG(FA3)-H2O+H]+_MZ_LOW"] = ppm_window_para( + (fa3_exactmass + gly_mg_base_exactmass), ms2_ppm * -1 + ) + lipid_dct["[MG(FA3)-H2O+H]+_MZ_HIGH"] = ppm_window_para( + (fa3_exactmass + gly_mg_base_exactmass), ms2_ppm + ) + lipid_dct["[MG(FA3)-H2O+H]+_Q"] = ( + lipid_dct["[MG(FA3)-H2O+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[MG(FA3)-H2O+H]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[M-(FA1)+H]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - fa1_exactmass + h_exactmass), ms2_ppm * -1 + ) + lipid_dct["[M-(FA1)+H]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - fa1_exactmass + h_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA1)+H]+_Q"] = ( + lipid_dct["[M-(FA1)+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA1)+H]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[M-(FA2)+H]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - fa2_exactmass + h_exactmass), ms2_ppm * -1 + ) + lipid_dct["[M-(FA2)+H]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - fa2_exactmass + h_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA2)+H]+_Q"] = ( + lipid_dct["[M-(FA2)+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA2)+H]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[M-(FA3)+H]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - fa3_exactmass + h_exactmass), ms2_ppm * -1 + ) + lipid_dct["[M-(FA3)+H]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - fa3_exactmass + h_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA3)+H]+_Q"] = ( + lipid_dct["[M-(FA3)+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA3)+H]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[M-(FA1-H2O)+H]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - (fa1_exactmass - nl_water) + h_exactmass), + ms2_ppm * -1, + ) + lipid_dct["[M-(FA1-H2O)+H]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - (fa1_exactmass - nl_water) + h_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA1-H2O)+H]+_Q"] = ( + lipid_dct["[M-(FA1-H2O)+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA1-H2O)+H]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[M-(FA2-H2O)+H]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - (fa2_exactmass - nl_water) + h_exactmass), + ms2_ppm * -1, + ) + lipid_dct["[M-(FA2-H2O)+H]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - (fa2_exactmass - nl_water) + h_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA2-H2O)+H]+_Q"] = ( + lipid_dct["[M-(FA2-H2O)+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA2-H2O)+H]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[M-(FA3-H2O)+H]+_MZ_LOW"] = ppm_window_para( + (m_exactmass - (fa3_exactmass - nl_water) + h_exactmass), + ms2_ppm * -1, + ) + lipid_dct["[M-(FA3-H2O)+H]+_MZ_HIGH"] = ppm_window_para( + (m_exactmass - (fa3_exactmass - nl_water) + h_exactmass), ms2_ppm + ) + lipid_dct["[M-(FA3-H2O)+H]+_Q"] = ( + lipid_dct["[M-(FA3-H2O)+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[M-(FA3-H2O)+H]+_MZ_HIGH"].astype(str) + ) # Fragments names when can occur 2 neutral losses of FA. 1 FA with the water and other without - mg_str = 'MG' - lipid_dct['[MG(FA1)-H2O+H]+_ABBR'] = '[%s(%s)-H2O+H]+' % (mg_str, fa1_abbr) - lipid_dct['[MG(FA2)-H2O+H]+_ABBR'] = '[%s(%s)-H2O+H]+' % (mg_str, fa2_abbr) - lipid_dct['[MG(FA3)-H2O+H]+_ABBR'] = '[%s(%s)-H2O+H]+' % (mg_str, fa3_abbr) - - lipid_dct['[MG(FA1)-H2O+H]+_MZ'] = round(fa1_exactmass + gly_mg_base_exactmass, 6) - lipid_dct['[MG(FA2)-H2O+H]+_MZ'] = round(fa2_exactmass + gly_mg_base_exactmass, 6) - lipid_dct['[MG(FA3)-H2O+H]+_MZ'] = round(fa3_exactmass + gly_mg_base_exactmass, 6) + mg_str = "MG" + lipid_dct["[MG(FA1)-H2O+H]+_ABBR"] = "[%s(%s)-H2O+H]+" % (mg_str, fa1_abbr) + lipid_dct["[MG(FA2)-H2O+H]+_ABBR"] = "[%s(%s)-H2O+H]+" % (mg_str, fa2_abbr) + lipid_dct["[MG(FA3)-H2O+H]+_ABBR"] = "[%s(%s)-H2O+H]+" % (mg_str, fa3_abbr) + + lipid_dct["[MG(FA1)-H2O+H]+_MZ"] = round( + fa1_exactmass + gly_mg_base_exactmass, 6 + ) + lipid_dct["[MG(FA2)-H2O+H]+_MZ"] = round( + fa2_exactmass + gly_mg_base_exactmass, 6 + ) + lipid_dct["[MG(FA3)-H2O+H]+_MZ"] = round( + fa3_exactmass + gly_mg_base_exactmass, 6 + ) # TODO (georgia.angelidou@uni-leipzig.de): add the fragments of Na [sodium] # Fragments when there only 1 neutral loss from the TG. - elif m_class in ['DG']: - mg_str = 'MG' - lipid_dct['[MG(FA1)-H2O+H]+_ABBR'] = '[%s(%s)-H2O+H]+' % (mg_str, fa1_abbr) - lipid_dct['[MG(FA2)-H2O+H]+_ABBR'] = '[%s(%s)-H2O+H]+' % (mg_str, fa2_abbr) - - lipid_dct['[MG(FA1)-H2O+H]+_MZ'] = round(fa1_exactmass + gly_mg_base_exactmass, 6) - lipid_dct['[MG(FA2)-H2O+H]+_MZ'] = round(fa2_exactmass + gly_mg_base_exactmass, 6) - - lipid_dct['[MG(FA1)-H2O+H]+_MZ_LOW'] = ppm_window_para((fa1_exactmass + gly_mg_base_exactmass), - ms2_ppm * -1) - lipid_dct['[MG(FA1)-H2O+H]+_MZ_HIGH'] = ppm_window_para((fa1_exactmass + gly_mg_base_exactmass), ms2_ppm) - lipid_dct['[MG(FA1)-H2O+H]+_Q'] = ( - lipid_dct['[MG(FA1)-H2O+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + - lipid_dct['[MG(FA1)-H2O+H]+_MZ_HIGH'].astype(str)) - - lipid_dct['[MG(FA2)-H2O+H]+_MZ_LOW'] = ppm_window_para((fa2_exactmass + gly_mg_base_exactmass), - ms2_ppm * -1) - lipid_dct['[MG(FA2)-H2O+H]+_MZ_HIGH'] = ppm_window_para((fa2_exactmass + gly_mg_base_exactmass), ms2_ppm) - lipid_dct['[MG(FA2)-H2O+H]+_Q'] = ( - lipid_dct['[MG(FA2)-H2O+H]+_MZ_LOW'].astype(str) + ' <= mz <= ' + - lipid_dct['[MG(FA2)-H2O+H]+_MZ_HIGH'].astype(str)) + elif m_class in ["DG"]: + mg_str = "MG" + lipid_dct["[MG(FA1)-H2O+H]+_ABBR"] = "[%s(%s)-H2O+H]+" % (mg_str, fa1_abbr) + lipid_dct["[MG(FA2)-H2O+H]+_ABBR"] = "[%s(%s)-H2O+H]+" % (mg_str, fa2_abbr) + + lipid_dct["[MG(FA1)-H2O+H]+_MZ"] = round( + fa1_exactmass + gly_mg_base_exactmass, 6 + ) + lipid_dct["[MG(FA2)-H2O+H]+_MZ"] = round( + fa2_exactmass + gly_mg_base_exactmass, 6 + ) + + lipid_dct["[MG(FA1)-H2O+H]+_MZ_LOW"] = ppm_window_para( + (fa1_exactmass + gly_mg_base_exactmass), ms2_ppm * -1 + ) + lipid_dct["[MG(FA1)-H2O+H]+_MZ_HIGH"] = ppm_window_para( + (fa1_exactmass + gly_mg_base_exactmass), ms2_ppm + ) + lipid_dct["[MG(FA1)-H2O+H]+_Q"] = ( + lipid_dct["[MG(FA1)-H2O+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[MG(FA1)-H2O+H]+_MZ_HIGH"].astype(str) + ) + + lipid_dct["[MG(FA2)-H2O+H]+_MZ_LOW"] = ppm_window_para( + (fa2_exactmass + gly_mg_base_exactmass), ms2_ppm * -1 + ) + lipid_dct["[MG(FA2)-H2O+H]+_MZ_HIGH"] = ppm_window_para( + (fa2_exactmass + gly_mg_base_exactmass), ms2_ppm + ) + lipid_dct["[MG(FA2)-H2O+H]+_Q"] = ( + lipid_dct["[MG(FA2)-H2O+H]+_MZ_LOW"].astype(str) + + " <= mz <= " + + lipid_dct["[MG(FA2)-H2O+H]+_MZ_HIGH"].astype(str) + ) else: # TODO (georgia.angelidou@uni-leipzig.de: Info for sphingomyelins @@ -757,45 +1076,47 @@ def compose_lipid(self, param_dct: dict, ms2_ppm: int = 100) -> pd.DataFrame: """ - lipid_class = param_dct['lipid_class'] - lipid_charge = param_dct['charge_mode'] - if param_dct['exact_position'] == 'TRUE': + lipid_class = param_dct["lipid_class"] + lipid_charge = param_dct["charge_mode"] + if param_dct["exact_position"] == "TRUE": position_set = True else: position_set = False - usr_fa_df = pd.read_excel(param_dct['fa_whitelist']) - usr_fa_df = usr_fa_df.fillna(value='F') + usr_fa_df = pd.read_excel(param_dct["fa_whitelist"]) + usr_fa_df = usr_fa_df.fillna(value="F") tmp_columns = usr_fa_df.columns.tolist() usr_fa_df.columns = usr_fa_df.columns.str.upper() # Todo: check SM section below: - if lipid_class in ['PL', 'PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'SM']: + if lipid_class in ["PL", "PA", "PC", "PE", "PG", "PI", "PS", "SM"]: if lipid_class in tmp_columns: pass - elif 'PL' in tmp_columns: + elif "PL" in tmp_columns: pass else: return False - elif lipid_class in ['LPL', 'LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPS']: + elif lipid_class in ["LPL", "LPA", "LPC", "LPE", "LPG", "LPI", "LPS"]: if lipid_class in tmp_columns: pass - elif 'LPL' in tmp_columns or 'PL' in tmp_columns: + elif "LPL" in tmp_columns or "PL" in tmp_columns: pass else: return False - elif lipid_class in ['TG', 'DG']: + elif lipid_class in ["TG", "DG"]: if lipid_class in tmp_columns: pass else: return False else: return False - print('[INFO] --> FA white list loaded ...') - lipid_comb_dct = self.gen_all_comb(lipid_class, usr_fa_df, position=position_set) + print("[INFO] --> FA white list loaded ...") + lipid_comb_dct = self.gen_all_comb( + lipid_class, usr_fa_df, position=position_set + ) lipid_info_dct = {} @@ -804,104 +1125,134 @@ def compose_lipid(self, param_dct: dict, ms2_ppm: int = 100) -> pd.DataFrame: for _lipid in list(lipid_comb_dct.keys()): _lipid_dct = lipid_comb_dct[_lipid] - _fa1_abbr = _lipid_dct['FA1'] + _fa1_abbr = _lipid_dct["FA1"] if _fa1_abbr: _fa1_info_dct = abbr_parser.get_fa_info(_fa1_abbr) for _fa1_k in list(_fa1_info_dct.keys()): - _lipid_dct['FA1_' + _fa1_k] = _fa1_info_dct[_fa1_k] + _lipid_dct["FA1_" + _fa1_k] = _fa1_info_dct[_fa1_k] else: - if 'FA2' in list(_lipid_dct.keys()): - if _lipid_dct['FA2']: - _lipid_dct['FA1'], _lipid_dct['FA2'] = _lipid_dct['FA2'], _lipid_dct['FA1'] - _fa1_abbr = _lipid_dct['FA1'] + if "FA2" in list(_lipid_dct.keys()): + if _lipid_dct["FA2"]: + _lipid_dct["FA1"], _lipid_dct["FA2"] = ( + _lipid_dct["FA2"], + _lipid_dct["FA1"], + ) + _fa1_abbr = _lipid_dct["FA1"] _fa1_info_dct = abbr_parser.get_fa_info(_fa1_abbr) for _fa1_k in list(_fa1_info_dct.keys()): - _lipid_dct['FA1_' + _fa1_k] = _fa1_info_dct[_fa1_k] + _lipid_dct["FA1_" + _fa1_k] = _fa1_info_dct[_fa1_k] else: _fa1_info_dct = {} - if 'FA2' in list(_lipid_dct.keys()): - _fa2_abbr = _lipid_dct['FA2'] + if "FA2" in list(_lipid_dct.keys()): + _fa2_abbr = _lipid_dct["FA2"] if _fa2_abbr: _fa2_info_dct = abbr_parser.get_fa_info(_fa2_abbr) for _fa2_k in list(_fa2_info_dct.keys()): - _lipid_dct['FA2_' + _fa2_k] = _fa2_info_dct[_fa2_k] + _lipid_dct["FA2_" + _fa2_k] = _fa2_info_dct[_fa2_k] else: - _fa2_abbr = '' + _fa2_abbr = "" _fa2_info_dct = {} # Todo: add and check SM, Cer below - if lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PS', 'DG']: - _lipid_dct['M_DB'] = _fa1_info_dct['DB'] + _fa2_info_dct['DB'] + if lipid_class in ["PA", "PC", "PE", "PG", "PI", "PS", "DG"]: + _lipid_dct["M_DB"] = _fa1_info_dct["DB"] + _fa2_info_dct["DB"] # TODO(georgia.angelidou@uni-leipzig.de): not important (just keep in mind for future correction) # consideration the case if the user choose the fa2 position for the different link types # or in that they may mistype something - if _fa1_info_dct['LINK'] in ['FA', 'A']: - lipid_bulk_str = '{pl}({c}:{db})'.format(pl=lipid_class, - c=_fa1_info_dct['C'] + _fa2_info_dct['C'], - db=lipid_comb_dct[_lipid]['M_DB']) + if _fa1_info_dct["LINK"] in ["FA", "A"]: + lipid_bulk_str = "{pl}({c}:{db})".format( + pl=lipid_class, + c=_fa1_info_dct["C"] + _fa2_info_dct["C"], + db=lipid_comb_dct[_lipid]["M_DB"], + ) else: - lipid_bulk_str = '{pl}({lk}{c}:{db})'.format(pl=lipid_class, lk=_fa1_info_dct['LINK'], - c=_fa1_info_dct['C'] + _fa2_info_dct['C'], - db=lipid_comb_dct[_lipid]['M_DB']) - elif lipid_class in ['LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPS']: - _lipid_dct['M_DB'] = _fa1_info_dct['DB'] + lipid_bulk_str = "{pl}({lk}{c}:{db})".format( + pl=lipid_class, + lk=_fa1_info_dct["LINK"], + c=_fa1_info_dct["C"] + _fa2_info_dct["C"], + db=lipid_comb_dct[_lipid]["M_DB"], + ) + elif lipid_class in ["LPA", "LPC", "LPE", "LPG", "LPI", "LPS"]: + _lipid_dct["M_DB"] = _fa1_info_dct["DB"] # TODO(georgia.angelidou@uni-leipzig.de): not important (just keep in mind for future correction) # consideration the case if the user choose the fa2 position for the different link types # or in that they may mistype something - if _fa1_info_dct['LINK'] in ['FA', 'A']: - lipid_bulk_str = '{pl}({c}:{db})'.format(pl=lipid_class, - c=_fa1_info_dct['C'], - db=lipid_comb_dct[_lipid]['M_DB']) + if _fa1_info_dct["LINK"] in ["FA", "A"]: + lipid_bulk_str = "{pl}({c}:{db})".format( + pl=lipid_class, + c=_fa1_info_dct["C"], + db=lipid_comb_dct[_lipid]["M_DB"], + ) else: - lipid_bulk_str = '{pl}({lk}{c}:{db})'.format(pl=lipid_class, lk=_fa1_info_dct['LINK'], - c=_fa1_info_dct['C'], - db=lipid_comb_dct[_lipid]['M_DB']) - elif lipid_class in ['TG']: - _fa3_abbr = _lipid_dct['FA3'] + lipid_bulk_str = "{pl}({lk}{c}:{db})".format( + pl=lipid_class, + lk=_fa1_info_dct["LINK"], + c=_fa1_info_dct["C"], + db=lipid_comb_dct[_lipid]["M_DB"], + ) + elif lipid_class in ["TG"]: + _fa3_abbr = _lipid_dct["FA3"] _fa3_info_dct = abbr_parser.get_fa_info(_fa3_abbr) for _fa3_k in _fa3_info_dct.keys(): - _lipid_dct['FA3_' + _fa3_k] = _fa3_info_dct[_fa3_k] + _lipid_dct["FA3_" + _fa3_k] = _fa3_info_dct[_fa3_k] - _lipid_dct['M_DB'] = _fa3_info_dct['DB'] + _fa2_info_dct['DB'] + _fa1_info_dct['DB'] + _lipid_dct["M_DB"] = ( + _fa3_info_dct["DB"] + _fa2_info_dct["DB"] + _fa1_info_dct["DB"] + ) # Note: For TG in the current default not consider the different lipids with other type of bond # If stay like this need to be mention in somewhere for the user - if _fa1_info_dct['LINK'] in ['FA', 'A']: - lipid_bulk_str = '{tg}({c}:{db})'.format(tg=lipid_class, - c=(_fa1_info_dct['C'] + _fa2_info_dct['C'] - + _fa3_info_dct['C']), - db=lipid_comb_dct[_lipid]['M_DB']) + if _fa1_info_dct["LINK"] in ["FA", "A"]: + lipid_bulk_str = "{tg}({c}:{db})".format( + tg=lipid_class, + c=( + _fa1_info_dct["C"] + _fa2_info_dct["C"] + _fa3_info_dct["C"] + ), + db=lipid_comb_dct[_lipid]["M_DB"], + ) else: - lipid_bulk_str = '{tg}({lk}{c}:{db})'.format(tg=lipid_class, lk=_fa1_info_dct['LINK'], - c=(_fa1_info_dct['C'] + _fa2_info_dct['C'] - + _fa3_info_dct['C']), - db=lipid_comb_dct[_lipid]['M_DB']) + lipid_bulk_str = "{tg}({lk}{c}:{db})".format( + tg=lipid_class, + lk=_fa1_info_dct["LINK"], + c=( + _fa1_info_dct["C"] + _fa2_info_dct["C"] + _fa3_info_dct["C"] + ), + db=lipid_comb_dct[_lipid]["M_DB"], + ) # Todo: check SM section below: - elif lipid_class in ['SM']: - lipid_bulk_str = '{sm}({c}:{db})'.format(sm=lipid_class, - c=_fa1_info_dct['C'] + _fa2_info_dct['C'], - db=lipid_comb_dct[_lipid]['M_DB']) + elif lipid_class in ["SM"]: + lipid_bulk_str = "{sm}({c}:{db})".format( + sm=lipid_class, + c=_fa1_info_dct["C"] + _fa2_info_dct["C"], + db=lipid_comb_dct[_lipid]["M_DB"], + ) else: - lipid_bulk_str = '' + lipid_bulk_str = "" - _lipid_dct['BULK_ABBR'] = lipid_bulk_str + _lipid_dct["BULK_ABBR"] = lipid_bulk_str _lipid_formula, _lipid_elem_dct = elem_calc.get_formula(lipid_bulk_str) - _lipid_dct['FORMULA'] = _lipid_formula - _lipid_dct['EXACTMASS'] = elem_calc.get_exactmass(_lipid_elem_dct) + _lipid_dct["FORMULA"] = _lipid_formula + _lipid_dct["EXACTMASS"] = elem_calc.get_exactmass(_lipid_elem_dct) for _elem_k in list(_lipid_elem_dct.keys()): - _lipid_dct['M_' + _elem_k] = _lipid_elem_dct[_elem_k] + _lipid_dct["M_" + _elem_k] = _lipid_elem_dct[_elem_k] # charged - _chg_lipid_formula, _chg_lipid_elem_dct = elem_calc.get_formula(lipid_bulk_str, charge=lipid_charge) - _lipid_dct[lipid_charge + '_FORMULA'] = _chg_lipid_formula - _lipid_dct[lipid_charge + '_MZ'] = elem_calc.get_exactmass(_chg_lipid_elem_dct) + _chg_lipid_formula, _chg_lipid_elem_dct = elem_calc.get_formula( + lipid_bulk_str, charge=lipid_charge + ) + _lipid_dct[lipid_charge + "_FORMULA"] = _chg_lipid_formula + _lipid_dct[lipid_charge + "_MZ"] = elem_calc.get_exactmass( + _chg_lipid_elem_dct + ) # fragments - _lipid_dct = self.calc_fragments(_lipid_dct, charge=lipid_charge, ms2_ppm=ms2_ppm) + _lipid_dct = self.calc_fragments( + _lipid_dct, charge=lipid_charge, ms2_ppm=ms2_ppm + ) lipid_info_dct[_lipid] = _lipid_dct del _lipid_dct diff --git a/LibLipidHunter/LipidHunter_Main.py b/LibLipidHunter/LipidHunter_Main.py index c099034..d74eb14 100644 --- a/LibLipidHunter/LipidHunter_Main.py +++ b/LibLipidHunter/LipidHunter_Main.py @@ -38,19 +38,19 @@ class LipidHunterMain(QtGui.QMainWindow, Ui_MainWindow): def __init__(self, parent=None, cwd=None): scale = 1 config = configparser.ConfigParser() - config.read('config.ini') - if config.has_section('settings'): - user_cfg = 'settings' + config.read("config.ini") + if config.has_section("settings"): + user_cfg = "settings" else: - if config.has_section('default'): - user_cfg = 'default' + if config.has_section("default"): + user_cfg = "default" else: - user_cfg = '' + user_cfg = "" if len(user_cfg) > 2: options = config.options(user_cfg) - if 'gui_scale' in options: + if "gui_scale" in options: try: - scale = float(config.get(user_cfg, 'gui_scale')) + scale = float(config.get(user_cfg, "gui_scale")) except (ValueError, TypeError): pass if scale != 1: @@ -58,38 +58,43 @@ def __init__(self, parent=None, cwd=None): scale = 2.75 elif scale < 0.75: scale = 0.75 - print('[INFO] Using GUI scale x{0}'.format(scale)) + print("[INFO] Using GUI scale x{0}".format(scale)) QtGui.QMainWindow.__init__(self, parent) self.ui = Ui_MainWindow() self.ui.setupUi(self, scale=scale) # set version - version_date = r'06, August, 2019' - version_html = (r'

' - r'LipidHunter 2 (RC2) # Released Date: {version_date}' - r'

').format(version_date=version_date) - self.ui.version_lb.setText(QtGui.QApplication.translate("MainWindow", version_html, None, - QtGui.QApplication.UnicodeUTF8)) + version_date = r"06, August, 2019" + version_html = ( + r'

' + r"LipidHunter 2 (RC2) # Released Date: {version_date}" + r"

" + ).format(version_date=version_date) + self.ui.version_lb.setText( + QtGui.QApplication.translate( + "MainWindow", version_html, None, QtGui.QApplication.UnicodeUTF8 + ) + ) # current folder: if cwd is not None: - print('User LipidHunter folder', cwd) + print("User LipidHunter folder", cwd) self.lipidhunter_cwd = cwd else: auto_cwd = os.getcwd() - print('User LipidHunter folder', auto_cwd) + print("User LipidHunter folder", auto_cwd) self.lipidhunter_cwd = auto_cwd self.load_cfg() self.a_max_ms() # disable un necessary UI elements - q_pgb_style = ''' + q_pgb_style = """ QProgressBar:horizontal { border: 1px #CCCCCC; border-radius: 0px; background: #CCCCCC; padding: 1px;} QProgressBar::chunk:horizontal { background: qlineargradient(x1: 0, y1: 0.5, x2: 0, y2: 0.5, stop: 0 #FF8C00, stop: 1 white);} - ''' + """ self.ui.tab_a_runhunter_pgb.setStyleSheet(q_pgb_style) self.ui.tab_a_runhunter_pgb.hide() @@ -141,176 +146,311 @@ def __init__(self, parent=None, cwd=None): self.lm_worker.info_update.connect(self.lm_worker_info_update) # slots for tab a - QtCore.QObject.connect(self.ui.tab_a_lipidclass_cmb, QtCore.SIGNAL("currentIndexChanged(const QString&)"), - self.a_lipid_class_fa_list) - QtCore.QObject.connect(self.ui.mode_lcms_rb, QtCore.SIGNAL("clicked()"), self.a_set_lc_mode) - QtCore.QObject.connect(self.ui.mode_static_rb, QtCore.SIGNAL("clicked()"), self.a_set_static_mode) - QtCore.QObject.connect(self.ui.tab_a_loadfalist_pb, QtCore.SIGNAL("clicked()"), self.a_load_xlsx) - QtCore.QObject.connect(self.ui.tab_a_loadscorecfg_pb, QtCore.SIGNAL("clicked()"), self.a_loadscore_xlsx) + QtCore.QObject.connect( + self.ui.tab_a_lipidclass_cmb, + QtCore.SIGNAL("currentIndexChanged(const QString&)"), + self.a_lipid_class_fa_list, + ) + QtCore.QObject.connect( + self.ui.mode_lcms_rb, QtCore.SIGNAL("clicked()"), self.a_set_lc_mode + ) + QtCore.QObject.connect( + self.ui.mode_static_rb, QtCore.SIGNAL("clicked()"), self.a_set_static_mode + ) + QtCore.QObject.connect( + self.ui.tab_a_loadfalist_pb, QtCore.SIGNAL("clicked()"), self.a_load_xlsx + ) + QtCore.QObject.connect( + self.ui.tab_a_loadscorecfg_pb, + QtCore.SIGNAL("clicked()"), + self.a_loadscore_xlsx, + ) # QtCore.QObject.connect(self.ui.tab_a_launchgen_pb, QtCore.SIGNAL("clicked()"), self.a_go_generator) - QtCore.QObject.connect(self.ui.tab_a_mzml_pb, QtCore.SIGNAL("clicked()"), self.a_load_mzml) - QtCore.QObject.connect(self.ui.tab_a_saveimgfolder_pb, QtCore.SIGNAL("clicked()"), self.a_save_img2folder) - QtCore.QObject.connect(self.ui.tab_a_msmax_chb, QtCore.SIGNAL("clicked()"), self.a_max_ms) - QtCore.QObject.connect(self.ui.tab_a_sumxlsxpath_pb, QtCore.SIGNAL("clicked()"), self.a_save_output) + QtCore.QObject.connect( + self.ui.tab_a_mzml_pb, QtCore.SIGNAL("clicked()"), self.a_load_mzml + ) + QtCore.QObject.connect( + self.ui.tab_a_saveimgfolder_pb, + QtCore.SIGNAL("clicked()"), + self.a_save_img2folder, + ) + QtCore.QObject.connect( + self.ui.tab_a_msmax_chb, QtCore.SIGNAL("clicked()"), self.a_max_ms + ) + QtCore.QObject.connect( + self.ui.tab_a_sumxlsxpath_pb, QtCore.SIGNAL("clicked()"), self.a_save_output + ) # QtCore.QObject.connect(self.ui.tab_a_runhunter_pb, QtCore.SIGNAL("clicked()"), self.a_run_hunter) - QtCore.QObject.connect(self.ui.tab_a_runhunter_pb, QtCore.SIGNAL("clicked()"), self.single_worker_hunter) - QtCore.QObject.connect(self.ui.tab_a_cfgpath_pb, QtCore.SIGNAL("clicked()"), self.a_save_cfg) - QtCore.QObject.connect(self.ui.tab_a_gencfg_pb, QtCore.SIGNAL("clicked()"), self.a_create_cfg) + QtCore.QObject.connect( + self.ui.tab_a_runhunter_pb, + QtCore.SIGNAL("clicked()"), + self.single_worker_hunter, + ) + QtCore.QObject.connect( + self.ui.tab_a_cfgpath_pb, QtCore.SIGNAL("clicked()"), self.a_save_cfg + ) + QtCore.QObject.connect( + self.ui.tab_a_gencfg_pb, QtCore.SIGNAL("clicked()"), self.a_create_cfg + ) # # slots for tab b - self.ui.tab_b_mutlimode_cmb.currentIndexChanged['QString'].connect(self.b_set_multi_mode) - QtCore.QObject.connect(self.ui.tab_b_addcfg_pb, QtCore.SIGNAL("clicked()"), self.b_load_batchcfg) - QtCore.QObject.connect(self.ui.tab_b_addcfgfolder_pb, QtCore.SIGNAL("clicked()"), self.b_load_batchcfgfolder) - QtCore.QObject.connect(self.ui.tab_b_clearall_pb, QtCore.SIGNAL("clicked()"), self.ui.tab_b_infiles_pte.clear) + self.ui.tab_b_mutlimode_cmb.currentIndexChanged["QString"].connect( + self.b_set_multi_mode + ) + QtCore.QObject.connect( + self.ui.tab_b_addcfg_pb, QtCore.SIGNAL("clicked()"), self.b_load_batchcfg + ) + QtCore.QObject.connect( + self.ui.tab_b_addcfgfolder_pb, + QtCore.SIGNAL("clicked()"), + self.b_load_batchcfgfolder, + ) + QtCore.QObject.connect( + self.ui.tab_b_clearall_pb, + QtCore.SIGNAL("clicked()"), + self.ui.tab_b_infiles_pte.clear, + ) # QtCore.QObject.connect(self.ui.tab_b_runbatch_pb, QtCore.SIGNAL("clicked()"), self.b_run_batchmode) - QtCore.QObject.connect(self.ui.tab_b_runbatch_pb, QtCore.SIGNAL("clicked()"), self.batch_worker_hunter) + QtCore.QObject.connect( + self.ui.tab_b_runbatch_pb, + QtCore.SIGNAL("clicked()"), + self.batch_worker_hunter, + ) # # slots for tab c - QtCore.QObject.connect(self.ui.tab_c_falistpl_pb, QtCore.SIGNAL("clicked()"), self.c_load_falist_pl) - QtCore.QObject.connect(self.ui.tab_c_falisttg_pb, QtCore.SIGNAL("clicked()"), self.c_load_falist_tg) - QtCore.QObject.connect(self.ui.tab_c_lmcalcfalist_pb, QtCore.SIGNAL("clicked()"), self.c_load_falist_dg) - QtCore.QObject.connect(self.ui.tab_c_hgcfg_pb, QtCore.SIGNAL("clicked()"), self.c_load_hgcfg) - QtCore.QObject.connect(self.ui.tab_c_scorecfgpl_pb, QtCore.SIGNAL("clicked()"), self.c_load_scorecfg_pl) - QtCore.QObject.connect(self.ui.tab_c_scorecfgtg_pb, QtCore.SIGNAL("clicked()"), self.c_load_scorecfg_tg) - QtCore.QObject.connect(self.ui.tab_c_scorecfgdg_pb, QtCore.SIGNAL("clicked()"), self.c_load_scorecfg_dg) - QtCore.QObject.connect(self.ui.tab_c_savesettings_pb, QtCore.SIGNAL("clicked()"), self.c_set_default_cfg) - QtCore.QObject.connect(self.ui.tab_c_lmexport_pb, QtCore.SIGNAL("clicked()"), self.c_lmexport) - QtCore.QObject.connect(self.ui.tab_c_lmrun_pb, QtCore.SIGNAL("clicked()"), self.lm_worker_hunter) + QtCore.QObject.connect( + self.ui.tab_c_falistpl_pb, QtCore.SIGNAL("clicked()"), self.c_load_falist_pl + ) + QtCore.QObject.connect( + self.ui.tab_c_falisttg_pb, QtCore.SIGNAL("clicked()"), self.c_load_falist_tg + ) + QtCore.QObject.connect( + self.ui.tab_c_lmcalcfalist_pb, + QtCore.SIGNAL("clicked()"), + self.c_load_falist_dg, + ) + QtCore.QObject.connect( + self.ui.tab_c_hgcfg_pb, QtCore.SIGNAL("clicked()"), self.c_load_hgcfg + ) + QtCore.QObject.connect( + self.ui.tab_c_scorecfgpl_pb, + QtCore.SIGNAL("clicked()"), + self.c_load_scorecfg_pl, + ) + QtCore.QObject.connect( + self.ui.tab_c_scorecfgtg_pb, + QtCore.SIGNAL("clicked()"), + self.c_load_scorecfg_tg, + ) + QtCore.QObject.connect( + self.ui.tab_c_scorecfgdg_pb, + QtCore.SIGNAL("clicked()"), + self.c_load_scorecfg_dg, + ) + QtCore.QObject.connect( + self.ui.tab_c_savesettings_pb, + QtCore.SIGNAL("clicked()"), + self.c_set_default_cfg, + ) + QtCore.QObject.connect( + self.ui.tab_c_lmexport_pb, QtCore.SIGNAL("clicked()"), self.c_lmexport + ) + QtCore.QObject.connect( + self.ui.tab_c_lmrun_pb, QtCore.SIGNAL("clicked()"), self.lm_worker_hunter + ) # load configurations def load_cfg(self): # set click able external links - for _link_lb in (self.ui.link_gplv2_lb, self.ui.link_source_lb, self.ui.link_tutorial_lb, - self.ui.link_paper_lb, self.ui.link_otherprojects_lb, self.ui.link_matplotlib_lb, - self.ui.link_numpy_lb, self.ui.link_pandas_lb, self.ui.link_pymzml_lb, self.ui.link_pyside_lb, - self.ui.link_bmbf_lb, self.ui.link_emed_lb, self.ui.link_sysmedos_lb, self.ui.link_uni_lb): + for _link_lb in ( + self.ui.link_gplv2_lb, + self.ui.link_source_lb, + self.ui.link_tutorial_lb, + self.ui.link_paper_lb, + self.ui.link_otherprojects_lb, + self.ui.link_matplotlib_lb, + self.ui.link_numpy_lb, + self.ui.link_pandas_lb, + self.ui.link_pymzml_lb, + self.ui.link_pyside_lb, + self.ui.link_bmbf_lb, + self.ui.link_emed_lb, + self.ui.link_sysmedos_lb, + self.ui.link_uni_lb, + ): _link_lb.setOpenExternalLinks(True) # self.ui.logo_lb.setOpenExternalLinks(True) config = configparser.ConfigParser() - config.read('config.ini') - if config.has_section('settings'): - user_cfg = 'settings' + config.read("config.ini") + if config.has_section("settings"): + user_cfg = "settings" else: - if config.has_section('default'): - user_cfg = 'default' + if config.has_section("default"): + user_cfg = "default" else: - user_cfg = '' + user_cfg = "" if len(user_cfg) > 2: options = config.options(user_cfg) - if 'fa_white_list_cfg_pl' in options: - pl_fawhitelist_path_str = config.get(user_cfg, 'fa_white_list_cfg_pl') - pl_fawhitelist_path_str, error_log = self.check_file(pl_fawhitelist_path_str, 'FA whitelist for PL') + if "fa_white_list_cfg_pl" in options: + pl_fawhitelist_path_str = config.get(user_cfg, "fa_white_list_cfg_pl") + pl_fawhitelist_path_str, error_log = self.check_file( + pl_fawhitelist_path_str, "FA whitelist for PL" + ) if error_log is not None: self.ui.tab_c_falistpl_le.setText(error_log) else: self.ui.tab_c_falistpl_le.setText(pl_fawhitelist_path_str) - if 'lipid_specific_cfg' in options: - lipid_specific_path_str = config.get(user_cfg, 'lipid_specific_cfg') - lipid_specific_path_str, error_log = self.check_file(lipid_specific_path_str, 'lipid_specific_cfg') + if "lipid_specific_cfg" in options: + lipid_specific_path_str = config.get(user_cfg, "lipid_specific_cfg") + lipid_specific_path_str, error_log = self.check_file( + lipid_specific_path_str, "lipid_specific_cfg" + ) if error_log is not None: self.ui.tab_c_hgcfg_le.setText(error_log) else: self.ui.tab_c_hgcfg_le.setText(lipid_specific_path_str) - if 'score_cfg_lpl' in options: - lpl_score_cfg_path_str = config.get(user_cfg, 'score_cfg_lpl') - lpl_score_cfg_path_str, error_log = self.check_file(lpl_score_cfg_path_str, 'Score cfg for LPL') + if "score_cfg_lpl" in options: + lpl_score_cfg_path_str = config.get(user_cfg, "score_cfg_lpl") + lpl_score_cfg_path_str, error_log = self.check_file( + lpl_score_cfg_path_str, "Score cfg for LPL" + ) if error_log is not None: self.ui.tab_c_falisttg_le.setText(error_log) else: self.ui.tab_c_falisttg_le.setText(lpl_score_cfg_path_str) - if 'score_cfg_pl' in options: - self.ui.tab_c_scorecfgpl_le.setText(config.get(user_cfg, 'score_cfg_pl')) - pl_score_cfg_path_str = config.get(user_cfg, 'score_cfg_pl') - pl_score_cfg_path_str, error_log = self.check_file(pl_score_cfg_path_str, 'Score cfg for PL') + if "score_cfg_pl" in options: + self.ui.tab_c_scorecfgpl_le.setText( + config.get(user_cfg, "score_cfg_pl") + ) + pl_score_cfg_path_str = config.get(user_cfg, "score_cfg_pl") + pl_score_cfg_path_str, error_log = self.check_file( + pl_score_cfg_path_str, "Score cfg for PL" + ) if error_log is not None: self.ui.tab_c_scorecfgpl_le.setText(error_log) else: self.ui.tab_c_scorecfgpl_le.setText(pl_score_cfg_path_str) - if 'score_cfg_tg' in options: - pl_score_cfg_path_str = config.get(user_cfg, 'score_cfg_tg') - pl_score_cfg_path_str, error_log = self.check_file(pl_score_cfg_path_str, 'Score cfg for TG') + if "score_cfg_tg" in options: + pl_score_cfg_path_str = config.get(user_cfg, "score_cfg_tg") + pl_score_cfg_path_str, error_log = self.check_file( + pl_score_cfg_path_str, "Score cfg for TG" + ) if error_log is not None: self.ui.tab_c_scorecfgtg_le.setText(error_log) else: self.ui.tab_c_scorecfgtg_le.setText(pl_score_cfg_path_str) - if 'score_cfg_dg' in options: - pl_score_cfg_path_str = config.get(user_cfg, 'score_cfg_dg') - pl_score_cfg_path_str, error_log = self.check_file(pl_score_cfg_path_str, 'Score cfg for DG') + if "score_cfg_dg" in options: + pl_score_cfg_path_str = config.get(user_cfg, "score_cfg_dg") + pl_score_cfg_path_str, error_log = self.check_file( + pl_score_cfg_path_str, "Score cfg for DG" + ) if error_log is not None: self.ui.tab_c_scorecfgdg_le.setText(error_log) else: self.ui.tab_c_scorecfgdg_le.setText(pl_score_cfg_path_str) - if 'score_mode' in options: - if config.get(user_cfg, 'score_mode').upper() in ['RANK', '']: + if "score_mode" in options: + if config.get(user_cfg, "score_mode").upper() in ["RANK", ""]: self.ui.tab_c_scoremode_cmb.setCurrentIndex(0) - elif config.get(user_cfg, 'score_mode') is None: + elif config.get(user_cfg, "score_mode") is None: self.ui.tab_c_scoremode_cmb.setCurrentIndex(0) - elif config.get(user_cfg, 'score_mode').upper() == 'INTENSITY': + elif config.get(user_cfg, "score_mode").upper() == "INTENSITY": self.ui.tab_c_scoremode_cmb.setCurrentIndex(1) else: self.ui.tab_c_scoremode_cmb.setCurrentIndex(0) else: self.ui.tab_c_scoremode_cmb.setCurrentIndex(0) - if 'isotope_13c_mode' in options: - if config.get(user_cfg, 'isotope_13c_mode').upper() == 'ON': + if "isotope_13c_mode" in options: + if config.get(user_cfg, "isotope_13c_mode").upper() == "ON": self.ui.tab_c_isotopescoremode_cmb.setCurrentIndex(1) - elif config.get(user_cfg, 'isotope_13c_mode').upper() == 'OFF': + elif config.get(user_cfg, "isotope_13c_mode").upper() == "OFF": self.ui.tab_c_isotopescoremode_cmb.setCurrentIndex(0) else: self.ui.tab_c_isotopescoremode_cmb.setCurrentIndex(0) else: self.ui.tab_c_isotopescoremode_cmb.setCurrentIndex(0) - if 'parallel_target' in options: - if config.get(user_cfg, 'parallel_target').upper() == 'CPU': + if "parallel_target" in options: + if config.get(user_cfg, "parallel_target").upper() == "CPU": self.ui.tab_c_parallization_cmb.setCurrentIndex(0) - elif config.get(user_cfg, 'parallel_target') in ['CPU_and_GPU', 'GPU', 'CPUandGPU', 'CPUGPU', - 'parallel']: + elif config.get(user_cfg, "parallel_target") in [ + "CPU_and_GPU", + "GPU", + "CPUandGPU", + "CPUGPU", + "parallel", + ]: self.ui.tab_c_parallization_cmb.setCurrentIndex(1) else: self.ui.tab_c_parallization_cmb.setCurrentIndex(0) - if 'max_cpu_core' in options: - self.ui.tab_c_cores_spb.setValue(int(config.get(user_cfg, 'max_cpu_core'))) - if 'max_ram' in options: - self.ui.tab_c_ram_spb.setValue(int(config.get(user_cfg, 'max_ram'))) - if 'img_type' in options: - if config.get(user_cfg, 'img_type').upper() == 'PNG': + if "max_cpu_core" in options: + self.ui.tab_c_cores_spb.setValue( + int(config.get(user_cfg, "max_cpu_core")) + ) + if "max_ram" in options: + self.ui.tab_c_ram_spb.setValue(int(config.get(user_cfg, "max_ram"))) + if "img_type" in options: + if config.get(user_cfg, "img_type").upper() == "PNG": self.ui.tab_c_imagetype_cmb.setCurrentIndex(0) - elif config.get(user_cfg, 'img_type').upper() == 'SVG': + elif config.get(user_cfg, "img_type").upper() == "SVG": self.ui.tab_c_imagetype_cmb.setCurrentIndex(1) else: self.ui.tab_c_imagetype_cmb.setCurrentIndex(0) - if 'img_dpi' in options: - self.ui.tab_c_dpi_spb.setValue(int(config.get(user_cfg, 'img_dpi'))) + if "img_dpi" in options: + self.ui.tab_c_dpi_spb.setValue(int(config.get(user_cfg, "img_dpi"))) else: self.ui.tab_c_dpi_spb.setValue(300) - if 'tag_all_fa_check' in options: - if config.get(user_cfg, 'tag_all_fa_check').upper() == 'ON': + if "tag_all_fa_check" in options: + if config.get(user_cfg, "tag_all_fa_check").upper() == "ON": self.ui.tab_c_tag_all_fa_chb.setChecked(True) else: self.ui.tab_c_tag_all_fa_chb.setChecked(False) else: self.ui.tab_c_tag_all_fa_chb.setChecked(True) # UI settings - if 'main_tab' in options and 1 <= int(config.get(user_cfg, 'main_tab')) <= 5: - self.ui.tabframe.setCurrentIndex(int(config.get(user_cfg, 'main_tab')) - 1) + if ( + "main_tab" in options + and 1 <= int(config.get(user_cfg, "main_tab")) <= 5 + ): + self.ui.tabframe.setCurrentIndex( + int(config.get(user_cfg, "main_tab")) - 1 + ) else: self.ui.tabframe.setCurrentIndex(0) - if 'runhunter_tab' in options and 1 <= int(config.get(user_cfg, 'runhunter_tab')) <= 2: - self.ui.runhunter_tabframe.setCurrentIndex(int(config.get(user_cfg, 'runhunter_tab')) - 1) + if ( + "runhunter_tab" in options + and 1 <= int(config.get(user_cfg, "runhunter_tab")) <= 2 + ): + self.ui.runhunter_tabframe.setCurrentIndex( + int(config.get(user_cfg, "runhunter_tab")) - 1 + ) else: self.ui.runhunter_tabframe.setCurrentIndex(0) - if 'lipidgen_tab' in options and 1 <= int(config.get(user_cfg, 'lipidgen_tab')) <= 2: - self.ui.lipidgen_tabframe.setCurrentIndex(int(config.get(user_cfg, 'lipidgen_tab')) - 1) + if ( + "lipidgen_tab" in options + and 1 <= int(config.get(user_cfg, "lipidgen_tab")) <= 2 + ): + self.ui.lipidgen_tabframe.setCurrentIndex( + int(config.get(user_cfg, "lipidgen_tab")) - 1 + ) else: self.ui.lipidgen_tabframe.setCurrentIndex(0) - if 'default_vendor' in options and 0 <= int(config.get(user_cfg, 'default_vendor')) <= 4: - self.ui.vendor_cmb.setCurrentIndex(int(config.get(user_cfg, 'default_vendor'))) + if ( + "default_vendor" in options + and 0 <= int(config.get(user_cfg, "default_vendor")) <= 4 + ): + self.ui.vendor_cmb.setCurrentIndex( + int(config.get(user_cfg, "default_vendor")) + ) else: self.ui.vendor_cmb.setCurrentIndex(0) - if 'default_lipid' in options and 0 <= int(config.get(user_cfg, 'default_lipid')) <= 9: - self.ui.tab_a_lipidclass_cmb.setCurrentIndex(int(config.get(user_cfg, 'default_lipid'))) + if ( + "default_lipid" in options + and 0 <= int(config.get(user_cfg, "default_lipid")) <= 9 + ): + self.ui.tab_a_lipidclass_cmb.setCurrentIndex( + int(config.get(user_cfg, "default_lipid")) + ) else: self.ui.tab_a_lipidclass_cmb.setCurrentIndex(0) @@ -323,7 +463,7 @@ def get_same_files(folder, filetype_lst): :return: a list of absolute file path :rtype: list """ - if folder is not '': + if folder is not "": os.chdir(folder) _pre_found_lst = [] for _filetype in filetype_lst: @@ -350,27 +490,27 @@ def open_file(self, info_str, lb_obj): @staticmethod def check_file(usr_path, info_str): - file_abs_path = '' + file_abs_path = "" try: if os.path.isfile(usr_path): error_log = None file_abs_path = os.path.abspath(usr_path) else: - error_log = '!! Failed to load {_file} !!'.format(_file=info_str) + error_log = "!! Failed to load {_file} !!".format(_file=info_str) except IOError: - error_log = '!! Failed to load {_file} !!'.format(_file=info_str) + error_log = "!! Failed to load {_file} !!".format(_file=info_str) return file_abs_path, error_log @staticmethod def check_folder(usr_path, info_str): - folder_abs_path = '' + folder_abs_path = "" try: if os.path.isdir(usr_path): - print('Folder existed...\n', usr_path) + print("Folder existed...\n", usr_path) error_log = None folder_abs_path = os.path.abspath(usr_path) - print('abs path of folder\n', folder_abs_path) + print("abs path of folder\n", folder_abs_path) # else: # if platform == "linux" or platform == "linux2": # l_cwd = os.getcwd() @@ -393,28 +533,28 @@ def check_folder(usr_path, info_str): # error_log = '' # os.chdir(l_cwd) else: - print('No folder...\n', usr_path) + print("No folder...\n", usr_path) os.makedirs(usr_path) - print('Folder created... %s' % usr_path) - error_log = '' + print("Folder created... %s" % usr_path) + error_log = "" except IOError: - error_log = '!! Failed to open folder {_file} !!'.format(_file=info_str) + error_log = "!! Failed to open folder {_file} !!".format(_file=info_str) return folder_abs_path, error_log def a_load_xlsx(self): - file_info_str = 'FA white list files (*.xlsx *.XLSX)' + file_info_str = "FA white list files (*.xlsx *.XLSX)" self.open_file(file_info_str, self.ui.tab_a_loadfalist_le) def a_loadscore_xlsx(self): - file_info_str = 'Weight list files (*.xlsx *.XLSX)' + file_info_str = "Weight list files (*.xlsx *.XLSX)" self.open_file(file_info_str, self.ui.tab_a_loadscorecfg_le) # def a_go_generator(self): # self.ui.tabframe.setCurrentIndex(3) def a_load_mzml(self): - file_info_str = 'mzML spectra files (*.mzML *.mzml)' + file_info_str = "mzML spectra files (*.mzML *.mzml)" self.open_file(file_info_str, self.ui.tab_a_mzml_le) def a_save_img2folder(self): @@ -423,11 +563,13 @@ def a_save_img2folder(self): self.ui.tab_a_saveimgfolder_le.setText(a_save_img2folder_str) def a_save_output(self): - a_save_output_path = QtGui.QFileDialog.getSaveFileName(caption='Save file', filter='.xlsx') + a_save_output_path = QtGui.QFileDialog.getSaveFileName( + caption="Save file", filter=".xlsx" + ) self.ui.tab_a_savexlsxpath_le.clear() usr_output_path = a_save_output_path[0] - if usr_output_path[-5:] != '.xlsx': - usr_output_path += '.xlsx' + if usr_output_path[-5:] != ".xlsx": + usr_output_path += ".xlsx" a_save_output_str = os.path.abspath(usr_output_path) self.ui.tab_a_savexlsxpath_le.setText(a_save_output_str) @@ -435,7 +577,9 @@ def a_save_output(self): def a_max_ms(self): if self.ui.tab_a_msmax_chb.isChecked(): self.ui.tab_a_msmax_spb.show() - self.ui.tab_a_msmax_spb.setValue(100 * self.ui.tab_a_msthreshold_spb.value()) + self.ui.tab_a_msmax_spb.setValue( + 100 * self.ui.tab_a_msthreshold_spb.value() + ) else: self.ui.tab_a_msmax_spb.hide() self.ui.tab_a_msmax_spb.setValue(0) @@ -450,7 +594,7 @@ def a_set_static_mode(self): def a_lipid_class_fa_list(self): _lipid_class_info = str(self.ui.tab_a_lipidclass_cmb.currentText()) - lipid_class_checker = re.compile(r'(.*)( [(])(\w{2,3})([)] )(.*)') + lipid_class_checker = re.compile(r"(.*)( [(])(\w{2,3})([)] )(.*)") lipid_class_match = lipid_class_checker.match(_lipid_class_info) if lipid_class_match: @@ -458,8 +602,8 @@ def a_lipid_class_fa_list(self): _lipid_class = lipid_class_info_lst[2] _lipid_charge = lipid_class_info_lst[4] else: - _lipid_class = '' - _lipid_charge = '' + _lipid_class = "" + _lipid_charge = "" pl_fa_cfg = self.ui.tab_c_falistpl_le.text() lpl_score_cfg = self.ui.tab_c_falisttg_le.text() @@ -469,7 +613,7 @@ def a_lipid_class_fa_list(self): usr_fa_cfg = self.ui.tab_a_loadfalist_le.text() usr_score_cfg = self.ui.tab_a_loadscorecfg_le.text() - if _lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PIP', 'PS']: + if _lipid_class in ["PA", "PC", "PE", "PG", "PI", "PIP", "PS"]: # if usr_fa_cfg in ['', tg_fa_cfg]: self.ui.tab_a_loadfalist_le.setText(pl_fa_cfg) # if usr_score_cfg in ['', dg_score_cfg, tg_score_cfg]: @@ -480,7 +624,7 @@ def a_lipid_class_fa_list(self): if self.ui.mode_lcms_rb.isChecked(): self.ui.tab_a_rtstart_dspb.setValue(10.0) self.ui.tab_a_rtend_dspb.setValue(25.0) - elif _lipid_class in ['LPA', 'LPC', 'LPE', 'LPG', 'LPI', 'LPIP', 'LPS']: + elif _lipid_class in ["LPA", "LPC", "LPE", "LPG", "LPI", "LPIP", "LPS"]: # if usr_fa_cfg in ['', tg_fa_cfg]: self.ui.tab_a_loadfalist_le.setText(pl_fa_cfg) # if usr_score_cfg in ['', dg_score_cfg, tg_score_cfg]: @@ -491,7 +635,7 @@ def a_lipid_class_fa_list(self): if self.ui.mode_lcms_rb.isChecked(): self.ui.tab_a_rtstart_dspb.setValue(3.0) self.ui.tab_a_rtend_dspb.setValue(15.0) - elif _lipid_class in ['TG', 'DG', 'MG']: + elif _lipid_class in ["TG", "DG", "MG"]: # if usr_fa_cfg in ['', pl_fa_cfg]: self.ui.tab_a_loadfalist_le.setText(pl_fa_cfg) self.ui.tab_a_mzstart_dspb.setValue(600) @@ -500,15 +644,16 @@ def a_lipid_class_fa_list(self): if self.ui.mode_lcms_rb.isChecked(): self.ui.tab_a_rtstart_dspb.setValue(20.0) self.ui.tab_a_rtend_dspb.setValue(30.0) - if _lipid_class in ['TG'] and _lipid_charge not in ['[M+Na]+']: + if _lipid_class in ["TG"] and _lipid_charge not in ["[M+Na]+"]: # if usr_score_cfg in ['', pl_score_cfg, dg_score_cfg]: self.ui.tab_a_loadscorecfg_le.setText(tg_score_cfg) - elif _lipid_class in ['TG'] and _lipid_charge in ['[M+Na]+']: - tg_na_abs_path, error_log = self.check_file('.\ConfigurationFiles\\2-Score_weight_TG_Na.xlsx', - 'TG [M+Na]+ Weight factor' - ) + elif _lipid_class in ["TG"] and _lipid_charge in ["[M+Na]+"]: + tg_na_abs_path, error_log = self.check_file( + ".\ConfigurationFiles\\2-Score_weight_TG_Na.xlsx", + "TG [M+Na]+ Weight factor", + ) self.ui.tab_a_loadscorecfg_le.setText(tg_na_abs_path) - elif _lipid_class in ['DG']: + elif _lipid_class in ["DG"]: # if usr_score_cfg in ['', pl_score_cfg, tg_score_cfg]: self.ui.tab_a_loadscorecfg_le.setText(dg_score_cfg) self.ui.tab_a_mzstart_dspb.setValue(300) @@ -518,33 +663,38 @@ def a_lipid_class_fa_list(self): self.ui.tab_a_rtstart_dspb.setValue(10.0) self.ui.tab_a_rtend_dspb.setValue(20.0) else: - self.ui.tab_a_loadscorecfg_le.setText('') + self.ui.tab_a_loadscorecfg_le.setText("") else: - self.ui.tab_a_loadfalist_le.setText('') - self.ui.tab_a_loadscorecfg_le.setText('') + self.ui.tab_a_loadfalist_le.setText("") + self.ui.tab_a_loadscorecfg_le.setText("") def a_get_params(self): error_log_lst = [] usr_vendor_str = self.ui.vendor_cmb.currentText().lower() - vendors_dct = {'therm': 'thermo', 'water': 'waters', 'sciex': 'sciex', 'agile': 'agilent'} + vendors_dct = { + "therm": "thermo", + "water": "waters", + "sciex": "sciex", + "agile": "agilent", + } if usr_vendor_str[0:5] in list(vendors_dct.keys()): usr_vendor = vendors_dct[usr_vendor_str[0:5]] else: - usr_vendor = '' - error_log_lst.append('!! Please select an instrument vendor!!') + usr_vendor = "" + error_log_lst.append("!! Please select an instrument vendor!!") if self.ui.mode_lcms_rb.isChecked(): - usr_exp_mode = 'LC-MS' + usr_exp_mode = "LC-MS" elif self.ui.mode_static_rb.isChecked(): - usr_exp_mode = 'Shotgun' + usr_exp_mode = "Shotgun" else: - usr_exp_mode = 'LC-MS' + usr_exp_mode = "LC-MS" _lipid_class_info = str(self.ui.tab_a_lipidclass_cmb.currentText()) - lipid_class_checker = re.compile(r'(.*)( [(])(\w{2,3})([)] )(.*)') + lipid_class_checker = re.compile(r"(.*)( [(])(\w{2,3})([)] )(.*)") lipid_class_match = lipid_class_checker.match(_lipid_class_info) @@ -553,9 +703,9 @@ def a_get_params(self): _lipid_class = lipid_class_info_lst[2] _lipid_charge = lipid_class_info_lst[4] else: - _lipid_class = '' - _lipid_charge = '' - error_log_lst.append('!! Please select a lipid class!!') + _lipid_class = "" + _lipid_charge = "" + error_log_lst.append("!! Please select a lipid class!!") # if _lipid_class in ['PA', 'PC', 'PE', 'PG', 'PI', 'PIP', 'PS']: # score_cfg = self.ui.tab_a_loadscorecfg_le.text() @@ -569,15 +719,15 @@ def a_get_params(self): fawhitelist_path_str = str(self.ui.tab_a_loadfalist_le.text()) mzml_path_str = str(self.ui.tab_a_mzml_le.text()) img_output_folder_str = str(self.ui.tab_a_saveimgfolder_le.text()) - if img_output_folder_str[-1] in ['\\', '/']: + if img_output_folder_str[-1] in ["\\", "/"]: img_output_folder_str = img_output_folder_str[:-1] self.ui.tab_a_saveimgfolder_le.clear() self.ui.tab_a_saveimgfolder_le.setText(img_output_folder_str) else: pass xlsx_output_path_str = str(self.ui.tab_a_savexlsxpath_le.text()) - if xlsx_output_path_str[-5:] != '.xlsx': - xlsx_output_path_str += '.xlsx' + if xlsx_output_path_str[-5:] != ".xlsx": + xlsx_output_path_str += ".xlsx" self.ui.tab_a_savexlsxpath_le.clear() self.ui.tab_a_savexlsxpath_le.setText(xlsx_output_path_str) @@ -596,7 +746,10 @@ def a_get_params(self): ms2_info_threshold = self.ui.tab_a_ms2infoth_dspb.value() * 0.01 ms_max = 0 - if self.ui.tab_a_msmax_chb.isChecked() and self.ui.tab_a_msmax_spb.value() > ms_th + 1: + if ( + self.ui.tab_a_msmax_chb.isChecked() + and self.ui.tab_a_msmax_spb.value() > ms_th + 1 + ): ms_max = self.ui.tab_a_msmax_spb.value() lipid_specific_cfg = self.ui.tab_c_hgcfg_le.text() @@ -605,16 +758,22 @@ def a_get_params(self): img_typ = self.ui.tab_c_imagetype_cmb.currentText()[1:] img_dpi = self.ui.tab_c_dpi_spb.value() - fawhitelist_path_str, error_log = self.check_file(fawhitelist_path_str, 'FA whitelist') + fawhitelist_path_str, error_log = self.check_file( + fawhitelist_path_str, "FA whitelist" + ) if error_log is not None: error_log_lst.append(error_log) - lipid_specific_cfg, error_log = self.check_file(lipid_specific_cfg, 'configuration for Phospholipids') + lipid_specific_cfg, error_log = self.check_file( + lipid_specific_cfg, "configuration for Phospholipids" + ) if error_log is not None: error_log_lst.append(error_log) - score_cfg, error_log = self.check_file(score_cfg, 'W_frag score configuration') + score_cfg, error_log = self.check_file(score_cfg, "W_frag score configuration") if error_log is not None: error_log_lst.append(error_log) - abs_img_output_folder_str, error_log = self.check_folder(img_output_folder_str, 'Output folder') + abs_img_output_folder_str, error_log = self.check_folder( + img_output_folder_str, "Output folder" + ) if error_log is not None: error_log_lst.append(error_log) self.ui.tab_a_saveimgfolder_le.setText(error_log) @@ -625,17 +784,17 @@ def a_get_params(self): if abs_img_output_folder_str != img_output_folder_str: self.ui.tab_a_saveimgfolder_le.clear() self.ui.tab_a_saveimgfolder_le.setText(abs_img_output_folder_str) - print('!! Image output folder not correct !!') - print('>> Propose to save in folder: %s' % abs_img_output_folder_str) + print("!! Image output folder not correct !!") + print(">> Propose to save in folder: %s" % abs_img_output_folder_str) img_output_folder_str = abs_img_output_folder_str - if xlsx_output_path_str[-5:] == '.xlsx': + if xlsx_output_path_str[-5:] == ".xlsx": pass else: - xlsx_output_path_str = '%s.xlsx' % xlsx_output_path_str + xlsx_output_path_str = "%s.xlsx" % xlsx_output_path_str self.ui.tab_a_savexlsxpath_le.setText(xlsx_output_path_str) - error_log_lst.append('!! Excel output path not correct !!') - error_log_lst.append('>> Propose to save as: %s' % xlsx_output_path_str) + error_log_lst.append("!! Excel output path not correct !!") + error_log_lst.append(">> Propose to save as: %s" % xlsx_output_path_str) usr_score_mode = self.ui.tab_c_scoremode_cmb.currentIndex() if usr_score_mode == 0: @@ -658,46 +817,60 @@ def a_get_params(self): score_filter = rank_score_filter - hunter_param_dct = {'vendor': usr_vendor, 'experiment_mode': usr_exp_mode, - 'lipid_class': _lipid_class, 'charge_mode': _lipid_charge, - 'fawhitelist_path_str': fawhitelist_path_str, - 'score_cfg': score_cfg, - 'mzml_path_str': mzml_path_str, - 'img_output_folder_str': img_output_folder_str, - 'xlsx_output_path_str': xlsx_output_path_str, - 'rt_start': rt_start, 'rt_end': rt_end, - 'mz_start': mz_start, 'mz_end': mz_end, - 'dda_top': dda_top, 'pr_window': pr_window, - 'ms_th': ms_th, 'ms_ppm': ms_ppm, - 'ms2_th': ms2_th, 'ms2_ppm': ms2_ppm, 'ms2_infopeak_threshold': ms2_info_threshold, - 'rank_score_filter': rank_score_filter, 'score_filter': score_filter, - 'isotope_score_filter': isotope_score_filter, - 'lipid_specific_cfg': lipid_specific_cfg, - 'core_number': core_num, 'max_ram': max_ram, - 'img_type': img_typ, 'img_dpi': img_dpi, - 'hunter_folder': self.lipidhunter_cwd, - 'hunter_start_time': start_time_str, - } - debug_mode = 'OFF' - if debug_mode == 'ON': - hunter_param_dct['rank_score'] = rank_score - hunter_param_dct['tag_all_sn'] = tag_all_sn - hunter_param_dct['fast_isotope'] = fast_isotope - hunter_param_dct['ms_max'] = ms_max + hunter_param_dct = { + "vendor": usr_vendor, + "experiment_mode": usr_exp_mode, + "lipid_class": _lipid_class, + "charge_mode": _lipid_charge, + "fawhitelist_path_str": fawhitelist_path_str, + "score_cfg": score_cfg, + "mzml_path_str": mzml_path_str, + "img_output_folder_str": img_output_folder_str, + "xlsx_output_path_str": xlsx_output_path_str, + "rt_start": rt_start, + "rt_end": rt_end, + "mz_start": mz_start, + "mz_end": mz_end, + "dda_top": dda_top, + "pr_window": pr_window, + "ms_th": ms_th, + "ms_ppm": ms_ppm, + "ms2_th": ms2_th, + "ms2_ppm": ms2_ppm, + "ms2_infopeak_threshold": ms2_info_threshold, + "rank_score_filter": rank_score_filter, + "score_filter": score_filter, + "isotope_score_filter": isotope_score_filter, + "lipid_specific_cfg": lipid_specific_cfg, + "core_number": core_num, + "max_ram": max_ram, + "img_type": img_typ, + "img_dpi": img_dpi, + "hunter_folder": self.lipidhunter_cwd, + "hunter_start_time": start_time_str, + } + debug_mode = "OFF" + if debug_mode == "ON": + hunter_param_dct["rank_score"] = rank_score + hunter_param_dct["tag_all_sn"] = tag_all_sn + hunter_param_dct["fast_isotope"] = fast_isotope + hunter_param_dct["ms_max"] = ms_max else: - hunter_param_dct['rank_score'] = True - hunter_param_dct['tag_all_sn'] = True - hunter_param_dct['fast_isotope'] = False - hunter_param_dct['ms_max'] = 0 + hunter_param_dct["rank_score"] = True + hunter_param_dct["tag_all_sn"] = True + hunter_param_dct["fast_isotope"] = False + hunter_param_dct["ms_max"] = 0 return hunter_param_dct, error_log_lst def a_save_cfg(self): - a_save_cfg_path = QtGui.QFileDialog.getSaveFileName(caption='Save file', filter='.txt') + a_save_cfg_path = QtGui.QFileDialog.getSaveFileName( + caption="Save file", filter=".txt" + ) self.ui.tab_a_cfgpath_le.clear() usr_cfg_path = a_save_cfg_path[0] - if usr_cfg_path[-4:] != '.txt': - usr_cfg_path += '.txt' + if usr_cfg_path[-4:] != ".txt": + usr_cfg_path += ".txt" a_save_cfg_str = os.path.abspath(usr_cfg_path) self.ui.tab_a_cfgpath_le.setText(a_save_cfg_str) @@ -705,50 +878,66 @@ def a_create_cfg(self): param_cfg_path_str = str(self.ui.tab_a_cfgpath_le.text()) try: - if param_cfg_path_str[-4:] == '.txt': + if param_cfg_path_str[-4:] == ".txt": pass else: - param_cfg_path_str = '%s.txt' % param_cfg_path_str + param_cfg_path_str = "%s.txt" % param_cfg_path_str self.ui.tab_a_cfgpath_le.clear() self.ui.tab_a_cfgpath_le.setText(param_cfg_path_str) param_cfg_directory = os.path.dirname(param_cfg_path_str) if not os.path.exists(param_cfg_directory): os.makedirs(param_cfg_directory) - abs_param_cfg_directory_str, error_log = self.check_folder(param_cfg_directory, 'Settings for batch mode') + abs_param_cfg_directory_str, error_log = self.check_folder( + param_cfg_directory, "Settings for batch mode" + ) if error_log is not None: self.ui.tab_a_gencfg_pte.insertPlainText(error_log) if abs_param_cfg_directory_str != param_cfg_directory: param_cfg_path = os.path.split(param_cfg_path_str) - param_cfg_path_str = os.path.join(abs_param_cfg_directory_str, param_cfg_path[1]) - self.ui.tab_a_gencfg_pte.insertPlainText('>>> try to save as: %s\n' % param_cfg_path_str) + param_cfg_path_str = os.path.join( + abs_param_cfg_directory_str, param_cfg_path[1] + ) + self.ui.tab_a_gencfg_pte.insertPlainText( + ">>> try to save as: %s\n" % param_cfg_path_str + ) except Exception as _err: print(_err) - self.ui.tab_a_gencfg_pte.insertPlainText('!!! Failed to save settings for batch mode !!!\n') - self.ui.tab_a_gencfg_pte.insertPlainText('!! Can not save settings to file !!\n') + self.ui.tab_a_gencfg_pte.insertPlainText( + "!!! Failed to save settings for batch mode !!!\n" + ) + self.ui.tab_a_gencfg_pte.insertPlainText( + "!! Can not save settings to file !!\n" + ) self.ui.tab_a_gencfg_pte.insertPlainText(str(_err)) hunter_param_dct, error_log_lst = self.a_get_params() error_log_lst = [_f for _f in error_log_lst if _f] if len(error_log_lst) > 0: - print('Parameter error:', error_log_lst) - error_log_lst.append('!!! Failed to save settings for batch mode !!!') - error_log_lst.append('>>> Please check your settings, and try to save again ...\n') - self.ui.tab_a_gencfg_pte.appendPlainText('\n'.join(error_log_lst) + '\n') + print("Parameter error:", error_log_lst) + error_log_lst.append("!!! Failed to save settings for batch mode !!!") + error_log_lst.append( + ">>> Please check your settings, and try to save again ...\n" + ) + self.ui.tab_a_gencfg_pte.appendPlainText("\n".join(error_log_lst) + "\n") else: try: config = configparser.ConfigParser() - with open(param_cfg_path_str, 'w') as usr_param_cfg: - config.add_section('parameters') + with open(param_cfg_path_str, "w") as usr_param_cfg: + config.add_section("parameters") for param in list(hunter_param_dct.keys()): - config.set('parameters', str(param), str(hunter_param_dct[param])) + config.set( + "parameters", str(param), str(hunter_param_dct[param]) + ) config.write(usr_param_cfg) - self.ui.tab_a_gencfg_pte.insertPlainText('>>> Successfully saved as: \n') + self.ui.tab_a_gencfg_pte.insertPlainText( + ">>> Successfully saved as: \n" + ) self.ui.tab_a_gencfg_pte.insertPlainText(param_cfg_path_str) - self.ui.tab_a_gencfg_pte.insertPlainText('\n') + self.ui.tab_a_gencfg_pte.insertPlainText("\n") except Exception as _err: print(_err) self.ui.tab_a_gencfg_pte.insertPlainText(str(_err)) @@ -758,7 +947,7 @@ def b_set_multi_mode(self): multi_mode_idx = self.ui.tab_b_mutlimode_cmb.currentIndex() if multi_mode_idx == 1: - print('Set Batch mode to: Multi processing mode') + print("Set Batch mode to: Multi processing mode") self.ui.tab_b_maxbatch_lb.show() self.ui.tab_b_maxbatch_spb.show() self.ui.tab_b_maxsubcore_lb.show() @@ -766,7 +955,7 @@ def b_set_multi_mode(self): self.ui.tab_b_maxsubram_lb.show() self.ui.tab_b_maxsubram_spb.show() elif multi_mode_idx == 0: - print('Set Batch mode to: Single processing mode') + print("Set Batch mode to: Single processing mode") self.ui.tab_b_maxbatch_lb.hide() self.ui.tab_b_maxbatch_spb.hide() self.ui.tab_b_maxsubcore_lb.hide() @@ -777,7 +966,7 @@ def b_set_multi_mode(self): @staticmethod def b_get_same_files(folder, filetype_lst): - if folder is not '': + if folder is not "": os.chdir(folder) _pre_found_lst = [] for _filetype in filetype_lst: @@ -795,53 +984,76 @@ def b_get_same_files(folder, filetype_lst): def b_load_batchcfg(self): # check existed files _loaded_files = str(self.ui.tab_b_infiles_pte.toPlainText()) - _loaded_lst = _loaded_files.split('\n') + _loaded_lst = _loaded_files.split("\n") b_load_cfg_dialog = QtGui.QFileDialog(self) - b_load_cfg_dialog.setNameFilters(['LipidHunter batch mode files (*.txt)']) - b_load_cfg_dialog.selectNameFilter('LipidHunter batch mode files (*.txt)') + b_load_cfg_dialog.setNameFilters(["LipidHunter batch mode files (*.txt)"]) + b_load_cfg_dialog.selectNameFilter("LipidHunter batch mode files (*.txt)") if b_load_cfg_dialog.exec_(): b_load_cfg_str = b_load_cfg_dialog.selectedFiles()[0] b_load_cfg_str = os.path.abspath(b_load_cfg_str) if b_load_cfg_str not in _loaded_lst: - self.ui.tab_b_infiles_pte.insertPlainText(b_load_cfg_str) # take unicode only - self.ui.tab_b_infiles_pte.insertPlainText('\n') + self.ui.tab_b_infiles_pte.insertPlainText( + b_load_cfg_str + ) # take unicode only + self.ui.tab_b_infiles_pte.insertPlainText("\n") else: _msgBox = QtGui.QMessageBox() - _msgBox.setText('Batch config file has been chosen already.') + _msgBox.setText("Batch config file has been chosen already.") _msgBox.exec_() def b_load_batchcfgfolder(self): # check existed files _loaded_files = str(self.ui.tab_b_infiles_pte.toPlainText()) - _loaded_lst = _loaded_files.split('\n') + _loaded_lst = _loaded_files.split("\n") b_load_cfgfolder_str = QtGui.QFileDialog.getExistingDirectory() - _cfg_name_lst, _cfg_path_lst = self.b_get_same_files(b_load_cfgfolder_str, filetype_lst=['*.txt', '*.txt']) - _duplicated_str = '' + _cfg_name_lst, _cfg_path_lst = self.b_get_same_files( + b_load_cfgfolder_str, filetype_lst=["*.txt", "*.txt"] + ) + _duplicated_str = "" for _cfg in _cfg_path_lst: if _cfg not in _loaded_lst: self.ui.tab_b_infiles_pte.insertPlainText(_cfg) - self.ui.tab_b_infiles_pte.insertPlainText('\n') + self.ui.tab_b_infiles_pte.insertPlainText("\n") else: - _duplicated_str = _duplicated_str + _cfg + '\n' + _duplicated_str = _duplicated_str + _cfg + "\n" if len(_duplicated_str) > 0: _msgBox = QtGui.QMessageBox() - _msgBox.setText(_duplicated_str + 'Already chosen. \n Skipped') + _msgBox.setText(_duplicated_str + "Already chosen. \n Skipped") _msgBox.exec_() @staticmethod def b_read_cfg(batch_cfg): cfg_params_dct = {} - cfg_error = '' - - i_type_key_lst = ['ms_th', 'ms2_th', 'ms_ppm', 'ms2_ppm', 'dda_top', 'sn_ratio', - 'core_number', 'max_ram', 'img_dpi', 'ms_max'] - f_type_key_lst = ['rt_start', 'rt_end', 'mz_start', 'mz_end', 'pr_window', 'ms2_infopeak_threshold', - 'score_filter', 'isotope_score_filter', 'rank_score_filter'] - b_type_key_lst = ['rank_score', 'fast_isotope', 'tag_all_sn'] - - print('Input LipidHunter configuration file : ', batch_cfg) + cfg_error = "" + + i_type_key_lst = [ + "ms_th", + "ms2_th", + "ms_ppm", + "ms2_ppm", + "dda_top", + "sn_ratio", + "core_number", + "max_ram", + "img_dpi", + "ms_max", + ] + f_type_key_lst = [ + "rt_start", + "rt_end", + "mz_start", + "mz_end", + "pr_window", + "ms2_infopeak_threshold", + "score_filter", + "isotope_score_filter", + "rank_score_filter", + ] + b_type_key_lst = ["rank_score", "fast_isotope", "tag_all_sn"] + + print("Input LipidHunter configuration file : ", batch_cfg) if os.path.isfile(batch_cfg): with open(batch_cfg) as _cfg_obj: config = configparser.ConfigParser() @@ -850,8 +1062,8 @@ def b_read_cfg(batch_cfg): config.read_file(_cfg_obj) except AttributeError: # for python 2.7.14 config.readfp(_cfg_obj) - if config.has_section('parameters'): - usr_cfg = 'parameters' + if config.has_section("parameters"): + usr_cfg = "parameters" options = config.options(usr_cfg) for param in options: _val = config.get(usr_cfg, param) @@ -863,110 +1075,123 @@ def b_read_cfg(batch_cfg): elif param in f_type_key_lst: cfg_params_dct[param] = float(_val) elif param in b_type_key_lst: - if _val.lower() == 'true': + if _val.lower() == "true": cfg_params_dct[param] = True - if _val.lower() == 'false': + if _val.lower() == "false": cfg_params_dct[param] = False else: cfg_params_dct[param] = _val except Exception as _cfg_e: - print('ERROR', _cfg_e) + print("ERROR", _cfg_e) cfg_error += str(_cfg_e) - cfg_error += '\n' + cfg_error += "\n" return cfg_params_dct, cfg_error def c_set_default_cfg(self): config = configparser.ConfigParser() - with open('config.ini', 'w') as default_cfg: - config.add_section('settings') - config.set('settings', 'fa_white_list_cfg_pl', self.ui.tab_c_falistpl_le.text()) - config.set('settings', 'fa_white_list_cfg_tg', self.ui.tab_c_falisttg_le.text()) - config.set('settings', 'score_cfg_pl', self.ui.tab_c_scorecfgpl_le.text()) - config.set('settings', 'score_cfg_tg', self.ui.tab_c_scorecfgtg_le.text()) - config.set('settings', 'score_cfg_dg', self.ui.tab_c_scorecfgdg_le.text()) - config.set('settings', 'lipid_specific_cfg', self.ui.tab_c_hgcfg_le.text()) + with open("config.ini", "w") as default_cfg: + config.add_section("settings") + config.set( + "settings", "fa_white_list_cfg_pl", self.ui.tab_c_falistpl_le.text() + ) + config.set( + "settings", "fa_white_list_cfg_tg", self.ui.tab_c_falisttg_le.text() + ) + config.set("settings", "score_cfg_pl", self.ui.tab_c_scorecfgpl_le.text()) + config.set("settings", "score_cfg_tg", self.ui.tab_c_scorecfgtg_le.text()) + config.set("settings", "score_cfg_dg", self.ui.tab_c_scorecfgdg_le.text()) + config.set("settings", "lipid_specific_cfg", self.ui.tab_c_hgcfg_le.text()) if self.ui.tab_c_scoremode_cmb.currentIndex() == 0: - config.set('settings', 'score_mode', 'RANK') + config.set("settings", "score_mode", "RANK") elif self.ui.tab_c_scoremode_cmb.currentIndex() == 1: - config.set('settings', 'score_mode', 'INTENSITY') + config.set("settings", "score_mode", "INTENSITY") else: - config.set('settings', 'score_mode', 'RANK') + config.set("settings", "score_mode", "RANK") if self.ui.tab_c_isotopescoremode_cmb.currentIndex() == 1: - config.set('settings', 'isotope_13c_mode', 'ON') + config.set("settings", "isotope_13c_mode", "ON") else: - config.set('settings', 'isotope_13c_mode', 'OFF') + config.set("settings", "isotope_13c_mode", "OFF") # parallel processing settings if self.ui.tab_c_parallization_cmb.currentIndex() == 0: - config.set('settings', 'parallel_target', 'CPU') + config.set("settings", "parallel_target", "CPU") elif self.ui.tab_c_parallization_cmb.currentIndex() == 1: - config.set('settings', 'parallel_target', 'CPU_and_GPU') + config.set("settings", "parallel_target", "CPU_and_GPU") else: - config.set('settings', 'parallel_target', 'CPU') - config.set('settings', 'max_cpu_core', str(self.ui.tab_c_cores_spb.value())) - config.set('settings', 'max_ram', str(self.ui.tab_c_ram_spb.value())) + config.set("settings", "parallel_target", "CPU") + config.set("settings", "max_cpu_core", str(self.ui.tab_c_cores_spb.value())) + config.set("settings", "max_ram", str(self.ui.tab_c_ram_spb.value())) # other settings - config.set('settings', 'img_type', str(self.ui.tab_c_imagetype_cmb.currentText()).upper()[1:]) - config.set('settings', 'img_dpi', str(self.ui.tab_c_dpi_spb.value())) + config.set( + "settings", + "img_type", + str(self.ui.tab_c_imagetype_cmb.currentText()).upper()[1:], + ) + config.set("settings", "img_dpi", str(self.ui.tab_c_dpi_spb.value())) if self.ui.tab_c_tag_all_fa_chb.isChecked(): - config.set('settings', 'tag_all_fa_check', 'ON') + config.set("settings", "tag_all_fa_check", "ON") else: - config.set('settings', 'tag_all_fa_check', 'OFF') + config.set("settings", "tag_all_fa_check", "OFF") - config.set('settings', 'main_tab', '1') - config.set('settings', 'runhunter_tab', '1') - config.set('settings', 'lipidgen_tab', '1') - config.set('settings', 'default_vendor', '0') - config.set('settings', 'default_lipid', '0') + config.set("settings", "main_tab", "1") + config.set("settings", "runhunter_tab", "1") + config.set("settings", "lipidgen_tab", "1") + config.set("settings", "default_vendor", "0") + config.set("settings", "default_lipid", "0") config.write(default_cfg) def c_load_falist_pl(self): - file_info_str = 'FA white list files (*.xlsx *.XLSX)' + file_info_str = "FA white list files (*.xlsx *.XLSX)" self.open_file(file_info_str, self.ui.tab_c_falistpl_le) def c_load_falist_tg(self): - file_info_str = 'FA white list files (*.xlsx *.XLSX)' + file_info_str = "FA white list files (*.xlsx *.XLSX)" self.open_file(file_info_str, self.ui.tab_c_falisttg_le) def c_load_falist_dg(self): - file_info_str = 'FA white list files (*.xlsx *.XLSX)' + file_info_str = "FA white list files (*.xlsx *.XLSX)" self.open_file(file_info_str, self.ui.tab_c_lmcalcfalist_le) def c_load_hgcfg(self): - file_info_str = 'MS Excel files (*.xlsx *.XLSX)' + file_info_str = "MS Excel files (*.xlsx *.XLSX)" self.open_file(file_info_str, self.ui.tab_c_hgcfg_le) def c_load_scorecfg_pl(self): - file_info_str = 'MS Excel files (*.xlsx *.XLSX)' + file_info_str = "MS Excel files (*.xlsx *.XLSX)" self.open_file(file_info_str, self.ui.tab_c_scorecfgpl_le) def c_load_scorecfg_tg(self): - file_info_str = 'MS Excel files (*.xlsx *.XLSX)' + file_info_str = "MS Excel files (*.xlsx *.XLSX)" self.open_file(file_info_str, self.ui.tab_c_scorecfgtg_le) def c_load_scorecfg_dg(self): - file_info_str = 'MS Excel files (*.xlsx *.XLSX)' + file_info_str = "MS Excel files (*.xlsx *.XLSX)" self.open_file(file_info_str, self.ui.tab_c_scorecfgdg_le) def c_lmexport(self): - c_lmexport_path = QtGui.QFileDialog.getSaveFileName(caption='Save file', filter='.csv') + c_lmexport_path = QtGui.QFileDialog.getSaveFileName( + caption="Save file", filter=".csv" + ) self.ui.tab_c_lmexport_le.clear() usr_lm_path = c_lmexport_path[0] - if usr_lm_path[-4:] != '.csv': - usr_lm_path += '.csv' + if usr_lm_path[-4:] != ".csv": + usr_lm_path += ".csv" c_lmexport_str = os.path.abspath(usr_lm_path) self.ui.tab_c_lmexport_le.setText(c_lmexport_str) def single_worker_on_finish(self): self.single_thread.quit() - print('!! single_worker stopped !!') - self.ui.tab_a_runhunter_pb.setText(QtGui.QApplication.translate('MainWindow', 'Hunt for lipids!', None, - QtGui.QApplication.UnicodeUTF8)) + print("!! single_worker stopped !!") + self.ui.tab_a_runhunter_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Hunt for lipids!", None, QtGui.QApplication.UnicodeUTF8 + ) + ) self.ui.tab_a_runhunter_pgb.setMinimum(0) self.ui.tab_a_runhunter_pgb.setMaximum(100) @@ -978,77 +1203,90 @@ def single_worker_on_finish(self): def single_worker_hunter(self): self.ui.tab_a_statusrun_pte.clear() - self.ui.tab_a_statusrun_pte.setPlainText('') + self.ui.tab_a_statusrun_pte.setPlainText("") ready_to_run = False hunter_param_dct, error_log_lst = self.a_get_params() - print('Vendor mode = %s, Experiment mode = %s' % (hunter_param_dct['vendor'], - hunter_param_dct['experiment_mode'])) - print('Isotope score mode = %s' % (hunter_param_dct['fast_isotope'])) - print('Rankscore mode = %s' % (hunter_param_dct['rank_score'])) - print('Hunter started!') + print( + "Vendor mode = %s, Experiment mode = %s" + % (hunter_param_dct["vendor"], hunter_param_dct["experiment_mode"]) + ) + print("Isotope score mode = %s" % (hunter_param_dct["fast_isotope"])) + print("Rankscore mode = %s" % (hunter_param_dct["rank_score"])) + print("Hunter started!") - output_folder_path = hunter_param_dct['img_output_folder_str'] + output_folder_path = hunter_param_dct["img_output_folder_str"] if platform == "linux" or platform == "linux2": l_cwd = os.getcwd() - os.chdir('/') + os.chdir("/") if os.path.isdir(output_folder_path): - print('Folder existed...\n', output_folder_path) + print("Folder existed...\n", output_folder_path) error_log = None folder_abs_path = os.path.abspath(output_folder_path) - print('abs path of folder\n', folder_abs_path) + print("abs path of folder\n", folder_abs_path) else: - if os.path.isdir('/' + output_folder_path): - print('Folder existed...\n', output_folder_path) + if os.path.isdir("/" + output_folder_path): + print("Folder existed...\n", output_folder_path) error_log = None folder_abs_path = os.path.abspath(output_folder_path) - print('abs path of folder\n', folder_abs_path) + print("abs path of folder\n", folder_abs_path) else: - print('No folder...\n', output_folder_path) + print("No folder...\n", output_folder_path) os.makedirs(output_folder_path) - print('Folder created... %s' % output_folder_path) - error_log = '' + print("Folder created... %s" % output_folder_path) + error_log = "" os.chdir(l_cwd) else: if os.path.isdir(output_folder_path): - print('Output folder path... %s' % output_folder_path) + print("Output folder path... %s" % output_folder_path) else: try: os.mkdir(output_folder_path) - print('Output folder created... %s' % output_folder_path) + print("Output folder created... %s" % output_folder_path) except IOError: - error_log_lst.append('!! Failed to create output folder !!') + error_log_lst.append("!! Failed to create output folder !!") - param_log_output_path_str = os.path.join(output_folder_path + '/LipidHunter_Params-Log_%s.txt' - % hunter_param_dct['hunter_start_time']) - print('param_log_output_path_str', param_log_output_path_str) + param_log_output_path_str = os.path.join( + output_folder_path + + "/LipidHunter_Params-Log_%s.txt" % hunter_param_dct["hunter_start_time"] + ) + print("param_log_output_path_str", param_log_output_path_str) try: config = configparser.ConfigParser() - with open(param_log_output_path_str, 'w') as usr_param_cfg: - config.add_section('parameters') + with open(param_log_output_path_str, "w") as usr_param_cfg: + config.add_section("parameters") for param in list(hunter_param_dct.keys()): - config.set('parameters', str(param), str(hunter_param_dct[param])) + config.set("parameters", str(param), str(hunter_param_dct[param])) config.write(usr_param_cfg) ready_to_run = True except IOError: - error_log_lst.append('!! Failed to save parameter log files !!\n%s' % param_log_output_path_str) + error_log_lst.append( + "!! Failed to save parameter log files !!\n%s" + % param_log_output_path_str + ) print(hunter_param_dct) error_log_lst = [_f for _f in error_log_lst if _f] if len(error_log_lst) > 0: - print('Parameter error:', error_log_lst) - error_log_lst.append('!!! Please check your settings !!!') - self.ui.tab_a_statusrun_pte.appendPlainText('\n'.join(error_log_lst)) + print("Parameter error:", error_log_lst) + error_log_lst.append("!!! Please check your settings !!!") + self.ui.tab_a_statusrun_pte.appendPlainText("\n".join(error_log_lst)) else: if ready_to_run is True: - self.ui.tab_a_runhunter_pb.setText(QtGui.QApplication.translate('MainWindow', 'Hunting ...', None, - QtGui.QApplication.UnicodeUTF8)) + self.ui.tab_a_runhunter_pb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Hunting ...", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) self.ui.tab_a_runhunter_pb.setEnabled(False) self.ui.tab_b_runbatch_pb.setEnabled(False) self.ui.tab_c_lmrun_pb.setEnabled(False) @@ -1065,10 +1303,15 @@ def single_worker_info_update(self): def batch_worker_on_finish(self): self.batch_thread.quit() - print('!! batch_worker stopped !!') - self.ui.tab_b_runbatch_pb.setText(QtGui.QApplication.translate('MainWindow', - 'Run batch mode identification >>>', None, - QtGui.QApplication.UnicodeUTF8)) + print("!! batch_worker stopped !!") + self.ui.tab_b_runbatch_pb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Run batch mode identification >>>", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) self.ui.tab_b_runbatch_pgb.setMinimum(0) self.ui.tab_b_runbatch_pgb.setMaximum(100) self.ui.tab_b_runbatch_pgb.hide() @@ -1082,7 +1325,7 @@ def batch_worker_hunter(self): ready_to_run = False loaded_cfg_files = str(self.ui.tab_b_infiles_pte.toPlainText()) - pre_loaded_cfg_lst = loaded_cfg_files.split('\n') + pre_loaded_cfg_lst = loaded_cfg_files.split("\n") # max_process = self.ui.tab_b_maxbatch_spb.value() sub_max_core = self.ui.tab_b_maxsubcore_spb.value() @@ -1099,26 +1342,29 @@ def batch_worker_hunter(self): os.chdir(self.lipidhunter_cwd) cfg_params_dct = {} - self.ui.tab_b_statusrun_pte.appendPlainText('>>> Hunter started ... Total run number: %i \n\n' % tot_num) + self.ui.tab_b_statusrun_pte.appendPlainText( + ">>> Hunter started ... Total run number: %i \n\n" % tot_num + ) for _cfg in loaded_cfg_lst: hunter_param_dct, cfg_error = self.b_read_cfg(_cfg) if len(cfg_error) > 0: self.ui.tab_b_statusrun_pte.appendPlainText(str(cfg_error)) - if 'vendor' in list(hunter_param_dct.keys()): - hunter_param_dct['batch_cfg_file'] = _cfg - hunter_param_dct['core_number'] = sub_max_core - hunter_param_dct['max_ram'] = sub_max_ram + if "vendor" in list(hunter_param_dct.keys()): + hunter_param_dct["batch_cfg_file"] = _cfg + hunter_param_dct["core_number"] = sub_max_core + hunter_param_dct["max_ram"] = sub_max_ram # capability issues to old batch mode files - if 'lipid_class' in list(hunter_param_dct.keys()): - hunter_param_dct['lipid_type'] = hunter_param_dct['lipid_class'] + if "lipid_class" in list(hunter_param_dct.keys()): + hunter_param_dct["lipid_type"] = hunter_param_dct["lipid_class"] ready_to_run = True - elif 'lipid_type' in list(hunter_param_dct.keys()): - hunter_param_dct['lipid_class'] = hunter_param_dct['lipid_type'] + elif "lipid_type" in list(hunter_param_dct.keys()): + hunter_param_dct["lipid_class"] = hunter_param_dct["lipid_type"] self.ui.tab_b_statusrun_pte.appendPlainText( - '[WARNING] Please use "lipid_class" instead of "lipid_type" in your batch config file...\n') + '[WARNING] Please use "lipid_class" instead of "lipid_type" in your batch config file...\n' + ) ready_to_run = True else: ready_to_run = False @@ -1128,13 +1374,21 @@ def batch_worker_hunter(self): else: run_counter += 1 - self.ui.tab_b_statusrun_pte.appendPlainText('!! Failed to read batch mode configure files: # %i / %i\n' - '%s\n!! Please check your settings ' - '... skip this one ...\n' % (run_counter, tot_num, _cfg)) + self.ui.tab_b_statusrun_pte.appendPlainText( + "!! Failed to read batch mode configure files: # %i / %i\n" + "%s\n!! Please check your settings " + "... skip this one ...\n" % (run_counter, tot_num, _cfg) + ) if ready_to_run is True: - self.ui.tab_b_runbatch_pb.setText(QtGui.QApplication.translate('MainWindow', 'Hunting in batch mode ...', - None, QtGui.QApplication.UnicodeUTF8)) + self.ui.tab_b_runbatch_pb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Hunting in batch mode ...", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) self.ui.tab_b_runbatch_pb.setEnabled(False) self.ui.tab_a_runhunter_pb.setEnabled(False) self.ui.tab_c_lmrun_pb.setEnabled(False) @@ -1144,20 +1398,27 @@ def batch_worker_hunter(self): self.batch_worker.request_work(cfg_params_dct, tot_num) else: - self.ui.tab_b_statusrun_pte.appendPlainText('!! Failed to read ALL batch mode configure files ...') + self.ui.tab_b_statusrun_pte.appendPlainText( + "!! Failed to read ALL batch mode configure files ..." + ) def batch_worker_info_update(self): back_info_str = self.batch_worker.infoback() - print('Got info: ', back_info_str) + print("Got info: ", back_info_str) self.ui.tab_b_statusrun_pte.appendPlainText(back_info_str) def lm_worker_on_finish(self): self.lm_thread.quit() - print('!! LipidMaster table export worker stopped !!') - self.ui.tab_c_lmrun_pb.setText(QtGui.QApplication.translate('MainWindow', - 'Generate Lipid Master table >>>', None, - QtGui.QApplication.UnicodeUTF8)) + print("!! LipidMaster table export worker stopped !!") + self.ui.tab_c_lmrun_pb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Generate Lipid Master table >>>", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) self.ui.tab_b_runbatch_pb.setEnabled(True) self.ui.tab_a_runhunter_pb.setEnabled(True) self.ui.tab_c_lmrun_pb.setEnabled(True) @@ -1170,7 +1431,7 @@ def lm_worker_hunter(self): self.ui.tab_c_lmstatus_pte.clear() _lipid_class_info = str(self.ui.tab_c_lipidclass_cmb.currentText()) - lipid_class_checker = re.compile(r'(.*)( [(])(\w{2,3})([)] )(.*)') + lipid_class_checker = re.compile(r"(.*)( [(])(\w{2,3})([)] )(.*)") lipid_class_match = lipid_class_checker.match(_lipid_class_info) lipid_class_chosen = False @@ -1182,44 +1443,61 @@ def lm_worker_hunter(self): usr_lipid_charge = lipid_class_info_lst[4] lipid_class_chosen = True else: - usr_lipid_class = '' - usr_lipid_charge = '' - self.ui.tab_c_lmstatus_pte.appendPlainText('\n!! Please select a lipid class!!') + usr_lipid_class = "" + usr_lipid_charge = "" + self.ui.tab_c_lmstatus_pte.appendPlainText( + "\n!! Please select a lipid class!!" + ) usr_ms2_ppm = self.ui.tab_c_lmms2ppm_spb.value() fawhitelist_path_str = str(self.ui.tab_c_lmcalcfalist_le.text()) lm_export_path_str = str(self.ui.tab_c_lmexport_le.text()) - if lm_export_path_str[-4:] != '.csv': - lm_export_path_str += '.csv' + if lm_export_path_str[-4:] != ".csv": + lm_export_path_str += ".csv" self.ui.tab_c_lmexport_le.clear() self.ui.tab_c_lmexport_le.setText(lm_export_path_str) if os.path.isfile(fawhitelist_path_str): fa_list_chosen = True else: - self.ui.tab_c_lmstatus_pte.appendPlainText('\n!! Please select a FA list!!') + self.ui.tab_c_lmstatus_pte.appendPlainText("\n!! Please select a FA list!!") if len(lm_export_path_str) > 0: lm_export_chosen = True else: - self.ui.tab_c_lmstatus_pte.appendPlainText('\n!! Please select a location to save the LipidMaster table!!') + self.ui.tab_c_lmstatus_pte.appendPlainText( + "\n!! Please select a location to save the LipidMaster table!!" + ) - if lipid_class_chosen is True and fa_list_chosen is True and lm_export_chosen is True: + if ( + lipid_class_chosen is True + and fa_list_chosen is True + and lm_export_chosen is True + ): os.chdir(self.lipidhunter_cwd) - composer_param_dct = {'lipid_class': usr_lipid_class, - 'charge_mode': usr_lipid_charge, - 'exact_position': 'FALSE', - 'ms2ppm': usr_ms2_ppm, - 'fa_whitelist': fawhitelist_path_str, - 'export_path': lm_export_path_str, - } + composer_param_dct = { + "lipid_class": usr_lipid_class, + "charge_mode": usr_lipid_charge, + "exact_position": "FALSE", + "ms2ppm": usr_ms2_ppm, + "fa_whitelist": fawhitelist_path_str, + "export_path": lm_export_path_str, + } print(composer_param_dct) - self.ui.tab_c_lmstatus_pte.appendPlainText('>>> Start to generate LipidMaster table...') - - self.ui.tab_c_lmrun_pb.setText(QtGui.QApplication.translate('MainWindow', '... Generating ...', - None, QtGui.QApplication.UnicodeUTF8)) + self.ui.tab_c_lmstatus_pte.appendPlainText( + ">>> Start to generate LipidMaster table..." + ) + + self.ui.tab_c_lmrun_pb.setText( + QtGui.QApplication.translate( + "MainWindow", + "... Generating ...", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) self.ui.tab_b_runbatch_pb.setEnabled(False) self.ui.tab_a_runhunter_pb.setEnabled(False) self.ui.tab_c_lmrun_pb.setEnabled(False) @@ -1230,12 +1508,14 @@ def lm_worker_hunter(self): self.lm_worker.request_work(composer_param_dct) else: - self.ui.tab_c_lmstatus_pte.appendPlainText('!! Please check your settings and try again !!\n') + self.ui.tab_c_lmstatus_pte.appendPlainText( + "!! Please check your settings and try again !!\n" + ) def lm_worker_info_update(self): back_info_str = self.lm_worker.infoback() - print('Got info: ', back_info_str) + print("Got info: ", back_info_str) self.ui.tab_c_lmstatus_pte.appendPlainText(back_info_str) @@ -1249,7 +1529,7 @@ def __init__(self, parent=None): self.params_dct = {} self.run_count = 0 self.total_count = 0 - self.info_str = '' + self.info_str = "" def request_work(self, params_dct): """ @@ -1266,13 +1546,15 @@ def infoback(self): def run_hunter(self): log_lst = [] - print('>>> Hunter single worker started ...') + print(">>> Hunter single worker started ...") time.sleep(1) # Wait for 3 sec to avoid overwriting the self.info_str - self.info_str = '>>> Hunter started ... Please wait ...\n' + self.info_str = ">>> Hunter started ... Please wait ...\n" self.infoback() self.info_update.emit(self.info_str) - hunter_time, log_lst, output_df2 = huntlipids(self.params_dct, error_lst=log_lst) + hunter_time, log_lst, output_df2 = huntlipids( + self.params_dct, error_lst=log_lst + ) # try: # hunter_time, log_lst, output_df2 = huntlipids(self.params_dct, error_lst=log_lst) @@ -1288,9 +1570,9 @@ def run_hunter(self): # time.sleep(1) # self.finished.emit() - err_info = '' + err_info = "" if isinstance(log_lst, list): - err_info = '\n'.join(log_lst) + err_info = "\n".join(log_lst) else: pass @@ -1298,24 +1580,36 @@ def run_hunter(self): if isinstance(hunter_time, float): time.sleep(1) - self.info_str = '%s\n>>> >>> >>> FINISHED in %.3f Sec <<< <<< <<<\n' % (err_info, hunter_time) + self.info_str = "%s\n>>> >>> >>> FINISHED in %.3f Sec <<< <<< <<<\n" % ( + err_info, + hunter_time, + ) self.infoback() self.info_update.emit(self.info_str) else: if isinstance(hunter_time, str): time.sleep(1) - self.info_str = '%s\n>>> >>> >>> FINISHED in %s Sec <<< <<< <<<\n' % (err_info, hunter_time) + self.info_str = ( + "%s\n>>> >>> >>> FINISHED in %s Sec <<< <<< <<<\n" + % (err_info, hunter_time) + ) self.infoback() self.info_update.emit(self.info_str) else: time.sleep(1) - self.info_str = '%s\n!! Sorry, an error has occurred, please check your settings !!\n\n' % err_info + self.info_str = ( + "%s\n!! Sorry, an error has occurred, please check your settings !!\n\n" + % err_info + ) self.infoback() self.info_update.emit(self.info_str) else: time.sleep(1) - self.info_str = '%s\n!! Sorry, an error has occurred, please check your settings !!\n\n' % err_info + self.info_str = ( + "%s\n!! Sorry, an error has occurred, please check your settings !!\n\n" + % err_info + ) self.infoback() self.info_update.emit(self.info_str) time.sleep(1) @@ -1335,7 +1629,7 @@ def __init__(self, parent=None): self.cfg_params_dct = {} self.run_count = 0 self.total_count = 0 - self.info_str = '' + self.info_str = "" def request_work(self, cfg_params_dct, total_count): """ @@ -1364,63 +1658,77 @@ def run_hunter(self): _param_dct = self.cfg_params_dct[cfg_idx][0] _cfg_path = self.cfg_params_dct[cfg_idx][1] self.run_count = int(cfg_idx) - print('>>> Hunter batch_worker started ...') + print(">>> Hunter batch_worker started ...") time.sleep(1) - self.info_str = 'Start processing file: # %i / %i\n%s\n' % (cfg_idx, self.total_count, _cfg_path) + self.info_str = "Start processing file: # %i / %i\n%s\n" % ( + cfg_idx, + self.total_count, + _cfg_path, + ) self.infoback() self.info_update.emit(self.info_str) start_time_str = time.strftime("%Y-%m-%d_%H-%M-%S", time.localtime()) - _param_dct['hunter_start_time'] = start_time_str + _param_dct["hunter_start_time"] = start_time_str - if not os.path.isdir(_param_dct['img_output_folder_str']): - os.makedirs(_param_dct['img_output_folder_str']) - self.info_str = 'Output folder created...\n\n' + if not os.path.isdir(_param_dct["img_output_folder_str"]): + os.makedirs(_param_dct["img_output_folder_str"]) + self.info_str = "Output folder created...\n\n" self.infoback() self.info_update.emit(self.info_str) - print('Output folder created...') - output_folder_path = os.path.abspath(_param_dct['img_output_folder_str']) - log_file_name = 'LipidHunter_Params-Log_%s.txt' % _param_dct['hunter_start_time'] + print("Output folder created...") + output_folder_path = os.path.abspath(_param_dct["img_output_folder_str"]) + log_file_name = ( + "LipidHunter_Params-Log_%s.txt" % _param_dct["hunter_start_time"] + ) param_log_output_path_str = os.path.join(output_folder_path, log_file_name) try: config = configparser.ConfigParser() - with open(param_log_output_path_str, 'w') as usr_param_cfg: - config.add_section('parameters') + with open(param_log_output_path_str, "w") as usr_param_cfg: + config.add_section("parameters") for param in list(_param_dct.keys()): - config.set('parameters', str(param), str(_param_dct[param])) + config.set("parameters", str(param), str(_param_dct[param])) config.write(usr_param_cfg) try: - os.chdir(_param_dct['hunter_folder']) - hunter_py_path = os.path.join(_param_dct['hunter_folder'], 'LipidHunter.py') - hunter_exe_path = os.path.join(_param_dct['hunter_folder'], 'LipidHunter.exe') + os.chdir(_param_dct["hunter_folder"]) + hunter_py_path = os.path.join( + _param_dct["hunter_folder"], "LipidHunter.py" + ) + hunter_exe_path = os.path.join( + _param_dct["hunter_folder"], "LipidHunter.exe" + ) if os.path.isfile(hunter_py_path): - print('>>> Running LipidHunter source code version ...') + print(">>> Running LipidHunter source code version ...") ready_to_run = True elif os.path.isfile(hunter_exe_path): - print('>>> Running LipidHunter .exe version ...') + print(">>> Running LipidHunter .exe version ...") ready_to_run = True else: ready_to_run = False time.sleep(1) - self.info_str = '!! LipidHunter folder path in configuration is not correct!!\n' + self.info_str = "!! LipidHunter folder path in configuration is not correct!!\n" self.infoback() self.info_update.emit(self.info_str) except IOError: ready_to_run = False time.sleep(1) - self.info_str = '!! LipidHunter folder path in configuration is not correct!!\n' + self.info_str = ( + "!! LipidHunter folder path in configuration is not correct!!\n" + ) self.infoback() self.info_update.emit(self.info_str) except IOError: ready_to_run = False time.sleep(1) - self.info_str = '!! Failed to save parameter log files ...\n' + self.info_str = "!! Failed to save parameter log files ...\n" self.infoback() self.info_update.emit(self.info_str) if ready_to_run is True: - hunter_time, log_lst, output_df2 = huntlipids(_param_dct, error_lst=log_lst) + hunter_time, log_lst, output_df2 = huntlipids( + _param_dct, error_lst=log_lst + ) # try: # hunter_time, log_lst, output_df2 = huntlipids(_param_dct, error_lst=log_lst) # except Exception as _e: @@ -1429,57 +1737,67 @@ def run_hunter(self): # log_lst = False # export_df = False - err_info = '' + err_info = "" if isinstance(log_lst, list): - err_info = '\n'.join(log_lst) + err_info = "\n".join(log_lst) else: pass if hunter_time is not False: - print('Hunter finished successfully ...') + print("Hunter finished successfully ...") if isinstance(hunter_time, float): - run_time = '%.3f' % hunter_time + run_time = "%.3f" % hunter_time time.sleep(1) - self.info_str = ('%s\n>>> FINISHED with file # %i / %i in %s Sec ...\n\n' - % (err_info, cfg_idx, self.total_count, run_time)) + self.info_str = ( + "%s\n>>> FINISHED with file # %i / %i in %s Sec ...\n\n" + % (err_info, cfg_idx, self.total_count, run_time) + ) self.infoback() self.info_update.emit(self.info_str) elif isinstance(hunter_time, str): time.sleep(1) - self.info_str = ('%s\n>>>FINISHED with file # %i / %i in %s Sec ...\n\n' - % (err_info, cfg_idx, self.total_count, hunter_time)) + self.info_str = ( + "%s\n>>>FINISHED with file # %i / %i in %s Sec ...\n\n" + % (err_info, cfg_idx, self.total_count, hunter_time) + ) self.infoback() self.info_update.emit(self.info_str) else: - err_info = '' + err_info = "" for err in log_lst: err_info += err time.sleep(1) - self.info_str = ('%s\n!! Failed to process batch mode configuration file ... ' - 'skip this one ...\n\n' % err_info) + self.info_str = ( + "%s\n!! Failed to process batch mode configuration file ... " + "skip this one ...\n\n" % err_info + ) self.infoback() self.info_update.emit(self.info_str) else: time.sleep(1) - self.info_str = ('%s\n!! Failed to process batch mode configuration file ... skip this one ...\n\n' - % err_info) + self.info_str = ( + "%s\n!! Failed to process batch mode configuration file ... skip this one ...\n\n" + % err_info + ) self.infoback() self.info_update.emit(self.info_str) else: time.sleep(1) - self.info_str = ('!! Failed to save parameter log files ...\n' - '!! Failed to process batch mode configuration file ... skip this one ...\n\n') + self.info_str = ( + "!! Failed to save parameter log files ...\n" + "!! Failed to process batch mode configuration file ... skip this one ...\n\n" + ) self.infoback() self.info_update.emit(self.info_str) t_end = time.time() - t_start time.sleep(3) - self.info_str = '\n>>> ALL FINISHED in %.3f Sec <<<' % t_end + self.info_str = "\n>>> ALL FINISHED in %.3f Sec <<<" % t_end self.infoback() self.info_update.emit(self.info_str) self.finished.emit() @@ -1493,7 +1811,7 @@ class LMWorker(QtCore.QObject): def __init__(self, parent=None): super(LMWorker, self).__init__(parent) self.lm_params_dct = {} - self.info_str = '' + self.info_str = "" def request_work(self, lm_params_dct): """ @@ -1511,16 +1829,20 @@ def run_lm_generator(self): t_start = time.time() lipidcomposer = LipidComposer() - usr_lipid_master_df = lipidcomposer.compose_lipid(param_dct=self.lm_params_dct, - ms2_ppm=self.lm_params_dct['ms2ppm']) + usr_lipid_master_df = lipidcomposer.compose_lipid( + param_dct=self.lm_params_dct, ms2_ppm=self.lm_params_dct["ms2ppm"] + ) if isinstance(usr_lipid_master_df, pd.DataFrame): if not usr_lipid_master_df.empty: - self.info_str = ('==> Number of predicted lipids (discrete form): %i' % usr_lipid_master_df.shape[0]) + self.info_str = ( + "==> Number of predicted lipids (discrete form): %i" + % usr_lipid_master_df.shape[0] + ) self.infoback() self.info_update.emit(self.info_str) - abs_export_path = os.path.abspath(self.lm_params_dct['export_path']) + abs_export_path = os.path.abspath(self.lm_params_dct["export_path"]) abs_export_folder = os.path.dirname(abs_export_path) if os.path.isdir(abs_export_folder): pass @@ -1528,28 +1850,38 @@ def run_lm_generator(self): os.mkdir(os.path.abspath(abs_export_folder)) try: usr_lipid_master_df.to_csv(abs_export_path) - self.info_str = ('==> --> Lipid Master table Saved as: \n %s' % abs_export_path) + self.info_str = ( + "==> --> Lipid Master table Saved as: \n %s" % abs_export_path + ) self.infoback() self.info_update.emit(self.info_str) except Exception as _err: print(_err) - self.info_str = '\n %s \n' % _err + self.info_str = "\n %s \n" % _err self.infoback() self.info_update.emit(self.info_str) else: - print('[ERROR] Failed to generate LipidMaster Table...\n' - '... ... Check if Lipid Class and FA are marked in FA whitelist...') - self.info_str = ('[ERROR] Failed to generate LipidMaster Table...\n' - ' ... ... Please check if Lipid Class and FA are marked in FA whitelist...') + print( + "[ERROR] Failed to generate LipidMaster Table...\n" + "... ... Check if Lipid Class and FA are marked in FA whitelist..." + ) + self.info_str = ( + "[ERROR] Failed to generate LipidMaster Table...\n" + " ... ... Please check if Lipid Class and FA are marked in FA whitelist..." + ) self.infoback() self.info_update.emit(self.info_str) else: - print('[ERROR] Failed to generate LipidMaster Table...\n' - '... ... Check if Lipid Class and FA are marked in FA whitelist...') - self.info_str = ('[ERROR] Failed to generate LipidMaster Table...\n' - '... ... Please check if Lipid Class and FA are marked in FA whitelist...') + print( + "[ERROR] Failed to generate LipidMaster Table...\n" + "... ... Check if Lipid Class and FA are marked in FA whitelist..." + ) + self.info_str = ( + "[ERROR] Failed to generate LipidMaster Table...\n" + "... ... Please check if Lipid Class and FA are marked in FA whitelist..." + ) self.infoback() self.info_update.emit(self.info_str) @@ -1557,13 +1889,13 @@ def run_lm_generator(self): time.sleep(0.25) self.lm_params_dct = {} - self.info_str = '\n>>> FINISHED in %.3f Sec <<<' % t_end + self.info_str = "\n>>> FINISHED in %.3f Sec <<<" % t_end self.infoback() self.info_update.emit(self.info_str) self.finished.emit() -if __name__ == '__main__': +if __name__ == "__main__": import sys multiprocessing.freeze_support() diff --git a/LibLipidHunter/LipidHunter_UI.py b/LibLipidHunter/LipidHunter_UI.py index c6ea00a..172119c 100644 --- a/LibLipidHunter/LipidHunter_UI.py +++ b/LibLipidHunter/LipidHunter_UI.py @@ -32,7 +32,9 @@ def setupUi(self, MainWindow, scale=1): MainWindow.setObjectName("MainWindow") MainWindow.resize(960 * scale, 720 * scale) icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap(":/LipidHunter.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + icon.addPixmap( + QtGui.QPixmap(":/LipidHunter.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off + ) MainWindow.setWindowIcon(icon) self.centralwidget = QtGui.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") @@ -42,7 +44,9 @@ def setupUi(self, MainWindow, scale=1): self.hunter_tab = QtGui.QWidget() self.hunter_tab.setObjectName("hunter_tab") self.gridLayoutWidget_5 = QtGui.QWidget(self.hunter_tab) - self.gridLayoutWidget_5.setGeometry(QtCore.QRect(10, 50 * scale, 901 * scale, 341 * scale)) + self.gridLayoutWidget_5.setGeometry( + QtCore.QRect(10, 50 * scale, 901 * scale, 341 * scale) + ) self.gridLayoutWidget_5.setObjectName("gridLayoutWidget_5") self.gridLayout_5 = QtGui.QGridLayout(self.gridLayoutWidget_5) self.gridLayout_5.setContentsMargins(0, 0, 0, 0) @@ -86,7 +90,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_rtend_dspb.setProperty("value", 25.0) self.tab_a_rtend_dspb.setObjectName("tab_a_rtend_dspb") self.horizontalLayout_11.addWidget(self.tab_a_rtend_dspb) - spacerItem = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + spacerItem = QtGui.QSpacerItem( + 20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_11.addItem(spacerItem) self.label_10 = QtGui.QLabel(self.gridLayoutWidget_5) self.label_10.setObjectName("label_10") @@ -106,7 +112,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_mzend_dspb.setProperty("value", 1000.0) self.tab_a_mzend_dspb.setObjectName("tab_a_mzend_dspb") self.horizontalLayout_11.addWidget(self.tab_a_mzend_dspb) - spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem1 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_11.addItem(spacerItem1) self.gridLayout_5.addLayout(self.horizontalLayout_11, 8, 1, 1, 1) self.label_6 = QtGui.QLabel(self.gridLayoutWidget_5) @@ -148,7 +156,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_ms2ppm_spb.setProperty("value", 50) self.tab_a_ms2ppm_spb.setObjectName("tab_a_ms2ppm_spb") self.horizontalLayout_15.addWidget(self.tab_a_ms2ppm_spb) - spacerItem2 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + spacerItem2 = QtGui.QSpacerItem( + 20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_15.addItem(spacerItem2) self.tab_d_ms2threshold_spb_2 = QtGui.QLabel(self.gridLayoutWidget_5) self.tab_d_ms2threshold_spb_2.setObjectName("tab_d_ms2threshold_spb_2") @@ -158,7 +168,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_ms2threshold_spb.setProperty("value", 10) self.tab_a_ms2threshold_spb.setObjectName("tab_a_ms2threshold_spb") self.horizontalLayout_15.addWidget(self.tab_a_ms2threshold_spb) - spacerItem3 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem3 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_15.addItem(spacerItem3) self.gridLayout_5.addLayout(self.horizontalLayout_15, 11, 1, 1, 1) self.horizontalLayout_7 = QtGui.QHBoxLayout() @@ -188,7 +200,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_lipidclass_cmb.addItem("") # self.tab_a_lipidclass_cmb.addItem("") self.horizontalLayout_7.addWidget(self.tab_a_lipidclass_cmb) - spacerItem4 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem4 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_7.addItem(spacerItem4) self.gridLayout_5.addLayout(self.horizontalLayout_7, 0, 1, 1, 1) self.label_5 = QtGui.QLabel(self.gridLayoutWidget_5) @@ -212,7 +226,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_isotopescore_spb.setProperty("value", 80.0) self.tab_a_isotopescore_spb.setObjectName("tab_a_isotopescore_spb") self.horizontalLayout_13.addWidget(self.tab_a_isotopescore_spb) - spacerItem5 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + spacerItem5 = QtGui.QSpacerItem( + 20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_13.addItem(spacerItem5) self.label_20 = QtGui.QLabel(self.gridLayoutWidget_5) self.label_20.setObjectName("label_20") @@ -224,7 +240,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_score_spb.setProperty("value", 40.0) self.tab_a_score_spb.setObjectName("tab_a_score_spb") self.horizontalLayout_13.addWidget(self.tab_a_score_spb) - spacerItem6 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + spacerItem6 = QtGui.QSpacerItem( + 20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_13.addItem(spacerItem6) self.label_38 = QtGui.QLabel(self.gridLayoutWidget_5) self.label_38.setObjectName("label_38") @@ -234,7 +252,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_ms2infoth_dspb.setProperty("value", 0.1) self.tab_a_ms2infoth_dspb.setObjectName("tab_a_ms2infoth_dspb") self.horizontalLayout_13.addWidget(self.tab_a_ms2infoth_dspb) - spacerItem7 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem7 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_13.addItem(spacerItem7) self.gridLayout_5.addLayout(self.horizontalLayout_13, 12, 1, 1, 1) self.horizontalLayout_12 = QtGui.QHBoxLayout() @@ -247,7 +267,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_msppm_spb.setProperty("value", 20) self.tab_a_msppm_spb.setObjectName("tab_a_msppm_spb") self.horizontalLayout_12.addWidget(self.tab_a_msppm_spb) - spacerItem8 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + spacerItem8 = QtGui.QSpacerItem( + 20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_12.addItem(spacerItem8) self.label_13 = QtGui.QLabel(self.gridLayoutWidget_5) self.label_13.setObjectName("label_13") @@ -257,7 +279,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_msthreshold_spb.setProperty("value", 1000) self.tab_a_msthreshold_spb.setObjectName("tab_a_msthreshold_spb") self.horizontalLayout_12.addWidget(self.tab_a_msthreshold_spb) - spacerItem9 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem9 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_12.addItem(spacerItem9) self.tab_a_msmax_chb = QtGui.QCheckBox(self.gridLayoutWidget_5) self.tab_a_msmax_chb.setObjectName("tab_a_msmax_chb") @@ -275,7 +299,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_prwindow_spb.setProperty("value", 0.75) self.tab_a_prwindow_spb.setObjectName("tab_a_prwindow_spb") self.horizontalLayout_16.addWidget(self.tab_a_prwindow_spb) - spacerItem10 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + spacerItem10 = QtGui.QSpacerItem( + 20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_16.addItem(spacerItem10) self.x = QtGui.QLabel(self.gridLayoutWidget_5) self.x.setObjectName("x") @@ -285,7 +311,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_dda_spb.setProperty("value", 6) self.tab_a_dda_spb.setObjectName("tab_a_dda_spb") self.horizontalLayout_16.addWidget(self.tab_a_dda_spb) - spacerItem11 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem11 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_16.addItem(spacerItem11) self.gridLayout_5.addLayout(self.horizontalLayout_16, 9, 1, 1, 1) self.tab_a_msmax_spb = QtGui.QSpinBox(self.gridLayoutWidget_5) @@ -293,23 +321,37 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_msmax_spb.setProperty("value", 1000) self.tab_a_msmax_spb.setObjectName("tab_a_msmax_spb") self.gridLayout_5.addWidget(self.tab_a_msmax_spb, 10, 2, 1, 1) - spacerItem12 = QtGui.QSpacerItem(10, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + spacerItem12 = QtGui.QSpacerItem( + 10, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding + ) self.gridLayout_5.addItem(spacerItem12, 8, 0, 1, 1) - spacerItem13 = QtGui.QSpacerItem(10, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + spacerItem13 = QtGui.QSpacerItem( + 10, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding + ) self.gridLayout_5.addItem(spacerItem13, 10, 0, 1, 1) - spacerItem14 = QtGui.QSpacerItem(10, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + spacerItem14 = QtGui.QSpacerItem( + 10, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding + ) self.gridLayout_5.addItem(spacerItem14, 9, 0, 1, 1) - spacerItem15 = QtGui.QSpacerItem(10, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + spacerItem15 = QtGui.QSpacerItem( + 10, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding + ) self.gridLayout_5.addItem(spacerItem15, 11, 0, 1, 1) - spacerItem16 = QtGui.QSpacerItem(10, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + spacerItem16 = QtGui.QSpacerItem( + 10, 10, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding + ) self.gridLayout_5.addItem(spacerItem16, 12, 0, 1, 1) self.runhunter_tabframe = QtGui.QTabWidget(self.hunter_tab) - self.runhunter_tabframe.setGeometry(QtCore.QRect(10, 420 * scale, 901 * scale, 181 * scale)) + self.runhunter_tabframe.setGeometry( + QtCore.QRect(10, 420 * scale, 901 * scale, 181 * scale) + ) self.runhunter_tabframe.setObjectName("runhunter_tabframe") self.singlerun_tab = QtGui.QWidget() self.singlerun_tab.setObjectName("singlerun_tab") self.horizontalLayoutWidget_3 = QtGui.QWidget(self.singlerun_tab) - self.horizontalLayoutWidget_3.setGeometry(QtCore.QRect(169 * scale, 9, 721 * scale, 131 * scale)) + self.horizontalLayoutWidget_3.setGeometry( + QtCore.QRect(169 * scale, 9, 721 * scale, 131 * scale) + ) self.horizontalLayoutWidget_3.setObjectName("horizontalLayoutWidget_3") self.horizontalLayout = QtGui.QHBoxLayout(self.horizontalLayoutWidget_3) self.horizontalLayout.setContentsMargins(0, 0, 0, 0) @@ -318,7 +360,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_a_statusrun_pte.setObjectName("tab_a_statusrun_pte") self.horizontalLayout.addWidget(self.tab_a_statusrun_pte) self.verticalLayoutWidget_8 = QtGui.QWidget(self.singlerun_tab) - self.verticalLayoutWidget_8.setGeometry(QtCore.QRect(10, 10, 152 * scale, 129 * scale)) + self.verticalLayoutWidget_8.setGeometry( + QtCore.QRect(10, 10, 152 * scale, 129 * scale) + ) self.verticalLayoutWidget_8.setObjectName("verticalLayoutWidget_8") self.verticalLayout_5 = QtGui.QVBoxLayout(self.verticalLayoutWidget_8) self.verticalLayout_5.setSizeConstraint(QtGui.QLayout.SetNoConstraint) @@ -339,7 +383,9 @@ def setupUi(self, MainWindow, scale=1): self.savecfg_tab = QtGui.QWidget() self.savecfg_tab.setObjectName("savecfg_tab") self.verticalLayoutWidget_2 = QtGui.QWidget(self.savecfg_tab) - self.verticalLayoutWidget_2.setGeometry(QtCore.QRect(10, 5, 881 * scale, 131 * scale)) + self.verticalLayoutWidget_2.setGeometry( + QtCore.QRect(10, 5, 881 * scale, 131 * scale) + ) self.verticalLayoutWidget_2.setObjectName("verticalLayoutWidget_2") self.verticalLayout = QtGui.QVBoxLayout(self.verticalLayoutWidget_2) self.verticalLayout.setContentsMargins(0, 0, 0, 0) @@ -367,7 +413,9 @@ def setupUi(self, MainWindow, scale=1): self.verticalLayout.addLayout(self.horizontalLayout_3) self.runhunter_tabframe.addTab(self.savecfg_tab, "") self.horizontalLayoutWidget_19 = QtGui.QWidget(self.hunter_tab) - self.horizontalLayoutWidget_19.setGeometry(QtCore.QRect(10, 10, 901 * scale, 31 * scale)) + self.horizontalLayoutWidget_19.setGeometry( + QtCore.QRect(10, 10, 901 * scale, 31 * scale) + ) self.horizontalLayoutWidget_19.setObjectName("horizontalLayoutWidget_19") self.horizontalLayout_31 = QtGui.QHBoxLayout(self.horizontalLayoutWidget_19) self.horizontalLayout_31.setContentsMargins(0, 0, 0, 0) @@ -409,13 +457,17 @@ def setupUi(self, MainWindow, scale=1): self.horizontalLayout_18.addWidget(self.mode_static_rb) self.horizontalLayout_14.addLayout(self.horizontalLayout_18) self.horizontalLayout_31.addLayout(self.horizontalLayout_14) - spacerItem17 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem17 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_31.addItem(spacerItem17) self.tabframe.addTab(self.hunter_tab, "") self.batch_tab = QtGui.QWidget() self.batch_tab.setObjectName("batch_tab") self.gridLayoutWidget_7 = QtGui.QWidget(self.batch_tab) - self.gridLayoutWidget_7.setGeometry(QtCore.QRect(10, 10, 901 * scale, 581 * scale)) + self.gridLayoutWidget_7.setGeometry( + QtCore.QRect(10, 10, 901 * scale, 581 * scale) + ) self.gridLayoutWidget_7.setObjectName("gridLayoutWidget_7") self.gridLayout_9 = QtGui.QGridLayout(self.gridLayoutWidget_7) self.gridLayout_9.setContentsMargins(0, 0, 0, 0) @@ -440,7 +492,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_b_addcfg_pb = QtGui.QPushButton(self.gridLayoutWidget_7) self.tab_b_addcfg_pb.setObjectName("tab_b_addcfg_pb") self.horizontalLayout_26.addWidget(self.tab_b_addcfg_pb) - spacerItem18 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem18 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_26.addItem(spacerItem18) self.tab_b_2_lb = QtGui.QLabel(self.gridLayoutWidget_7) self.tab_b_2_lb.setObjectName("tab_b_2_lb") @@ -451,12 +505,16 @@ def setupUi(self, MainWindow, scale=1): self.gridLayout_9.addLayout(self.horizontalLayout_26, 0, 1, 1, 1) self.verticalLayout_2 = QtGui.QVBoxLayout() self.verticalLayout_2.setObjectName("verticalLayout_2") - spacerItem19 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + spacerItem19 = QtGui.QSpacerItem( + 20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding + ) self.verticalLayout_2.addItem(spacerItem19) self.tab_b_clearall_pb = QtGui.QPushButton(self.gridLayoutWidget_7) self.tab_b_clearall_pb.setObjectName("tab_b_clearall_pb") self.verticalLayout_2.addWidget(self.tab_b_clearall_pb) - spacerItem20 = QtGui.QSpacerItem(20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding) + spacerItem20 = QtGui.QSpacerItem( + 20, 40, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding + ) self.verticalLayout_2.addItem(spacerItem20) self.gridLayout_9.addLayout(self.verticalLayout_2, 1, 2, 1, 1) self.line_22 = QtGui.QFrame(self.gridLayoutWidget_7) @@ -473,7 +531,9 @@ def setupUi(self, MainWindow, scale=1): sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.tab_b_runbatch_pgb.sizePolicy().hasHeightForWidth()) + sizePolicy.setHeightForWidth( + self.tab_b_runbatch_pgb.sizePolicy().hasHeightForWidth() + ) self.tab_b_runbatch_pgb.setSizePolicy(sizePolicy) self.tab_b_runbatch_pgb.setMaximumSize(QtCore.QSize(160, 16777215)) self.tab_b_runbatch_pgb.setProperty("value", 5) @@ -492,7 +552,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_b_maxsubcore_spb.setProperty("value", 4) self.tab_b_maxsubcore_spb.setObjectName("tab_b_maxsubcore_spb") self.horizontalLayout_25.addWidget(self.tab_b_maxsubcore_spb) - spacerItem21 = QtGui.QSpacerItem(20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + spacerItem21 = QtGui.QSpacerItem( + 20, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_25.addItem(spacerItem21) self.tab_b_maxsubram_lb = QtGui.QLabel(self.gridLayoutWidget_7) self.tab_b_maxsubram_lb.setObjectName("tab_b_maxsubram_lb") @@ -503,7 +565,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_b_maxsubram_spb.setProperty("value", 6) self.tab_b_maxsubram_spb.setObjectName("tab_b_maxsubram_spb") self.horizontalLayout_25.addWidget(self.tab_b_maxsubram_spb) - spacerItem22 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem22 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_25.addItem(spacerItem22) self.gridLayout_9.addLayout(self.horizontalLayout_25, 3, 1, 1, 1) self.horizontalLayout_27 = QtGui.QHBoxLayout() @@ -522,7 +586,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_b_maxbatch_spb.setProperty("value", 3) self.tab_b_maxbatch_spb.setObjectName("tab_b_maxbatch_spb") self.horizontalLayout_27.addWidget(self.tab_b_maxbatch_spb) - spacerItem23 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem23 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_27.addItem(spacerItem23) self.gridLayout_9.addLayout(self.horizontalLayout_27, 4, 1, 1, 1) self.tab_b_infiles_pte = QtGui.QPlainTextEdit(self.gridLayoutWidget_7) @@ -535,7 +601,9 @@ def setupUi(self, MainWindow, scale=1): self.cfg_tab = QtGui.QWidget() self.cfg_tab.setObjectName("cfg_tab") self.gridLayoutWidget_6 = QtGui.QWidget(self.cfg_tab) - self.gridLayoutWidget_6.setGeometry(QtCore.QRect(10, 10, 901 * scale, 320 * scale)) + self.gridLayoutWidget_6.setGeometry( + QtCore.QRect(10, 10, 901 * scale, 320 * scale) + ) self.gridLayoutWidget_6.setObjectName("gridLayoutWidget_6") self.gridLayout_6 = QtGui.QGridLayout(self.gridLayoutWidget_6) self.gridLayout_6.setContentsMargins(0, 0, 0, 0) @@ -563,7 +631,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_c_dpi_spb.setProperty("value", 300) self.tab_c_dpi_spb.setObjectName("tab_c_dpi_spb") self.horizontalLayout_23.addWidget(self.tab_c_dpi_spb) - spacerItem24 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem24 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_23.addItem(spacerItem24) self.gridLayout_6.addLayout(self.horizontalLayout_23, 8, 1, 1, 1) self.line_12 = QtGui.QFrame(self.gridLayoutWidget_6) @@ -646,7 +716,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_c_ram_spb.setProperty("value", 5) self.tab_c_ram_spb.setObjectName("tab_c_ram_spb") self.horizontalLayout_22.addWidget(self.tab_c_ram_spb) - spacerItem25 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem25 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_22.addItem(spacerItem25) self.gridLayout_6.addLayout(self.horizontalLayout_22, 7, 1, 1, 1) self.horizontalLayout_30 = QtGui.QHBoxLayout() @@ -655,7 +727,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_c_tag_all_fa_chb.setChecked(True) self.tab_c_tag_all_fa_chb.setObjectName("tab_c_tag_all_fa_chb") self.horizontalLayout_30.addWidget(self.tab_c_tag_all_fa_chb) - spacerItem26 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem26 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_30.addItem(spacerItem26) self.gridLayout_6.addLayout(self.horizontalLayout_30, 9, 1, 1, 1) self.label_12 = QtGui.QLabel(self.gridLayoutWidget_6) @@ -667,7 +741,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_c_savesettings_pb = QtGui.QPushButton(self.gridLayoutWidget_6) self.tab_c_savesettings_pb.setObjectName("tab_c_savesettings_pb") self.gridLayout_6.addWidget(self.tab_c_savesettings_pb, 11, 1, 1, 1) - spacerItem27 = QtGui.QSpacerItem(190, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum) + spacerItem27 = QtGui.QSpacerItem( + 190, 20, QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Minimum + ) self.gridLayout_6.addItem(spacerItem27, 11, 0, 1, 1) self.horizontalLayout_38 = QtGui.QHBoxLayout() self.horizontalLayout_38.setObjectName("horizontalLayout_38") @@ -709,7 +785,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_c_scoremode_cmb.addItem("") self.tab_c_scoremode_cmb.addItem("") self.horizontalLayout_24.addWidget(self.tab_c_scoremode_cmb) - spacerItem28 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem28 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_24.addItem(spacerItem28) self.gridLayout_6.addLayout(self.horizontalLayout_24, 10, 1, 1, 1) self.label_35 = QtGui.QLabel(self.gridLayoutWidget_6) @@ -719,7 +797,9 @@ def setupUi(self, MainWindow, scale=1): self.label_54.setObjectName("label_54") self.gridLayout_6.addWidget(self.label_54, 8, 0, 1, 1) self.gridLayoutWidget = QtGui.QWidget(self.cfg_tab) - self.gridLayoutWidget.setGeometry(QtCore.QRect(10, 360 * scale, 901 * scale, 251 * scale)) + self.gridLayoutWidget.setGeometry( + QtCore.QRect(10, 360 * scale, 901 * scale, 251 * scale) + ) self.gridLayoutWidget.setObjectName("gridLayoutWidget") self.gridLayout_2 = QtGui.QGridLayout(self.gridLayoutWidget) self.gridLayout_2.setContentsMargins(0, 0, 0, 0) @@ -788,7 +868,9 @@ def setupUi(self, MainWindow, scale=1): self.tab_c_lmms2ppm_spb.setProperty("value", 50) self.tab_c_lmms2ppm_spb.setObjectName("tab_c_lmms2ppm_spb") self.horizontalLayout_44.addWidget(self.tab_c_lmms2ppm_spb) - spacerItem29 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem29 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_44.addItem(spacerItem29) self.gridLayout_2.addLayout(self.horizontalLayout_44, 1, 1, 1, 1) self.verticalLayout_6 = QtGui.QVBoxLayout() @@ -802,7 +884,9 @@ def setupUi(self, MainWindow, scale=1): sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.tab_c_runlm_pgb.sizePolicy().hasHeightForWidth()) + sizePolicy.setHeightForWidth( + self.tab_c_runlm_pgb.sizePolicy().hasHeightForWidth() + ) self.tab_c_runlm_pgb.setSizePolicy(sizePolicy) self.tab_c_runlm_pgb.setMaximumSize(QtCore.QSize(190, 16777215)) self.tab_c_runlm_pgb.setProperty("value", 5) @@ -820,12 +904,16 @@ def setupUi(self, MainWindow, scale=1): self.generator_tab = QtGui.QWidget() self.generator_tab.setObjectName("generator_tab") self.lipidgen_tabframe = QtGui.QTabWidget(self.generator_tab) - self.lipidgen_tabframe.setGeometry(QtCore.QRect(10, 0, 911 * scale, 611 * scale)) + self.lipidgen_tabframe.setGeometry( + QtCore.QRect(10, 0, 911 * scale, 611 * scale) + ) self.lipidgen_tabframe.setObjectName("lipidgen_tabframe") self.lipidgen_tab1 = QtGui.QWidget() self.lipidgen_tab1.setObjectName("lipidgen_tab1") self.horizontalLayoutWidget_7 = QtGui.QWidget(self.lipidgen_tab1) - self.horizontalLayoutWidget_7.setGeometry(QtCore.QRect(20, 0, 861 * scale, 31 * scale)) + self.horizontalLayoutWidget_7.setGeometry( + QtCore.QRect(20, 0, 861 * scale, 31 * scale) + ) self.horizontalLayoutWidget_7.setObjectName("horizontalLayoutWidget_7") self.horizontalLayout_5 = QtGui.QHBoxLayout(self.horizontalLayoutWidget_7) self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0) @@ -833,7 +921,9 @@ def setupUi(self, MainWindow, scale=1): self.label_2 = QtGui.QLabel(self.horizontalLayoutWidget_7) self.label_2.setObjectName("label_2") self.horizontalLayout_5.addWidget(self.label_2) - self.lipidgen_tab1_lipidclass_cmb = QtGui.QComboBox(self.horizontalLayoutWidget_7) + self.lipidgen_tab1_lipidclass_cmb = QtGui.QComboBox( + self.horizontalLayoutWidget_7 + ) self.lipidgen_tab1_lipidclass_cmb.setMinimumSize(QtCore.QSize(250, 0)) self.lipidgen_tab1_lipidclass_cmb.setObjectName("lipidgen_tab1_lipidclass_cmb") self.lipidgen_tab1_lipidclass_cmb.addItem("") @@ -846,10 +936,14 @@ def setupUi(self, MainWindow, scale=1): self.lipidgen_tab1_all_sn_chb = QtGui.QCheckBox(self.horizontalLayoutWidget_7) self.lipidgen_tab1_all_sn_chb.setObjectName("lipidgen_tab1_all_sn_chb") self.horizontalLayout_5.addWidget(self.lipidgen_tab1_all_sn_chb) - spacerItem30 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem30 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_5.addItem(spacerItem30) self.horizontalLayoutWidget_9 = QtGui.QWidget(self.lipidgen_tab1) - self.horizontalLayoutWidget_9.setGeometry(QtCore.QRect(20, 510 * scale, 861 * scale, 31 * scale)) + self.horizontalLayoutWidget_9.setGeometry( + QtCore.QRect(20, 510 * scale, 861 * scale, 31 * scale) + ) self.horizontalLayoutWidget_9.setObjectName("horizontalLayoutWidget_9") self.horizontalLayout_8 = QtGui.QHBoxLayout(self.horizontalLayoutWidget_9) self.horizontalLayout_8.setContentsMargins(0, 0, 0, 0) @@ -861,21 +955,31 @@ def setupUi(self, MainWindow, scale=1): self.lipidgen_tab1_savelist_le = QtGui.QLineEdit(self.horizontalLayoutWidget_9) self.lipidgen_tab1_savelist_le.setObjectName("lipidgen_tab1_savelist_le") self.horizontalLayout_8.addWidget(self.lipidgen_tab1_savelist_le) - self.lipidgen_tab1_savelist_pb = QtGui.QPushButton(self.horizontalLayoutWidget_9) + self.lipidgen_tab1_savelist_pb = QtGui.QPushButton( + self.horizontalLayoutWidget_9 + ) self.lipidgen_tab1_savelist_pb.setObjectName("lipidgen_tab1_savelist_pb") self.horizontalLayout_8.addWidget(self.lipidgen_tab1_savelist_pb) self.verticalLayoutWidget_3 = QtGui.QWidget(self.lipidgen_tab1) - self.verticalLayoutWidget_3.setGeometry(QtCore.QRect(20, 30 * scale, 861 * scale, 146 * scale)) + self.verticalLayoutWidget_3.setGeometry( + QtCore.QRect(20, 30 * scale, 861 * scale, 146 * scale) + ) self.verticalLayoutWidget_3.setObjectName("verticalLayoutWidget_3") - self.lipidgen_tab1_sn1_verticalLayout = QtGui.QVBoxLayout(self.verticalLayoutWidget_3) + self.lipidgen_tab1_sn1_verticalLayout = QtGui.QVBoxLayout( + self.verticalLayoutWidget_3 + ) self.lipidgen_tab1_sn1_verticalLayout.setContentsMargins(0, 0, 0, 0) - self.lipidgen_tab1_sn1_verticalLayout.setObjectName("lipidgen_tab1_sn1_verticalLayout") + self.lipidgen_tab1_sn1_verticalLayout.setObjectName( + "lipidgen_tab1_sn1_verticalLayout" + ) self.horizontalLayout_19 = QtGui.QHBoxLayout() self.horizontalLayout_19.setObjectName("horizontalLayout_19") self.lipidgen_tab1_sn1_lb = QtGui.QLabel(self.verticalLayoutWidget_3) self.lipidgen_tab1_sn1_lb.setObjectName("lipidgen_tab1_sn1_lb") self.horizontalLayout_19.addWidget(self.lipidgen_tab1_sn1_lb) - spacerItem31 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem31 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_19.addItem(spacerItem31) self.lipidgen_tab1_sn1allfa_chb = QtGui.QCheckBox(self.verticalLayoutWidget_3) self.lipidgen_tab1_sn1allfa_chb.setObjectName("lipidgen_tab1_sn1allfa_chb") @@ -971,17 +1075,25 @@ def setupUi(self, MainWindow, scale=1): self.label_62.setObjectName("label_62") self.lipidgen_tab1_sn1_verticalLayout.addWidget(self.label_62) self.verticalLayoutWidget_4 = QtGui.QWidget(self.lipidgen_tab1) - self.verticalLayoutWidget_4.setGeometry(QtCore.QRect(20, 180 * scale, 861 * scale, 100 * scale)) + self.verticalLayoutWidget_4.setGeometry( + QtCore.QRect(20, 180 * scale, 861 * scale, 100 * scale) + ) self.verticalLayoutWidget_4.setObjectName("verticalLayoutWidget_4") - self.lipidgen_tab1_sn2_verticalLayout = QtGui.QVBoxLayout(self.verticalLayoutWidget_4) + self.lipidgen_tab1_sn2_verticalLayout = QtGui.QVBoxLayout( + self.verticalLayoutWidget_4 + ) self.lipidgen_tab1_sn2_verticalLayout.setContentsMargins(0, 0, 0, 0) - self.lipidgen_tab1_sn2_verticalLayout.setObjectName("lipidgen_tab1_sn2_verticalLayout") + self.lipidgen_tab1_sn2_verticalLayout.setObjectName( + "lipidgen_tab1_sn2_verticalLayout" + ) self.horizontalLayout_20 = QtGui.QHBoxLayout() self.horizontalLayout_20.setObjectName("horizontalLayout_20") self.lipidgen_tab1_sn2_lb = QtGui.QLabel(self.verticalLayoutWidget_4) self.lipidgen_tab1_sn2_lb.setObjectName("lipidgen_tab1_sn2_lb") self.horizontalLayout_20.addWidget(self.lipidgen_tab1_sn2_lb) - spacerItem32 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem32 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_20.addItem(spacerItem32) self.lipidgen_tab1_sn2allfa_chb = QtGui.QCheckBox(self.verticalLayoutWidget_4) self.lipidgen_tab1_sn2allfa_chb.setObjectName("lipidgen_tab1_sn2allfa_chb") @@ -1053,17 +1165,25 @@ def setupUi(self, MainWindow, scale=1): self.horizontalLayout_32.addWidget(self.sn2_otherfa_lb) self.lipidgen_tab1_sn2_verticalLayout.addLayout(self.horizontalLayout_32) self.verticalLayoutWidget_5 = QtGui.QWidget(self.lipidgen_tab1) - self.verticalLayoutWidget_5.setGeometry(QtCore.QRect(20, 290 * scale, 861 * scale, 101 * scale)) + self.verticalLayoutWidget_5.setGeometry( + QtCore.QRect(20, 290 * scale, 861 * scale, 101 * scale) + ) self.verticalLayoutWidget_5.setObjectName("verticalLayoutWidget_5") - self.lipidgen_tab1_sn3_verticalLayout = QtGui.QVBoxLayout(self.verticalLayoutWidget_5) + self.lipidgen_tab1_sn3_verticalLayout = QtGui.QVBoxLayout( + self.verticalLayoutWidget_5 + ) self.lipidgen_tab1_sn3_verticalLayout.setContentsMargins(0, 0, 0, 0) - self.lipidgen_tab1_sn3_verticalLayout.setObjectName("lipidgen_tab1_sn3_verticalLayout") + self.lipidgen_tab1_sn3_verticalLayout.setObjectName( + "lipidgen_tab1_sn3_verticalLayout" + ) self.horizontalLayout_21 = QtGui.QHBoxLayout() self.horizontalLayout_21.setObjectName("horizontalLayout_21") self.lipidgen_tab1_sn3_lb = QtGui.QLabel(self.verticalLayoutWidget_5) self.lipidgen_tab1_sn3_lb.setObjectName("lipidgen_tab1_sn3_lb") self.horizontalLayout_21.addWidget(self.lipidgen_tab1_sn3_lb) - spacerItem33 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem33 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_21.addItem(spacerItem33) self.lipidgen_tab1_sn3allfa_chb = QtGui.QCheckBox(self.verticalLayoutWidget_5) self.lipidgen_tab1_sn3allfa_chb.setObjectName("lipidgen_tab1_sn3allfa_chb") @@ -1151,17 +1271,25 @@ def setupUi(self, MainWindow, scale=1): self.line_4.setFrameShadow(QtGui.QFrame.Sunken) self.line_4.setObjectName("line_4") self.verticalLayoutWidget_6 = QtGui.QWidget(self.lipidgen_tab1) - self.verticalLayoutWidget_6.setGeometry(QtCore.QRect(20, 400 * scale, 859 * scale, 100 * scale)) + self.verticalLayoutWidget_6.setGeometry( + QtCore.QRect(20, 400 * scale, 859 * scale, 100 * scale) + ) self.verticalLayoutWidget_6.setObjectName("verticalLayoutWidget_6") - self.lipidgen_tab1_sn4_verticalLayout = QtGui.QVBoxLayout(self.verticalLayoutWidget_6) + self.lipidgen_tab1_sn4_verticalLayout = QtGui.QVBoxLayout( + self.verticalLayoutWidget_6 + ) self.lipidgen_tab1_sn4_verticalLayout.setContentsMargins(0, 0, 0, 0) - self.lipidgen_tab1_sn4_verticalLayout.setObjectName("lipidgen_tab1_sn4_verticalLayout") + self.lipidgen_tab1_sn4_verticalLayout.setObjectName( + "lipidgen_tab1_sn4_verticalLayout" + ) self.horizontalLayout_34 = QtGui.QHBoxLayout() self.horizontalLayout_34.setObjectName("horizontalLayout_34") self.lipidgen_tab1_sn4_lb = QtGui.QLabel(self.verticalLayoutWidget_6) self.lipidgen_tab1_sn4_lb.setObjectName("lipidgen_tab1_sn4_lb") self.horizontalLayout_34.addWidget(self.lipidgen_tab1_sn4_lb) - spacerItem34 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum) + spacerItem34 = QtGui.QSpacerItem( + 40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum + ) self.horizontalLayout_34.addItem(spacerItem34) self.lipidgen_tab1_sn3allfa_chb_2 = QtGui.QCheckBox(self.verticalLayoutWidget_6) self.lipidgen_tab1_sn3allfa_chb_2.setObjectName("lipidgen_tab1_sn3allfa_chb_2") @@ -1244,7 +1372,9 @@ def setupUi(self, MainWindow, scale=1): self.line_11.setFrameShadow(QtGui.QFrame.Sunken) self.line_11.setObjectName("line_11") self.horizontalLayoutWidget_6 = QtGui.QWidget(self.lipidgen_tab1) - self.horizontalLayoutWidget_6.setGeometry(QtCore.QRect(20, 540 * scale, 781 * scale, 31 * scale)) + self.horizontalLayoutWidget_6.setGeometry( + QtCore.QRect(20, 540 * scale, 781 * scale, 31 * scale) + ) self.horizontalLayoutWidget_6.setObjectName("horizontalLayoutWidget_6") self.horizontalLayout_40 = QtGui.QHBoxLayout(self.horizontalLayoutWidget_6) self.horizontalLayout_40.setContentsMargins(0, 0, 0, 0) @@ -1260,7 +1390,9 @@ def setupUi(self, MainWindow, scale=1): self.lipidgen_tab2 = QtGui.QWidget() self.lipidgen_tab2.setObjectName("lipidgen_tab2") self.horizontalLayoutWidget_10 = QtGui.QWidget(self.lipidgen_tab2) - self.horizontalLayoutWidget_10.setGeometry(QtCore.QRect(10, 10, 881 * scale, 31 * scale)) + self.horizontalLayoutWidget_10.setGeometry( + QtCore.QRect(10, 10, 881 * scale, 31 * scale) + ) self.horizontalLayoutWidget_10.setObjectName("horizontalLayoutWidget_10") self.horizontalLayout_9 = QtGui.QHBoxLayout(self.horizontalLayoutWidget_10) self.horizontalLayout_9.setContentsMargins(0, 0, 0, 0) @@ -1271,46 +1403,76 @@ def setupUi(self, MainWindow, scale=1): self.lipidgen_tab2_loadlist_le = QtGui.QLineEdit(self.horizontalLayoutWidget_10) self.lipidgen_tab2_loadlist_le.setObjectName("lipidgen_tab2_loadlist_le") self.horizontalLayout_9.addWidget(self.lipidgen_tab2_loadlist_le) - self.lipidgen_tab2_loadlist_pb = QtGui.QPushButton(self.horizontalLayoutWidget_10) + self.lipidgen_tab2_loadlist_pb = QtGui.QPushButton( + self.horizontalLayoutWidget_10 + ) self.lipidgen_tab2_loadlist_pb.setObjectName("lipidgen_tab2_loadlist_pb") self.horizontalLayout_9.addWidget(self.lipidgen_tab2_loadlist_pb) self.lipidgen_tab2_loadlist_lb = QtGui.QLabel(self.lipidgen_tab2) - self.lipidgen_tab2_loadlist_lb.setGeometry(QtCore.QRect(10, 50 * scale, 881 * scale, 16 * scale)) + self.lipidgen_tab2_loadlist_lb.setGeometry( + QtCore.QRect(10, 50 * scale, 881 * scale, 16 * scale) + ) self.lipidgen_tab2_loadlist_lb.setObjectName("lipidgen_tab2_loadlist_lb") self.horizontalLayoutWidget_11 = QtGui.QWidget(self.lipidgen_tab2) - self.horizontalLayoutWidget_11.setGeometry(QtCore.QRect(10, 70 * scale, 881 * scale, 31 * scale)) + self.horizontalLayoutWidget_11.setGeometry( + QtCore.QRect(10, 70 * scale, 881 * scale, 31 * scale) + ) self.horizontalLayoutWidget_11.setObjectName("horizontalLayoutWidget_11") self.horizontalLayout_41 = QtGui.QHBoxLayout(self.horizontalLayoutWidget_11) self.horizontalLayout_41.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_41.setObjectName("horizontalLayout_41") - self.lipidgen_tab2_savemasterlist_lb = QtGui.QLabel(self.horizontalLayoutWidget_11) - self.lipidgen_tab2_savemasterlist_lb.setObjectName("lipidgen_tab2_savemasterlist_lb") + self.lipidgen_tab2_savemasterlist_lb = QtGui.QLabel( + self.horizontalLayoutWidget_11 + ) + self.lipidgen_tab2_savemasterlist_lb.setObjectName( + "lipidgen_tab2_savemasterlist_lb" + ) self.horizontalLayout_41.addWidget(self.lipidgen_tab2_savemasterlist_lb) - self.lipidgen_tab2_savemasterlist_le = QtGui.QLineEdit(self.horizontalLayoutWidget_11) - self.lipidgen_tab2_savemasterlist_le.setObjectName("lipidgen_tab2_savemasterlist_le") + self.lipidgen_tab2_savemasterlist_le = QtGui.QLineEdit( + self.horizontalLayoutWidget_11 + ) + self.lipidgen_tab2_savemasterlist_le.setObjectName( + "lipidgen_tab2_savemasterlist_le" + ) self.horizontalLayout_41.addWidget(self.lipidgen_tab2_savemasterlist_le) - self.lipidgen_tab2_savemasterlist_pb = QtGui.QPushButton(self.horizontalLayoutWidget_11) - self.lipidgen_tab2_savemasterlist_pb.setObjectName("lipidgen_tab2_savemasterlist_pb") + self.lipidgen_tab2_savemasterlist_pb = QtGui.QPushButton( + self.horizontalLayoutWidget_11 + ) + self.lipidgen_tab2_savemasterlist_pb.setObjectName( + "lipidgen_tab2_savemasterlist_pb" + ) self.horizontalLayout_41.addWidget(self.lipidgen_tab2_savemasterlist_pb) self.horizontalLayoutWidget_8 = QtGui.QWidget(self.lipidgen_tab2) - self.horizontalLayoutWidget_8.setGeometry(QtCore.QRect(10, 110 * scale, 881 * scale, 231 * scale)) + self.horizontalLayoutWidget_8.setGeometry( + QtCore.QRect(10, 110 * scale, 881 * scale, 231 * scale) + ) self.horizontalLayoutWidget_8.setObjectName("horizontalLayoutWidget_8") self.horizontalLayout_42 = QtGui.QHBoxLayout(self.horizontalLayoutWidget_8) self.horizontalLayout_42.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_42.setObjectName("horizontalLayout_42") - self.lipidgen_tab1_genmasterlist_pb = QtGui.QPushButton(self.horizontalLayoutWidget_8) + self.lipidgen_tab1_genmasterlist_pb = QtGui.QPushButton( + self.horizontalLayoutWidget_8 + ) self.lipidgen_tab1_genmasterlist_pb.setMinimumSize(QtCore.QSize(120, 0)) - self.lipidgen_tab1_genmasterlist_pb.setObjectName("lipidgen_tab1_genmasterlist_pb") + self.lipidgen_tab1_genmasterlist_pb.setObjectName( + "lipidgen_tab1_genmasterlist_pb" + ) self.horizontalLayout_42.addWidget(self.lipidgen_tab1_genmasterlist_pb) - self.lipidgen_tab1_genmasterlist_pte = QtGui.QPlainTextEdit(self.horizontalLayoutWidget_8) - self.lipidgen_tab1_genmasterlist_pte.setObjectName("lipidgen_tab1_genmasterlist_pte") + self.lipidgen_tab1_genmasterlist_pte = QtGui.QPlainTextEdit( + self.horizontalLayoutWidget_8 + ) + self.lipidgen_tab1_genmasterlist_pte.setObjectName( + "lipidgen_tab1_genmasterlist_pte" + ) self.horizontalLayout_42.addWidget(self.lipidgen_tab1_genmasterlist_pte) self.lipidgen_tabframe.addTab(self.lipidgen_tab2, "") self.tabframe.addTab(self.generator_tab, "") self.tab = QtGui.QWidget() self.tab.setObjectName("tab") self.verticalLayoutWidget = QtGui.QWidget(self.tab) - self.verticalLayoutWidget.setGeometry(QtCore.QRect(210 * scale, 10, 701 * scale, 201 * scale)) + self.verticalLayoutWidget.setGeometry( + QtCore.QRect(210 * scale, 10, 701 * scale, 201 * scale) + ) self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") self.verticalLayout_4 = QtGui.QVBoxLayout(self.verticalLayoutWidget) self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) @@ -1359,7 +1521,9 @@ def setupUi(self, MainWindow, scale=1): self.line_8.setFrameShadow(QtGui.QFrame.Sunken) self.line_8.setObjectName("line_8") self.label_30 = QtGui.QLabel(self.tab) - self.label_30.setGeometry(QtCore.QRect(20, 228 * scale, 881 * scale, 16 * scale)) + self.label_30.setGeometry( + QtCore.QRect(20, 228 * scale, 881 * scale, 16 * scale) + ) self.label_30.setObjectName("label_30") self.logo_pb = QtGui.QPushButton(self.tab) self.logo_pb.setGeometry(QtCore.QRect(40, 40, 128 * scale, 128 * scale)) @@ -1367,16 +1531,22 @@ def setupUi(self, MainWindow, scale=1): self.logo_pb.setMaximumSize(QtCore.QSize(128, 128)) self.logo_pb.setText("") icon1 = QtGui.QIcon() - icon1.addPixmap(QtGui.QPixmap("LipidHunter.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) + icon1.addPixmap( + QtGui.QPixmap("LipidHunter.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off + ) self.logo_pb.setIcon(icon1) self.logo_pb.setIconSize(QtCore.QSize(128, 128)) self.logo_pb.setObjectName("logo_pb") self.formLayoutWidget_3 = QtGui.QWidget(self.tab) - self.formLayoutWidget_3.setGeometry(QtCore.QRect(20, 250 * scale, 881 * scale, 261 * scale)) + self.formLayoutWidget_3.setGeometry( + QtCore.QRect(20, 250 * scale, 881 * scale, 261 * scale) + ) self.formLayoutWidget_3.setObjectName("formLayoutWidget_3") self.formLayout_3 = QtGui.QFormLayout(self.formLayoutWidget_3) self.formLayout_3.setFieldGrowthPolicy(QtGui.QFormLayout.AllNonFixedFieldsGrow) - self.formLayout_3.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) + self.formLayout_3.setFormAlignment( + QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop + ) self.formLayout_3.setContentsMargins(0, 0, 0, 0) self.formLayout_3.setObjectName("formLayout_3") self.label_31 = QtGui.QLabel(self.formLayoutWidget_3) @@ -1384,7 +1554,9 @@ def setupUi(self, MainWindow, scale=1): self.formLayout_3.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_31) self.link_matplotlib_lb = QtGui.QLabel(self.formLayoutWidget_3) self.link_matplotlib_lb.setObjectName("link_matplotlib_lb") - self.formLayout_3.setWidget(0, QtGui.QFormLayout.FieldRole, self.link_matplotlib_lb) + self.formLayout_3.setWidget( + 0, QtGui.QFormLayout.FieldRole, self.link_matplotlib_lb + ) self.label_36 = QtGui.QLabel(self.formLayoutWidget_3) self.label_36.setObjectName("label_36") self.formLayout_3.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_36) @@ -1429,20 +1601,28 @@ def setupUi(self, MainWindow, scale=1): self.line_10.setFrameShadow(QtGui.QFrame.Sunken) self.line_10.setObjectName("line_10") self.label_46 = QtGui.QLabel(self.tab) - self.label_46.setGeometry(QtCore.QRect(20 * scale, 520 * scale, 881 * scale, 16 * scale)) + self.label_46.setGeometry( + QtCore.QRect(20 * scale, 520 * scale, 881 * scale, 16 * scale) + ) self.label_46.setObjectName("label_46") self.formLayoutWidget_2 = QtGui.QWidget(self.tab) - self.formLayoutWidget_2.setGeometry(QtCore.QRect(20 * scale, 540 * scale, 881 * scale, 71 * scale)) + self.formLayoutWidget_2.setGeometry( + QtCore.QRect(20 * scale, 540 * scale, 881 * scale, 71 * scale) + ) self.formLayoutWidget_2.setObjectName("formLayoutWidget_2") self.formLayout_2 = QtGui.QFormLayout(self.formLayoutWidget_2) - self.formLayout_2.setFormAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) + self.formLayout_2.setFormAlignment( + QtCore.Qt.AlignLeading | QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop + ) self.formLayout_2.setContentsMargins(0, 0, 0, 0) self.formLayout_2.setObjectName("formLayout_2") self.label_47 = QtGui.QLabel(self.formLayoutWidget_2) self.label_47.setObjectName("label_47") self.formLayout_2.setWidget(0, QtGui.QFormLayout.LabelRole, self.label_47) self.label_49 = QtGui.QLabel(self.formLayoutWidget_2) - self.label_49.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_49.setAlignment( + QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter + ) self.label_49.setObjectName("label_49") self.formLayout_2.setWidget(1, QtGui.QFormLayout.LabelRole, self.label_49) self.link_bmbf_lb = QtGui.QLabel(self.formLayoutWidget_2) @@ -1453,19 +1633,27 @@ def setupUi(self, MainWindow, scale=1): self.formLayout_2.setWidget(1, QtGui.QFormLayout.FieldRole, self.link_emed_lb) self.link_sysmedos_lb = QtGui.QLabel(self.formLayoutWidget_2) self.link_sysmedos_lb.setObjectName("link_sysmedos_lb") - self.formLayout_2.setWidget(2, QtGui.QFormLayout.FieldRole, self.link_sysmedos_lb) + self.formLayout_2.setWidget( + 2, QtGui.QFormLayout.FieldRole, self.link_sysmedos_lb + ) self.label_58 = QtGui.QLabel(self.formLayoutWidget_2) - sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed) + sizePolicy = QtGui.QSizePolicy( + QtGui.QSizePolicy.MinimumExpanding, QtGui.QSizePolicy.Fixed + ) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label_58.sizePolicy().hasHeightForWidth()) self.label_58.setSizePolicy(sizePolicy) - self.label_58.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter) + self.label_58.setAlignment( + QtCore.Qt.AlignRight | QtCore.Qt.AlignTrailing | QtCore.Qt.AlignVCenter + ) self.label_58.setObjectName("label_58") self.formLayout_2.setWidget(2, QtGui.QFormLayout.LabelRole, self.label_58) self.tabframe.addTab(self.tab, "") self.link_uni_lb = QtGui.QLabel(self.centralwidget) - self.link_uni_lb.setGeometry(QtCore.QRect(20 * scale, 650 * scale, 901 * scale, 16 * scale)) + self.link_uni_lb.setGeometry( + QtCore.QRect(20 * scale, 650 * scale, 901 * scale, 16 * scale) + ) self.link_uni_lb.setContextMenuPolicy(QtCore.Qt.NoContextMenu) self.link_uni_lb.setObjectName("link_uni_lb") MainWindow.setCentralWidget(self.centralwidget) @@ -1486,284 +1674,1834 @@ def setupUi(self, MainWindow, scale=1): QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): - MainWindow.setWindowTitle(QtGui.QApplication.translate("MainWindow", "LipidHunter 2 (RC2) | University of Leipzig ", None, QtGui.QApplication.UnicodeUTF8)) - self.label_50.setText(QtGui.QApplication.translate("MainWindow", "Score weight factor settings:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_mzml_pb.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) - self.label_3.setText(QtGui.QApplication.translate("MainWindow", "Select lipid class:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_4.setText(QtGui.QApplication.translate("MainWindow", "Scan time range (min):", None, QtGui.QApplication.UnicodeUTF8)) - self.label_9.setText(QtGui.QApplication.translate("MainWindow", "to", None, QtGui.QApplication.UnicodeUTF8)) - self.label_10.setText(QtGui.QApplication.translate("MainWindow", "

m/z  range:

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_11.setText(QtGui.QApplication.translate("MainWindow", "to", None, QtGui.QApplication.UnicodeUTF8)) - self.label_6.setText(QtGui.QApplication.translate("MainWindow", "Input .mzML file:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_loadfalist_pb.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) - self.label_7.setText(QtGui.QApplication.translate("MainWindow", "Save report to folder:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_loadscorecfg_pb.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_sumxlsxpath_pb.setText(QtGui.QApplication.translate("MainWindow", "Save as", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_saveimgfolder_pb.setText(QtGui.QApplication.translate("MainWindow", "Save as", None, QtGui.QApplication.UnicodeUTF8)) - self.label_8.setText(QtGui.QApplication.translate("MainWindow", "Export summary .xlsx table:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_16.setText(QtGui.QApplication.translate("MainWindow", "MS/MS level tolerance:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_ms2ppm_spb.setSuffix(QtGui.QApplication.translate("MainWindow", " ppm", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_ms2ppm_spb.setPrefix(QtGui.QApplication.translate("MainWindow", "+/- ", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_d_ms2threshold_spb_2.setText(QtGui.QApplication.translate("MainWindow", "MS/MS level threshold (absolute intensity):", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(0, QtGui.QApplication.translate("MainWindow", "--- Please select ---", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(1, QtGui.QApplication.translate("MainWindow", "Phosphatidic acid (PA) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(2, QtGui.QApplication.translate("MainWindow", "Phosphatidylcholine (PC) [M+HCOO]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(3, QtGui.QApplication.translate("MainWindow", "Phosphatidylcholine (PC) [M+CH3COO]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(4, QtGui.QApplication.translate("MainWindow", "Phosphatidylethanolamine (PE) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(5, QtGui.QApplication.translate("MainWindow", "Phosphatidylglycerol (PG) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(6, QtGui.QApplication.translate("MainWindow", "Phosphatidylinositol (PI) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(7, QtGui.QApplication.translate("MainWindow", "Phosphatidylserine (PS) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(8, QtGui.QApplication.translate("MainWindow", "Triacylglycerol (TG) [M+NH4]+", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(9, QtGui.QApplication.translate("MainWindow", "Triacylglycerol (TG) [M+H]+", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(10, QtGui.QApplication.translate("MainWindow", "Triacylglycerol (TG) [M+Na]+", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(11, QtGui.QApplication.translate("MainWindow", "Diacylglycerol (DG) [M+NH4]+", None, QtGui.QApplication.UnicodeUTF8)) + MainWindow.setWindowTitle( + QtGui.QApplication.translate( + "MainWindow", + "LipidHunter 2 (RC2) | University of Leipzig ", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_50.setText( + QtGui.QApplication.translate( + "MainWindow", + "Score weight factor settings:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_a_mzml_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_3.setText( + QtGui.QApplication.translate( + "MainWindow", + "Select lipid class:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_4.setText( + QtGui.QApplication.translate( + "MainWindow", + "Scan time range (min):", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_9.setText( + QtGui.QApplication.translate( + "MainWindow", "to", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_10.setText( + QtGui.QApplication.translate( + "MainWindow", + '

m/z  range:

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_11.setText( + QtGui.QApplication.translate( + "MainWindow", "to", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_6.setText( + QtGui.QApplication.translate( + "MainWindow", "Input .mzML file:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_a_loadfalist_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_7.setText( + QtGui.QApplication.translate( + "MainWindow", + "Save report to folder:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_a_loadscorecfg_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_a_sumxlsxpath_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Save as", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_a_saveimgfolder_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Save as", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_8.setText( + QtGui.QApplication.translate( + "MainWindow", + "Export summary .xlsx table:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_16.setText( + QtGui.QApplication.translate( + "MainWindow", + "MS/MS level tolerance:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_a_ms2ppm_spb.setSuffix( + QtGui.QApplication.translate( + "MainWindow", " ppm", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_a_ms2ppm_spb.setPrefix( + QtGui.QApplication.translate( + "MainWindow", "+/- ", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_d_ms2threshold_spb_2.setText( + QtGui.QApplication.translate( + "MainWindow", + "MS/MS level threshold (absolute intensity):", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_a_lipidclass_cmb.setItemText( + 0, + QtGui.QApplication.translate( + "MainWindow", + "--- Please select ---", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 1, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidic acid (PA) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 2, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylcholine (PC) [M+HCOO]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 3, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylcholine (PC) [M+CH3COO]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 4, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylethanolamine (PE) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 5, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylglycerol (PG) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 6, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylinositol (PI) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 7, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylserine (PS) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 8, + QtGui.QApplication.translate( + "MainWindow", + "Triacylglycerol (TG) [M+NH4]+", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 9, + QtGui.QApplication.translate( + "MainWindow", + "Triacylglycerol (TG) [M+H]+", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 10, + QtGui.QApplication.translate( + "MainWindow", + "Triacylglycerol (TG) [M+Na]+", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 11, + QtGui.QApplication.translate( + "MainWindow", + "Diacylglycerol (DG) [M+NH4]+", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) # self.tab_a_lipidclass_cmb.setItemText(12, QtGui.QApplication.translate("MainWindow", "Diacylglycerol (DG) [M+H]+", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(13-1, QtGui.QApplication.translate("MainWindow", "Lyso PA (LPA) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(14-1, QtGui.QApplication.translate("MainWindow", "Lyso PC (LPC) [M+HCOO]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(15-1, QtGui.QApplication.translate("MainWindow", "Lyso PC (LPC) [M+CH3COO]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(16-1, QtGui.QApplication.translate("MainWindow", "Lyso PE (LPE) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(17-1, QtGui.QApplication.translate("MainWindow", "Lyso PG (LPG) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(18-1, QtGui.QApplication.translate("MainWindow", "Lyso PI (LPI) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_lipidclass_cmb.setItemText(19-1, QtGui.QApplication.translate("MainWindow", "Lyso PS (LPS) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.label_5.setText(QtGui.QApplication.translate("MainWindow", "FA white list:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_19.setText(QtGui.QApplication.translate("MainWindow", "

Isotope score ≥

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_20.setText(QtGui.QApplication.translate("MainWindow", "

Rank score ≥

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_38.setText(QtGui.QApplication.translate("MainWindow", "Minimum relative intensity for scoring:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_ms2infoth_dspb.setSuffix(QtGui.QApplication.translate("MainWindow", " %", None, QtGui.QApplication.UnicodeUTF8)) - self.label_15.setText(QtGui.QApplication.translate("MainWindow", "MS level tolerance:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_msppm_spb.setSuffix(QtGui.QApplication.translate("MainWindow", " ppm", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_msppm_spb.setPrefix(QtGui.QApplication.translate("MainWindow", "+/- ", None, QtGui.QApplication.UnicodeUTF8)) - self.label_13.setText(QtGui.QApplication.translate("MainWindow", "MS level threshold (absolute intensity):", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_msmax_chb.setText(QtGui.QApplication.translate("MainWindow", "Set MS max inetnsity", None, QtGui.QApplication.UnicodeUTF8)) - self.label_25.setText(QtGui.QApplication.translate("MainWindow", "Precursor window:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_prwindow_spb.setPrefix(QtGui.QApplication.translate("MainWindow", "+/- ", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_prwindow_spb.setSuffix(QtGui.QApplication.translate("MainWindow", " m/z", None, QtGui.QApplication.UnicodeUTF8)) - self.x.setText(QtGui.QApplication.translate("MainWindow", "DDA Top:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_runhunter_pb.setText(QtGui.QApplication.translate("MainWindow", "Hunt for lipids !", None, QtGui.QApplication.UnicodeUTF8)) - self.runhunter_tabframe.setTabText(self.runhunter_tabframe.indexOf(self.singlerun_tab), QtGui.QApplication.translate("MainWindow", "Run LipidHunter identification directly", None, QtGui.QApplication.UnicodeUTF8)) - self.label.setText(QtGui.QApplication.translate("MainWindow", "Save configuration file as:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_cfgpath_pb.setText(QtGui.QApplication.translate("MainWindow", "Save As", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_a_gencfg_pb.setText(QtGui.QApplication.translate("MainWindow", "Generate configuration file for batch mode >>>", None, QtGui.QApplication.UnicodeUTF8)) - self.runhunter_tabframe.setTabText(self.runhunter_tabframe.indexOf(self.savecfg_tab), QtGui.QApplication.translate("MainWindow", "Save parameters for Batch Mode Hunter", None, QtGui.QApplication.UnicodeUTF8)) - self.label_23.setText(QtGui.QApplication.translate("MainWindow", "Instrument vendor:", None, QtGui.QApplication.UnicodeUTF8)) - self.vendor_cmb.setItemText(0, QtGui.QApplication.translate("MainWindow", "--- Please select ---", None, QtGui.QApplication.UnicodeUTF8)) - self.vendor_cmb.setItemText(1, QtGui.QApplication.translate("MainWindow", "Agilent", None, QtGui.QApplication.UnicodeUTF8)) - self.vendor_cmb.setItemText(2, QtGui.QApplication.translate("MainWindow", "SCIEX", None, QtGui.QApplication.UnicodeUTF8)) - self.vendor_cmb.setItemText(3, QtGui.QApplication.translate("MainWindow", "Thermo", None, QtGui.QApplication.UnicodeUTF8)) - self.vendor_cmb.setItemText(4, QtGui.QApplication.translate("MainWindow", "Waters", None, QtGui.QApplication.UnicodeUTF8)) - self.label_24.setText(QtGui.QApplication.translate("MainWindow", "Mode:", None, QtGui.QApplication.UnicodeUTF8)) - self.mode_lcms_rb.setText(QtGui.QApplication.translate("MainWindow", "LC-MS/MS", None, QtGui.QApplication.UnicodeUTF8)) - self.mode_static_rb.setText(QtGui.QApplication.translate("MainWindow", "Shotgun", None, QtGui.QApplication.UnicodeUTF8)) - self.tabframe.setTabText(self.tabframe.indexOf(self.hunter_tab), QtGui.QApplication.translate("MainWindow", "Hunt for Lipids", None, QtGui.QApplication.UnicodeUTF8)) - self.label_98.setText(QtGui.QApplication.translate("MainWindow", "Load batch configurations files (.txt):", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_1_lb.setText(QtGui.QApplication.translate("MainWindow", "Input batch configuration file:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_addcfg_pb.setText(QtGui.QApplication.translate("MainWindow", "Add a single file", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_2_lb.setText(QtGui.QApplication.translate("MainWindow", "Add all batch configurations in a folder:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_addcfgfolder_pb.setText(QtGui.QApplication.translate("MainWindow", "Select a folder", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_clearall_pb.setText(QtGui.QApplication.translate("MainWindow", "Clear all", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_runbatch_pb.setText(QtGui.QApplication.translate("MainWindow", "Run batch mode identification >>>", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_maxsubcore_lb.setText(QtGui.QApplication.translate("MainWindow", "Max cores for each task:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_maxsubram_lb.setText(QtGui.QApplication.translate("MainWindow", "Max RAM for each task:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_maxsubram_spb.setSuffix(QtGui.QApplication.translate("MainWindow", " GB", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_mutlimode_cmb.setItemText(0, QtGui.QApplication.translate("MainWindow", "Process as a sequence", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_mutlimode_cmb.setItemText(1, QtGui.QApplication.translate("MainWindow", "Process multiple files in parallel", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_b_maxbatch_lb.setText(QtGui.QApplication.translate("MainWindow", "Max number of files in parallel:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_99.setText(QtGui.QApplication.translate("MainWindow", "Batch mode settings:", None, QtGui.QApplication.UnicodeUTF8)) - self.tabframe.setTabText(self.tabframe.indexOf(self.batch_tab), QtGui.QApplication.translate("MainWindow", "Batch Mode Hunter", None, QtGui.QApplication.UnicodeUTF8)) - self.label_93.setText(QtGui.QApplication.translate("MainWindow", "Image format:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_imagetype_cmb.setItemText(0, QtGui.QApplication.translate("MainWindow", ".png", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_imagetype_cmb.setItemText(1, QtGui.QApplication.translate("MainWindow", ".svg", None, QtGui.QApplication.UnicodeUTF8)) - self.label_94.setText(QtGui.QApplication.translate("MainWindow", "dpi:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_scorecfgtg_lb.setText(QtGui.QApplication.translate("MainWindow", "

"Wfrag" for TG:

", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_scorecfgdg_lb.setText(QtGui.QApplication.translate("MainWindow", "

"Wfrag" for DG:

", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_isotopescoremode_lb.setText(QtGui.QApplication.translate("MainWindow", "Isotope Score mode:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_14.setText(QtGui.QApplication.translate("MainWindow", "Lipid specific FRAG & NL list:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_scorecfgdg_pb.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_scorecfgpl_lb.setText(QtGui.QApplication.translate("MainWindow", "

"Wfrag" for PL:

", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_scorecfgpl_pb.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_scorecfgtg_pb.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_hgcfg_pb.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) - self.label_21.setText(QtGui.QApplication.translate("MainWindow", "

Score weight factor settings:

", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_parallization_cmb.setItemText(0, QtGui.QApplication.translate("MainWindow", "CPU prarallization mode", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_parallization_cmb.setItemText(1, QtGui.QApplication.translate("MainWindow", "CPU +GPU mode (experimental)", None, QtGui.QApplication.UnicodeUTF8)) - self.label_63.setText(QtGui.QApplication.translate("MainWindow", "Max CPU cores to use:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_64.setText(QtGui.QApplication.translate("MainWindow", "Max RAM to use:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_ram_spb.setSuffix(QtGui.QApplication.translate("MainWindow", " GB", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_tag_all_fa_chb.setText(QtGui.QApplication.translate("MainWindow", "Favoured for TG with all three FA residues identified", None, QtGui.QApplication.UnicodeUTF8)) - self.label_12.setText(QtGui.QApplication.translate("MainWindow", "Default Fatty acid white list:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_falistpl_pb.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_savesettings_pb.setText(QtGui.QApplication.translate("MainWindow", "Save above settings as defaullt", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_falisttg_lb.setText(QtGui.QApplication.translate("MainWindow", "

"Wfrag" for LPL:

", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_falistpl_lb.setText(QtGui.QApplication.translate("MainWindow", "Default FA list:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_falisttg_pb.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_isotopescoremode_cmb.setItemText(0, QtGui.QApplication.translate("MainWindow", "All elements", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_isotopescoremode_cmb.setItemText(1, QtGui.QApplication.translate("MainWindow", "Fast (only 13C)", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_scoremode_lb.setText(QtGui.QApplication.translate("MainWindow", "Score mode:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_scoremode_cmb.setItemText(0, QtGui.QApplication.translate("MainWindow", "Signal rank mode", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_scoremode_cmb.setItemText(1, QtGui.QApplication.translate("MainWindow", "Relative Intensity mode", None, QtGui.QApplication.UnicodeUTF8)) - self.label_35.setText(QtGui.QApplication.translate("MainWindow", "Prarallel processing settings:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_54.setText(QtGui.QApplication.translate("MainWindow", "Output image settings:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_28.setText(QtGui.QApplication.translate("MainWindow", "FA white list:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lmcalcfalist_pb.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lmexport_pb.setText(QtGui.QApplication.translate("MainWindow", "Save as", None, QtGui.QApplication.UnicodeUTF8)) - self.label_29.setText(QtGui.QApplication.translate("MainWindow", "

Lipid Composer: Generate Lipid Master table from selected FA white list

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_27.setText(QtGui.QApplication.translate("MainWindow", "Export Lipid Master table as (.csv): ", None, QtGui.QApplication.UnicodeUTF8)) - self.label_48.setText(QtGui.QApplication.translate("MainWindow", "Select lipid class:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(0, QtGui.QApplication.translate("MainWindow", "--- Please select ---", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(1, QtGui.QApplication.translate("MainWindow", "Phosphatidic acid (PA) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(2, QtGui.QApplication.translate("MainWindow", "Phosphatidylcholine (PC) [M+HCOO]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(3, QtGui.QApplication.translate("MainWindow", "Phosphatidylcholine (PC) [M+CH3COO]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(4, QtGui.QApplication.translate("MainWindow", "Phosphatidylethanolamine (PE) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(5, QtGui.QApplication.translate("MainWindow", "Phosphatidylglycerol (PG) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(6, QtGui.QApplication.translate("MainWindow", "Phosphatidylinositol (PI) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(7, QtGui.QApplication.translate("MainWindow", "Phosphatidylserine (PS) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(8, QtGui.QApplication.translate("MainWindow", "Triacylglycerol (TG) [M+NH4]+", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(9, QtGui.QApplication.translate("MainWindow", "Triacylglycerol (TG) [M+H]+", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(10, QtGui.QApplication.translate("MainWindow", "Triacylglycerol (TG) [M+Na]+", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(11, QtGui.QApplication.translate("MainWindow", "Diacylglycerol (DG) [M+NH4]+", None, QtGui.QApplication.UnicodeUTF8)) + self.tab_a_lipidclass_cmb.setItemText( + 13 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PA (LPA) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 14 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PC (LPC) [M+HCOO]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 15 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PC (LPC) [M+CH3COO]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 16 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PE (LPE) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 17 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PG (LPG) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 18 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PI (LPI) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_a_lipidclass_cmb.setItemText( + 19 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PS (LPS) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.label_5.setText( + QtGui.QApplication.translate( + "MainWindow", "FA white list:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_19.setText( + QtGui.QApplication.translate( + "MainWindow", + "

Isotope score ≥

", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_20.setText( + QtGui.QApplication.translate( + "MainWindow", + "

Rank score ≥

", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_38.setText( + QtGui.QApplication.translate( + "MainWindow", + "Minimum relative intensity for scoring:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_a_ms2infoth_dspb.setSuffix( + QtGui.QApplication.translate( + "MainWindow", " %", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_15.setText( + QtGui.QApplication.translate( + "MainWindow", + "MS level tolerance:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_a_msppm_spb.setSuffix( + QtGui.QApplication.translate( + "MainWindow", " ppm", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_a_msppm_spb.setPrefix( + QtGui.QApplication.translate( + "MainWindow", "+/- ", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_13.setText( + QtGui.QApplication.translate( + "MainWindow", + "MS level threshold (absolute intensity):", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_a_msmax_chb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Set MS max inetnsity", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_25.setText( + QtGui.QApplication.translate( + "MainWindow", "Precursor window:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_a_prwindow_spb.setPrefix( + QtGui.QApplication.translate( + "MainWindow", "+/- ", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_a_prwindow_spb.setSuffix( + QtGui.QApplication.translate( + "MainWindow", " m/z", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.x.setText( + QtGui.QApplication.translate( + "MainWindow", "DDA Top:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_a_runhunter_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Hunt for lipids !", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.runhunter_tabframe.setTabText( + self.runhunter_tabframe.indexOf(self.singlerun_tab), + QtGui.QApplication.translate( + "MainWindow", + "Run LipidHunter identification directly", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.label.setText( + QtGui.QApplication.translate( + "MainWindow", + "Save configuration file as:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_a_cfgpath_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Save As", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_a_gencfg_pb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Generate configuration file for batch mode >>>", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.runhunter_tabframe.setTabText( + self.runhunter_tabframe.indexOf(self.savecfg_tab), + QtGui.QApplication.translate( + "MainWindow", + "Save parameters for Batch Mode Hunter", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.label_23.setText( + QtGui.QApplication.translate( + "MainWindow", "Instrument vendor:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.vendor_cmb.setItemText( + 0, + QtGui.QApplication.translate( + "MainWindow", + "--- Please select ---", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.vendor_cmb.setItemText( + 1, + QtGui.QApplication.translate( + "MainWindow", "Agilent", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.vendor_cmb.setItemText( + 2, + QtGui.QApplication.translate( + "MainWindow", "SCIEX", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.vendor_cmb.setItemText( + 3, + QtGui.QApplication.translate( + "MainWindow", "Thermo", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.vendor_cmb.setItemText( + 4, + QtGui.QApplication.translate( + "MainWindow", "Waters", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.label_24.setText( + QtGui.QApplication.translate( + "MainWindow", "Mode:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.mode_lcms_rb.setText( + QtGui.QApplication.translate( + "MainWindow", "LC-MS/MS", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.mode_static_rb.setText( + QtGui.QApplication.translate( + "MainWindow", "Shotgun", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tabframe.setTabText( + self.tabframe.indexOf(self.hunter_tab), + QtGui.QApplication.translate( + "MainWindow", "Hunt for Lipids", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.label_98.setText( + QtGui.QApplication.translate( + "MainWindow", + "Load batch configurations files (.txt):", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_b_1_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Input batch configuration file:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_b_addcfg_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Add a single file", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_b_2_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Add all batch configurations in a folder:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_b_addcfgfolder_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Select a folder", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_b_clearall_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Clear all", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_b_runbatch_pb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Run batch mode identification >>>", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_b_maxsubcore_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Max cores for each task:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_b_maxsubram_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Max RAM for each task:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_b_maxsubram_spb.setSuffix( + QtGui.QApplication.translate( + "MainWindow", " GB", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_b_mutlimode_cmb.setItemText( + 0, + QtGui.QApplication.translate( + "MainWindow", + "Process as a sequence", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_b_mutlimode_cmb.setItemText( + 1, + QtGui.QApplication.translate( + "MainWindow", + "Process multiple files in parallel", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_b_maxbatch_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Max number of files in parallel:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_99.setText( + QtGui.QApplication.translate( + "MainWindow", + "Batch mode settings:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tabframe.setTabText( + self.tabframe.indexOf(self.batch_tab), + QtGui.QApplication.translate( + "MainWindow", "Batch Mode Hunter", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.label_93.setText( + QtGui.QApplication.translate( + "MainWindow", "Image format:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_imagetype_cmb.setItemText( + 0, + QtGui.QApplication.translate( + "MainWindow", ".png", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.tab_c_imagetype_cmb.setItemText( + 1, + QtGui.QApplication.translate( + "MainWindow", ".svg", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.label_94.setText( + QtGui.QApplication.translate( + "MainWindow", "dpi:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_scorecfgtg_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

"Wfrag" for TG:

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_c_scorecfgdg_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

"Wfrag" for DG:

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_c_isotopescoremode_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Isotope Score mode:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_14.setText( + QtGui.QApplication.translate( + "MainWindow", + "Lipid specific FRAG & NL list:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_c_scorecfgdg_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_scorecfgpl_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

"Wfrag" for PL:

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_c_scorecfgpl_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_scorecfgtg_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_hgcfg_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_21.setText( + QtGui.QApplication.translate( + "MainWindow", + "

Score weight factor settings:

", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_c_parallization_cmb.setItemText( + 0, + QtGui.QApplication.translate( + "MainWindow", + "CPU prarallization mode", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_parallization_cmb.setItemText( + 1, + QtGui.QApplication.translate( + "MainWindow", + "CPU +GPU mode (experimental)", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.label_63.setText( + QtGui.QApplication.translate( + "MainWindow", + "Max CPU cores to use:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_64.setText( + QtGui.QApplication.translate( + "MainWindow", "Max RAM to use:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_ram_spb.setSuffix( + QtGui.QApplication.translate( + "MainWindow", " GB", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_tag_all_fa_chb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Favoured for TG with all three FA residues identified", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_12.setText( + QtGui.QApplication.translate( + "MainWindow", + "Default Fatty acid white list:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_c_falistpl_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_savesettings_pb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Save above settings as defaullt", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_c_falisttg_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

"Wfrag" for LPL:

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_c_falistpl_lb.setText( + QtGui.QApplication.translate( + "MainWindow", "Default FA list:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_falisttg_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_isotopescoremode_cmb.setItemText( + 0, + QtGui.QApplication.translate( + "MainWindow", "All elements", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.tab_c_isotopescoremode_cmb.setItemText( + 1, + QtGui.QApplication.translate( + "MainWindow", "Fast (only 13C)", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.tab_c_scoremode_lb.setText( + QtGui.QApplication.translate( + "MainWindow", "Score mode:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_scoremode_cmb.setItemText( + 0, + QtGui.QApplication.translate( + "MainWindow", "Signal rank mode", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.tab_c_scoremode_cmb.setItemText( + 1, + QtGui.QApplication.translate( + "MainWindow", + "Relative Intensity mode", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.label_35.setText( + QtGui.QApplication.translate( + "MainWindow", + "Prarallel processing settings:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_54.setText( + QtGui.QApplication.translate( + "MainWindow", + "Output image settings:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_28.setText( + QtGui.QApplication.translate( + "MainWindow", "FA white list:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_lmcalcfalist_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_lmexport_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Save as", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_29.setText( + QtGui.QApplication.translate( + "MainWindow", + '

Lipid Composer: Generate Lipid Master table from selected FA white list

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_27.setText( + QtGui.QApplication.translate( + "MainWindow", + "Export Lipid Master table as (.csv): ", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_48.setText( + QtGui.QApplication.translate( + "MainWindow", + "Select lipid class:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_c_lipidclass_cmb.setItemText( + 0, + QtGui.QApplication.translate( + "MainWindow", + "--- Please select ---", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 1, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidic acid (PA) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 2, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylcholine (PC) [M+HCOO]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 3, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylcholine (PC) [M+CH3COO]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 4, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylethanolamine (PE) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 5, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylglycerol (PG) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 6, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylinositol (PI) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 7, + QtGui.QApplication.translate( + "MainWindow", + "Phosphatidylserine (PS) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 8, + QtGui.QApplication.translate( + "MainWindow", + "Triacylglycerol (TG) [M+NH4]+", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 9, + QtGui.QApplication.translate( + "MainWindow", + "Triacylglycerol (TG) [M+H]+", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 10, + QtGui.QApplication.translate( + "MainWindow", + "Triacylglycerol (TG) [M+Na]+", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 11, + QtGui.QApplication.translate( + "MainWindow", + "Diacylglycerol (DG) [M+NH4]+", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) # self.tab_c_lipidclass_cmb.setItemText(12, QtGui.QApplication.translate("MainWindow", "Diacylglycerol (DG) [M+H]+", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(13-1, QtGui.QApplication.translate("MainWindow", "Lyso PA (LPA) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(14-1, QtGui.QApplication.translate("MainWindow", "Lyso PC (LPC) [M+HCOO]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(15-1, QtGui.QApplication.translate("MainWindow", "Lyso PC (LPC) [M+CH3COO]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(16-1, QtGui.QApplication.translate("MainWindow", "Lyso PE (LPE) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(17-1, QtGui.QApplication.translate("MainWindow", "Lyso PG (LPG) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(18-1, QtGui.QApplication.translate("MainWindow", "Lyso PI (LPI) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lipidclass_cmb.setItemText(19-1, QtGui.QApplication.translate("MainWindow", "Lyso PS (LPS) [M-H]-", None, QtGui.QApplication.UnicodeUTF8)) - self.label_17.setText(QtGui.QApplication.translate("MainWindow", "MS/MS level query window:", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lmms2ppm_spb.setSuffix(QtGui.QApplication.translate("MainWindow", " ppm", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lmms2ppm_spb.setPrefix(QtGui.QApplication.translate("MainWindow", "+/- ", None, QtGui.QApplication.UnicodeUTF8)) - self.tab_c_lmrun_pb.setText(QtGui.QApplication.translate("MainWindow", "Generate Lipid Master table >>>", None, QtGui.QApplication.UnicodeUTF8)) - self.tabframe.setTabText(self.tabframe.indexOf(self.cfg_tab), QtGui.QApplication.translate("MainWindow", "Settings", None, QtGui.QApplication.UnicodeUTF8)) - self.label_2.setText(QtGui.QApplication.translate("MainWindow", "Lipid Class", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_lipidclass_cmb.setItemText(0, QtGui.QApplication.translate("MainWindow", "Phospholipid", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_lipidclass_cmb.setItemText(1, QtGui.QApplication.translate("MainWindow", "Triacylglycerol", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_lipidclass_cmb.setItemText(2, QtGui.QApplication.translate("MainWindow", "Sphingolipid", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_lipidclass_cmb.setItemText(3, QtGui.QApplication.translate("MainWindow", "Ceramide", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_lipidclass_cmb.setItemText(4, QtGui.QApplication.translate("MainWindow", "Cardiolipin", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_lipidclass_cmb.setItemText(5, QtGui.QApplication.translate("MainWindow", "Diacylglycerol", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_all_sn_chb.setText(QtGui.QApplication.translate("MainWindow", "Apply settings to all sn positions", None, QtGui.QApplication.UnicodeUTF8)) - self.label_59.setText(QtGui.QApplication.translate("MainWindow", "Save FA whitelist as .xlsx:", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_savelist_pb.setText(QtGui.QApplication.translate("MainWindow", "Save as", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_sn1_lb.setText(QtGui.QApplication.translate("MainWindow", "sn1", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_sn1allfa_chb.setText(QtGui.QApplication.translate("MainWindow", "Select all", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa12x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA12:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa22x5_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:5", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa18x2_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:2", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa18x1_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:1", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa22x4_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:4", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa20x5_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:5", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa18x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa22x6_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:6", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa16x1_chb.setText(QtGui.QApplication.translate("MainWindow", "FA16:1", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa14x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA14:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa20x3_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:3", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa16x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA16:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa18x3_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:3", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_fa20x4_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:4", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_showop_chb.setText(QtGui.QApplication.translate("MainWindow", "Consider O- & P- (PC,PE only)", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_o16x0_chb.setText(QtGui.QApplication.translate("MainWindow", "O-16:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_o18x0_chb.setText(QtGui.QApplication.translate("MainWindow", "O-18:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_o20x0_chb.setText(QtGui.QApplication.translate("MainWindow", "O-20:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_p16x0_chb.setText(QtGui.QApplication.translate("MainWindow", "P-16:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_p18x0_chb.setText(QtGui.QApplication.translate("MainWindow", "P-18:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn1_p20x0_chb.setText(QtGui.QApplication.translate("MainWindow", "P-20:0", None, QtGui.QApplication.UnicodeUTF8)) - self.label_22.setText(QtGui.QApplication.translate("MainWindow", "Other residues*:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_62.setText(QtGui.QApplication.translate("MainWindow", "*: Add additional FA residue(s) using corresponging abbreviation(s) and put \", \" in between e.g. FA17:0, FA14:1", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_sn2_lb.setText(QtGui.QApplication.translate("MainWindow", "sn2", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_sn2allfa_chb.setText(QtGui.QApplication.translate("MainWindow", "Select all", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa22x5_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:5", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa22x4_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:4", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa20x5_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:5", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa22x6_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:6", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa18x1_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:1", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa14x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA14:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa16x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA16:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa18x3_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:3", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa18x2_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:2", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa18x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa16x1_chb.setText(QtGui.QApplication.translate("MainWindow", "FA16:1", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa20x4_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:4", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa20x3_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:3", None, QtGui.QApplication.UnicodeUTF8)) - self.sn2_fa12x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA12:0", None, QtGui.QApplication.UnicodeUTF8)) - self.label_41.setText(QtGui.QApplication.translate("MainWindow", "Other residues*:", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_sn3_lb.setText(QtGui.QApplication.translate("MainWindow", "sn3", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_sn3allfa_chb.setText(QtGui.QApplication.translate("MainWindow", "Select all", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa14x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA14:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa22x4_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:4", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa18x1_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:1", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa22x5_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:5", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa22x6_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:6", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa18x3_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:3", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa16x1_chb.setText(QtGui.QApplication.translate("MainWindow", "FA16:1", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa20x4_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:4", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa18x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa20x5_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:5", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa18x2_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:2", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa16x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA16:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa12x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA12:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn3_fa20x3_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:3", None, QtGui.QApplication.UnicodeUTF8)) - self.label_61.setText(QtGui.QApplication.translate("MainWindow", "Other residues*:", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_sn4_lb.setText(QtGui.QApplication.translate("MainWindow", "sn4", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_sn3allfa_chb_2.setText(QtGui.QApplication.translate("MainWindow", "Select all", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa22x6_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:6", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa22x5_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:5", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa22x4_chb.setText(QtGui.QApplication.translate("MainWindow", "FA22:4", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa20x5_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:5", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa20x4_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:4", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa20x3_chb.setText(QtGui.QApplication.translate("MainWindow", "FA20:3", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa18x3_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:3", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa18x2_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:2", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa18x1_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:1", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa18x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA18:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa16x1_chb.setText(QtGui.QApplication.translate("MainWindow", "FA16:1", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa16x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA16:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa14x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA14:0", None, QtGui.QApplication.UnicodeUTF8)) - self.sn4_fa12x0_chb.setText(QtGui.QApplication.translate("MainWindow", "FA12:0", None, QtGui.QApplication.UnicodeUTF8)) - self.label_66.setText(QtGui.QApplication.translate("MainWindow", "Other residues*:", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_genlist_pb.setText(QtGui.QApplication.translate("MainWindow", "Generate FA whitelist ", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tabframe.setTabText(self.lipidgen_tabframe.indexOf(self.lipidgen_tab1), QtGui.QApplication.translate("MainWindow", "Lipid Generator Wizard", None, QtGui.QApplication.UnicodeUTF8)) - self.label_60.setText(QtGui.QApplication.translate("MainWindow", "Load FA white list from .xlsx:", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab2_loadlist_pb.setText(QtGui.QApplication.translate("MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab2_loadlist_lb.setText(QtGui.QApplication.translate("MainWindow", "Sucessfully loaded!", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab2_savemasterlist_lb.setText(QtGui.QApplication.translate("MainWindow", "Save lipid master list as .xlsx:", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab2_savemasterlist_pb.setText(QtGui.QApplication.translate("MainWindow", "Save as", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tab1_genmasterlist_pb.setText(QtGui.QApplication.translate("MainWindow", "Generate lipid master list >>> ", None, QtGui.QApplication.UnicodeUTF8)) - self.lipidgen_tabframe.setTabText(self.lipidgen_tabframe.indexOf(self.lipidgen_tab2), QtGui.QApplication.translate("MainWindow", "Create lipid master list from FA white list", None, QtGui.QApplication.UnicodeUTF8)) - self.tabframe.setTabText(self.tabframe.indexOf(self.generator_tab), QtGui.QApplication.translate("MainWindow", "FA White List Generator", None, QtGui.QApplication.UnicodeUTF8)) - self.version_lb.setText(QtGui.QApplication.translate("MainWindow", "

LipidHunter 2 RC [Relased Date: 27, April, 2018]

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_26.setText(QtGui.QApplication.translate("MainWindow", "Developed by: SysMedOs team", None, QtGui.QApplication.UnicodeUTF8)) - self.label_43.setText(QtGui.QApplication.translate("MainWindow", "

LipidHunter is Dual-Licensed:

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_42.setText(QtGui.QApplication.translate("MainWindow", " For academic & non-commercial use:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_44.setText(QtGui.QApplication.translate("MainWindow", " For commercial use please contact the developers:", None, QtGui.QApplication.UnicodeUTF8)) - self.link_gplv2_lb.setText(QtGui.QApplication.translate("MainWindow", "

Under GPL v2 License: https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_45.setText(QtGui.QApplication.translate("MainWindow", "

oxlpp@bbz.uni-leipzig.de

", None, QtGui.QApplication.UnicodeUTF8)) - self.link_source_lb.setText(QtGui.QApplication.translate("MainWindow", "

Project page: https://bitbucket.org/SysMedOs/lipidhunter

", None, QtGui.QApplication.UnicodeUTF8)) - self.link_tutorial_lb.setText(QtGui.QApplication.translate("MainWindow", "

Online tutorial: https://bitbucket.org/SysMedOs/lipidhunter/wiki/

", None, QtGui.QApplication.UnicodeUTF8)) - self.link_paper_lb.setText(QtGui.QApplication.translate("MainWindow", "

Please cite our publication: Ni, Z., Angelidou, G., Lange, M., Hoffmann, R., & Fedorova, M. (2017). LipidHunter identifies phospholipids by high-throughput processing of LC-MS and shotgun lipidomics datasets. Analytical chemistry, 89(17), 8800-8807.

", None, QtGui.QApplication.UnicodeUTF8)) - self.link_otherprojects_lb.setText(QtGui.QApplication.translate("MainWindow", "

Other SysMedOs software Projects: https://home.uni-leipzig.de/fedorova/software/

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_30.setText(QtGui.QApplication.translate("MainWindow", "We acknowlege all open source libraries used in LipidHunter:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_31.setText(QtGui.QApplication.translate("MainWindow", "matplotlib", None, QtGui.QApplication.UnicodeUTF8)) - self.link_matplotlib_lb.setText(QtGui.QApplication.translate("MainWindow", "

http://www.matplotlib.org
John D. Hunter. Matplotlib: A 2D Graphics Environment,
Computing in Science & Engineering, 9, 90-95 (2007), DOI:10.1109/MCSE.2007.55

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_36.setText(QtGui.QApplication.translate("MainWindow", "numpy & scipy", None, QtGui.QApplication.UnicodeUTF8)) - self.link_numpy_lb.setText(QtGui.QApplication.translate("MainWindow", "

https://www.numpy.org & https://www.scipy.org
Stéfan van der Walt, S. Chris Colbert and Gaël Varoquaux. The NumPy Array: A Structure for Efficient Numerical Computation,
Computing in Science & Engineering, 13, 22-30 (2011), DOI:10.1109/MCSE.2011.37

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_32.setText(QtGui.QApplication.translate("MainWindow", "pandas", None, QtGui.QApplication.UnicodeUTF8)) - self.link_pandas_lb.setText(QtGui.QApplication.translate("MainWindow", "

http://pandas.pydata.org
Wes McKinney. Data Structures for Statistical Computing in Python,
Proceedings of the 9th Python in Science Conference, 51-56 (2010)

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_33.setText(QtGui.QApplication.translate("MainWindow", "pymzML", None, QtGui.QApplication.UnicodeUTF8)) - self.link_pymzml_lb.setText(QtGui.QApplication.translate("MainWindow", "

https://pymzml.github.io
Bald, T., Barth, J., Niehues, A., Specht, M., Hippler, M., and Fufezan, C. (2012)
pymzML - Python module for high throughput bioinformatics on mass spectrometry data,
Bioinformatics, DOI: 10.1093/bioinformatics/bts066

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_34.setText(QtGui.QApplication.translate("MainWindow", "pyside", None, QtGui.QApplication.UnicodeUTF8)) - self.link_pyside_lb.setText(QtGui.QApplication.translate("MainWindow", "

https://wiki.qt.io/PySide

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_37.setText(QtGui.QApplication.translate("MainWindow", "numba", None, QtGui.QApplication.UnicodeUTF8)) - self.label_97.setText(QtGui.QApplication.translate("MainWindow", "

http://numba.pydata.org
Siu Kwan Lam, Antoine Pitrou, and Stanley Seibert. Numba: a LLVM-based Python JIT compiler,
DOI:10.1145/2833157.2833162

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_46.setText(QtGui.QApplication.translate("MainWindow", "We acknowlege all projects that support the development of LipidHunter:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_47.setText(QtGui.QApplication.translate("MainWindow", "BMBF - Federal Ministry of Education and Research Germany:", None, QtGui.QApplication.UnicodeUTF8)) - self.label_49.setText(QtGui.QApplication.translate("MainWindow", "e:Med Systems Medicine Network:", None, QtGui.QApplication.UnicodeUTF8)) - self.link_bmbf_lb.setText(QtGui.QApplication.translate("MainWindow", "

https://www.bmbf.de/en/

", None, QtGui.QApplication.UnicodeUTF8)) - self.link_emed_lb.setText(QtGui.QApplication.translate("MainWindow", "

http://www.sys-med.de/en/

", None, QtGui.QApplication.UnicodeUTF8)) - self.link_sysmedos_lb.setText(QtGui.QApplication.translate("MainWindow", "

https://home.uni-leipzig.de/fedorova/sysmedos/

", None, QtGui.QApplication.UnicodeUTF8)) - self.label_58.setText(QtGui.QApplication.translate("MainWindow", "SysMedOS Project : ", None, QtGui.QApplication.UnicodeUTF8)) - self.tabframe.setTabText(self.tabframe.indexOf(self.tab), QtGui.QApplication.translate("MainWindow", "About LipidHunter 2", None, QtGui.QApplication.UnicodeUTF8)) - self.link_uni_lb.setText(QtGui.QApplication.translate("MainWindow", "

LipidHunter (C) 2016-2018 | University of Leipzig | AG Bioanalytik | Fedorova Research Group

", None, QtGui.QApplication.UnicodeUTF8)) - + self.tab_c_lipidclass_cmb.setItemText( + 13 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PA (LPA) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 14 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PC (LPC) [M+HCOO]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 15 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PC (LPC) [M+CH3COO]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 16 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PE (LPE) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 17 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PG (LPG) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 18 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PI (LPI) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tab_c_lipidclass_cmb.setItemText( + 19 - 1, + QtGui.QApplication.translate( + "MainWindow", + "Lyso PS (LPS) [M-H]-", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.label_17.setText( + QtGui.QApplication.translate( + "MainWindow", + "MS/MS level query window:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tab_c_lmms2ppm_spb.setSuffix( + QtGui.QApplication.translate( + "MainWindow", " ppm", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_lmms2ppm_spb.setPrefix( + QtGui.QApplication.translate( + "MainWindow", "+/- ", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.tab_c_lmrun_pb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Generate Lipid Master table >>>", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tabframe.setTabText( + self.tabframe.indexOf(self.cfg_tab), + QtGui.QApplication.translate( + "MainWindow", "Settings", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.label_2.setText( + QtGui.QApplication.translate( + "MainWindow", "Lipid Class", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.lipidgen_tab1_lipidclass_cmb.setItemText( + 0, + QtGui.QApplication.translate( + "MainWindow", "Phospholipid", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.lipidgen_tab1_lipidclass_cmb.setItemText( + 1, + QtGui.QApplication.translate( + "MainWindow", "Triacylglycerol", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.lipidgen_tab1_lipidclass_cmb.setItemText( + 2, + QtGui.QApplication.translate( + "MainWindow", "Sphingolipid", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.lipidgen_tab1_lipidclass_cmb.setItemText( + 3, + QtGui.QApplication.translate( + "MainWindow", "Ceramide", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.lipidgen_tab1_lipidclass_cmb.setItemText( + 4, + QtGui.QApplication.translate( + "MainWindow", "Cardiolipin", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.lipidgen_tab1_lipidclass_cmb.setItemText( + 5, + QtGui.QApplication.translate( + "MainWindow", "Diacylglycerol", None, QtGui.QApplication.UnicodeUTF8 + ), + ) + self.lipidgen_tab1_all_sn_chb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Apply settings to all sn positions", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_59.setText( + QtGui.QApplication.translate( + "MainWindow", + "Save FA whitelist as .xlsx:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.lipidgen_tab1_savelist_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Save as", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.lipidgen_tab1_sn1_lb.setText( + QtGui.QApplication.translate( + "MainWindow", "sn1", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.lipidgen_tab1_sn1allfa_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "Select all", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa12x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA12:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa22x5_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:5", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa18x2_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:2", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa18x1_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:1", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa22x4_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:4", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa20x5_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:5", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa18x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa22x6_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:6", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa16x1_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA16:1", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa14x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA14:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa20x3_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:3", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa16x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA16:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa18x3_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:3", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_fa20x4_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:4", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_showop_chb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Consider O- & P- (PC,PE only)", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.sn1_o16x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "O-16:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_o18x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "O-18:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_o20x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "O-20:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_p16x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "P-16:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_p18x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "P-18:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn1_p20x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "P-20:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_22.setText( + QtGui.QApplication.translate( + "MainWindow", "Other residues*:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_62.setText( + QtGui.QApplication.translate( + "MainWindow", + '*: Add additional FA residue(s) using corresponging abbreviation(s) and put ", " in between e.g. FA17:0, FA14:1', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.lipidgen_tab1_sn2_lb.setText( + QtGui.QApplication.translate( + "MainWindow", "sn2", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.lipidgen_tab1_sn2allfa_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "Select all", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa22x5_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:5", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa22x4_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:4", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa20x5_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:5", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa22x6_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:6", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa18x1_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:1", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa14x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA14:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa16x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA16:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa18x3_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:3", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa18x2_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:2", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa18x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa16x1_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA16:1", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa20x4_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:4", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa20x3_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:3", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn2_fa12x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA12:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_41.setText( + QtGui.QApplication.translate( + "MainWindow", "Other residues*:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.lipidgen_tab1_sn3_lb.setText( + QtGui.QApplication.translate( + "MainWindow", "sn3", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.lipidgen_tab1_sn3allfa_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "Select all", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa14x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA14:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa22x4_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:4", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa18x1_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:1", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa22x5_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:5", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa22x6_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:6", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa18x3_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:3", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa16x1_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA16:1", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa20x4_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:4", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa18x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa20x5_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:5", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa18x2_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:2", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa16x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA16:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa12x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA12:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn3_fa20x3_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:3", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_61.setText( + QtGui.QApplication.translate( + "MainWindow", "Other residues*:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.lipidgen_tab1_sn4_lb.setText( + QtGui.QApplication.translate( + "MainWindow", "sn4", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.lipidgen_tab1_sn3allfa_chb_2.setText( + QtGui.QApplication.translate( + "MainWindow", "Select all", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa22x6_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:6", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa22x5_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:5", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa22x4_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA22:4", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa20x5_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:5", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa20x4_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:4", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa20x3_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA20:3", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa18x3_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:3", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa18x2_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:2", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa18x1_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:1", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa18x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA18:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa16x1_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA16:1", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa16x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA16:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa14x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA14:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.sn4_fa12x0_chb.setText( + QtGui.QApplication.translate( + "MainWindow", "FA12:0", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_66.setText( + QtGui.QApplication.translate( + "MainWindow", "Other residues*:", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.lipidgen_tab1_genlist_pb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Generate FA whitelist ", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.lipidgen_tabframe.setTabText( + self.lipidgen_tabframe.indexOf(self.lipidgen_tab1), + QtGui.QApplication.translate( + "MainWindow", + "Lipid Generator Wizard", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.label_60.setText( + QtGui.QApplication.translate( + "MainWindow", + "Load FA white list from .xlsx:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.lipidgen_tab2_loadlist_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Open", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.lipidgen_tab2_loadlist_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Sucessfully loaded!", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.lipidgen_tab2_savemasterlist_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Save lipid master list as .xlsx:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.lipidgen_tab2_savemasterlist_pb.setText( + QtGui.QApplication.translate( + "MainWindow", "Save as", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.lipidgen_tab1_genmasterlist_pb.setText( + QtGui.QApplication.translate( + "MainWindow", + "Generate lipid master list >>> ", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.lipidgen_tabframe.setTabText( + self.lipidgen_tabframe.indexOf(self.lipidgen_tab2), + QtGui.QApplication.translate( + "MainWindow", + "Create lipid master list from FA white list", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.tabframe.setTabText( + self.tabframe.indexOf(self.generator_tab), + QtGui.QApplication.translate( + "MainWindow", + "FA White List Generator", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.version_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

LipidHunter 2 RC [Relased Date: 27, April, 2018]

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_26.setText( + QtGui.QApplication.translate( + "MainWindow", + "Developed by: SysMedOs team", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_43.setText( + QtGui.QApplication.translate( + "MainWindow", + '

LipidHunter is Dual-Licensed:

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_42.setText( + QtGui.QApplication.translate( + "MainWindow", + " For academic & non-commercial use:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_44.setText( + QtGui.QApplication.translate( + "MainWindow", + " For commercial use please contact the developers:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.link_gplv2_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

Under GPL v2 License: https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_45.setText( + QtGui.QApplication.translate( + "MainWindow", + "

oxlpp@bbz.uni-leipzig.de

", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.link_source_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

Project page: https://bitbucket.org/SysMedOs/lipidhunter

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.link_tutorial_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

Online tutorial: https://bitbucket.org/SysMedOs/lipidhunter/wiki/

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.link_paper_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

Please cite our publication: Ni, Z., Angelidou, G., Lange, M., Hoffmann, R., & Fedorova, M. (2017). LipidHunter identifies phospholipids by high-throughput processing of LC-MS and shotgun lipidomics datasets. Analytical chemistry, 89(17), 8800-8807.

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.link_otherprojects_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

Other SysMedOs software Projects: https://home.uni-leipzig.de/fedorova/software/

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_30.setText( + QtGui.QApplication.translate( + "MainWindow", + "We acknowlege all open source libraries used in LipidHunter:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_31.setText( + QtGui.QApplication.translate( + "MainWindow", "matplotlib", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.link_matplotlib_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

http://www.matplotlib.org
John D. Hunter. Matplotlib: A 2D Graphics Environment,
Computing in Science & Engineering, 9, 90-95 (2007), DOI:10.1109/MCSE.2007.55

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_36.setText( + QtGui.QApplication.translate( + "MainWindow", "numpy & scipy", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.link_numpy_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

https://www.numpy.org & https://www.scipy.org
Stéfan van der Walt, S. Chris Colbert and Gaël Varoquaux. The NumPy Array: A Structure for Efficient Numerical Computation,
Computing in Science & Engineering, 13, 22-30 (2011), DOI:10.1109/MCSE.2011.37

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_32.setText( + QtGui.QApplication.translate( + "MainWindow", "pandas", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.link_pandas_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

http://pandas.pydata.org
Wes McKinney. Data Structures for Statistical Computing in Python,
Proceedings of the 9th Python in Science Conference, 51-56 (2010)

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_33.setText( + QtGui.QApplication.translate( + "MainWindow", "pymzML", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.link_pymzml_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

https://pymzml.github.io
Bald, T., Barth, J., Niehues, A., Specht, M., Hippler, M., and Fufezan, C. (2012)
pymzML - Python module for high throughput bioinformatics on mass spectrometry data,
Bioinformatics, DOI: 10.1093/bioinformatics/bts066

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_34.setText( + QtGui.QApplication.translate( + "MainWindow", "pyside", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.link_pyside_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

https://wiki.qt.io/PySide

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_37.setText( + QtGui.QApplication.translate( + "MainWindow", "numba", None, QtGui.QApplication.UnicodeUTF8 + ) + ) + self.label_97.setText( + QtGui.QApplication.translate( + "MainWindow", + '

http://numba.pydata.org
Siu Kwan Lam, Antoine Pitrou, and Stanley Seibert. Numba: a LLVM-based Python JIT compiler,
DOI:10.1145/2833157.2833162

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_46.setText( + QtGui.QApplication.translate( + "MainWindow", + "We acknowlege all projects that support the development of LipidHunter:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_47.setText( + QtGui.QApplication.translate( + "MainWindow", + "BMBF - Federal Ministry of Education and Research Germany:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_49.setText( + QtGui.QApplication.translate( + "MainWindow", + "e:Med Systems Medicine Network:", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.link_bmbf_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

https://www.bmbf.de/en/

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.link_emed_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

http://www.sys-med.de/en/

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.link_sysmedos_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

https://home.uni-leipzig.de/fedorova/sysmedos/

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.label_58.setText( + QtGui.QApplication.translate( + "MainWindow", + "SysMedOS Project : ", + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) + self.tabframe.setTabText( + self.tabframe.indexOf(self.tab), + QtGui.QApplication.translate( + "MainWindow", + "About LipidHunter 2", + None, + QtGui.QApplication.UnicodeUTF8, + ), + ) + self.link_uni_lb.setText( + QtGui.QApplication.translate( + "MainWindow", + '

LipidHunter (C) 2016-2018 | University of Leipzig | AG Bioanalytik | Fedorova Research Group

', + None, + QtGui.QApplication.UnicodeUTF8, + ) + ) import LibLipidHunter.LipidHunter_rcc - diff --git a/LibLipidHunter/LipidHunter_rcc.py b/LibLipidHunter/LipidHunter_rcc.py index 0da56ab..261dc05 100644 --- a/LibLipidHunter/LipidHunter_rcc.py +++ b/LibLipidHunter/LipidHunter_rcc.py @@ -29,10 +29,18 @@ qt_resource_data = b"\x00\x00\xc9\x16\x00\x00\x01\x00\x0c\x00 \x10\x00\x01\x00\x04\x00\xe8\x02\x00\x00\xc6\x00\x00\x00\x10\x10\x10\x00\x01\x00\x04\x00(\x01\x00\x00\xae\x03\x00\x0000\x00\x00\x01\x00\x08\x00\xa8\x0e\x00\x00\xd6\x04\x00\x00 \x00\x00\x01\x00\x08\x00\xa8\x08\x00\x00~\x13\x00\x00\x10\x10\x00\x00\x01\x00\x08\x00h\x05\x00\x00&\x1c\x00\x00@@\x00\x00\x01\x00 \x00(B\x00\x00\x8e!\x00\x0000\x00\x00\x01\x00 \x00\xa8%\x00\x00\xb6c\x00\x00((\x00\x00\x01\x00 \x00h\x1a\x00\x00^\x89\x00\x00 \x00\x00\x01\x00 \x00\xa8\x10\x00\x00\xc6\xa3\x00\x00\x18\x18\x00\x00\x01\x00 \x00\x88\x09\x00\x00n\xb4\x00\x00\x14\x14\x00\x00\x01\x00 \x00\xb8\x06\x00\x00\xf6\xbd\x00\x00\x10\x10\x00\x00\x01\x00 \x00h\x04\x00\x00\xae\xc4\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\x00\x01\x00\x04\x00\x00\x00\x00\x00\x80\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x80\x00\x00\x00\x80\x80\x00\x80\x00\x00\x00\x80\x00\x80\x00\x80\x80\x00\x00\x80\x80\x80\x00\xc0\xc0\xc0\x00\x00\x00\xff\x00\x00\xff\x00\x00\x00\xff\xff\x00\xff\x00\x00\x00\xff\x00\xff\x00\xff\xff\x00\x00\xff\xff\xff\x00\x87\x87\x87\x87x{\x89\x87\x87x{\x89\x87xx\x989\xb9\xb9\xb9\xb9\xb9\x89\xb9\xb9\xb9\xb9\x89\xb9\xb9\xb9\xb8\xb9y\xb9\xb7\x9b\x9by\xb9\xb7\x9b\x9by\xb9\xb7\x9b\x97\x89{y\xb9\xb7\x9b\x9by\xb9\xb7\x9b\x9by\xb9\xb7\x98\x8b\x9b\x8f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x9b\x9b9\xb9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xb9{\x89\xb9\x8f\xff\x88\x88\xf8\x88\x88\x88\x8f\x88\x88\x88{\x97\x89\xb9\x8f\xf8\x9by\xb9\xb9\xb9\x8b\x9b\x9b\x9b\x9b\x9b\x98\x89\xb9\xbf\xf8\x98\xf8\xf8\xf8\xb8\x8f\x8f\x88\x9b\x9b\x9b\x9b9\xb9\x88\xff\xb8\xff\xff\xf8\x9f\xff\xff\xf8\x9b\x9b\x9b\x98{\x9b\x98\xff\x98\xff\xff\xff\x98\xff\xff\xff\x9b\x9b\x9b\x97\x89w\x98\xff\x8b\xff\xff\xff\xb8\xff\xff\xf8\xb9\xb9\xb9\xb8\x8b\x9b\x9b\xff\x89\x8f\xff\xff\x89\xff\xff\xff\x89\xb9w\x9b9\xb9\xb9\xff\x8b\x88\xf8\x8f\x8b\x8f\x8f\xff\x89\xb9\xb9\xb7\x89\xb9\xb9\x8f\x88\x9b{\x98\x9b\x98\x9b\x9b\x97\x9b\x9b\x97\x89\xb9\xb9\x8f\xf8\xb8\x88\x8f\x8bx\x88\xf8\x8b\x97\xb9\xb7\x89\xb9\xb9\xbf\xf8\xb8\xff\xff\xf8\xbf\xff\xff\x88\xb9w\x9b9\xb9\xb9\xb8\xf8\x98\xff\xff\xf8\xb8\xff\xff\xf8\xb9\xb9\xb8\x89\xb9w\x98\xff\x8b\xff\xff\xff\x98\xff\xff\xff\x9b\x9b\x97\x89\xb9\xb9\xb8\xff\x89\xff\xff\xffw\xff\xff\xf8\x9b\x9b\x98{\x9b\x9b\x9b\xff\x87\x88\xff\xff\x8b\x8f\xff\xff{\x9b\x9b9\xb9\xb9\xb9\xff\x8b\x9b{\x9b\x9bw\x9b\x9b\x9b\x9b\x98{\x9b\x97y\x8f\x88\x98\x88\x88\x89\xb8\x88\x88\x88\x9b\x97\x89w\x9b\x9b\x8f\xf8\xbf\xff\xff\xf7\x7f\xff\xff\xf9\xb9\xb7\x8b\x9b\x9b\x9b\x9f\xf8\xb8\xff\xff\xf8\xbf\xff\xff\x88\xb7\x9b9\xb9\xb9\xb9\xbf\xf8\x98\xff\xff\xf8\xb8\xff\xff\xf8\xb9\xb8\x89\xb9\xb9w\x98\xff\x8b\xff\xff\xff\x98\xff\xff\xff\x9b\x97\x89\xb9\xb9\xb9\xb8\xff\xb9\xff\xff\xf8\xb8\xff\xf8\xf8\x97\x98\x89y\xb9\xb9\xb9\x87\x89\x89\x87\x89\x89\x87\x87\x87\xb7\x9b9\xb7\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb9\xb7\xb3\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x97\x9b\x97\x89\x8b{{{{{{{{{{{{{x\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\x00\x01\x00\x04\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x80\x00\x00\x00\x80\x80\x00\x80\x00\x00\x00\x80\x00\x80\x00\x80\x80\x00\x00\x80\x80\x80\x00\xc0\xc0\xc0\x00\x00\x00\xff\x00\x00\xff\x00\x00\x00\xff\xff\x00\xff\x00\x00\x00\xff\x00\xff\x00\xff\xff\x00\x00\xff\xff\xff\x00\xb7\xb7\x87\xb7\x87\xb7\xb8\x989\x89\xb9\xb9\xb9\xb9\x89\xb7{\x8f\xf8\xf8\xf8\xf8\xf8\xb7\x89\xf8\x88\x88\x88\x88\x8b\x98\xb9\x88\x7f\x88\x88\xff\x9b\x9b9\x8f\x8f\xff\x8f\xff\x9b\x98\x89\xb8\x88\x88x\x88\x8b\x97\x89\xb8\x8b\x88\xb8\x88\xb9\xb7{\x98\x88\xff\x88\xff\x87\x9b9\x88\xf8\xff\x88\xff\x89\xb8{\x9b\x88\x88\x8b\x88\x8b\x97\x89\xb9\xf8\x88\xf8\x88\xfb\x98\x89\xb9\x88\x8f\xf8\x8f\xff\x9b9\xb9\x8f\xbf\xf8\x8f\xf8\x98{\x99yy\x89y{\x97\x89\x8b{{{{{x\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x000\x00\x00\x00`\x00\x00\x00\x01\x00\x08\x00\x00\x00\x00\x00\x80\x0a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x001}\xed\x004~\xed\x006\x80\xed\x00:\x82\xed\x00=\x84\xee\x00@\x86\xee\x00B\x88\xee\x00D\x89\xef\x00H\x8b\xef\x00J\x8c\xee\x00L\x8e\xef\x00O\x90\xef\x00P\x91\xef\x00M\x8e\xf0\x00N\x90\xf0\x00Q\x91\xf0\x00T\x93\xf0\x00V\x94\xf0\x00Y\x96\xf0\x00]\x99\xf0\x00`\x9a\xf0\x00b\x9c\xf0\x00f\x9e\xf2\x00i\xa1\xf2\x00l\xa2\xf2\x00o\xa4\xf3\x00q\xa6\xf2\x00t\xa7\xf3\x00v\xa8\xf3\x00y\xaa\xf3\x00{\xac\xf3\x00}\xae\xf3\x00z\xab\xf4\x00{\xac\xf4\x00}\xad\xf4\x00\x80\xaf\xf4\x00\x83\xb1\xf4\x00\x86\xb2\xf5\x00\x8b\xb6\xf5\x00\x8d\xb7\xf5\x00\x8f\xb9\xf6\x00\x90\xb9\xf5\x00\x95\xbc\xf6\x00\x99\xbe\xf6\x00\x9d\xc1\xf6\x00\xa1\xc4\xf7\x00\xa5\xc6\xf7\x00\xa9\xc8\xf7\x00\xa9\xc9\xf8\x00\xae\xcc\xf8\x00\xb0\xcd\xf8\x00\xb4\xd0\xf8\x00\xb9\xd3\xf9\x00\xbb\xd4\xf9\x00\xbd\xd5\xf9\x00\xc0\xd7\xf9\x00\xc1\xd8\xf9\x00\xc5\xdb\xfa\x00\xc7\xdc\xfa\x00\xc8\xdc\xfa\x00\xcc\xdf\xfa\x00\xce\xe0\xfa\x00\xd1\xe1\xfb\x00\xd4\xe4\xfb\x00\xd6\xe5\xfc\x00\xd8\xe7\xfc\x00\xda\xe8\xfc\x00\xdd\xea\xfc\x00\xe0\xeb\xfc\x00\xe1\xec\xfc\x00\xe4\xee\xfd\x00\xe7\xf0\xfd\x00\xe9\xf1\xfd\x00\xec\xf3\xfd\x00\xee\xf4\xfe\x00\xf0\xf6\xfe\x00\xf5\xf9\xfe\x00\xf8\xfa\xfe\x00\xfa\xfc\xfe\x00\xfe\xfe\xff\x00\x00\x00\x00\x00\x02/\x00\x00\x04P\x00\x00\x06p\x00\x00\x08\x90\x00\x00\x0a\xb0\x00\x00\x0b\xcf\x00\x00\x0e\xf0\x00\x00 \xff\x12\x00=\xff1\x00[\xffQ\x00y\xffq\x00\x98\xff\x91\x00\xb5\xff\xb1\x00\xd4\xff\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00\x14/\x00\x00\x22P\x00\x000p\x00\x00=\x90\x00\x00L\xb0\x00\x00Y\xcf\x00\x00g\xf0\x00\x00x\xff\x11\x00\x8a\xff1\x00\x9c\xffQ\x00\xae\xffq\x00\xc0\xff\x91\x00\xd2\xff\xb1\x00\xe4\xff\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00&/\x00\x00@P\x00\x00Zp\x00\x00t\x90\x00\x00\x8e\xb0\x00\x00\xa9\xcf\x00\x00\xc2\xf0\x00\x00\xd1\xff\x11\x00\xd8\xff1\x00\xde\xffQ\x00\xe3\xffq\x00\xe9\xff\x91\x00\xef\xff\xb1\x00\xf6\xff\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00/&\x00\x00PA\x00\x00p[\x00\x00\x90t\x00\x00\xb0\x8e\x00\x00\xcf\xa9\x00\x00\xf0\xc3\x00\x00\xff\xd2\x11\x00\xff\xd81\x00\xff\xddQ\x00\xff\xe4q\x00\xff\xea\x91\x00\xff\xf0\xb1\x00\xff\xf6\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00/\x14\x00\x00P\x22\x00\x00p0\x00\x00\x90>\x00\x00\xb0M\x00\x00\xcf[\x00\x00\xf0i\x00\x00\xffy\x11\x00\xff\x8a1\x00\xff\x9dQ\x00\xff\xafq\x00\xff\xc1\x91\x00\xff\xd2\xb1\x00\xff\xe5\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00/\x03\x00\x00P\x04\x00\x00p\x06\x00\x00\x90\x09\x00\x00\xb0\x0a\x00\x00\xcf\x0c\x00\x00\xf0\x0e\x00\x00\xff \x12\x00\xff>1\x00\xff\x5cQ\x00\xffzq\x00\xff\x97\x91\x00\xff\xb6\xb1\x00\xff\xd4\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00/\x00\x0e\x00P\x00\x17\x00p\x00!\x00\x90\x00+\x00\xb0\x006\x00\xcf\x00@\x00\xf0\x00I\x00\xff\x11Z\x00\xff1p\x00\xffQ\x86\x00\xffq\x9c\x00\xff\x91\xb2\x00\xff\xb1\xc8\x00\xff\xd1\xdf\x00\xff\xff\xff\x00\x00\x00\x00\x00/\x00 \x00P\x006\x00p\x00L\x00\x90\x00b\x00\xb0\x00x\x00\xcf\x00\x8e\x00\xf0\x00\xa4\x00\xff\x11\xb3\x00\xff1\xbe\x00\xffQ\xc7\x00\xffq\xd1\x00\xff\x91\xdc\x00\xff\xb1\xe5\x00\xff\xd1\xf0\x00\xff\xff\xff\x00\x00\x00\x00\x00,\x00/\x00K\x00P\x00i\x00p\x00\x87\x00\x90\x00\xa5\x00\xb0\x00\xc4\x00\xcf\x00\xe1\x00\xf0\x00\xf0\x11\xff\x00\xf21\xff\x00\xf4Q\xff\x00\xf6q\xff\x00\xf7\x91\xff\x00\xf9\xb1\xff\x00\xfb\xd1\xff\x00\xff\xff\xff\x00\x00\x00\x00\x00\x1b\x00/\x00-\x00P\x00?\x00p\x00R\x00\x90\x00c\x00\xb0\x00v\x00\xcf\x00\x88\x00\xf0\x00\x99\x11\xff\x00\xa61\xff\x00\xb4Q\xff\x00\xc2q\xff\x00\xcf\x91\xff\x00\xdc\xb1\xff\x00\xeb\xd1\xff\x00\xff\xff\xff\x00\x00\x00\x00\x00\x08\x00/\x00\x0e\x00P\x00\x15\x00p\x00\x1b\x00\x90\x00!\x00\xb0\x00&\x00\xcf\x00,\x00\xf0\x00>\x11\xff\x00X1\xff\x00qQ\xff\x00\x8cq\xff\x00\xa6\x91\xff\x00\xbf\xb1\xff\x00\xda\xd1\xff\x00\xff\xff\xff\x00\x14\x09\x09\x09\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x09\x0a\x0a\x0a\x0a\x0a\x09\x09\x0a\x09\x15\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x01\x08\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x08\x02\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x056FEEFEFEFEFEFEFFFFFFFFFFFFFFEFFFFF?\x12\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x023_________________________________N#\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00%N________________________________O2\x02\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x14K__LBAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3\x05\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x08B__C\x11\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x06\x01\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x024__J\x13\x00\x01\x03\x04\x03\x04\x03\x04\x04\x04\x03\x00\x00\x03\x04\x04\x04\x04\x04\x04\x04\x04\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00(N_N$\x00\x08399999993\x08\x00\x1d:;;;;;;<(\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x16L_O1\x02\x05>OOOOOOOL\x19\x00\x18LOOOOOOO>\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x08B__>\x06\x010O_____OO+\x00\x0dD_______I\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x025O_I\x12\x00\x22N______O8\x03\x037_______N\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00(O_N#\x00\x12I_______E\x0e\x01*O_____OO0\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x17LOO0\x02\x05>O______L\x19\x00\x18LO_____O>\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x0aD__>\x05\x010O______O*\x01\x0aD_______I\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x037__H\x12\x00\x1fNOOOOOOO8\x04\x037OOOOOOON\x22\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x01*OON!\x00\x0e02222222,\x05\x00 22222222\x1c\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x19L_O.\x01\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x0eF__<\x05\x00\x07\x13\x13\x13\x13\x13\x13\x13\x13\x0e\x01\x02\x10\x13\x13\x13\x13\x13\x13\x13\x12\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x038__G\x10\x00\x1bHKKKKKKK6\x04\x034KKKKKKKH\x1b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x01+O_M\x1d\x00\x12H_______F\x0c\x01,O______O-\x01\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1aL_O-\x01\x05=O______L\x1b\x00\x1bL_______;\x05\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0fF_O;\x04\x01.O______O,\x01\x0fG_______G\x10\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04:__G\x10\x00 N_______9\x04\x04:_______M\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01,O_L\x1b\x00\x11H_______F\x0c\x01,O______O-\x01\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1bM_O,\x01\x05=_______L\x1b\x00\x1bL_______;\x04\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10G__:\x04\x01.LMMMMMML*\x01\x0fDMMMMMMMD\x0f\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04;__F\x0b\x00\x0f\x1b\x1b\x1b\x1c\x1b\x1c\x1b\x1b\x13\x01\x02\x16\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1a\x06\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01.O_L\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1dM_O+\x00\x02\x1c())))))(\x10\x00\x08%&&&&'&'!\x03\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11H__8\x03\x02.NNNNNNNN*\x00\x0aDONNNNNNG\x11\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05=__E\x0e\x00\x1fN______O7\x03\x048O______M \x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01/O_L\x18\x00\x12I_______E\x0d\x00+O______O.\x01\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x22M_O*\x00\x05>_______L\x18\x00\x19L_______=\x05\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x12I_O5\x02\x010O______O*\x00\x0eF_______H\x11\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05>__C\x08\x00\x22M______O7\x03\x049_______M\x1e\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x010O_K\x16\x00\x12I_______E\x0a\x01+O______O.\x01\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1eEFE\x1f\x00\x056EEEEEEE@\x14\x00\x17CFFFFFFF3\x04\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x0a\x0a\x0a\x05\x00\x00\x07\x09\x09\x09\x09\x09\x09\x09\x08\x03\x00\x02\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x0a\x08\x01\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0a\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x09\x14\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\x00\x01\x00\x08\x00\x00\x00\x00\x00\x80\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x001}\xed\x004\x7f\xed\x006\x80\xed\x009\x82\xed\x00=\x84\xee\x00@\x86\xee\x00B\x88\xee\x00E\x8a\xef\x00J\x8c\xee\x00N\x8f\xf0\x00R\x91\xf0\x00T\x93\xf0\x00U\x94\xf0\x00Y\x96\xf0\x00[\x98\xf1\x00^\x99\xf1\x00a\x9a\xf0\x00b\x9c\xf1\x00e\x9e\xf2\x00i\xa0\xf2\x00m\xa3\xf2\x00n\xa4\xf2\x00t\xa7\xf3\x00v\xa9\xf3\x00x\xaa\xf3\x00z\xab\xf4\x00{\xac\xf4\x00~\xad\xf4\x00\x80\xaf\xf4\x00\x82\xb0\xf4\x00\x85\xb2\xf5\x00\x8a\xb5\xf5\x00\x8d\xb6\xf5\x00\x8e\xb8\xf5\x00\x93\xbb\xf6\x00\x95\xbc\xf6\x00\x98\xbe\xf6\x00\x9d\xc1\xf6\x00\xa3\xc5\xf7\x00\xa7\xc7\xf7\x00\xa7\xc8\xf7\x00\xa9\xc9\xf7\x00\xa9\xc9\xf8\x00\xac\xcb\xf8\x00\xad\xcc\xf8\x00\xb0\xce\xf8\x00\xb6\xd1\xf8\x00\xb9\xd2\xf9\x00\xbd\xd5\xf9\x00\xc0\xd7\xfa\x00\xc2\xd8\xfa\x00\xc4\xda\xfa\x00\xc7\xdc\xfa\x00\xca\xdd\xfa\x00\xce\xe0\xfb\x00\xd1\xe2\xfb\x00\xd4\xe4\xfb\x00\xd7\xe6\xfc\x00\xd9\xe7\xfc\x00\xda\xe8\xfc\x00\xdd\xe9\xfc\x00\xe0\xeb\xfc\x00\xe2\xed\xfc\x00\xe4\xee\xfd\x00\xe9\xf1\xfd\x00\xec\xf3\xfd\x00\xed\xf4\xfe\x00\xf1\xf6\xfe\x00\xf3\xf8\xfe\x00\xf5\xf8\xfe\x00\xf8\xfb\xff\x00\xfa\xfc\xff\x00\xfe\xfe\xff\x001\xffq\x00Q\xff\x87\x00q\xff\x9d\x00\x91\xff\xb2\x00\xb1\xff\xc9\x00\xd1\xff\xdf\x00\xff\xff\xff\x00\x00\x00\x00\x00\x02/\x00\x00\x04P\x00\x00\x06p\x00\x00\x08\x90\x00\x00\x0a\xb0\x00\x00\x0b\xcf\x00\x00\x0e\xf0\x00\x00 \xff\x12\x00=\xff1\x00[\xffQ\x00y\xffq\x00\x98\xff\x91\x00\xb5\xff\xb1\x00\xd4\xff\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00\x14/\x00\x00\x22P\x00\x000p\x00\x00=\x90\x00\x00L\xb0\x00\x00Y\xcf\x00\x00g\xf0\x00\x00x\xff\x11\x00\x8a\xff1\x00\x9c\xffQ\x00\xae\xffq\x00\xc0\xff\x91\x00\xd2\xff\xb1\x00\xe4\xff\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00&/\x00\x00@P\x00\x00Zp\x00\x00t\x90\x00\x00\x8e\xb0\x00\x00\xa9\xcf\x00\x00\xc2\xf0\x00\x00\xd1\xff\x11\x00\xd8\xff1\x00\xde\xffQ\x00\xe3\xffq\x00\xe9\xff\x91\x00\xef\xff\xb1\x00\xf6\xff\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00/&\x00\x00PA\x00\x00p[\x00\x00\x90t\x00\x00\xb0\x8e\x00\x00\xcf\xa9\x00\x00\xf0\xc3\x00\x00\xff\xd2\x11\x00\xff\xd81\x00\xff\xddQ\x00\xff\xe4q\x00\xff\xea\x91\x00\xff\xf0\xb1\x00\xff\xf6\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00/\x14\x00\x00P\x22\x00\x00p0\x00\x00\x90>\x00\x00\xb0M\x00\x00\xcf[\x00\x00\xf0i\x00\x00\xffy\x11\x00\xff\x8a1\x00\xff\x9dQ\x00\xff\xafq\x00\xff\xc1\x91\x00\xff\xd2\xb1\x00\xff\xe5\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00/\x03\x00\x00P\x04\x00\x00p\x06\x00\x00\x90\x09\x00\x00\xb0\x0a\x00\x00\xcf\x0c\x00\x00\xf0\x0e\x00\x00\xff \x12\x00\xff>1\x00\xff\x5cQ\x00\xffzq\x00\xff\x97\x91\x00\xff\xb6\xb1\x00\xff\xd4\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00/\x00\x0e\x00P\x00\x17\x00p\x00!\x00\x90\x00+\x00\xb0\x006\x00\xcf\x00@\x00\xf0\x00I\x00\xff\x11Z\x00\xff1p\x00\xffQ\x86\x00\xffq\x9c\x00\xff\x91\xb2\x00\xff\xb1\xc8\x00\xff\xd1\xdf\x00\xff\xff\xff\x00\x00\x00\x00\x00/\x00 \x00P\x006\x00p\x00L\x00\x90\x00b\x00\xb0\x00x\x00\xcf\x00\x8e\x00\xf0\x00\xa4\x00\xff\x11\xb3\x00\xff1\xbe\x00\xffQ\xc7\x00\xffq\xd1\x00\xff\x91\xdc\x00\xff\xb1\xe5\x00\xff\xd1\xf0\x00\xff\xff\xff\x00\x00\x00\x00\x00,\x00/\x00K\x00P\x00i\x00p\x00\x87\x00\x90\x00\xa5\x00\xb0\x00\xc4\x00\xcf\x00\xe1\x00\xf0\x00\xf0\x11\xff\x00\xf21\xff\x00\xf4Q\xff\x00\xf6q\xff\x00\xf7\x91\xff\x00\xf9\xb1\xff\x00\xfb\xd1\xff\x00\xff\xff\xff\x00\x00\x00\x00\x00\x1b\x00/\x00-\x00P\x00?\x00p\x00R\x00\x90\x00c\x00\xb0\x00v\x00\xcf\x00\x88\x00\xf0\x00\x99\x11\xff\x00\xa61\xff\x00\xb4Q\xff\x00\xc2q\xff\x00\xcf\x91\xff\x00\xdc\xb1\xff\x00\xeb\xd1\xff\x00\xff\xff\xff\x00\x00\x00\x00\x00\x08\x00/\x00\x0e\x00P\x00\x15\x00p\x00\x1b\x00\x90\x00!\x00\xb0\x00&\x00\xcf\x00,\x00\xf0\x00>\x11\xff\x00X1\xff\x00qQ\xff\x00\x8cq\xff\x00\xa6\x91\xff\x00\xbf\xb1\xff\x00\xda\xd1\xff\x00\xff\xff\xff\x00\x10\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x10\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x08\x00\x00\x01\x08\x08\x09\x09\x08\x09\x09\x08\x09\x09\x08\x09\x09\x08\x09\x08\x09\x08\x09\x08\x09\x08\x09\x04\x00\x00\x00\x08\x08\x00\x00\x050??????????????????????\x1e\x00\x00\x00\x08\x08\x00\x00\x01-OOOOOOOOOOOOOOOOOOOOOO0\x03\x00\x00\x08\x08\x00\x00\x00\x1eGH3*+*+++*++++++++++**#\x04\x00\x00\x08\x08\x00\x00\x00\x0fCH\x1e\x01\x04\x06\x05\x06\x06\x06\x03\x02\x05\x06\x06\x06\x06\x06\x02\x01\x01\x01\x01\x00\x00\x00\x08\x08\x00\x00\x00\x07:O-\x03$87877\x17\x05.88885\x0c\x00\x00\x00\x00\x00\x00\x00\x08\x08\x00\x00\x00\x02.O8\x06 HOOOO-\x03/OOOOG\x1c\x00\x00\x00\x00\x00\x00\x00\x08\x08\x00\x00\x00\x00\x1fHB\x0e\x11DOOOO8\x06!HOOOO+\x01\x00\x00\x00\x00\x00\x00\x08\x08\x00\x00\x00\x00\x11DG\x1c\x07;OOOOB\x0e\x12DOOOO8\x05\x00\x00\x00\x00\x00\x00\x08\x08\x00\x00\x00\x01\x07H&\x03%88786\x15\x07188781\x08\x00\x00\x00\x00\x08\x08\x00\x00\x00\x00\x00\x00\x032O5\x05\x03\x06\x06\x06\x06\x06\x04\x00\x05\x05\x05\x06\x05\x06\x02\x00\x00\x00\x00\x08\x08\x00\x00\x00\x00\x00\x00\x00$H@\x0b\x08'----%\x04\x11+-,,,\x1d\x01\x00\x00\x00\x08\x08\x00\x00\x00\x00\x00\x00\x00\x15FF\x16\x07>>>7\x0a\x11\x00\x00\xb0M\x00\x00\xcf[\x00\x00\xf0i\x00\x00\xffy\x11\x00\xff\x8a1\x00\xff\x9dQ\x00\xff\xafq\x00\xff\xc1\x91\x00\xff\xd2\xb1\x00\xff\xe5\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00/\x03\x00\x00P\x04\x00\x00p\x06\x00\x00\x90\x09\x00\x00\xb0\x0a\x00\x00\xcf\x0c\x00\x00\xf0\x0e\x00\x00\xff \x12\x00\xff>1\x00\xff\x5cQ\x00\xffzq\x00\xff\x97\x91\x00\xff\xb6\xb1\x00\xff\xd4\xd1\x00\xff\xff\xff\x00\x00\x00\x00\x00/\x00\x0e\x00P\x00\x17\x00p\x00!\x00\x90\x00+\x00\xb0\x006\x00\xcf\x00@\x00\xf0\x00I\x00\xff\x11Z\x00\xff1p\x00\xffQ\x86\x00\xffq\x9c\x00\xff\x91\xb2\x00\xff\xb1\xc8\x00\xff\xd1\xdf\x00\xff\xff\xff\x00\x00\x00\x00\x00/\x00 \x00P\x006\x00p\x00L\x00\x90\x00b\x00\xb0\x00x\x00\xcf\x00\x8e\x00\xf0\x00\xa4\x00\xff\x11\xb3\x00\xff1\xbe\x00\xffQ\xc7\x00\xffq\xd1\x00\xff\x91\xdc\x00\xff\xb1\xe5\x00\xff\xd1\xf0\x00\xff\xff\xff\x00\x00\x00\x00\x00,\x00/\x00K\x00P\x00i\x00p\x00\x87\x00\x90\x00\xa5\x00\xb0\x00\xc4\x00\xcf\x00\xe1\x00\xf0\x00\xf0\x11\xff\x00\xf21\xff\x00\xf4Q\xff\x00\xf6q\xff\x00\xf7\x91\xff\x00\xf9\xb1\xff\x00\xfb\xd1\xff\x00\xff\xff\xff\x00\x00\x00\x00\x00\x1b\x00/\x00-\x00P\x00?\x00p\x00R\x00\x90\x00c\x00\xb0\x00v\x00\xcf\x00\x88\x00\xf0\x00\x99\x11\xff\x00\xa61\xff\x00\xb4Q\xff\x00\xc2q\xff\x00\xcf\x91\xff\x00\xdc\xb1\xff\x00\xeb\xd1\xff\x00\xff\xff\xff\x00\x00\x00\x00\x00\x08\x00/\x00\x0e\x00P\x00\x15\x00p\x00\x1b\x00\x90\x00!\x00\xb0\x00&\x00\xcf\x00,\x00\xf0\x00>\x11\xff\x00X1\xff\x00qQ\xff\x00\x8cq\xff\x00\xa6\x91\xff\x00\xbf\xb1\xff\x00\xda\xd1\xff\x00\xff\xff\xff\x00\x0e\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x0e\x09\x01\x08\x09\x09\x0a\x09\x09\x0a\x09\x09\x09\x0a\x06\x01\x09\x09\x04%3222222222#\x03\x09\x09\x01\x22,\x14\x17\x17\x15\x14\x18\x18\x14\x12\x0f\x02\x09\x09\x00\x17-\x11.1\x22\x1401\x1e\x01\x00\x00\x09\x09\x00\x0d2\x134?3\x135?-\x05\x00\x00\x09\x09\x00\x06.\x18\x22.+\x10%.(\x0a\x00\x00\x09\x09\x00\x02# \x0e\x1a\x1b\x0f\x10\x1b\x1a\x0c\x00\x00\x09\x09\x00\x00\x18,\x1468'\x1b8?\x1f\x01\x00\x09\x09\x00\x00\x0e2\x123?3\x145?,\x05\x00\x09\x09\x00\x00\x07/\x16\x14\x1d\x1b\x0b\x17\x1d\x18\x05\x00\x09\x09\x00\x00\x02$\x1f\x15++\x17\x1b+*\x11\x00\x09\x09\x00\x00\x00\x19+\x147?&\x1b8? \x01\x09\x09\x00\x00\x00\x0e)\x0f,3)\x1103%\x04\x09\x09\x00\x00\x00\x02\x08\x03\x07\x09\x08\x03\x08\x09\x08\x01\x09\x0e\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x09\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00@\x00\x00\x00\x80\x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00\x00B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001|\xec\xc31|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xc31|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff4\x80\xed\xffI\x8c\xef\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffD\x8a\xef\xff2~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff@\x87\xee\xff\xba\xd3\xf9\xff\xe1\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xb4\xd0\xf9\xff=\x85\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff7\x80\xee\xff\xaf\xcd\xf8\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe3\xee\xfd\xffS\x92\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2}\xed\xff\x88\xb4\xf5\xff\xf9\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf4\xf8\xfe\xffx\xaa\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffb\x9c\xf1\xff\xed\xf4\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\xa5\xc6\xf7\xff5\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffG\x8b\xef\xff\xd6\xe5\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf6\xfa\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xef\xf6\xfe\xff\xc0\xd7\xfa\xff?\x86\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff8\x81\xee\xff\xb3\xcf\xf9\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\xb1\xce\xf8\xffj\xa2\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffi\xa1\xf2\xffa\x9b\xf1\xff8\x82\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff\x8d\xb7\xf5\xff\xfa\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xb0\xcd\xf8\xff6\x81\xed\xff0}\xed\xff0}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xfff\x9f\xf2\xff\xef\xf5\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd4\xe4\xfb\xffF\x8b\xef\xff1}\xed\xff1}\xed\xff5\x80\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff6\x80\xee\xff1}\xed\xff1}\xed\xff3~\xed\xff:\x83\xee\xff:\x83\xee\xff:\x83\xee\xff:\x83\xee\xff:\x83\xee\xff:\x83\xee\xff:\x83\xee\xff:\x83\xee\xff:\x83\xee\xff:\x83\xee\xff:\x83\xee\xff:\x83\xee\xff3~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffJ\x8d\xef\xff\xda\xe8\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xec\xf3\xfd\xffa\x9b\xf1\xff1}\xed\xff2}\xed\xffp\xa5\xf2\xff\xb7\xd2\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xb9\xd3\xf9\xff\x8a\xb6\xf5\xff6\x80\xee\xff1}\xed\xffC\x89\xef\xff\xa9\xc9\xf8\xff\xbf\xd7\xfa\xff\xbf\xd7\xfa\xff\xbf\xd7\xfa\xff\xbf\xd7\xfa\xff\xbf\xd7\xfa\xff\xbf\xd7\xfa\xff\xbf\xd7\xfa\xff\xbf\xd7\xfa\xff\xbf\xd7\xfa\xff\xbf\xd7\xfa\xff\xb4\xcf\xf9\xffS\x93\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff9\x82\xee\xff\xb7\xd2\xf9\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf9\xfb\xff\xff\x86\xb3\xf5\xff1}\xed\xff1}\xed\xffn\xa3\xf3\xff\xf1\xf6\xfe\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfd\xfe\xff\xff\xd2\xe3\xfb\xffE\x8a\xef\xff2}\xed\xff=\x84\xee\xff\xc1\xd8\xfa\xff\xfd\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xf6\xfa\xff\xff\x80\xaf\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff\x92\xba\xf6\xff\xfb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xae\xcc\xf8\xff6\x80\xee\xff1}\xed\xffO\x90\xf0\xff\xdf\xeb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xec\xf3\xfd\xff_\x9a\xf1\xff1}\xed\xff3~\xed\xff\x9b\xc0\xf6\xff\xfd\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xa9\xc9\xf8\xff5\x80\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffj\xa1\xf2\xff\xf0\xf5\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd2\xe2\xfb\xffE\x89\xef\xff2}\xed\xff;\x83\xee\xff\xbd\xd5\xfa\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xfb\xff\xff\x85\xb2\xf4\xff1}\xed\xff1}\xed\xffq\xa6\xf3\xff\xf2\xf7\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xce\xe0\xfb\xffB\x88\xef\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffL\x8e\xf0\xff\xdd\xea\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xeb\xf2\xfd\xff^\x99\xf1\xff1}\xed\xff3~\xed\xff\x97\xbe\xf6\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xae\xcc\xf8\xff6\x80\xee\xff2}\xed\xffQ\x91\xf0\xff\xe2\xed\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe9\xf1\xfd\xff[\x98\xf1\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff:\x83\xee\xff\xbb\xd4\xf9\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf7\xfa\xff\xff\x82\xb0\xf4\xff1}\xed\xff1}\xed\xffn\xa4\xf3\xff\xf1\xf6\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd2\xe3\xfb\xffE\x8a\xef\xff2}\xed\xff<\x84\xee\xff\xc1\xd8\xfa\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf7\xfa\xff\xff\x80\xaf\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff3~\xed\xff\x96\xbd\xf6\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xab\xca\xf8\xff6\x80\xee\xff1}\xed\xffO\x90\xf0\xff\xdf\xeb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xec\xf3\xfd\xff_\x9a\xf1\xff1}\xed\xff3~\xed\xff\x9b\xc0\xf6\xff\xfd\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xa9\xc9\xf8\xff5\x80\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffn\xa3\xf3\xff\xf1\xf6\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xce\xe0\xfb\xffB\x88\xef\xff1}\xed\xff;\x83\xee\xff\xbd\xd5\xfa\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xfb\xff\xff\x85\xb2\xf4\xff1}\xed\xff1}\xed\xffq\xa6\xf3\xff\xf2\xf7\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xce\xe0\xfb\xffB\x88\xef\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffO\x90\xf0\xff\xe0\xeb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe9\xf1\xfd\xff[\x97\xf1\xff1}\xed\xff3~\xed\xff\x97\xbe\xf6\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xae\xcc\xf8\xff6\x80\xee\xff2}\xed\xffQ\x91\xf0\xff\xe2\xed\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe9\xf1\xfd\xff[\x98\xf1\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff;\x84\xee\xff\xbf\xd7\xfa\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf6\xfa\xff\xff\x7f\xae\xf4\xff1}\xed\xff1}\xed\xffn\xa4\xf3\xff\xf1\xf6\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xd2\xe3\xfb\xffE\x8a\xef\xff2}\xed\xff<\x84\xee\xff\xc1\xd8\xfa\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf7\xfa\xff\xff\x80\xaf\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff3~\xed\xff\x9a\xbf\xf6\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\xa7\xc7\xf7\xff5\x7f\xed\xff1}\xed\xffO\x8f\xf0\xff\xde\xeb\xfc\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xeb\xf2\xfd\xff_\x9a\xf1\xff1}\xed\xff3~\xed\xff\x9b\xc0\xf6\xff\xfb\xfc\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfd\xfe\xff\xff\xfc\xfd\xff\xff\xa9\xc8\xf8\xff5\x7f\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffq\xa6\xf3\xff\xf2\xf7\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xcb\xde\xfb\xffA\x87\xef\xff1}\xed\xff8\x81\xee\xff\x7f\xaf\xf4\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x94\xbb\xf6\xffT\x93\xf0\xff1}\xed\xff1}\xed\xffY\x96\xf0\xff\x95\xbc\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff{\xab\xf4\xff7\x80\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffR\x91\xf0\xff\xe2\xed\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe7\xf0\xfd\xffX\x96\xf1\xff1}\xed\xff1}\xed\xff1~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff1}\xed\xff1}\xed\xff2}\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff=\x85\xee\xff\xc3\xd9\xfa\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf5\xf9\xfe\xff{\xac\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff2~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff3\x7f\xed\xff\x9e\xc2\xf7\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\xa3\xc5\xf7\xff4\x7f\xed\xff1}\xed\xff;\x84\xee\xff\x88\xb4\xf5\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x98\xbe\xf6\xffS\x93\xf0\xff1}\xed\xff1}\xed\xffh\xa0\xf2\xff\x9d\xc1\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xff\x9e\xc2\xf6\xfft\xa7\xf3\xff3~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffv\xa8\xf3\xff\xf4\xf8\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xc7\xdc\xfa\xff?\x86\xee\xff2}\xed\xff:\x83\xee\xff\xbb\xd4\xf9\xff\xfd\xfe\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xf9\xfb\xfe\xff\x8c\xb7\xf5\xff2~\xed\xff1}\xed\xff{\xab\xf4\xff\xf5\xf9\xfe\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfd\xfe\xff\xff\xc5\xdb\xfa\xff>\x85\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffT\x94\xf0\xff\xe5\xef\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe5\xef\xfd\xffU\x94\xf0\xff1}\xed\xff2~\xed\xff\x94\xbc\xf6\xff\xfb\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xb4\xd0\xf9\xff7\x82\xee\xff1}\xed\xffW\x95\xf1\xff\xe7\xf0\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe5\xef\xfd\xffT\x93\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff?\x86\xee\xff\xc6\xdb\xfa\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf4\xf8\xfe\xffw\xa9\xf3\xff1}\xed\xff1}\xed\xffk\xa2\xf2\xff\xf0\xf6\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd7\xe6\xfc\xffH\x8c\xef\xff1}\xed\xff@\x87\xef\xff\xc9\xdd\xfb\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf4\xf8\xfe\xffv\xa9\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff4\x7f\xed\xff\xa2\xc4\xf7\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\x9f\xc3\xf7\xff4\x7f\xed\xff1}\xed\xffL\x8e\xf0\xff\xdd\xea\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xee\xf4\xfe\xffd\x9e\xf2\xff1}\xed\xff4\x7f\xed\xff\xa4\xc6\xf7\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\xa0\xc3\xf7\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffz\xab\xf4\xff\xf5\xf9\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xc4\xda\xfa\xff=\x85\xee\xff2}\xed\xff:\x83\xee\xff\xbb\xd4\xf9\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfc\xff\xff\x8c\xb7\xf5\xff2~\xed\xff1}\xed\xff{\xac\xf4\xff\xf5\xf9\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xc6\xdb\xfa\xff>\x85\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffX\x95\xf1\xff\xe7\xf0\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe3\xee\xfd\xffS\x92\xf0\xff1}\xed\xff2~\xed\xff\x94\xbc\xf6\xff\xfb\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xb4\xd0\xf9\xff7\x82\xee\xff1}\xed\xffW\x95\xf1\xff\xe7\xf0\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe5\xef\xfd\xffT\x93\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff@\x87\xef\xff\xca\xde\xfb\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf3\xf7\xfe\xffs\xa7\xf3\xff0}\xed\xff1}\xed\xffk\xa2\xf2\xff\xf0\xf6\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd7\xe6\xfc\xffH\x8c\xef\xff1}\xed\xff@\x87\xef\xff\xc9\xdd\xfb\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf4\xf8\xfe\xffv\xa9\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff5\x7f\xed\xff\xa6\xc7\xf7\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfd\xff\xff\x9c\xc1\xf6\xff3~\xed\xff1}\xed\xffL\x8e\xf0\xff\xdd\xea\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xee\xf4\xfe\xffd\x9e\xf2\xff1}\xed\xff4\x7f\xed\xff\xa4\xc6\xf7\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\xa0\xc3\xf7\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff~\xae\xf4\xff\xf6\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xc1\xd8\xfa\xff<\x84\xee\xff2~\xed\xff:\x83\xee\xff\xbb\xd4\xf9\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfc\xff\xff\x8c\xb7\xf5\xff2~\xed\xff1}\xed\xff{\xac\xf4\xff\xf5\xf9\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xc6\xdb\xfa\xff>\x85\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffZ\x97\xf1\xff\xe9\xf1\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe1\xed\xfc\xffP\x91\xf0\xff1}\xed\xff2~\xed\xff\x94\xbc\xf6\xff\xfa\xfd\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfd\xfe\xff\xff\xb4\xcf\xf9\xff8\x81\xee\xff1}\xed\xffW\x95\xf1\xff\xe6\xef\xfd\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xe4\xee\xfd\xffT\x93\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffB\x88\xef\xff\xce\xe0\xfb\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf2\xf7\xfe\xffo\xa5\xf3\xff1}\xed\xff1}\xed\xff^\x9a\xf1\xff\xb3\xd0\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xb9\xd4\xf9\xff\x9c\xc1\xf6\xff=\x85\xee\xff1}\xed\xff>\x85\xee\xff\x9d\xc1\xf6\xff\xb9\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xba\xd4\xf9\xff\xb2\xcf\xf8\xffZ\x97\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff5\x80\xee\xff\xaa\xca\xf8\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\xfd\xff\xff\x98\xbe\xf6\xff3~\xed\xff1}\xed\xff3\x7f\xed\xff8\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff8\x82\xee\xff2~\xed\xff1}\xed\xff1~\xed\xff7\x80\xed\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff9\x82\xee\xff8\x82\xee\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff\x82\xb0\xf4\xff\xf7\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xbd\xd5\xfa\xff;\x83\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff^\x99\xf1\xff\xeb\xf2\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdf\xeb\xfc\xffN\x8f\xf0\xff1}\xed\xff1}\xed\xffM\x8f\xf0\xffs\xa6\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xffa\x9b\xf1\xff4\x7f\xed\xff1}\xed\xff7\x81\xee\xffd\x9d\xf1\xffo\xa4\xf3\xffo\xa4\xf3\xffo\xa4\xf3\xffo\xa4\xf3\xffo\xa4\xf3\xffo\xa4\xf3\xffo\xa4\xf3\xffo\xa4\xf3\xffo\xa4\xf3\xffo\xa4\xf3\xffk\xa2\xf3\xffB\x88\xef\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffE\x89\xef\xff\xd2\xe2\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf1\xf6\xfe\xffl\xa2\xf2\xff1}\xed\xff0}\xed\xffk\xa2\xf2\xff\xe8\xf0\xfd\xff\xf4\xf8\xfe\xff\xf4\xf8\xfe\xff\xf4\xf8\xfe\xff\xf4\xf8\xfe\xff\xf4\xf8\xfe\xff\xf4\xf8\xfe\xff\xf4\xf8\xfe\xff\xf4\xf8\xfe\xff\xf4\xf8\xfe\xff\xf3\xf7\xfe\xff\xca\xde\xfb\xffD\x88\xef\xff1}\xed\xff<\x84\xee\xff\xbb\xd4\xf9\xff\xf1\xf7\xfe\xff\xf2\xf7\xfe\xff\xf2\xf7\xfe\xff\xf2\xf7\xfe\xff\xf2\xf7\xfe\xff\xf2\xf7\xfe\xff\xf2\xf7\xfe\xff\xf2\xf7\xfe\xff\xf2\xf7\xfe\xff\xf2\xf7\xfe\xff\xeb\xf2\xfe\xffz\xab\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff7\x80\xee\xff\xae\xcc\xf8\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xfd\xff\xff\x94\xbc\xf6\xff2~\xed\xff1}\xed\xffO\x90\xf0\xff\xe0\xec\xfc\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xeb\xf2\xfd\xff]\x99\xf1\xff1}\xed\xff4\x7f\xed\xff\x9e\xc2\xf7\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\xa5\xc6\xf7\xff5\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff\x87\xb3\xf5\xff\xf9\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xba\xd3\xf9\xff:\x82\xee\xff2~\xed\xff;\x83\xee\xff\xbe\xd6\xfa\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xfa\xff\xff\x83\xb1\xf4\xff1}\xed\xff1}\xed\xffu\xa8\xf3\xff\xf4\xf8\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xca\xde\xfb\xff@\x87\xef\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffa\x9b\xf1\xff\xed\xf3\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdc\xe9\xfc\xffL\x8e\xf0\xff1}\xed\xff3~\xed\xff\x98\xbf\xf6\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xac\xcb\xf8\xff6\x80\xee\xff1}\xed\xffT\x93\xf0\xff\xe4\xee\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe8\xf0\xfd\xffX\x96\xf1\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffF\x8b\xef\xff\xd5\xe5\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\xf5\xfe\xffi\xa0\xf2\xff1}\xed\xff1}\xed\xffo\xa4\xf3\xff\xf2\xf6\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xd0\xe2\xfb\xffD\x89\xef\xff1}\xed\xff>\x85\xee\xff\xc5\xda\xfa\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf6\xf9\xff\xff|\xac\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff7\x81\xee\xff\xb2\xcf\xf8\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfc\xff\xff\x8e\xb8\xf5\xff2~\xed\xff1}\xed\xffO\x90\xf0\xff\xe0\xec\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xeb\xf2\xfd\xff]\x99\xf1\xff1}\xed\xff4\x7f\xed\xff\x9f\xc2\xf7\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\xa5\xc6\xf7\xff5\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff\x8b\xb6\xf5\xff\xfa\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xb1\xce\xf8\xff7\x81\xee\xff2}\xed\xff;\x83\xee\xff\xbe\xd6\xfa\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xfa\xff\xff\x83\xb1\xf4\xff1}\xed\xff1}\xed\xffu\xa8\xf3\xff\xf4\xf8\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xca\xde\xfb\xff@\x87\xef\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff0}\xed\xffd\x9e\xf2\xff\xee\xf4\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd4\xe4\xfb\xffF\x8b\xef\xff2}\xed\xff3~\xed\xff\x98\xbf\xf6\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xac\xcb\xf8\xff6\x80\xee\xff1}\xed\xffT\x93\xf0\xff\xe4\xee\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe8\xf0\xfd\xffX\x96\xf1\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffI\x8c\xef\xff\xd8\xe7\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xec\xf3\xfd\xffa\x9b\xf1\xff1}\xed\xff1}\xed\xffo\xa4\xf3\xff\xf2\xf6\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xd0\xe2\xfb\xffD\x89\xef\xff1}\xed\xff>\x85\xee\xff\xc5\xda\xfa\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf6\xf9\xff\xff|\xac\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff8\x82\xee\xff\xb5\xd1\xf9\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xfa\xff\xff\x86\xb3\xf5\xff1}\xed\xff1}\xed\xffO\x90\xf0\xff\xe0\xec\xfc\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xeb\xf2\xfd\xff^\x99\xf1\xff1}\xed\xff4\x7f\xed\xff\x9f\xc2\xf7\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\xa5\xc6\xf7\xff5\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff\x87\xb3\xf5\xff\xe0\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\x9b\xc0\xf6\xff5\x7f\xed\xff2}\xed\xff;\x83\xee\xff\xad\xcb\xf8\xff\xdd\xe9\xfc\xff\xdd\xea\xfc\xff\xdd\xea\xfc\xff\xdd\xea\xfc\xff\xdd\xea\xfc\xff\xdd\xea\xfc\xff\xdd\xea\xfc\xff\xdd\xea\xfc\xff\xdd\xea\xfc\xff\xdd\xea\xfc\xff\xd7\xe6\xfc\xffr\xa6\xf3\xff1}\xed\xff1}\xed\xffp\xa5\xf3\xff\xdb\xe9\xfc\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe2\xec\xfd\xff\xe1\xec\xfd\xff\xb3\xcf\xf9\xff<\x84\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff=\x84\xee\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffD\x8a\xef\xff2~\xed\xff1}\xed\xff2~\xed\xffA\x87\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffI\x8c\xef\xff=\x85\xee\xff1}\xed\xff1}\xed\xff9\x82\xee\xffL\x8e\xef\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffM\x8f\xf0\xffH\x8c\xef\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xc31|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x000\x00\x00\x00`\x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00\x80%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000|\xec\xc21}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde1}\xec\xde0}\xec\xc11|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff4\x7f\xed\xffG\x8b\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffH\x8c\xef\xff5\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff?\x86\xee\xff\xbc\xd5\xf9\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xd4\xe4\xfb\xffW\x95\xf1\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff6\x80\xed\xff\xb3\xcf\xf8\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf9\xfb\xff\xff\x80\xaf\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff\x87\xb3\xf5\xff\xfb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xb0\xcd\xf8\xff6\x80\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffa\x9b\xf1\xff\xef\xf5\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf5\xf9\xfe\xff\xda\xe8\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xd8\xe7\xfc\xff\xb4\xd0\xf8\xff>\x85\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffF\x8a\xef\xff\xd9\xe7\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdc\xe9\xfc\xffV\x95\xf0\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffD\x89\xef\xffB\x88\xee\xff3~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff7\x81\xed\xff\xb6\xd1\xf8\xff\xff\xff\xff\xff\xff\xff\xff\xff\xed\xf4\xfe\xff]\x99\xf1\xff1}\xed\xff3~\xed\xff:\x83\xee\xff;\x83\xee\xff;\x83\xee\xff;\x83\xee\xff;\x83\xee\xff;\x83\xee\xff;\x83\xee\xff;\x83\xee\xff9\x82\xee\xff2~\xed\xff1}\xed\xff8\x81\xed\xff<\x84\xee\xff<\x84\xee\xff<\x84\xee\xff<\x84\xee\xff<\x84\xee\xff<\x84\xee\xff<\x84\xee\xff<\x84\xee\xff8\x81\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff\x8d\xb7\xf5\xff\xfb\xfd\xff\xff\xff\xff\xff\xff\xfa\xfc\xff\xff\x83\xb1\xf4\xff1}\xed\xffI\x8c\xef\xff\xb4\xd0\xf8\xff\xc5\xdb\xfa\xff\xc5\xdb\xfa\xff\xc5\xdb\xfa\xff\xc5\xdb\xfa\xff\xc5\xdb\xfa\xff\xc5\xdb\xfa\xff\xc5\xdb\xfa\xff\xb4\xd0\xf9\xffH\x8c\xef\xff2~\xed\xffw\xa9\xf3\xff\xc7\xdb\xfa\xff\xc9\xdd\xfa\xff\xc9\xdd\xfa\xff\xc9\xdd\xfa\xff\xc9\xdd\xfa\xff\xc9\xdd\xfa\xff\xc9\xdd\xfa\xff\xc9\xdd\xfa\xff\x8f\xb9\xf6\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xfff\x9e\xf2\xff\xf2\xf6\xfe\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xae\xcc\xf8\xff5\x7f\xed\xff@\x86\xee\xff\xcf\xe1\xfb\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xf4\xf9\xfe\xffm\xa3\xf2\xff1}\xed\xffl\xa2\xf3\xff\xf4\xf8\xfe\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xcf\xe1\xfb\xff@\x87\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffH\x8c\xef\xff\xdc\xe8\xfc\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xd2\xe2\xfb\xffB\x87\xee\xff4\x7f\xed\xff\xa8\xc8\xf7\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\xfd\xff\xff\x98\xbe\xf6\xff2~\xed\xffL\x8e\xf0\xff\xe0\xeb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xea\xf2\xfd\xffX\x96\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff8\x81\xed\xff\xbb\xd4\xf9\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xec\xf3\xfd\xffZ\x97\xf1\xff1}\xed\xff}\xad\xf4\xff\xf9\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xc1\xd8\xfa\xff:\x83\xee\xff:\x82\xee\xff\xc0\xd7\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf9\xfb\xff\xff}\xae\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff\x90\xb9\xf5\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xfa\xfc\xfe\xff\x7f\xae\xf4\xff2}\xed\xffX\x96\xf1\xff\xeb\xf2\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe1\xec\xfc\xffM\x8f\xef\xff3~\xed\xff\x95\xbc\xf6\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\xaa\xc9\xf7\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffh\xa0\xf2\xff\xf3\xf7\xfe\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xa9\xc9\xf8\xff5\x7f\xed\xff@\x86\xee\xff\xcf\xe0\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf5\xf8\xfe\xffm\xa3\xf2\xff1}\xed\xffk\xa2\xf2\xff\xf4\xf8\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xcf\xe1\xfb\xff@\x87\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffK\x8e\xef\xff\xdf\xeb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xcf\xe1\xfb\xff@\x86\xee\xff4\x7f\xed\xff\xa9\xc9\xf7\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\x96\xbd\xf6\xff2~\xed\xffL\x8e\xef\xff\xe0\xeb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xea\xf2\xfd\xffX\x96\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff9\x82\xee\xff\xbf\xd6\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xea\xf2\xfd\xffW\x95\xf0\xff1}\xed\xff}\xad\xf4\xff\xf8\xfb\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xc1\xd8\xf9\xff:\x83\xee\xff9\x82\xee\xff\xc0\xd7\xf9\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xfe\xfe\xff\xff\xf8\xfb\xfe\xff}\xad\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2}\xed\xff\x96\xbd\xf6\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xf8\xfb\xfe\xff{\xac\xf4\xff1}\xed\xffN\x90\xf0\xff\xa8\xc8\xf8\xff\xb0\xcd\xf8\xff\xb0\xcd\xf8\xff\xb0\xcd\xf8\xff\xb0\xcd\xf8\xff\xb0\xcd\xf8\xff\xb0\xcd\xf8\xff\xb0\xcd\xf8\xff\x9b\xbf\xf6\xff>\x85\xee\xff2}\xed\xffx\xaa\xf3\xff\xaf\xcd\xf8\xff\xb0\xcd\xf8\xff\xb0\xcd\xf8\xff\xb0\xcd\xf8\xff\xb0\xcd\xf8\xff\xb0\xcd\xf8\xff\xb0\xcd\xf8\xff\xaf\xcd\xf8\xffu\xa8\xf3\xff2~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffm\xa3\xf2\xff\xf5\xf8\xfe\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xa5\xc6\xf7\xff4\x7f\xed\xff1}\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff4\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3\x7f\xed\xff3~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffM\x8f\xf0\xff\xe2\xed\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xcc\xdf\xfa\xff>\x86\xee\xff1}\xed\xffE\x8a\xef\xff\x5c\x99\xf1\xff]\x99\xf1\xff]\x99\xf1\xff]\x99\xf1\xff]\x99\xf1\xff]\x99\xf1\xff]\x99\xf1\xff]\x99\xf1\xffM\x8f\xef\xff2~\xed\xff5\x80\xed\xffT\x94\xf0\xff]\x99\xf1\xff]\x99\xf1\xff]\x99\xf1\xff]\x99\xf1\xff]\x99\xf1\xff]\x99\xf1\xff]\x99\xf1\xffZ\x97\xf1\xff=\x84\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff;\x83\xee\xff\xc2\xd9\xfa\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xe7\xf0\xfd\xffT\x93\xf0\xff1}\xed\xffs\xa7\xf3\xff\xe9\xf2\xfd\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xbd\xd5\xf9\xff<\x84\xee\xff:\x83\xee\xff\xb9\xd3\xf9\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xf0\xf6\xfe\xff\xe9\xf1\xfd\xfft\xa7\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff3~\xed\xff\x9a\xbf\xf6\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xf8\xfa\xff\xffw\xa9\xf3\xff1}\xed\xffW\x95\xf0\xff\xe9\xf1\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe4\xee\xfd\xffP\x91\xf0\xff3~\xed\xff\x9d\xc1\xf6\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xa1\xc4\xf7\xff4~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffq\xa5\xf3\xff\xf5\xf9\xfe\xff\xff\xff\xff\xff\xfd\xfd\xff\xff\xa2\xc4\xf7\xff3~\xed\xff?\x86\xee\xff\xcd\xdf\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf6\xfa\xfe\xffr\xa6\xf3\xff0}\xed\xffs\xa6\xf3\xff\xf6\xf9\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc9\xdd\xfa\xff>\x85\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffP\x91\xf0\xff\xe4\xee\xfd\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xc8\xdc\xfa\xff=\x84\xee\xff4\x7f\xed\xff\xa5\xc6\xf7\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\x9d\xc1\xf6\xff3~\xed\xffQ\x91\xf0\xff\xe5\xef\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe7\xf0\xfd\xffS\x93\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff<\x84\xee\xff\xc7\xdb\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe6\xef\xfd\xffR\x92\xf0\xff1}\xed\xffz\xab\xf3\xff\xf8\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc5\xdb\xfa\xff<\x84\xee\xff<\x84\xee\xff\xc7\xdc\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xfa\xff\xffv\xa9\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff3\x7f\xed\xff\x9e\xc2\xf7\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xf6\xfa\xfe\xffs\xa7\xf3\xff1}\xed\xffV\x95\xf1\xff\xe9\xf1\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe4\xee\xfd\xffP\x91\xef\xff3\x7f\xed\xff\x9d\xc1\xf6\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfd\xff\xff\xa2\xc4\xf7\xff3~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xfft\xa7\xf3\xff\xf7\xfa\xfe\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\x9c\xc1\xf7\xff3~\xed\xff?\x86\xee\xff\xcd\xdf\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf6\xf9\xfe\xffq\xa6\xf3\xff1}\xed\xffr\xa6\xf3\xff\xf6\xf9\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc9\xdd\xfa\xff=\x85\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffS\x92\xf0\xff\xe7\xf0\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc6\xdb\xfa\xff;\x83\xee\xff3\x7f\xed\xff\xa4\xc6\xf7\xff\xf6\xf9\xfe\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xf5\xf9\xfe\xff\x96\xbd\xf6\xff3~\xed\xffP\x91\xf0\xff\xdf\xeb\xfc\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xdf\xeb\xfc\xffQ\x91\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff=\x85\xee\xff\xc9\xdd\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe3\xee\xfc\xffO\x90\xef\xff1}\xed\xffP\x91\xf0\xffs\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xffs\xa7\xf3\xff\x5c\x98\xf0\xff3~\xed\xff7\x81\xed\xffg\x9f\xf2\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xfft\xa7\xf3\xffp\xa5\xf3\xffB\x88\xef\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff3~\xed\xff\xa4\xc5\xf7\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xf5\xf9\xfe\xffp\xa5\xf2\xff1}\xed\xff1}\xed\xff0}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff0}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffy\xaa\xf3\xff\xf8\xfb\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\x9a\xbf\xf6\xff2~\xed\xff5\x80\xee\xffu\xa8\xf3\xff\x90\xb9\xf5\xff\x90\xb9\xf5\xff\x90\xb9\xf5\xff\x90\xb9\xf5\xff\x90\xb9\xf5\xff\x90\xb9\xf5\xff\x90\xb9\xf5\xff\x8d\xb7\xf5\xffS\x92\xf0\xff1}\xed\xffF\x8a\xef\xff\x85\xb2\xf5\xff\x8b\xb6\xf5\xff\x8b\xb6\xf5\xff\x8b\xb6\xf5\xff\x8b\xb6\xf5\xff\x8b\xb6\xf5\xff\x8b\xb6\xf5\xff\x8b\xb6\xf5\xff{\xac\xf4\xff:\x83\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffV\x94\xf1\xff\xe8\xf1\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc1\xd8\xfa\xff:\x83\xee\xff4\x7f\xed\xff\xa7\xc7\xf7\xff\xfb\xfc\xff\xff\xfb\xfd\xff\xff\xfb\xfd\xff\xff\xfb\xfd\xff\xff\xfb\xfd\xff\xff\xfb\xfd\xff\xff\xfb\xfd\xff\xff\xf9\xfc\xff\xff\x95\xbc\xf6\xff2~\xed\xffM\x8e\xef\xff\xdf\xeb\xfc\xff\xfb\xfc\xff\xff\xfb\xfc\xff\xff\xfb\xfc\xff\xff\xfb\xfc\xff\xff\xfb\xfc\xff\xff\xfb\xfc\xff\xff\xfb\xfc\xff\xff\xe6\xef\xfd\xffV\x94\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff?\x86\xee\xff\xce\xe0\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe1\xec\xfc\xffM\x8f\xef\xff1}\xed\xff~\xad\xf4\xff\xf9\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xbf\xd6\xf9\xff:\x83\xee\xff;\x83\xee\xff\xc2\xd8\xfa\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xfb\xfe\xffz\xab\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff4\x7f\xed\xff\xa7\xc7\xf7\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xf4\xf9\xfe\xffl\xa3\xf2\xff1}\xed\xffY\x96\xf0\xff\xeb\xf2\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\xec\xfc\xffL\x8e\xef\xff2~\xed\xff\x99\xbe\xf6\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xa5\xc6\xf7\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff}\xad\xf4\xff\xf8\xfb\xfe\xff\xff\xff\xff\xff\xfc\xfd\xff\xff\x95\xbc\xf6\xff2}\xed\xff@\x87\xee\xff\xd0\xe1\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf4\xf8\xfe\xffl\xa2\xf2\xff1}\xed\xffo\xa4\xf3\xff\xf5\xf9\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xcd\xe0\xfa\xff?\x86\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffZ\x96\xf1\xff\xeb\xf2\xfd\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xbb\xd4\xf9\xff7\x81\xed\xff4\x7f\xed\xff\xa9\xc9\xf8\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\xfd\xff\xff\x96\xbd\xf6\xff2~\xed\xffN\x8f\xf0\xff\xe2\xed\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe8\xf1\xfd\xffV\x94\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff@\x87\xee\xff\xd1\xe2\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdc\xe9\xfc\xffH\x8c\xef\xff1}\xed\xff}\xad\xf4\xff\xf9\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xc0\xd7\xfa\xff9\x82\xee\xff;\x83\xee\xff\xc3\xd9\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\xfb\xff\xffz\xab\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff5\x7f\xed\xff\xab\xca\xf8\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xf1\xf6\xfe\xffe\x9e\xf2\xff1}\xed\xffY\x96\xf1\xff\xeb\xf2\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\xec\xfc\xffL\x8e\xef\xff3~\xed\xff\x98\xbe\xf6\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\xa6\xc7\xf7\xff4~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff{\xac\xf3\xff\xe1\xec\xfd\xff\xe4\xee\xfd\xff\xe1\xec\xfd\xff}\xad\xf4\xff1}\xed\xff@\x86\xee\xff\xbd\xd5\xf9\xff\xe1\xec\xfc\xff\xe1\xec\xfc\xff\xe1\xec\xfc\xff\xe1\xec\xfc\xff\xe1\xec\xfc\xff\xe1\xec\xfc\xff\xe1\xec\xfc\xff\xd6\xe5\xfc\xff_\x9a\xf1\xff1}\xed\xffj\xa1\xf2\xff\xdd\xea\xfc\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe3\xee\xfd\xff\xb6\xd1\xf8\xff<\x84\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff:\x82\xee\xffL\x8e\xef\xffL\x8f\xef\xffL\x8f\xef\xff?\x86\xee\xff1}\xed\xff2~\xed\xffD\x88\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffJ\x8d\xef\xffI\x8c\xef\xff:\x83\xee\xff1}\xed\xff7\x81\xee\xffK\x8e\xef\xffL\x8f\xef\xffL\x8f\xef\xffL\x8f\xef\xffL\x8f\xef\xffL\x8f\xef\xffL\x8f\xef\xffL\x8f\xef\xffH\x8b\xef\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xec\xde1|\xec\xc40}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe01}\xec\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00(\x00\x00\x00P\x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00@\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001|\xec\xc41|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xc30}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff4\x7f\xed\xffG\x8b\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffJ\x8d\xef\xff8\x81\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff>\x85\xee\xff\xbd\xd5\xf9\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xdf\xea\xfc\xffn\xa3\xf2\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff5\x7f\xed\xff\xb0\xcd\xf8\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xa0\xc3\xf7\xff3~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff\x85\xb2\xf4\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xf7\xfa\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xc4\xda\xfa\xff=\x84\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff_\x9a\xf1\xff\xef\xf5\xfe\xff\xff\xff\xff\xff\xf0\xf6\xfe\xff\x86\xb3\xf4\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffm\xa3\xf2\xffc\x9d\xf1\xff8\x81\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffE\x89\xef\xff\xd8\xe6\xfc\xff\xff\xff\xff\xff\xf6\xf9\xfe\xffo\xa4\xf2\xff1}\xed\xff6\x80\xee\xff=\x85\xee\xff=\x85\xee\xff=\x85\xee\xff=\x85\xee\xff=\x85\xee\xff=\x85\xee\xff<\x84\xee\xff4\x7f\xed\xff2}\xed\xff;\x83\xee\xff>\x85\xee\xff>\x85\xee\xff>\x85\xee\xff>\x85\xee\xff>\x85\xee\xff>\x85\xee\xff;\x83\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff6\x81\xed\xff\xb5\xd0\xf9\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\x9a\xbf\xf6\xff2~\xed\xffj\xa1\xf2\xff\xc9\xdd\xfa\xff\xcc\xdf\xfb\xff\xcc\xdf\xfb\xff\xcc\xdf\xfb\xff\xcc\xdf\xfb\xff\xcc\xdf\xfb\xff\xc5\xdb\xfa\xff\x5c\x99\xf1\xff5\x7f\xed\xff\x98\xbe\xf6\xff\xcf\xe1\xfb\xff\xcf\xe1\xfb\xff\xcf\xe1\xfb\xff\xcf\xe1\xfb\xff\xcf\xe1\xfb\xff\xcf\xe1\xfb\xff\xb1\xce\xf8\xff?\x86\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff\x8a\xb5\xf5\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xc3\xd9\xfa\xff:\x82\xed\xff]\x98\xf1\xff\xee\xf4\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfd\xff\xff\x8d\xb7\xf5\xff3~\xed\xff\x90\xb9\xf6\xff\xfd\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xec\xf3\xfd\xffY\x97\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffc\x9c\xf2\xff\xf1\xf7\xfe\xff\xff\xff\xff\xff\xe2\xed\xfc\xffM\x8f\xef\xffC\x88\xef\xff\xd5\xe4\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xb9\xd3\xf9\xff7\x81\xed\xffg\x9f\xf2\xff\xf3\xf8\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfc\xff\xff\x7f\xae\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffG\x8b\xef\xff\xdb\xe9\xfc\xff\xff\xff\xff\xff\xf5\xf9\xfe\xffl\xa2\xf2\xff5\x80\xed\xff\xaf\xcc\xf8\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdc\xe9\xfc\xffH\x8b\xef\xffI\x8c\xef\xff\xde\xea\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xab\xcb\xf8\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff7\x81\xed\xff\xb9\xd3\xf9\xff\xff\xff\xff\xff\xfd\xfe\xff\xff\x96\xbd\xf6\xff2~\xed\xff\x83\xb1\xf4\xff\xfb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf2\xf7\xfe\xffd\x9d\xf1\xff8\x82\xed\xff\xbc\xd4\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd1\xe2\xfb\xffA\x87\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2}\xed\xff\x8f\xb8\xf5\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xbf\xd7\xf9\xff9\x82\xed\xff]\x98\xf1\xff\xee\xf4\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\xfd\xff\xff\x8d\xb7\xf5\xff2~\xed\xff\x91\xba\xf6\xff\xfd\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xec\xf3\xfd\xffY\x96\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffg\x9f\xf2\xff\xf3\xf7\xfe\xff\xff\xff\xff\xff\xe0\xeb\xfc\xffJ\x8d\xef\xffB\x88\xee\xff\xce\xe0\xfb\xff\xf3\xf7\xfe\xff\xf3\xf7\xfe\xff\xf3\xf7\xfe\xff\xf3\xf7\xfe\xff\xf3\xf7\xfe\xff\xf3\xf7\xfe\xff\xb0\xcd\xf8\xff6\x80\xed\xfff\x9e\xf2\xff\xea\xf1\xfd\xff\xf3\xf7\xfe\xff\xf3\xf7\xfe\xff\xf3\xf7\xfe\xff\xf3\xf7\xfe\xff\xf3\xf7\xfe\xff\xef\xf5\xfe\xffy\xab\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffI\x8c\xef\xff\xde\xea\xfc\xff\xff\xff\xff\xff\xf4\xf8\xfe\xffi\xa0\xf2\xff3~\xed\xffU\x94\xf0\xffb\x9c\xf1\xffb\x9c\xf1\xffb\x9c\xf1\xffb\x9c\xf1\xffb\x9c\xf1\xffb\x9c\xf1\xffV\x95\xf0\xff4\x7f\xed\xff:\x83\xee\xff^\x9a\xf1\xffb\x9c\xf1\xffb\x9c\xf1\xffb\x9c\xf1\xffb\x9c\xf1\xffb\x9c\xf1\xffb\x9c\xf1\xffI\x8c\xef\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff8\x82\xed\xff\xbd\xd5\xf9\xff\xff\xff\xff\xff\xfc\xfe\xff\xff\x92\xba\xf6\xff1}\xed\xff6\x81\xee\xffF\x8b\xef\xffG\x8b\xef\xffG\x8b\xef\xffG\x8b\xef\xffG\x8b\xef\xffG\x8b\xef\xffG\x8b\xef\xff:\x83\xee\xff1}\xed\xff>\x85\xee\xffG\x8b\xef\xffG\x8b\xef\xffG\x8b\xef\xffG\x8b\xef\xffG\x8b\xef\xffG\x8b\xef\xffD\x8a\xef\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff\x93\xbb\xf5\xff\xfd\xfd\xff\xff\xff\xff\xff\xff\xbb\xd5\xf9\xff8\x81\xed\xffQ\x92\xf0\xff\xcf\xe1\xfb\xff\xe0\xeb\xfc\xff\xe0\xeb\xfc\xff\xe0\xeb\xfc\xff\xe0\xeb\xfc\xff\xe0\xeb\xfc\xff\xde\xea\xfc\xff\x88\xb4\xf4\xff2~\xed\xff\x84\xb1\xf4\xff\xde\xea\xfc\xff\xe0\xeb\xfc\xff\xe0\xeb\xfc\xff\xe0\xeb\xfc\xff\xe0\xeb\xfc\xff\xe0\xeb\xfc\xff\xd0\xe2\xfb\xffR\x92\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffj\xa1\xf2\xff\xf5\xf8\xfe\xff\xff\xff\xff\xff\xdd\xea\xfc\xffH\x8c\xef\xffB\x88\xee\xff\xd3\xe3\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xbd\xd5\xf9\xff8\x82\xed\xffm\xa3\xf2\xff\xf5\xf9\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf9\xfb\xff\xffy\xab\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffL\x8e\xef\xff\xe1\xec\xfc\xff\xff\xff\xff\xff\xf2\xf7\xfe\xffe\x9e\xf1\xff4\x7f\xed\xff\xae\xcc\xf8\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdf\xea\xfc\xffI\x8d\xef\xffM\x8f\xef\xff\xe2\xed\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xa5\xc6\xf7\xff3\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff:\x82\xee\xff\xc1\xd8\xfa\xff\xff\xff\xff\xff\xfc\xfd\xff\xff\x8d\xb7\xf5\xff1}\xed\xff\x81\xaf\xf4\xff\xfa\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf3\xf8\xfe\xffh\xa0\xf2\xff9\x82\xee\xff\xc1\xd8\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xcd\xdf\xfa\xff>\x85\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff\x98\xbe\xf6\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xb7\xd2\xf9\xff7\x81\xed\xff[\x97\xf0\xff\xed\xf4\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\xfd\xff\xff\x92\xba\xf5\xff3~\xed\xff\x97\xbd\xf6\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe9\xf1\xfd\xffU\x94\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffn\xa4\xf2\xff\xf6\xf9\xfe\xff\xff\xff\xff\xff\xda\xe8\xfc\xffF\x8a\xef\xffB\x87\xee\xff\xd3\xe3\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xbd\xd5\xf9\xff8\x82\xed\xffl\xa3\xf2\xff\xf5\xf9\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf9\xfb\xff\xffy\xaa\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffN\x90\xef\xff\xe4\xee\xfd\xff\xff\xff\xff\xff\xf1\xf6\xfe\xffb\x9c\xf1\xff5\x7f\xed\xff\xa4\xc6\xf7\xff\xe9\xf1\xfd\xff\xe9\xf1\xfd\xff\xe9\xf1\xfd\xff\xe9\xf1\xfd\xff\xe9\xf1\xfd\xff\xe9\xf1\xfd\xff\xcb\xde\xfb\xffE\x8a\xef\xffL\x8e\xef\xff\xd2\xe3\xfb\xff\xe9\xf1\xfd\xff\xe9\xf1\xfd\xff\xe9\xf1\xfd\xff\xe9\xf1\xfd\xff\xe9\xf1\xfd\xff\xe9\xf1\xfd\xff\x96\xbd\xf6\xff3~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff;\x83\xee\xff\xc5\xdb\xfa\xff\xff\xff\xff\xff\xfc\xfd\xff\xff\x89\xb4\xf5\xff2}\xed\xffC\x88\xef\xffS\x93\xf0\xffS\x93\xf0\xffS\x93\xf0\xffS\x93\xf0\xffS\x93\xf0\xffS\x93\xf0\xffP\x91\xf0\xff7\x80\xed\xff4\x7f\xed\xffM\x8f\xef\xffS\x93\xf0\xffS\x93\xf0\xffS\x93\xf0\xffS\x93\xf0\xffS\x93\xf0\xffS\x93\xf0\xffG\x8b\xef\xff2~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff3~\xed\xff\x9c\xc1\xf6\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xb4\xcf\xf8\xff6\x80\xed\xff5\x80\xed\xffM\x8f\xef\xffQ\x91\xf0\xffQ\x91\xf0\xffQ\x91\xf0\xffQ\x91\xf0\xffQ\x91\xf0\xffQ\x91\xf0\xffD\x89\xef\xff1}\xed\xff;\x84\xee\xffN\x8f\xf0\xffO\x90\xf0\xffO\x90\xf0\xffO\x90\xf0\xffO\x90\xf0\xffO\x90\xf0\xffN\x8f\xf0\xff:\x83\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffr\xa6\xf3\xff\xf7\xfa\xfe\xff\xff\xff\xff\xff\xd8\xe6\xfc\xffD\x89\xef\xff?\x86\xee\xff\xc1\xd8\xfa\xff\xe7\xf0\xfd\xff\xe7\xf0\xfd\xff\xe7\xf0\xfd\xff\xe7\xf0\xfd\xff\xe7\xf0\xfd\xff\xe7\xf0\xfd\xff\xac\xcb\xf8\xff7\x81\xed\xff_\x9a\xf1\xff\xdb\xe8\xfc\xff\xe5\xef\xfd\xff\xe5\xef\xfd\xff\xe5\xef\xfd\xff\xe5\xef\xfd\xff\xe5\xef\xfd\xff\xe2\xec\xfd\xffw\xa9\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffQ\x91\xf0\xff\xe6\xef\xfd\xff\xff\xff\xff\xff\xef\xf5\xfe\xff_\x9a\xf1\xff5\x80\xed\xff\xb0\xcd\xf8\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdb\xe8\xfc\xffG\x8a\xef\xffJ\x8d\xef\xff\xdf\xeb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xa8\xc8\xf8\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff<\x84\xee\xff\xc9\xdd\xfa\xff\xff\xff\xff\xff\xfb\xfd\xff\xff\x85\xb2\xf4\xff1}\xed\xff\x84\xb1\xf4\xff\xfb\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf1\xf6\xfe\xffc\x9d\xf1\xff9\x82\xee\xff\xbe\xd6\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xcf\xe1\xfb\xff@\x86\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff3~\xed\xff\xa1\xc3\xf7\xff\xfe\xff\xff\xff\xfe\xff\xff\xff\xaf\xcd\xf8\xff5\x7f\xed\xff]\x99\xf1\xff\xee\xf5\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\xfd\xff\xff\x8c\xb6\xf5\xff3~\xed\xff\x93\xbb\xf6\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xeb\xf3\xfd\xffW\x95\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffv\xa9\xf3\xff\xf8\xfb\xfe\xff\xff\xff\xff\xff\xd2\xe2\xfb\xffA\x87\xef\xffC\x88\xef\xff\xd6\xe5\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff\xb8\xd2\xf9\xff6\x81\xed\xffi\xa0\xf2\xff\xf4\xf8\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfc\xff\xff|\xad\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffT\x93\xf0\xff\xe8\xf1\xfd\xff\xff\xff\xff\xff\xec\xf3\xfd\xffY\x96\xf1\xff5\x80\xed\xff\xb0\xcd\xf8\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdb\xe8\xfc\xffG\x8b\xef\xffK\x8d\xef\xff\xdf\xeb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xa8\xc8\xf8\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff=\x85\xee\xff\xbc\xd5\xf9\xff\xe4\xee\xfd\xff\xdf\xeb\xfc\xffp\xa5\xf3\xff1}\xed\xff}\xad\xf4\xff\xdf\xea\xfc\xff\xe1\xec\xfc\xff\xe1\xec\xfc\xff\xe1\xec\xfc\xff\xe1\xec\xfc\xff\xe1\xec\xfc\xff\xd5\xe4\xfb\xffX\x96\xf0\xff9\x82\xed\xff\xb0\xcd\xf8\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xb8\xd2\xf9\xff<\x84\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xffD\x89\xef\xffK\x8e\xef\xffK\x8e\xef\xff=\x84\xee\xff1}\xed\xff9\x82\xee\xffI\x8c\xef\xffI\x8c\xef\xffI\x8c\xef\xffI\x8c\xef\xffI\x8c\xef\xffI\x8c\xef\xffH\x8c\xef\xff8\x82\xee\xff1}\xed\xffB\x88\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffG\x8b\xef\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf0}\xec\xe01}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1}\xec\xc50}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe01|\xec\xc4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00 \x00\x00\x00@\x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00\x80\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001|\xec\xc31|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xc31|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff4\x7f\xed\xffG\x8b\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8d\xef\xff;\x83\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff>\x85\xee\xff\xbe\xd5\xf9\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe3\xee\xfd\xff\x87\xb3\xf5\xff2}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff5\x7f\xed\xff\xb0\xce\xf8\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xbd\xd5\xf9\xff8\x81\xee\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff\x85\xb2\xf5\xff\xfc\xfd\xff\xff\xfc\xfd\xff\xff\xc2\xd9\xfa\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\xaa\xca\xf8\xff\x94\xbc\xf6\xff<\x84\xee\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff_\x9a\xf1\xff\xf0\xf6\xfe\xff\xfc\xfd\xff\xff\x85\xb2\xf5\xff4\x7f\xed\xff=\x85\xee\xffA\x87\xee\xffA\x87\xee\xffA\x87\xee\xffA\x87\xee\xffA\x87\xee\xff8\x81\xee\xff5\x80\xed\xff@\x87\xee\xffB\x88\xef\xffB\x88\xef\xffB\x88\xef\xffB\x88\xef\xffA\x87\xee\xff6\x80\xed\xff3~\xed\xff3~\xed\xff3~\xed\xff3~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xffD\x89\xef\xff\xd9\xe7\xfc\xff\xff\xff\xff\xff\xb0\xcd\xf8\xff8\x81\xee\xff\x96\xbd\xf6\xff\xd2\xe3\xfb\xff\xd2\xe3\xfb\xff\xd2\xe3\xfb\xff\xd2\xe3\xfb\xff\xd0\xe2\xfb\xffv\xa9\xf3\xff@\x86\xee\xff\xb6\xd1\xf9\xff\xd4\xe4\xfb\xff\xd4\xe4\xfb\xff\xd4\xe4\xfb\xff\xd4\xe4\xfb\xff\xc9\xdd\xfa\xffU\x94\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff6\x80\xed\xff\xb5\xd0\xf8\xff\xff\xff\xff\xff\xd5\xe4\xfb\xffB\x88\xef\xff\x8b\xb6\xf5\xff\xfd\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xae\xcc\xf8\xff:\x83\xee\xff\xb9\xd3\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xfc\xff\xff\x7f\xae\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff\x8a\xb5\xf5\xff\xfc\xfd\xff\xff\xee\xf4\xfe\xff[\x97\xf1\xffc\x9c\xf1\xff\xf2\xf7\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd5\xe4\xfb\xffB\x88\xef\xff\x8e\xb7\xf5\xff\xfd\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xac\xcb\xf8\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffb\x9c\xf2\xff\xf2\xf7\xfe\xff\xfb\xfc\xff\xff\x80\xaf\xf4\xffF\x8a\xef\xff\xdb\xe8\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xee\xf4\xfe\xff[\x98\xf1\xffd\x9d\xf2\xff\xf3\xf7\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd3\xe3\xfb\xff@\x87\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffF\x8b\xef\xff\xdc\xe9\xfc\xff\xff\xff\xff\xff\xab\xca\xf8\xff9\x82\xee\xff\xb7\xd2\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xfc\xff\xff\x82\xb0\xf4\xffG\x8b\xef\xff\xdd\xe9\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xed\xf4\xfe\xffY\x96\xf1\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff7\x81\xee\xff\xb9\xd3\xf9\xff\xff\xff\xff\xff\xd1\xe2\xfb\xff@\x86\xee\xffx\xaa\xf3\xff\xc3\xd9\xfa\xff\xc4\xda\xfa\xff\xc4\xda\xfa\xff\xc4\xda\xfa\xff\xc4\xd9\xfa\xff\x85\xb2\xf5\xff8\x81\xee\xff\x99\xbf\xf6\xff\xc4\xda\xfa\xff\xc4\xda\xfa\xff\xc4\xda\xfa\xff\xc4\xda\xfa\xff\xc0\xd7\xfa\xffc\x9c\xf1\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff\x8e\xb8\xf5\xff\xfd\xfd\xff\xff\xec\xf3\xfd\xffX\x95\xf0\xff5\x80\xed\xff?\x86\xee\xff@\x87\xee\xff@\x87\xee\xff@\x87\xee\xff@\x87\xee\xff=\x85\xee\xff3~\xed\xff8\x81\xee\xff?\x87\xee\xff@\x87\xee\xff@\x87\xee\xff@\x87\xee\xff@\x87\xee\xff:\x83\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xfff\x9f\xf2\xff\xf4\xf8\xfe\xff\xfa\xfc\xff\xff{\xac\xf4\xff=\x84\xee\xff\xa8\xc8\xf8\xff\xc7\xdc\xfa\xff\xc7\xdc\xfa\xff\xc7\xdc\xfa\xff\xc7\xdc\xfa\xff\xbf\xd6\xf9\xffV\x95\xf0\xffT\x93\xf0\xff\xbe\xd6\xf9\xff\xc7\xdc\xfa\xff\xc7\xdc\xfa\xff\xc7\xdc\xfa\xff\xc7\xdc\xfa\xff\xa9\xc9\xf7\xff=\x84\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffI\x8c\xef\xff\xdf\xeb\xfc\xff\xff\xff\xff\xff\xa7\xc8\xf7\xff8\x82\xee\xff\xb6\xd1\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\xfd\xff\xff\x85\xb3\xf5\xffJ\x8d\xef\xff\xe0\xeb\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xeb\xf2\xfd\xffV\x94\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff8\x82\xee\xff\xbd\xd6\xf9\xff\xff\xff\xff\xff\xce\xe0\xfb\xff>\x86\xee\xff\x8a\xb5\xf5\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xb2\xcf\xf8\xff<\x84\xee\xff\xbe\xd6\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfc\xff\xffz\xab\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2}\xed\xff\x93\xbb\xf6\xff\xfd\xfe\xff\xff\xea\xf2\xfd\xffU\x94\xf0\xffa\x9c\xf1\xff\xf2\xf6\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd7\xe6\xfc\xffD\x89\xef\xff\x93\xbb\xf6\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xa7\xc7\xf7\xff3\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffj\xa1\xf2\xff\xf5\xf9\xfe\xff\xf9\xfb\xff\xffx\xaa\xf3\xffE\x8a\xef\xff\xda\xe8\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0\xf5\xfe\xff^\x99\xf1\xffh\xa0\xf2\xff\xf5\xf9\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xcf\xe0\xfb\xff>\x85\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffK\x8e\xef\xff\xe1\xec\xfc\xff\xfe\xff\xff\xff\xa3\xc5\xf7\xff8\x81\xed\xff\x9f\xc2\xf7\xff\xd2\xe3\xfb\xff\xd2\xe3\xfb\xff\xd2\xe3\xfb\xff\xd2\xe3\xfb\xff\xcf\xe1\xfb\xffn\xa4\xf2\xffG\x8b\xef\xff\xbe\xd6\xf9\xff\xd2\xe3\xfb\xff\xd2\xe3\xfb\xff\xd2\xe3\xfb\xff\xd2\xe3\xfb\xff\xc0\xd7\xfa\xffJ\x8d\xef\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff9\x82\xee\xff\xc1\xd8\xfa\xff\xff\xff\xff\xff\xcb\xde\xfa\xff=\x85\xee\xff:\x83\xee\xffB\x88\xee\xffB\x88\xee\xffB\x88\xee\xffB\x88\xee\xffB\x88\xee\xff:\x83\xee\xff2~\xed\xff>\x85\xee\xffA\x87\xee\xffA\x87\xee\xffA\x87\xee\xffA\x87\xee\xff@\x87\xee\xff6\x80\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2}\xed\xff\x98\xbe\xf6\xff\xfe\xfe\xff\xff\xe8\xf0\xfd\xffR\x92\xf0\xffJ\x8d\xef\xff\xa7\xc7\xf7\xff\xb1\xce\xf8\xff\xb1\xce\xf8\xff\xb1\xce\xf8\xff\xb1\xce\xf8\xff\x9c\xc0\xf6\xff>\x85\xee\xffc\x9d\xf2\xff\xac\xcb\xf8\xff\xae\xcc\xf8\xff\xae\xcc\xf8\xff\xae\xcc\xf8\xff\xae\xcc\xf8\xff\x82\xb0\xf4\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffm\xa3\xf2\xff\xf6\xf9\xfe\xff\xf8\xfb\xff\xfft\xa7\xf3\xffF\x8b\xef\xff\xdb\xe8\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xee\xf4\xfe\xff[\x97\xf1\xfff\x9e\xf2\xff\xf3\xf8\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd1\xe2\xfb\xff@\x86\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffN\x8f\xf0\xff\xe4\xee\xfd\xff\xfe\xff\xff\xff\x9f\xc2\xf7\xff8\x81\xee\xff\xb8\xd2\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xfc\xff\xff\x81\xaf\xf4\xffH\x8c\xef\xff\xde\xea\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xec\xf3\xfd\xffX\x96\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff:\x83\xee\xff\xc5\xdb\xfa\xff\xff\xff\xff\xff\xc6\xdb\xfa\xff;\x83\xee\xff\x8c\xb6\xf5\xff\xfd\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xad\xcc\xf8\xff;\x83\xee\xff\xbc\xd4\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfc\xff\xff}\xad\xf4\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2~\xed\xff\x9c\xc1\xf7\xff\xfe\xff\xff\xff\xe4\xee\xfd\xffN\x8f\xf0\xffc\x9d\xf2\xff\xf2\xf7\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd4\xe4\xfb\xffB\x87\xee\xff\x8f\xb9\xf6\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xaa\xc9\xf8\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffm\xa3\xf2\xff\xdf\xeb\xfc\xff\xdc\xe9\xfc\xffb\x9c\xf1\xffE\x8a\xef\xff\xc7\xdb\xfa\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xe2\xed\xfd\xff\xd2\xe2\xfb\xffR\x91\xf0\xffb\x9c\xf1\xff\xdc\xe9\xfc\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xba\xd3\xf9\xff<\x84\xee\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff8\x81\xee\xffJ\x8d\xef\xffK\x8d\xef\xff:\x83\xee\xff3~\xed\xffD\x89\xef\xffI\x8c\xef\xffI\x8c\xef\xffI\x8c\xef\xffI\x8c\xef\xffH\x8c\xef\xff7\x81\xee\xff6\x80\xed\xffI\x8c\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffK\x8e\xef\xffG\x8b\xef\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xc31|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00\x18\x00\x00\x000\x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00`\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001|\xec\xc31|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xc31|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff4\x7f\xed\xffG\x8b\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xff?\x86\xee\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff>\x85\xee\xff\xbe\xd6\xfa\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xa2\xc4\xf7\xff4\x7f\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff4\x7f\xed\xff\xb1\xce\xf8\xff\xff\xff\xff\xff\xed\xf3\xfd\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xdf\xeb\xfc\xff\xba\xd3\xf9\xff=\x85\xee\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff\x84\xb2\xf4\xff\xfc\xfd\xff\xff\xa8\xc8\xf7\xffJ\x8d\xef\xffU\x94\xf0\xffW\x95\xf0\xffW\x95\xf0\xffW\x95\xf0\xffO\x90\xf0\xffK\x8e\xef\xffW\x95\xf0\xffX\x96\xf0\xffX\x96\xf0\xffW\x95\xf0\xffL\x8e\xef\xffF\x8b\xef\xffF\x8b\xef\xffC\x89\xef\xff3\x7f\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff^\x9a\xf1\xff\xf1\xf6\xfe\xff\xc4\xda\xfa\xffJ\x8d\xef\xff\xbd\xd5\xf9\xff\xd7\xe6\xfc\xff\xd7\xe6\xfc\xff\xd7\xe6\xfc\xff\x93\xbb\xf6\xffV\x95\xf0\xff\xcd\xe0\xfb\xff\xd9\xe7\xfc\xff\xd9\xe7\xfc\xff\xd7\xe6\xfc\xffv\xa8\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xffD\x89\xef\xff\xd9\xe7\xfc\xff\xe3\xed\xfd\xffS\x92\xf0\xff\xc0\xd7\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xcd\xdf\xfa\xffQ\x91\xf0\xff\xdb\xe8\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xad\xcb\xf8\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff5\x80\xed\xff\xb5\xd0\xf9\xff\xf6\xf9\xfe\xffl\xa2\xf2\xff\x94\xbc\xf6\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xea\xf1\xfd\xffX\x96\xf0\xff\xb7\xd2\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd4\xe4\xfb\xff@\x87\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff\x89\xb5\xf5\xff\xfc\xfd\xff\xff\x95\xbc\xf6\xffi\xa0\xf2\xff\xf2\xf7\xfe\xff\xfb\xfc\xff\xff\xfb\xfc\xff\xff\xf5\xf9\xfe\xffu\xa8\xf3\xff\x89\xb5\xf5\xff\xf9\xfb\xff\xff\xfb\xfc\xff\xff\xfb\xfc\xff\xff\xea\xf2\xfd\xffX\x96\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xffb\x9c\xf1\xff\xf2\xf7\xfe\xff\xc0\xd7\xfa\xffD\x89\xef\xffp\xa5\xf2\xffv\xa9\xf3\xffv\xa9\xf3\xffu\xa8\xf3\xffP\x91\xf0\xffG\x8a\xef\xfft\xa7\xf3\xffv\xa9\xf3\xffv\xa9\xf3\xffs\xa7\xf3\xffE\x89\xef\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xffF\x8a\xef\xff\xdc\xe9\xfc\xff\xe1\xec\xfc\xffK\x8e\xef\xff|\xac\xf4\xff\xa6\xc7\xf7\xff\xa6\xc7\xf7\xff\xa6\xc7\xf7\xff\x91\xba\xf5\xffD\x89\xef\xff\x8f\xb8\xf5\xff\xa6\xc7\xf7\xff\xa6\xc7\xf7\xff\xa6\xc7\xf7\xff}\xad\xf4\xff3~\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff6\x80\xed\xff\xb9\xd3\xf9\xff\xf5\xf9\xfe\xffh\xa0\xf2\xff\x92\xbb\xf6\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xeb\xf2\xfd\xff[\x97\xf1\xff\xba\xd4\xf9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd0\xe2\xfb\xff?\x86\xee\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff\x8e\xb8\xf5\xff\xfc\xfd\xff\xff\x91\xba\xf5\xffh\xa0\xf2\xff\xf5\xf9\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfa\xfc\xff\xffz\xab\xf3\xff\x8e\xb8\xf5\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xec\xf3\xfd\xffW\x95\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffe\x9e\xf2\xff\xf4\xf8\xfe\xff\xbd\xd5\xf9\xffP\x90\xf0\xff\xe0\xec\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xa6\xc7\xf7\xfff\x9f\xf2\xff\xf4\xf8\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xfc\xff\xff|\xac\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffH\x8c\xef\xff\xdf\xeb\xfc\xff\xde\xea\xfc\xffM\x8f\xef\xff\x90\xb9\xf5\xff\xb2\xce\xf8\xff\xb2\xce\xf8\xff\xb2\xce\xf8\xff\x8f\xb8\xf5\xffG\x8b\xef\xff\xa2\xc4\xf7\xff\xb2\xce\xf8\xff\xb2\xce\xf8\xff\xb2\xce\xf8\xffu\xa8\xf3\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff7\x81\xee\xff\xbe\xd6\xf9\xff\xf4\xf8\xfe\xffe\x9e\xf2\xffG\x8b\xef\xffj\xa1\xf2\xffj\xa1\xf2\xffj\xa1\xf2\xffg\x9f\xf2\xff?\x86\xee\xffP\x91\xf0\xffh\xa0\xf2\xffh\xa0\xf2\xffh\xa0\xf2\xff`\x9b\xf1\xff7\x81\xee\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff2}\xed\xff\x93\xbb\xf6\xff\xfc\xfd\xff\xff\x8d\xb7\xf5\xfff\x9e\xf2\xff\xed\xf4\xfe\xff\xf6\xfa\xfe\xff\xf6\xfa\xfe\xff\xf2\xf7\xfe\xfft\xa7\xf3\xff\x86\xb3\xf4\xff\xf4\xf8\xfe\xff\xf6\xf9\xfe\xff\xf6\xf9\xfe\xff\xe6\xef\xfd\xffX\x96\xf0\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffi\xa0\xf2\xff\xf6\xf9\xfe\xff\xb8\xd3\xf9\xffO\x90\xf0\xff\xe2\xec\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xa3\xc5\xf7\xffd\x9d\xf1\xff\xf3\xf7\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xfd\xff\xff~\xad\xf4\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffK\x8d\xef\xff\xe2\xec\xfc\xff\xda\xe8\xfc\xffK\x8e\xef\xff\xc0\xd7\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xcc\xdf\xfa\xffQ\x92\xf0\xff\xdc\xe9\xfc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xab\xca\xf8\xff4\x7f\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff8\x82\xee\xff\xb3\xcf\xf8\xff\xd7\xe6\xfc\xffW\x95\xf0\xff\x8b\xb6\xf5\xff\xe2\xed\xfd\xff\xe3\xed\xfd\xff\xe3\xed\xfd\xff\xcf\xe0\xfb\xffP\x91\xf0\xff\xab\xca\xf8\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xe4\xee\xfd\xff\xbb\xd4\xf9\xff<\x84\xee\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffB\x88\xef\xffJ\x8d\xef\xff8\x82\xee\xff;\x83\xee\xffI\x8c\xef\xffJ\x8c\xef\xffJ\x8c\xef\xffH\x8b\xef\xff6\x80\xed\xffA\x87\xee\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffG\x8b\xef\xff4\x7f\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xc40}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe00}\xec\xe01|\xec\xc4\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00\x14\x00\x00\x00(\x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00\x90\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001|\xec\xc31|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xc31|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff]\x99\xf1\xff\x97\xbd\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x98\xbe\xf6\xff\x91\xba\xf6\xffH\x8c\xef\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xffm\xa3\xf2\xff\xf7\xfa\xfe\xff\xf7\xfa\xfe\xff\xf0\xf5\xfe\xff\xf0\xf5\xfe\xff\xf0\xf5\xfe\xff\xf0\xf5\xfe\xff\xf0\xf5\xfe\xff\xf0\xf5\xfe\xff\xf0\xf5\xfe\xff\xf0\xf5\xfe\xff\xf0\xf5\xfe\xff\xf0\xf5\xfe\xff\xf0\xf5\xfe\xff\xeb\xf3\xfd\xffs\xa7\xf3\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xffN\x8f\xf0\xff\xe5\xef\xfd\xff\xbc\xd5\xf9\xff`\x9a\xf1\xffj\xa1\xf2\xffk\xa2\xf2\xffk\xa2\xf2\xffd\x9d\xf1\xffa\x9b\xf1\xffl\xa2\xf2\xffl\xa2\xf2\xffl\xa2\xf2\xffa\x9c\xf1\xffZ\x97\xf1\xffY\x97\xf1\xffD\x89\xef\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff:\x83\xee\xff\xc7\xdc\xfa\xff\xcd\xdf\xfb\xff[\x98\xf1\xff\xcb\xde\xfb\xff\xda\xe8\xfc\xff\xda\xe8\xfc\xff\xa2\xc4\xf7\xffg\x9f\xf2\xff\xd5\xe5\xfc\xff\xdb\xe8\xfc\xff\xdb\xe8\xfc\xff\x8a\xb5\xf5\xff2}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff2~\xed\xff\x9d\xc1\xf7\xff\xe9\xf1\xfd\xffc\x9c\xf1\xff\xd5\xe5\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd9\xe7\xfc\xffc\x9d\xf1\xff\xe8\xf0\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc2\xd9\xfa\xff8\x82\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xffr\xa6\xf3\xff\xf3\xf7\xfe\xffx\xaa\xf3\xff\xaf\xcd\xf8\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf1\xf6\xfe\xffi\xa0\xf2\xff\xca\xdd\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe3\xed\xfc\xffK\x8e\xef\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xffQ\x91\xf0\xff\xe7\xf0\xfd\xff\xa1\xc3\xf7\xffi\xa0\xf2\xff\xa9\xc9\xf8\xff\xaa\xc9\xf8\xff\xa8\xc8\xf7\xff]\x99\xf1\xffz\xab\xf3\xff\xaa\xc9\xf8\xff\xaa\xc9\xf8\xff\xa3\xc5\xf7\xffM\x8e\xf0\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff;\x84\xee\xff\xcb\xde\xfa\xff\xca\xdd\xfa\xffJ\x8d\xef\xff\x89\xb5\xf5\xff\x95\xbc\xf6\xff\x95\xbc\xf6\xffx\xaa\xf3\xffO\x90\xf0\xff\x90\xba\xf5\xff\x95\xbc\xf6\xff\x95\xbc\xf6\xffh\xa0\xf2\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff2~\xed\xff\xa2\xc4\xf7\xff\xe7\xf0\xfd\xff_\x9a\xf1\xff\xd5\xe4\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdb\xe8\xfc\xfff\x9f\xf2\xff\xe9\xf1\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xff\xbf\xd7\xfa\xff7\x81\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xffv\xa8\xf3\xff\xf3\xf8\xfe\xfft\xa7\xf3\xff\xae\xcc\xf8\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf2\xf7\xfe\xffl\xa2\xf2\xff\xcc\xdf\xfb\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe1\xec\xfc\xffJ\x8d\xef\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xffS\x93\xf0\xff\xe9\xf1\xfd\xff\x9d\xc1\xf6\xff|\xac\xf4\xff\xe6\xef\xfd\xff\xe8\xf0\xfd\xff\xe6\xef\xfd\xff}\xad\xf4\xff\x9a\xbf\xf6\xff\xe8\xf0\xfd\xff\xe8\xf0\xfd\xff\xde\xeb\xfc\xff_\x9a\xf1\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff=\x85\xee\xff\xce\xe0\xfb\xff\xc6\xdb\xfa\xffF\x8a\xef\xfff\x9f\xf2\xffk\xa2\xf2\xffk\xa2\xf2\xffV\x94\xf0\xffF\x8b\xef\xffh\xa0\xf2\xffj\xa1\xf2\xffi\xa1\xf2\xffL\x8e\xef\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff3~\xed\xff\xa7\xc7\xf7\xff\xe5\xee\xfd\xffZ\x97\xf1\xff\xc0\xd7\xfa\xff\xe7\xf0\xfd\xff\xe7\xf0\xfd\xff\xc8\xdc\xfa\xff\x5c\x98\xf1\xff\xd0\xe1\xfb\xff\xe6\xef\xfd\xff\xe6\xef\xfd\xff\xb3\xcf\xf8\xff8\x82\xee\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffz\xab\xf3\xff\xf3\xf8\xfe\xffp\xa5\xf2\xff\xb0\xcd\xf8\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf1\xf6\xfe\xffi\xa0\xf2\xff\xcb\xde\xfa\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe2\xed\xfd\xffK\x8d\xef\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xffW\x95\xf0\xff\xeb\xf3\xfd\xff\x96\xbd\xf6\xff\x83\xb0\xf4\xff\xfc\xfd\xff\xff\xff\xff\xff\xff\xfc\xfd\xff\xff\x87\xb3\xf5\xff\xa1\xc4\xf7\xff\xfe\xff\xff\xff\xff\xff\xff\xff\xf6\xf9\xfe\xffj\xa1\xf2\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff;\x83\xee\xff\x87\xb3\xf5\xffs\xa6\xf3\xffM\x8e\xef\xff\x91\xb9\xf5\xff\x95\xbc\xf6\xff\x95\xbc\xf6\xffj\xa1\xf2\xffZ\x97\xf1\xff\x97\xbd\xf6\xff\x98\xbe\xf6\xff\x97\xbd\xf6\xff[\x98\xf1\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xc31|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(\x00\x00\x00\x10\x00\x00\x00 \x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00@\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x001|\xec\xc31|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xc31|\xec\xdf4\x7f\xed\xffG\x8b\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffK\x8d\xef\xffC\x88\xef\xff2}\xed\xff1|\xec\xdf1|\xec\xdf=\x85\xee\xff\xbe\xd6\xf9\xff\xe3\xed\xfd\xff\xe0\xec\xfc\xff\xe0\xec\xfc\xff\xe0\xec\xfc\xff\xe0\xec\xfc\xff\xe0\xec\xfc\xff\xe0\xec\xfc\xff\xe0\xec\xfc\xff\xe0\xec\xfc\xff\xe0\xec\xfc\xff\xb6\xd1\xf9\xff:\x83\xee\xff1|\xec\xdf1|\xec\xdf4\x7f\xed\xff\xb1\xce\xf8\xff\xd0\xe1\xfb\xff}\xad\xf4\xff\x86\xb3\xf4\xff\x86\xb3\xf4\xff\x80\xaf\xf4\xff}\xad\xf4\xff\x87\xb3\xf5\xff\x87\xb3\xf5\xff~\xae\xf4\xffs\xa7\xf3\xffh\xa0\xf2\xff7\x81\xee\xff1|\xec\xdf1|\xec\xdf1}\xed\xff\x84\xb2\xf4\xff\xd3\xe3\xfb\xffq\xa5\xf3\xff\xd6\xe5\xfc\xff\xdd\xe9\xfc\xff\xb0\xcd\xf8\xff|\xac\xf4\xff\xdb\xe9\xfc\xff\xde\xea\xfc\xff\x9e\xc2\xf7\xff4\x7f\xed\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff^\x99\xf1\xff\xe1\xec\xfc\xffx\xaa\xf3\xff\xe7\xf0\xfd\xff\xff\xff\xff\xff\xe4\xee\xfd\xffz\xab\xf3\xff\xf1\xf7\xfe\xff\xff\xff\xff\xff\xd4\xe4\xfb\xff@\x87\xee\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xffC\x88\xef\xff\xd6\xe5\xfb\xff\x88\xb4\xf5\xff\xaf\xcc\xf8\xff\xd6\xe5\xfb\xff\xcf\xe1\xfb\xffm\xa3\xf2\xff\xbc\xd5\xf9\xff\xd6\xe5\xfb\xff\xc7\xdc\xfa\xffN\x8f\xf0\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff5\x80\xed\xff\xb5\xd0\xf8\xff\xac\xcb\xf8\xff_\x9b\xf1\xff\x8f\xb9\xf5\xff\x8f\xb9\xf5\xffh\xa0\xf2\xffk\xa2\xf2\xff\x90\xb9\xf5\xff\x8f\xb8\xf5\xffY\x96\xf1\xff1}\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff\x89\xb4\xf5\xff\xd1\xe2\xfb\xff}\xad\xf4\xff\xf7\xfa\xfe\xff\xfd\xfe\xff\xff\xc5\xda\xfa\xff\x91\xb9\xf5\xff\xfc\xfd\xff\xff\xfd\xfe\xff\xff\xaa\xca\xf7\xff3~\xed\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xffa\x9b\xf1\xff\xe1\xec\xfc\xfft\xa7\xf3\xff\xe5\xef\xfd\xff\xfe\xfe\xff\xff\xe4\xee\xfd\xff}\xad\xf4\xff\xf2\xf7\xfe\xff\xfe\xfe\xff\xff\xd2\xe2\xfb\xff?\x86\xee\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xffE\x8a\xef\xff\xd9\xe7\xfc\xff\x81\xb0\xf4\xff~\xad\xf4\xff\x94\xbc\xf6\xff\x8f\xb8\xf5\xffV\x94\xf0\xff\x86\xb3\xf4\xff\x94\xbb\xf6\xff\x88\xb4\xf5\xff@\x86\xee\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff6\x80\xed\xff\xba\xd3\xf9\xff\xa8\xc8\xf7\xff\x80\xaf\xf4\xff\xce\xe0\xfb\xff\xce\xe0\xfb\xff\x87\xb3\xf4\xff\x91\xba\xf5\xff\xcd\xe0\xfb\xff\xcc\xdf\xfb\xffq\xa6\xf3\xff1}\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff\x8e\xb7\xf5\xff\xce\xe0\xfb\xff}\xad\xf4\xff\xf9\xfb\xff\xff\xff\xff\xff\xff\xc3\xd9\xfa\xff\x8f\xb9\xf5\xff\xfd\xfe\xff\xff\xff\xff\xff\xff\xac\xcb\xf8\xff3~\xed\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xffa\x9b\xf1\xff\xc9\xdd\xfa\xffh\xa0\xf2\xff\xd1\xe2\xfb\xff\xe4\xee\xfd\xff\xca\xde\xfa\xffq\xa5\xf3\xff\xdb\xe9\xfc\xff\xe5\xee\xfd\xff\xbd\xd5\xf9\xff<\x84\xee\xff1|\xec\xdf1|\xec\xdf1}\xed\xff1}\xed\xff1}\xed\xff6\x80\xed\xffG\x8b\xef\xff9\x82\xee\xffF\x8a\xef\xffJ\x8d\xef\xffH\x8b\xef\xff:\x82\xee\xffH\x8c\xef\xffK\x8d\xef\xffG\x8b\xef\xff4\x7f\xed\xff1|\xec\xdf1|\xec\xc31|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xdf1|\xec\xc3\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xea\x89PNG\x0d\x0a\x1a\x0a\x00\x00\x00\x0dIHDR\x00\x00\x00\x80\x00\x00\x00\x80\x08\x02\x00\x00\x00L\x5c\xf6\x9c\x00\x00\x00\x09pHYs\x00\x00\x0e\xc3\x00\x00\x0e\xc3\x01\xc7o\xa8d\x00\x00\x0f\x9cIDATx\x9c\xed]Kl\x1cWv=\xf7UU\xffH\x8a\x14%Q\x94DI\xb4e\xd9\x1a\xcb\xb2'\xb6'\x01&\x080@\x02\x0c\x02\x04\xd9\xcc,\x06Y\x05\x08\x92U\x16I\x90M\x10x\x95Y\x06\x08\x82,\xb2\xf3\x22H\x82\x04\xc1\x04\xc1L\x06\xc8g5\x01f2\x8a\xc7\x96dI\x96l}LR\x149\x94H\x91\xe2\xbf\xba\xde{7\x8bW\xfd\xa9\xee\xaa\x16\xeb\xd7\xcdQ\xd7\x81\xb4hv\xf7\xad\xd7u\xde\xbb\xe7}\xee\xbdEk\x1f\xfc\x12\x0a\x0c\x0eb\xd0\x0d\x18v\x14\x04\x0c\x18\x05\x01\x03FA\xc0\x80Q\x100`\x14\x04\x0c\x18\x05\x01\x03FA\xc0\x80Q\x100`\x14\x04\x0c\x18\x05\x01\x03FA\xc0\x80a\x0f\xe6\xb2D\xbd\xdee\xff\x7f\xf7\xd72\xba|\x98\xf1\xdeM\x8aa;\xb4\xe5\x91\x18\x10\x01Z\x81u\xe4\xbbD +\xe4\xef\xac\xb2\xb9:u\x8d{fh\x99\x8dq\x11\xef\x96\x0e\x82\x00f*\xd5\xe0\x94\xc3;\x0b\x11d\x9d\xdd\xdd\xee.IN%\x83\xab\x13\xb1\xac\x07.\xcd\x0c\xcb\xa6\xcaD\xdc\xce\x1b\x0a\xde\xdf\x8ae\xa7\xef\x04\x10Ay\xa3\xbf\xf3W\xce\xec\xbb\xec\xeetvF\xad\xa86\xb1\xf3\xfd\xef\xee\xff\xf8\xef\xa86\x01\xad\x00@X\xbc\xbbQ\xf9\x95\xef\xd4~\xeb\xcfxw\x03\x22lp\x1c\x04\xcc\xe4\x94\xd5\xea\xdc\xe6\x87\xbf\x0f\xd6>\xc1\xc2\xe2\x9d\xf5\xeao\xfca\xed\x9b\x7f\xc4;\xeb)\x8ck*\xd5\xbc\x85\x1b[\x1f\xfe\x1e\x84\x13\xe1BC\xd0_\x02\x88 \xebb|\xda>{\x05\x96C\xb5\xf1.\xb7\xce\x00\xa9\xe5\xbb\x10vG?r.~\x9d\xca5r\xca\xc9\xef\x91V\x10\x96~p\x95\xf76\xa96\xee\xb3\xcb\x0c\xcbq.\xfc2\x00\xaa\x1eIi\x5c\xad\xdccw\x97F\x8e\xfa\xc6\x0f\x80>\x13 X\xba\xd6\xa9KT\xaaA+\x90\x08\xf4\x14f\x08\xa17\x96\xd5\x93\x07\xd4rP\x04%\xa96a\x9d\xb9\xdc\xfaX20\x03\xf0\x1e^m\xc9\x0f\x11\x94'\xc6N\xd8\xd3\x97\xfck\xa5\xf3B\xf2\xcb\x8fB\x04\xa6'\xfa\xee\x82\xb4\xb2\xcf7\x0eA;\xbciQ\xdb\x14\x80\xd3\x97\x80\xb0\xc5\xc1\xc1A\xe4\x1b\x8fo\xa4\x9f.\x88\xa0\xa5}\xfe\xab@\x98\x90\x1a\x17\xb1|G\xef\xacA\xd8\xbe8\x13\xb1t\xad\xe3\xb3\xbe\x00\xa4\xb9G\xc2\x82\x19^A\x01\xb0\xa6/\xd2\xc8$\x98S\xb0\xcb \xc1\xde\xbe\x5c\xfa,\xae\x00\xa0\xaf\x040\xc3.\xd9\xe7\xbe\x0a jS\xc1\x9b\xbf\x06\xe5\xb5\xeeE\xf6\x02\xf0\xe5\xa1\x12\x00\xf4\x8f\x00\x7f\xbcO\xd9\xd3o\xf8/;? \x00\xc8\x85\x1b9\x0b\xc0\xf3C%\x00\xe8\xe3\x08 \x96\xaeu\xf2\x22\x8d\x1c\x0d\x19\xef\xcc \xe2\xbd\xe7\xea\xe9C\xb2K\x8d\xc5A\xe6\x02\xf0\xf1a\x13\x00\xf4y\x04\xd8f\x02\x1a2\xde\x19\x80Z[\xe0\xedg\x10\x8d\x11\x90\xbd\x00\xdc\xfb\xb6\xf9@B\xe3ZAX{\xff\xf3!\x7f\xfco\xe4TR\x06\xcd\xe7F\x00\x09\xf6\xf6\xac\xa9\x0b\xd6\x89Y b\x05\xd0\xb9I\x00hE\x95Q\x7f\x13\x945\x12\xfbX\xad`\x97\xbc{?\x81\xbb\x0bs\x8fL\x5c\xf0\xc4)k\xea\x82\xef\xbeS\xc6\x98\xde\xfb1\x84u\xf0(\xe8(\xe4G\x00A\xd6\xed3\x97!\xec0\x01`\x10\xe9\x8d%\xf5\xf4\xcb\xc0\x16\x90\xe7Z'^\xb1N\xbc\x0a\x98P\xce\xa4\x9e\xdal\x93=\xfa\x14V3\xc4H\xb0\xe7Z\xa7\xdf\xa4\xf2\x08X\xc7M\xa3\x08\xb4\x5c\x10\xefn\xa8\x95\xfb\xe4T\xd2k@\x9e\x9bq\xcc\xd1\x87\xc0\x1a\x80|\xfc\x19\xef\xae\xc3r\x9a\xf7\xc8\x17m\xcbN\xb5\x04c\x06\x09\xde{.\x97?\xa7\xf64\x10V\xce\xec\xbb\xfe\x07\x12\xc3lA/\xdf\xd5[O:#h\x12!7\x02\xb4\xa2\xf2\x88e\x9cI\xaf8\xdc\xa0\x97a\xce\xe0\x0c\x00\xe6\x1e}\xae7WZ\xdbd\xac\xa9T\xf3\xc3\xc2RM\x81\x18\xe6\xf4\x22\xcd\x1eI\x1b\xf2!\xc08\xdc\xa3g\xac\x13\xaf\xf8/;/k\xc2\xb0\x82q\xb8\xed\x02\x90\xe6\xb7q\xf3\x1e5\xa6\x9bM\x018\xf9ZZ\xe3$`\x22\xf8\x9a\xf1\x93\xe9\x90\x13\x01\x82\xa5k\x9fy\x93\xec2\xb4\xeet&~\x1c\xee\x8az\xfa\xb0\xe5\x22\x88X\xd6\xc5\xe4Y_\x00R\xdd\xa3F\x8c\x85\xe8\x12\x80\x92\xd9\x14J\xe3\xdc\x88w7\xd4\xf2\xe7\x99\x08\x00rtA\xcc\x8d\x15@x\x1c\xae\x5c\xba\xa3\xb7\xdb\xe3p\x87Q\x00\x90\x17\x01\xac\xa9T\xf5\x0f=\x22\x05\xe0\x1a\xb4\x0c\xbc;|\x02\x80\x5c\x08\xf0\x1d\xeeik\xea\x82\xff\xb2\xf3\x03aq\xb8C)\x00\xc8\x87\x00\xc1\x9e\xc9\xc4\xab\x868\x5c\xb3\x02\xd8^U+\xf7[[@\xc3*\x00\xc8\xcd\x05\xa9F\xd4MD\x22\xc6\xd2]\xbd\xbd:\xe4+\x00\x83\x1c\x08`\x0d\xa7j\xf7\xcc\xc4\xf3\x16\xae\x07\x1210\xa4\x02\x80\xec\x090\x99x\xe3\xd1\x99x\xbe\x00\x5co\x85\xa1cx\x05\x009\x10 X\xba\xf6\xf4\x1bT\x19\x0d\xcf\xc4#\xe2\xddu\xf5\xf3{\xe4\x94\xdb\x12\xc1\x86T\x00\x90\x8b\x0b\xd2\xd2\x8e\x14\x00\xe3\x22\xbe\x08\xb8\xd1!\x16\x00dO\x003\xecr\xb4\x00\xf8\xc1\x94\x9dntX\x05\x00\x19\x13@\x04U\x17G\xa6\xec\xe9\xd7\xcd\xeb\x90\x0ft\xb8\x08\x0c\xb5\x00 s\x02\xd8s\xad\xe9\xd7\xa96\x11\x91\x89'xoS\xfe\xfc\x8bb\x0b\xa8\x89l\x0fd\x08Z:\xcdD\x8c\xce\xaaW\x0c\x90\x5c\xb9\xa77WZ?# \x002\xf9\x19S\x0f\x01h\xe6\x01\xa4\x88\xb0\x03YF\x00\xa84\x92I0D\x13\x99\x8e\x00\x13w\x7f\xaew&\xdeux\xfb\x81\xf3Xfg\xf6}\x00\x00%\xff\xc7\x80\x91\xf7n\x010aa$R\xd8\x07\xf2\x11\x00d9\x02\xfc\xb8\xfb\xe3\xd6)\x93\x8a\x1d\x9d\x89\xd7~<\xa9\x15U\xc7\xac3o\x02`\xe5%\x8f\x97\xd2\x8aJU9\xf73\xc8:\xca#\xe0\xd6\x96\x948~\x9e\x95\x04\xa7\x99_i\x12\x967\xf7I`\xed\x92\x112tA\xc4\xd2\xb5O\xbe&F\x8fE\x0a\x80\xbb\xa3\x96?\x0f\x86\x812\xc8\xda\xfe\xc7?\xce\x22\x0aH\xf0\xce3\xaa\x8c\xb5Ja\x09\x9b\xf7\x9eo\xfe\xedw\xb2\xb8k\xac7W\xa9\x5c\xcd\xd6\xff \xf3\x11\xe0oAG\x08\x80Z\xb9\xaf6\x96\x03>\x1a\x04\xd6z}1\x9b6\x88`\xb89\x11{.\xaf-dc\xdc*%\x1fC\xd1\xc8\x8e\x00~Q&\x1eA>\xba\x01o\x0f\xa5jg,\x8d]\xce\xac\x0d\x1d \xca\xd1x\x16\xc8\x8a\x00\x82\x96b\xf4Xd&\x1e\x11\xcc<\xba+\x15;\xa3\x06D\xdc\xfd\xfc\x8cg\x84\x8c\x08 \xe2\xbak\xcf\x5c\x11G\xa6\x80\x88Tlo_u\x97T\xeb]\xc15N\x0bB\xc2\xe8r5\x9e\x112#\x00\xcak\xa4\xf5\xea\xd00,\xf5\xe4Ag:\x153\x9c2\x95j\x19\xf4/\xd6\xbc\xbf\xddyQ\xa7B\xa5jj\xe3\x04\xad\xd8\xdd~\xf1\x07\x13!;\x0d\x10\xe2E\x02\x10L\xa7\x12\x16\xef>\x1f\xfd\xed?/\xbf\xff\xadT\xe5X\xb5\xa2\xda\xb8{\xfd\x87\xdb\xff\xf4\xa7m\xb5\x16\x05\xbb[\xa3\xdf\xfen\xf9\xcao\xf2\xde\xf3t\xc6'\xf6\xaf\xfe\xf3\xce\xbf~\xd0\x9dB\x92\x092!\x80\xa0<\xaa\x1d\xb5\xcfDe\xe25kq\xb4\xb9&-\xa9:f\xbf\xf2>\x88\xa86\x9e*T\x96\x84Z\xba\xd3\xb6\x93J\xd0R\x8c\x1cuf\xdf\x83\x10T\x9bH.\x06Z\x81H-}v\xb85\x80\x88\xbd\xba}\xea\x92\x988m^\x06\xdff\x08\xc1\xb2\x1eH\xc56\xb9\x1b\xa7/Y\xc7\xce\x990\xa1\xe4\xbf\xb0\xb9Mf\xb7\x15\x1a\xaa\xbb\xf6\x99\xcbb|\xda\xdf\x02Jh\xdc$\x91Ko\xe1Fd\xa5\xeb\xd4\xc8\x86\x80@]\x87\xd08\xdc\xa7_\xea\xf5\xc7\xedq\xb8\x90\xae=s%l?\xe2o[\x91\xa4(\xc7j\x92\xc8\xd7\xe6\xf5\xb3\xee\x1c\xc2\xcc\x90\xd1^\x10\x89\x17\x14cZ\xbc\xc9\xfb\xdb\x81\x1bMdgP\x0aB\x03\x90\x8b\xb7\x03A\xbe\x00\x84\xb0g3*\x05\xf1\xe8\x06\xefm\xe57\x0b\xca\x82\x00%\xa96\xee\xd7v\x8e:\x85\x9f\xfb\xa4K\x00\x8e\xf8\xf5\x0bR\xcf\xd6\xbd\xb9\x8f\xdb\x82|\x09\xca\x13#\x93\xb6\xdf\x9e\xb4?\xb0\xb3\xe5Y#5\x01\xa6\x1e\xf7\xb1\xf3\x11\x99x\x0caAK\xf9\xb8-\x15\x9b\x04{u\xeb\xf8\xacu\xec|\xd8W\xe2\xc0\xcf\xf2\xb8\x11\x10\x00\xcf\xb5\xa6.\x88\x89S\xe6eR\xd3\xa6\xe5*$\x870S\xa4'\xc0\x08@\xefZ\x1c\xf3\xfa\xd9\xa3`\xb5\x06#\x00\x94\xae\x16\x10\x03\xd0\x1bK\xeaI\x84\x00\xa46\xaeV\xe7tH\x12y\x96\xc8\xc2\x05\x11\xbd\xa0\x18\xd3\xe2M\xde\xdf*\x04 \x14\xa9\x09\xd0\x8a*cv\xcf\xc2>r\xeeZ`\x08\x17\x02\xd0\x86tM\xf4\x05\xe0\x5c\xa47\x17\x16\x98\xe5\xe2\xadVE\x8bB\x00\x82HI\x00A\xd6\xad3o\x99\xe6v\xbe\xdb\xac\xd7\xb66ON\xa9\x10\x80P\xa4vA\xcc\xcelo\x01\xb8\xc5{\xcf\x03Y\x89\x85\x00\xb4!\x1d\x01&\xa4\xa7g*vg-\x8eB\x00\x82HU\xb2\x8ee]L\xceDg\xe2u\xd5\xe2(\x04\xa0\x0bi\x08\x10\x90\xae}\xfa2,'$\xa6\xd3\xf8\xe8g\x8b\x8dzm\x1d[@\x85\x00\xf8H7N[\x99x\xddo\x99T\xec\xdb\xbc\xb3\xd1JWG!\x00\x9dHA\x80\xd6T\xae\xf5\x8e\xe9\xf4\xe6\xaf\x05\x0f \x0b\x01\xe8D\xd2\x86\x9a8\xdc\x893\xd6TDLg\xb3bs[\x18z!\x00\xddHL\x80\x89{\xfd\x0a9\x95\xf0L<@?_\xd6\xc1T\xecB\x00\xba\x91\xe2@\xa6=\x13\xaf\xf3\x10L\x83,\xf98\xf8L\xbc\x0aw\x87\xa5\xdb\x1fOzh@T\x19\x8b5\x07K\xe0\x82\x08Z6*Kv\x09\x80\x81\x92\x95_\xfb\xddX\xcf\xb6\x7f\x19@\x04\xaf\xee\xfe\xec{\x5c\xdf=\xf8:?>\x01~&\xde;\x91\x8d\x00\xc4\xc4\xa9\xda7\xff$\xb6\xe5_h\x98J\xcc+\xf7\xf7\xff\xf7\x1fb\xed\xb2\xc4$\xa0\x99\x897\xdd\xfb\x098\x9co\xed\xf3C\x08S*\xf6\xc1Oy\xef9\x8dL\x1e\x5c\x09\xe2\x8e\x00\x93\x89wQ\x8c\xf6~\x02N\x8e\x19\x0d\x87\x14~\x0e\xe8\xf5\xae\xe4\xb8\x17 \xe6\x1c\x85z?\x14uhaR\x80\x5c\xb9t\xbb\x15~p0\xc4$\x80\x19\x96\x13y\x083\xb40{\xa8\xcbw\xf5\xb3\xc5\xb8\x8f\x94\x89E\x00A\xf5\xcc\xc4\x1bZ0\x03\xa8\xdf\xfd\x11\xbb1\xe6?\x06q>\xddz(\xea\x89\xb0L\xbc!F\xb3\x0c\x98\x1d;\x95>\x8e\x08\x13A\xd5\xed\x99\xb7\x01@\xa5\xc8\xaax\xc9\xc0\x0c!\xf4\xd6\xaaZ\xf9\x82\xecr\xdc\xa5O\xacY\x10C\xd8\xf6+\xef\x01\x00Q1\x02|\x98\x00\xc0\xe5\xbbzk\xb5s\xf3\xf1\x0088\x01\xe6\x99xG\xad\xc9\xb3\x5c\xdf\xcb\xa3n\xc8/*\xb4\xa2\x91\xa3\xde\x83\xabP2d\xf3\xf1E\xa0\xb5\x0f\x0e>\xa5a\x90E\x95\xb1\xe1\xda`8\x08\x88x\x7f;\xd9s\xf9b\xb9 \x02+\xdeY\x8b{\x8d\xa1\x80\xb0\x92\x9db\xc6^\x09\xc3r\x12\x5c\xe6\xe5G\xd2M\xdfD\x9bq\x05\xb2C\xb1\x98\x1a0\x0a\x02\x06\x8c\x82\x80\x01\xa3 `\xc0(\x08\x180\x0a\x02\x06\x8c\x82\x80\x01\xa3 `\xc0(\x08\x180\x0a\x02\x06\x8c\x82\x80\x01\xa3 `\xc0\xf8\x7f\xfeK\x92\xab\xc78\x7f\x04\x00\x00\x00\x00IEND\xaeB`\x82" qt_resource_name = b"\x00\x0f\x075\xf3?\x00L\x00i\x00p\x00i\x00d\x00H\x00u\x00n\x00t\x00e\x00r\x00.\x00i\x00c\x00o\x00\x0f\x075\xeb\xe7\x00L\x00i\x00p\x00i\x00d\x00H\x00u\x00n\x00t\x00e\x00r\x00.\x00p\x00n\x00g" qt_resource_struct = b"\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x01\x00\x00\x00$\x00\x00\x00\x00\x00\x01\x00\x00\xc9\x1a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00" + + def qInitResources(): - QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + QtCore.qRegisterResourceData( + 0x01, qt_resource_struct, qt_resource_name, qt_resource_data + ) + def qCleanupResources(): - QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data) + QtCore.qUnregisterResourceData( + 0x01, qt_resource_struct, qt_resource_name, qt_resource_data + ) + qInitResources() diff --git a/LibLipidHunter/LipidNomenclature.py b/LibLipidHunter/LipidNomenclature.py index 5150791..1a387e0 100644 --- a/LibLipidHunter/LipidNomenclature.py +++ b/LibLipidHunter/LipidNomenclature.py @@ -21,44 +21,56 @@ class NameParserFA: - def __init__(self): - self.elem_dct = {'H': [1.0078250321, 0.999885], - 'D': [2.0141017780, 0.0001157], - 'C': [12.0, 0.9893], - 'N': [14.0030740052, 0.99632], - 'O': [15.9949146221, 0.99757], - 'Na': [22.98976967, 1.0], - 'P': [30.97376151, 1.0], - 'S': [31.97207069, 0.9493], - 'K': [38.9637069, 0.932581]} - - self.fa_rgx = re.compile(r'(FA)(\d{1,2})(:)(\d)') - self.o_rgx = re.compile(r'(O-)(\d{1,2})(:)(\d)') - self.p_rgx = re.compile(r'(P-)(\d{1,2})(:)(\d)') + self.elem_dct = { + "H": [1.0078250321, 0.999885], + "D": [2.0141017780, 0.0001157], + "C": [12.0, 0.9893], + "N": [14.0030740052, 0.99632], + "O": [15.9949146221, 0.99757], + "Na": [22.98976967, 1.0], + "P": [30.97376151, 1.0], + "S": [31.97207069, 0.9493], + "K": [38.9637069, 0.932581], + } + + self.fa_rgx = re.compile(r"(FA)(\d{1,2})(:)(\d)") + self.o_rgx = re.compile(r"(O-)(\d{1,2})(:)(\d)") + self.p_rgx = re.compile(r"(P-)(\d{1,2})(:)(\d)") self.fa_rgx_lst = [self.fa_rgx, self.o_rgx, self.p_rgx] def calc_fa_mass(self, fa_info_dct): - exactmass = (fa_info_dct['C'] * self.elem_dct['C'][0] + fa_info_dct['H'] * self.elem_dct['H'][0] + - fa_info_dct['O'] * self.elem_dct['O'][0]) + exactmass = ( + fa_info_dct["C"] * self.elem_dct["C"][0] + + fa_info_dct["H"] * self.elem_dct["H"][0] + + fa_info_dct["O"] * self.elem_dct["O"][0] + ) return round(exactmass, 6) def calc_fa_all_mz(self, fa_info_dct): exactmass = self.calc_fa_mass(fa_info_dct) - fa_info_dct['EXACTMASS'] = exactmass - fa_info_dct['[FA-H]-_MZ'] = round(exactmass - self.elem_dct['H'][0], 6) - fa_info_dct['[FA-H2O-H]-_MZ'] = round(exactmass - 3 * self.elem_dct['H'][0] - self.elem_dct['O'][0], 6) - fa_info_dct['[FA-H2O]_MZ'] = round(exactmass - 2 * self.elem_dct['H'][0] - self.elem_dct['O'][0], 6) - fa_info_dct['[FA-H2O+H]+_MZ'] = round(exactmass - self.elem_dct['H'][0] - self.elem_dct['O'][0], 6) - fa_info_dct['[FA-H+Na]_MZ'] = round(exactmass - self.elem_dct['H'][0] + self.elem_dct['Na'][0], 6) - - fa_info_dct['[FA-H]-_ABBR'] = '[{fa}-H]-'.format(fa=fa_info_dct['ABBR']) - fa_info_dct['[FA-H2O-H]-_ABBR'] = '[{fa}-H2O-H]-'.format(fa=fa_info_dct['ABBR']) - fa_info_dct['[FA-H2O]_ABBR'] = '[{fa}-H2O]'.format(fa=fa_info_dct['ABBR']) - fa_info_dct['[FA-H2O+H]+_ABBR'] = '[{fa}-H2O+H]+'.format(fa=fa_info_dct['ABBR']) - fa_info_dct['[FA-H+Na]_ABBR'] = '[{fa}-H+Na]'.format(fa=fa_info_dct['ABBR']) + fa_info_dct["EXACTMASS"] = exactmass + fa_info_dct["[FA-H]-_MZ"] = round(exactmass - self.elem_dct["H"][0], 6) + fa_info_dct["[FA-H2O-H]-_MZ"] = round( + exactmass - 3 * self.elem_dct["H"][0] - self.elem_dct["O"][0], 6 + ) + fa_info_dct["[FA-H2O]_MZ"] = round( + exactmass - 2 * self.elem_dct["H"][0] - self.elem_dct["O"][0], 6 + ) + fa_info_dct["[FA-H2O+H]+_MZ"] = round( + exactmass - self.elem_dct["H"][0] - self.elem_dct["O"][0], 6 + ) + fa_info_dct["[FA-H+Na]_MZ"] = round( + exactmass - self.elem_dct["H"][0] + self.elem_dct["Na"][0], 6 + ) + + fa_info_dct["[FA-H]-_ABBR"] = "[{fa}-H]-".format(fa=fa_info_dct["ABBR"]) + fa_info_dct["[FA-H2O-H]-_ABBR"] = "[{fa}-H2O-H]-".format(fa=fa_info_dct["ABBR"]) + fa_info_dct["[FA-H2O]_ABBR"] = "[{fa}-H2O]".format(fa=fa_info_dct["ABBR"]) + fa_info_dct["[FA-H2O+H]+_ABBR"] = "[{fa}-H2O+H]+".format(fa=fa_info_dct["ABBR"]) + fa_info_dct["[FA-H+Na]_ABBR"] = "[{fa}-H+Na]".format(fa=fa_info_dct["ABBR"]) return fa_info_dct @@ -78,31 +90,36 @@ def get_fa_formula(self, fa_str): fa_info_dct = {} fa_info_lst = self.decode_fa(fa_str) - if fa_info_lst[0] == 'FA': - fa_info_dct['ABBR'] = fa_str - fa_info_dct['LINK'] = 'FA' - fa_info_dct['C'] = int(fa_info_lst[1]) - fa_info_dct['H'] = 2 * int(fa_info_lst[1]) - 2 * int(fa_info_lst[3]) - fa_info_dct['O'] = 2 - fa_info_dct['DB'] = int(fa_info_lst[3]) - fa_info_dct['FORMULA'] = 'C{num_c}H{num_h}O{num_o}'.format(num_c=fa_info_dct['C'], num_h=fa_info_dct['H'], - num_o=fa_info_dct['O']) - elif fa_info_lst[0] == 'O-': - fa_info_dct['ABBR'] = fa_str - fa_info_dct['LINK'] = 'O-' - fa_info_dct['C'] = int(fa_info_lst[1]) - fa_info_dct['H'] = 2 * int(fa_info_lst[1]) + 2 - 2 * int(fa_info_lst[3]) - fa_info_dct['O'] = 1 - fa_info_dct['DB'] = int(fa_info_lst[3]) - fa_info_dct['FORMULA'] = 'C{num_c}H{num_h}O'.format(num_c=fa_info_dct['C'], num_h=fa_info_dct['H']) - elif fa_info_lst[0] == 'P-': - fa_info_dct['ABBR'] = fa_str - fa_info_dct['LINK'] = 'P-' - fa_info_dct['C'] = int(fa_info_lst[1]) - fa_info_dct['H'] = 2 * int(fa_info_lst[1]) - 2 * int(fa_info_lst[3]) - fa_info_dct['O'] = 1 - fa_info_dct['DB'] = int(fa_info_lst[3]) - fa_info_dct['FORMULA'] = 'C{num_c}H{num_h}O'.format(num_c=fa_info_dct['C'], num_h=fa_info_dct['H']) + if fa_info_lst[0] == "FA": + fa_info_dct["ABBR"] = fa_str + fa_info_dct["LINK"] = "FA" + fa_info_dct["C"] = int(fa_info_lst[1]) + fa_info_dct["H"] = 2 * int(fa_info_lst[1]) - 2 * int(fa_info_lst[3]) + fa_info_dct["O"] = 2 + fa_info_dct["DB"] = int(fa_info_lst[3]) + fa_info_dct["FORMULA"] = "C{num_c}H{num_h}O{num_o}".format( + num_c=fa_info_dct["C"], num_h=fa_info_dct["H"], num_o=fa_info_dct["O"] + ) + elif fa_info_lst[0] == "O-": + fa_info_dct["ABBR"] = fa_str + fa_info_dct["LINK"] = "O-" + fa_info_dct["C"] = int(fa_info_lst[1]) + fa_info_dct["H"] = 2 * int(fa_info_lst[1]) + 2 - 2 * int(fa_info_lst[3]) + fa_info_dct["O"] = 1 + fa_info_dct["DB"] = int(fa_info_lst[3]) + fa_info_dct["FORMULA"] = "C{num_c}H{num_h}O".format( + num_c=fa_info_dct["C"], num_h=fa_info_dct["H"] + ) + elif fa_info_lst[0] == "P-": + fa_info_dct["ABBR"] = fa_str + fa_info_dct["LINK"] = "P-" + fa_info_dct["C"] = int(fa_info_lst[1]) + fa_info_dct["H"] = 2 * int(fa_info_lst[1]) - 2 * int(fa_info_lst[3]) + fa_info_dct["O"] = 1 + fa_info_dct["DB"] = int(fa_info_lst[3]) + fa_info_dct["FORMULA"] = "C{num_c}H{num_h}O".format( + num_c=fa_info_dct["C"], num_h=fa_info_dct["H"] + ) return fa_info_dct @@ -114,7 +131,7 @@ def get_fa_info(self, fa_str): return fa_info_dct -if __name__ == '__main__': +if __name__ == "__main__": from test.test_LipidNomenclature import test_get_fa_info diff --git a/LibLipidHunter/LogPageCreator.py b/LibLipidHunter/LogPageCreator.py index 1ae6bb9..49a29fe 100644 --- a/LibLipidHunter/LogPageCreator.py +++ b/LibLipidHunter/LogPageCreator.py @@ -28,42 +28,70 @@ class LogPageCreator(object): def __init__(self, output_folder, start_time, params): # print(os.getcwd()) self.output_folder = output_folder - self.output_img_folder = output_folder + r'/LipidHunter_Results_Figures_%s' % start_time - self.main_page = output_folder + r'/LipidHunter_Results_%s.html' % start_time - self.logo = r'LipidHunter_Results_Figures_%s/LipidHunter.ico' % start_time - _image_lst_page = r'LipidHunter_Results_Figures_%s/LipidHunter_Results_Figures_list.html' % start_time - _params_lst_page = r'LipidHunter_Results_Figures_%s/LipidHunter_Params_list.html' % start_time - _idx_lst_page = r'LipidHunter_Results_Figures_%s/LipidHunter_Identification_list.html' % start_time - self.image_lst_page = self.output_img_folder + r'/LipidHunter_Results_Figures_list.html' - self.params_lst_page = self.output_img_folder + r'/LipidHunter_Params_list.html' - self.idx_lst_page = self.output_img_folder + r'/LipidHunter_Identification_list.html' - self.cfg_sum_page = self.output_img_folder + r'/LipidHunter_Configuration_Summary.html' + self.output_img_folder = ( + output_folder + r"/LipidHunter_Results_Figures_%s" % start_time + ) + self.main_page = output_folder + r"/LipidHunter_Results_%s.html" % start_time + self.logo = r"LipidHunter_Results_Figures_%s/LipidHunter.ico" % start_time + _image_lst_page = ( + r"LipidHunter_Results_Figures_%s/LipidHunter_Results_Figures_list.html" + % start_time + ) + _params_lst_page = ( + r"LipidHunter_Results_Figures_%s/LipidHunter_Params_list.html" % start_time + ) + _idx_lst_page = ( + r"LipidHunter_Results_Figures_%s/LipidHunter_Identification_list.html" + % start_time + ) + self.image_lst_page = ( + self.output_img_folder + r"/LipidHunter_Results_Figures_list.html" + ) + self.params_lst_page = self.output_img_folder + r"/LipidHunter_Params_list.html" + self.idx_lst_page = ( + self.output_img_folder + r"/LipidHunter_Identification_list.html" + ) + self.cfg_sum_page = ( + self.output_img_folder + r"/LipidHunter_Configuration_Summary.html" + ) - self.lipid_class = params['lipid_class'] - hunter_folder = params['hunter_folder'] + self.lipid_class = params["lipid_class"] + hunter_folder = params["hunter_folder"] - if params['rank_score'] is True: - score_mode = '' + if params["rank_score"] is True: + score_mode = "" else: - score_mode = '(Intensity mode)' + score_mode = "(Intensity mode)" - if params['fast_isotope'] is True: - isotope_score_mode = '(Fast mode)' + if params["fast_isotope"] is True: + isotope_score_mode = "(Fast mode)" else: - isotope_score_mode = '' + isotope_score_mode = "" - with open(self.main_page, 'w') as _m_page: + with open(self.main_page, "w") as _m_page: # Merge sub pages into one report page, set _params_lst_page width 345, height 345 - m_info_lst = ['\n', '\nLipidHunter_Results ', start_time, - '\n\n\n', - '\n', - '\n\n', - '\n\n\n'] - _m_page.write(''.join(m_info_lst)) + m_info_lst = [ + "\n", + '\nLipidHunter_Results ', + start_time, + '\n\n\n', + '\n', + '\n\n', + '\n\n\n', + ] + _m_page.write("".join(m_info_lst)) - with open(self.image_lst_page, 'w') as _img_page: - _img_page.write(''' + with open(self.image_lst_page, "w") as _img_page: + _img_page.write( + """ \n\n\n''') + a:visited {text-decoration:none; color:black;}\n\n""" + ) - with open(self.cfg_sum_page, 'w') as _cfg_page: + with open(self.cfg_sum_page, "w") as _cfg_page: - cfg_sum_dct = {'fawhitelist_path_str': 'FA white list:', - 'mzml_path_str': 'mzML file used:', - 'img_output_folder_str': 'Output images saved in folder:', - 'xlsx_output_path_str': 'Summary Output table saved as:', - 'lipid_specific_cfg': 'PL specific ions defined in:', - 'score_cfg': 'Weight factor defined in:', - 'hunter_start_time': 'Run start from:', - 'vendor': 'Instrument vendor:', 'experiment_mode': 'Experiment type:', - 'lipid_class': 'Lipid class:', 'charge_mode': 'Precursor charge mode:', - 'rt_start': 'RT start:', 'rt_end': 'RT end:', - 'mz_start': r'm/z start:', 'mz_end': r'm/z end:', 'score_filter': 'Score >=', - 'rank_score': 'Rank score mode:', 'rank_score_filter': 'Rank score >=', - 'isotope_score_filter': 'Isotope score >=', 'fast_isotope': 'Fast Isotope score mode:', - 'ms_th': 'Threshold @ MS level =', 'ms_ppm': 'ppm @ MS level <=', - 'ms_max': 'For precursor intensity <=', 'pr_window': 'Precursor selection window +/-', - 'dda_top': 'DDA Top =', 'ms2_th': 'Threshold @ MS/MS level =', - 'ms2_ppm': 'ppm @ MS/MS level <=', 'ms2_infopeak_threshold': 'Consider MS/MS with i (%) >=', - 'hg_th': 'For PL specific peaks Consider MS/MS with i (abs) >=', - 'hg_ppm': 'For PL specific peaks Consider MS/MS ppm <=', - 'ms2_hginfopeak_threshold': 'For PL specific peaks Consider MS/MS with i (%) >=', - 'hunter_folder': 'LipidHunter program folder', - 'core_number': 'Run with max CPU core number =', - 'max_ram': 'Run with max RAM (GB) =', - 'img_type': 'Save image format:', 'img_dpi': 'Save image with dpi =', - 'tag_all_sn': 'Prefer all sn identified for TAGs:'} + cfg_sum_dct = { + "fawhitelist_path_str": "FA white list:", + "mzml_path_str": "mzML file used:", + "img_output_folder_str": "Output images saved in folder:", + "xlsx_output_path_str": "Summary Output table saved as:", + "lipid_specific_cfg": "PL specific ions defined in:", + "score_cfg": "Weight factor defined in:", + "hunter_start_time": "Run start from:", + "vendor": "Instrument vendor:", + "experiment_mode": "Experiment type:", + "lipid_class": "Lipid class:", + "charge_mode": "Precursor charge mode:", + "rt_start": "RT start:", + "rt_end": "RT end:", + "mz_start": r"m/z start:", + "mz_end": r"m/z end:", + "score_filter": "Score >=", + "rank_score": "Rank score mode:", + "rank_score_filter": "Rank score >=", + "isotope_score_filter": "Isotope score >=", + "fast_isotope": "Fast Isotope score mode:", + "ms_th": "Threshold @ MS level =", + "ms_ppm": "ppm @ MS level <=", + "ms_max": "For precursor intensity <=", + "pr_window": "Precursor selection window +/-", + "dda_top": "DDA Top =", + "ms2_th": "Threshold @ MS/MS level =", + "ms2_ppm": "ppm @ MS/MS level <=", + "ms2_infopeak_threshold": "Consider MS/MS with i (%) >=", + "hg_th": "For PL specific peaks Consider MS/MS with i (abs) >=", + "hg_ppm": "For PL specific peaks Consider MS/MS ppm <=", + "ms2_hginfopeak_threshold": "For PL specific peaks Consider MS/MS with i (%) >=", + "hunter_folder": "LipidHunter program folder", + "core_number": "Run with max CPU core number =", + "max_ram": "Run with max RAM (GB) =", + "img_type": "Save image format:", + "img_dpi": "Save image with dpi =", + "tag_all_sn": "Prefer all sn identified for TAGs:", + } - cfg_sum_lst = ['lipid_class', 'charge_mode', 'vendor', 'experiment_mode', 'hunter_start_time', - 'img_output_folder_str', 'xlsx_output_path_str', - 'mzml_path_str', 'fawhitelist_path_str', 'lipid_specific_cfg', 'score_cfg', - 'rt_start', 'rt_end', 'mz_start', 'mz_end', 'dda_top', - 'hunter_folder', 'isotope_score_filter', 'fast_isotope', - 'score_filter', 'rank_score', 'rank_score_filter', - 'ms_ppm', 'ms_th', 'pr_window', - 'ms2_ppm', 'ms2_th', 'ms2_infopeak_threshold', - 'hg_ppm', 'hg_th', 'ms2_hginfopeak_threshold', - 'core_number', 'max_ram', 'img_type', 'img_dpi', 'ms_max', 'tag_all_sn'] + cfg_sum_lst = [ + "lipid_class", + "charge_mode", + "vendor", + "experiment_mode", + "hunter_start_time", + "img_output_folder_str", + "xlsx_output_path_str", + "mzml_path_str", + "fawhitelist_path_str", + "lipid_specific_cfg", + "score_cfg", + "rt_start", + "rt_end", + "mz_start", + "mz_end", + "dda_top", + "hunter_folder", + "isotope_score_filter", + "fast_isotope", + "score_filter", + "rank_score", + "rank_score_filter", + "ms_ppm", + "ms_th", + "pr_window", + "ms2_ppm", + "ms2_th", + "ms2_infopeak_threshold", + "hg_ppm", + "hg_th", + "ms2_hginfopeak_threshold", + "core_number", + "max_ram", + "img_type", + "img_dpi", + "ms_max", + "tag_all_sn", + ] param_key_lst = list(params.keys()) disp_cfg_lst = [] for _key in cfg_sum_lst: if _key in param_key_lst: - disp_cfg_lst.append('
  • {k} {v}
  • \n'. - format(k=cfg_sum_dct[_key], v=params[_key])) + disp_cfg_lst.append( + "
  • {k} {v}
  • \n".format( + k=cfg_sum_dct[_key], v=params[_key] + ) + ) - params_li_str = ''.join(disp_cfg_lst) + params_li_str = "".join(disp_cfg_lst) - cfg_template = ''' + cfg_template = """