From d336196e24e7fe3ee3604a11a90489cdf6b42083 Mon Sep 17 00:00:00 2001 From: Dan Howe Date: Fri, 19 Jul 2019 16:29:42 +1000 Subject: [PATCH] Remove modules --- wafo/SpecData1D.mm | 69 -- wafo/autumn.gif | Bin 245819 -> 0 bytes wafo/bitwise.py | 97 --- wafo/conftest.py | 3 - wafo/definitions.py | 310 ------- wafo/demos.py | 146 ---- wafo/f2py_tools.py | 65 -- wafo/fig.py | 908 -------------------- wafo/gaussian.py | 1040 ----------------------- wafo/integrate.py | 1476 --------------------------------- wafo/integrate_oscillating.py | 538 ------------ wafo/padua.py | 532 ------------ wafo/setup.py | 18 - wafo/wavemodels.py | 268 ------ wafo/win32_utils.py | 258 ------ 15 files changed, 5728 deletions(-) delete mode 100644 wafo/SpecData1D.mm delete mode 100644 wafo/autumn.gif delete mode 100644 wafo/bitwise.py delete mode 100644 wafo/conftest.py delete mode 100644 wafo/definitions.py delete mode 100644 wafo/demos.py delete mode 100644 wafo/f2py_tools.py delete mode 100644 wafo/fig.py delete mode 100644 wafo/gaussian.py delete mode 100644 wafo/integrate.py delete mode 100644 wafo/integrate_oscillating.py delete mode 100644 wafo/padua.py delete mode 100644 wafo/setup.py delete mode 100644 wafo/wavemodels.py delete mode 100644 wafo/win32_utils.py diff --git a/wafo/SpecData1D.mm b/wafo/SpecData1D.mm deleted file mode 100644 index f70b0c8..0000000 --- a/wafo/SpecData1D.mm +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/wafo/autumn.gif b/wafo/autumn.gif deleted file mode 100644 index fa351ddeaba9578d6953011cc5049088914ff450..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 245819 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%0Adz98tBYM;* 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%0Dar-)jq#MJhZMJ+6m?uy{mGq0Lv1l9SU* zo&0rhZJc0X&@y!Oc%P(?5KJuWa}$5G5d33BIk-7`qBXb7>l41xn2|$WX*OozyPP;5-Av6% zO4c+7t*f++#tEzsGJQoy`4n4>3N6Po)8sj@#<7Q-=p%vsi6X21B}#O0xm;jc%$ zOd~4YsucW~+FhU7#|myow%uEC%&6aRKCZpCM42LbyVbbHK{*n1lXf*_F=wKzd2ydf z=N>EQY;iswy0>qkFPjVDd|N9^HuAb#UQ;vKmcH+V*Ndg|L)(r8h1s zpRtlAHMu6jHufaH)rEI$2rHsxYb(i#Zw66B{%@hny{Y?ujr-D9G4u<5 zla_kjqcFR(H)zq7T!7e~SE!fJN7c(yc66yLy}YR{WzJz;ys`qn<|pyQK!q{Ukx1w$ z=XbWQs!i1WuC+2G)YXn%i<_$2^m@9ne9=iquaVcOgDqnBwM`ZfclyZ3a%gS$pvKvc zK`jGzbahM?iq18|9&6uDNujjaD_a#uMtPsT3KapUMcX#;VeZixIi4sKJbC2C&P(mv z6mQ&|=mE=e%IBblsx%pwZdF{tFPlbG>PUsS2fLA#-G^VCZ8^wY99VCxcJ#UT&ADFJ zE)c3hJA$>mu>h=-2&UidmVTP|3wCKX&-r8)NErWHBjLBXNCG8?F698B@J3?yg%vxb z&&$SVxIn6GuzFU{jdI|l`zIfeicGX9js)NTUX72=E8|WAw32?SNv?$$S{=^tLiHJk z>zfgAHo>*-Yk{v6KulFG!vO2Mgf$%ZXB_7&8~Cp1 z8_46i(WT1NOMNwn3YL#9C{Z}(VjTQDoqYk^sR2&j_dp53mG{O}t}eU#@~Lwca zbTZRjNyN}VN15FnJs}8|F8&<9+B+dDNI7jL^KNBTUV0l8Bg|#2%u@L^O(t=x)KpBK zm0Xk{UhG1kWl>;~)_#)6RImD6h^kg<@lvI;+)+kSJuWO44ImDD2ljz6-ORn`fzz5xv?RAKSMKl4KRQL8C{cJ9nmGgbBn8l{VK<@73w2+L(@H{csM)QbRUBg0ffQ{anKn~Nq{mAivF%o(6@IHSbT#Z zq{IbXQXbW0UMgZ40bg*@R5b3pXF|X-sr^S3y7Na_#rv*`*Ig8QwZSgyH5Fou#oG`{U!qf`vj+QdTf-0K|L^Q_ac}j+deaC92;`r@0YaNM zUbaN=%80htq5LydsB|TO+dA9p`5)lxJpjXNiU>SmjfNYi#_1+d0qLoy&l!s6No{ei z8Hk2k^C$k+S}^#d5}i@y$cU=9c%E3JF_rSmp0u=^v^Bcs2mCY zOi(>}-2C+j9E?M0R}YMsPILaTV4)wNcB1gqj_Bl-k-}WB%ZO8*`%rc0z0Id<^{Z;; z=ax8EmbK1ZtYeFtIf0Aq7x9m``M4;J#5DyPuv$?Lo2|>g7@UIF>oHEv92{_4kBdP8ALL@a@ExEl?lb z?D7x~xtj2Oq;K3?zI?_39J5Q@fk6VJOS1CKMV+GQyptQ>jF~%rjmPOgMZemO6WW4a zR14MnsyNJT%~f~GPFF|D;Lb$D*X&Cith=Ek1Q+{_mnv^x(W0hoDEFcg zK_B>^HXvC{D*qBQLgtkj5ehc%b9JKS>;yg)5n1rtAEiCrcBn!nDhL5Fx)0`9>}P?O{H2x)T3>(73F zDyrI0w+LW<{B_^rfico?+c99f%s+|~jC&Fa^k%e+~nb;}YXgad059(4t{8^x7zQiY;v}@eW z|IF`%%%*x5u}hAXJPVSD7Kd`?1t)qwyFa79OEEn1f_Yj>Ni_UHe zAEpk;H%j*Y)99CJb*qx_!5d7X*n9gBI)`504j+T7jjzlt#-u!aTx%4Ds*nI^D~ouI zDl;3p5o(S^;J1PyaWwg@O1XA}D!6&06x1X>`b08|qZ;~mMf}Q4Uj=5l1dGH!r;Ew?D$s7_D>Zl>Y`J3L zD;>-u%&3DI%48z3QG8aqk^-moNse%cS_J@HOL=9NII$|=52q-z4__vWi7Z`>Li~@y zQV(O2vZ_DPKg6>T#X#LQC1LMe@=X@TOd7oVp5=HEXA~wjMI$I|9_R|-v8`4j+8i@$ z`F7m=(zJTjCg$08MsO1umkp-2X`;_ST$yyoG`z@$EK-_xJz7SkI9|KJ4SWQ=x;nV3 zNoupK?2_bCt*k0>c9i*d?Xs1_h)a9*2N^(woBSpv!TR2HoW6s%)laBquh?F%>2a@D zR$;oB_#n|QdvgeDog?`J=UT!)T#64X$-&8zCo_wrTDd~p`D6il{!AjW%|Ruj{o z5MeN8z|4ciKd!crCe{JFQAgVHh;}hiuqo$i5)?rTDz+VH9mV(MPFDfJlZcBsH&aN% z$yKa5%IGU9= zqcrvB#NmYN(r>D^*A!4B=_BUm9J6B(Lc^o1<1kg%TEH^P9~=eIFwtg~Gb~)o zDuBIwom`yJBxX)LeTf&B&U$1scnnGS$C>&0$W2vK&8 z7ttHzIFrt|)7-JIVDgKrDEh43r`0WmmB(g{`*D8t8-~LNLELbBz$_fVP%-Nq1{1gm zZ+6$g-pT1{5mi0|4hKd2bi!q%rq^#!956R%A>}9kDrRq+26p@=jphG5uCEHow|cdz zSKj&m65*LO9tW+gd@&P`u%;1WUR}~h=2OhI0@G@89k4uI#gqZh{g6+eNNFbK-+hRG zKICLGCsmvv4gldcb5I0|T-+NZbs_Xw7z3-*lVENuYLQ$;?UDGjn2D?cjzSF7flM2Z zY=$|+4Iad0$y>{yc3K}(_1Vzx2VbnF;Z>D=@noQ!YVAMQrwYk73piGng^raVpSUc! z2H$weozRk>dVZlTn|-{uPg2xn zo;)Ka8)4Tj%cMaZI}3u39%L|S(^X*R9&6=~gqee4t})kuUbcT&eqj62BTbd{*W9Y` z;M~yjYPsU;S%h*h*-4qa{hjI+!x~tX=v^hDnk0Kpx_5~zOreU^b)yEI``F<C>dXw0N8~&3lg7F>L&eO9JadDEiH>(L zvi`7Y_3`7|vb7&=cc${=0UPqpf;-V;_Jgf{$rF4QT=EaCp#8AN#Z)MQTu8(Q&0UD6 zrmN`eqh3lg`SAi|z`8IA!;k@QssP6?U)XSiIh@MaCiUh^)&BxNT|@8vhqNK=9({Wf zvl}4FN`j^>K}x_?3jR)!-rJt%-De>wKzhDv`z-vDw=RW(?%5z=?v7hDDBd}Nc>UBH z`;R-Nl}4nDv$Dk-o`I4{7eeuqU+VjAi7hc#;{w`G`bfo}FvI}SHtUb>HDvbi8lLPw z@Eh{*P~ePl{cYTd=K=l#{7)v-!92$i{X@_ATM4_50eHqc{W5Q@ z*c~Yd=(b+%GJ2Up-r;eb!j+%yc4~YE2qssR5yV^IPie`V4}anP?Pfx3{L0-bmvO{p zx7Z-BJ>0p|nn`o`20t`xoW{R*O6pP|KE>NFAG{xV(fWO! zxWNLPm#%7NZ~v}QX8NNhig8Vw*6LFRQtaH*Z z5E(lagM4-4nln9pqxAN%4|C1I&(6gCvRWLT4}}}Frdc0Xw3?;xRs?>@Vw60k76oTp ztXAZA`7=_wWpSgf(N_J#Rta0b&%5pzF{1Znl{v_2jbniG1`*;w<TZCF^Q80{PEafdEl1zqw?U#vNGH>Wu4#_@ZkEpVgbRO}G8Z0qHVwCjO5X zyV9pA|4!Z9n4?;e1ID>no)O#&db(bOZJiq#a`>%;j~;Q(i2HcDYx_`OY-NHu(V+dy z^BPN#??&npf$c%TgO1&>^NjK#a;c4{8=|25gOm=1J|wCg-X*%WE93Rny*H_kpOV|v zK3DJYDD2=l1&2DjNAE6kW4|MtH1)>c=O)peqEd>;p|4vFKh__cyvJ_`LJTKMbxuDp zp`(0&-t|2+=}k97u7)e8EtIkAqxv0>7plI=S;P7v^9B>fy1hq=LM|OqSeQ+_Yij=c zR%E$(uvG0mf{I*5{jkn9slV_`wBVqM!xjVG=C0y?+A{#~7>aI2zHi*y^P3j6@@1a5 zQT_^$Vy*OHaQELptUK^00SS(sBJcKS{1WF-JUg?s8y|eOQT9@rj`l@RzI+7eb`n+n z5RX?8Cq5wuR?@59SKqtaT~hWe-|34;&l6D>g2S5I`g)66pA<9Hlwp|4hsgp7WA1AI z!#p>N5*0EG7k5iP+K@BX|0ssaP*v`FklzvQQ;zEmDhb0)V^S^ z%g=IC+UHW&K6{?WvC~Yu81?Y_tv#wm#VGzyn$Krdx1R&gnu4*hs1fGUl-k@N9q1$# zGxI_25%KRxA?H`}DPp|5`}zmr&yYLvyTY8bbJyqn4;&4NuI%f6-M14m1WtWY-_NgU z-7HHApuhW4ZhC3Ub0SVNEtl0DBtVN=yf`9o($xmSchs>EC)=(V!ohi%J`qPu8=2?*WsPGhrhZrrVBha6vTRpvAxf|4dikhPE0J_pBD^2aTx`$xFJ z8JygaKPHCGWkII*9W)d*IbAz!M%wgVs3ILDu{JN>(?3hNsc3 zRc_`Jk#bwhl2iNh{Fm`>9f^NMc_*tqf0(?K=*)ZxZo-z`lL(zc>X4z<)b50+tQ^g= z_yFuHKI|tG7mH2R#L&z+kNO#eO5+u^3a%6DF`Ib`;x3`PPB8O_}?G zl1oJ`csI^XZrPIItUPJ}TDY9Y9% zt0dKxTARdCJ*Fen6l>p6Wl>}Ke$~NEqUF{6+00SeQmrz#6@5k&2f7&W{L0Hytg$bb z#{S(~&h1o&IkKI4(u&tDx5B)Y{va+zIbtrkBl;S)U_B4mAj}1Z1jGilDka#xJ%$pX zNTTj5r)EBCE(@+ONWBssfMqp{N>oHm)_8Y|J~d1N-VNE#;)2u(v$YnErfwuG?U{hW z`Zwn#lzI_a%`VhH`$r zxwrsPm=TR*n*j}sP6V)XPJOyKdQtRWbxqF6hpkqCbm06E{doMpwOQzsjc zCUY*DbjO@aB=t{#&a4AMV_9rxx3$DOwqd#=xZQpoS)Zy*toQoOY20f&qxgJ9(97cH z`bhb(ljCf(dtC^=qd`+UiyfE)GmvqGICQdK-UvACz%gl3kt3uIpYd7fz zFR?5%>W`e2T<-~)j_Ckx(X}In;{sP{sov%2!@JvjD|wRnd|Y6Q`ML8Js+F9{ylxZoh*+OfKn$i~|a=<(?e+f&dac^>K)Kj>wX#L#-T1OZX-GcMjt)A&tIiFB% zgqP@ZxC*fHr#uUGvkj{5F%tg$fX1dM;tgm8n>*^be-#dUhiaZVmrU_l*+!UH58jKOlYh`W5ws(iAgsS~>O z4A~P*k$6fMR&<8)q8AVHc!kvS(U!KYUY9{al`r6b5X6TJllLi*<18&2b%6trlc(wa zuePAuWSB*Et@EBPt3S&DOi;^Z;6yv&i9-i>bPon^cOhToNZe-S!T)Q&i#^IJiN@EV z7rR;s@rYl|gVfs@Hu>Qa`>@|;1=e#w@%e+7379XiT56_>u*PJOj=?2C!+qf8Kn>&w zlm#)wkPvpmjt#YCW%I}v5s>(s3iD~PhE&13A#hEiu82LYKxrme*Y!eb(RD8@O24-C_Eh%+VQL3 z0XaGl15kyOZMJryJcyBtk(!a)4c~lw=5``|p8<5qeCs7v!jzi-`tY!y?HfjJVz6E1 zw)jCE|MB&r#ZG2?g$cEdnTszmX#bpY7@8tSdT)?I&gN)i1#Ohf?&J9CNeqct$jxFo zSOhcr>FQ0)TTf5E$D2tLIW1vtzyE~BzYJZsn@ihe1D`OKl~B9!OkX@qN`LzB{Bnt;DQq){!FZ}`B?757i*JVt)CChJ+PAmGTib;*6`x^>StKRpczJ!@4 zcFxq5ZE`)mhEP+2R}3V{ghQxn^_!Xc%zHj)s@I<678rt-(V8YP;%>-ww*idV*{5;O zAA=%gIvy|qS?ps+J2*wfd1{Gs-KM~LdYyKp1+Hmnky z$IPFv2zI2Cd-eR*j3m#3Muwi$kA^wZ(eW6X^e@>VD{Ob_GE615)tV zA@!peue(TQZ)D+6_`zKIDOtSxy+lkqQ=GO~DP|uK{-rvX?p4BaJS-16eR_3Z(=cA@ zK4H=f5rFZ4Mr|As!OWil{Ps_%{o5zeVx}5*P68U|`4!E3G)myRG+0q)Rml&&z(%Zk zoJbj*|7SfQ1zLS7o@AJUkeuXU&o4}lPhZnZhJ+gW!Ov(X<}CNXFhx9P$!K}Bj*MUO zw7qdd^!X?!-IH}E@l^ykU8{_}J6`&2`$R9V(~Qq~C31p9kRVJlA*q62makdv`N}vS zW3*bo_Pe1zO5r|&t$)%i-VJNsq8Q3AQEN?)$q6v##kdN_9KT<`!Bywg9&oSIOq`vE zgL+Bml0t>ieHx9qCo4VFH+_A%c0__#nCC(!`^ih*OwJk?Da8Q|=Od@S?thTXy5n+d z1C-UNzFG_8FZov|p~{=kx08hBHtr$+W(uu$&&)E?2nT*VP9QpA8Ju;$p-Zz{2zSmo z%g!#*B2 z4k;Ycnc{v#b0Qj{thHceW^gk?da#k%9V~sIYu1XtmYl<#Gakothc_hBXBB`O80A2) zdO(81b2)AS`Gq)AkM$mZxX32KiJt5d9NxJ}ViZIem z#)yNj$&QUzghTlexqjdxbJi#rkJqp|hkyGN&EUA06#pjJJrWe?Y8WpGA$I%c{W_DKe;a$x7mz&Z^tD+y-^GO z(nOTy>8Kyg(yO(&Jb>m{#4N(2IEVMOg!%ksA8a|h>y8?32w%*eFZ#QTP)c4xu@D=^ zpEOyoE?L>zy174LvcI2~wYixa$9JmOh;F$^j`SsW;h&|AzZ-C&j&P#=Kjn4}G}Z!e z(m9Gj!J`AE6K9wrmn9Q=oayuu+4W0FTh2Jl;w_v7JxG|5lT90&>+x6s>@}j%=8HuD zy$MK-jR&$5y^;XTkIH=^UHFf7uYU+xXNEA*At6QS371(6eLy@2m&#>oN*gD&ggHfR4_ zFN}Xnh;f6``kOM^bgE+>9-T1vx5rQIiY`R>n2>g`ErGy5!#K5;OsZ$ zY+?YZSB&)CoKKU+Xt}U&4no>(^vs9pV}L0_m1BajCOk?Gkj-xi{+9HBQC7gibE3k) zgRdo5ILqfZ2dOyBF-4|-?y2dQ+z;j#KbFqzOItmp4_s262+v$#!q;T&M)a8dC+vk? z2QK`wvlPGG-s?^R1FxzyQ}|{pM6UM z@Y&5Fyu063yl@14{(f&Z@U%Er3o-w^;XRB^dpg};&{GZIO6}9RDz;g-C&X9lANhjQ zOzuRSbT}M-;z-Dwh>T`Wi8F?CG3O)jzfJ`eU5-2X)O#qf3gAZz==2JQGt#Uxn3<4~ zqK`M&=&P(xz5KRk7Jf7mSE|j{@7%=?>PSq=0jidDpKBT&Lp)Rd#=~8Jh%;BI#HI zP;F4)B5ByyVb*cZ$^&pg9$Z$`>tygRtwq8dz^m*UHrI%r8wzMa$1_===(&Dd-U9hu4F;P0!l9oeQn?tm2gz|tx3si4Neht#C&)CSrF+1t66)XPw z%Z(E>=fz{Sbd54k0-CR3T&^NxJ4C(?VA1xS6{*ncGj9%cZZstEbmO!nz0 z*ssz8QgM3`^aRlSo62#43Hb>2fZ{ycNT31En*l}C3eqG%&baWL6Sz8iwX??&6q0h( z;YRv%mNU(?_rA=vT-p6?hqEDnx$$BvYx|Lo$)BIn2H@0hg#3oH;p;4cap&+f!Rjf_ z;Q<$~&(%(c6yfO6pU^^FbhE={jtTem?n=YGd z6zZGP@}gACK7FdQqA51?#LEQ#HYYB1@+&G`P*0G5BA~i?6APH z+pbBZ>qi7hN^2J#TnAta{Nc>J6~cBbaO z_Q9#xYuI97kl*>Sp|I?bdE;*#6m)X2PKc>6>=Um@HTtH%c|K9&1T?dx+&sP?NC3f-qqq(`)(SAi6 z(+VJQW1LX@cZS8uj2%DlB1i!X&LI@Goph4x#f~*^;d&d=zpNfRv0btB=f5r- z3%&3kfQc?xTw(4}zS%}obQynXrw0H%3Rn6wT8{-|pD4f}c>iYHG$D55Vw?%4NB@-| zeBm6s56-q4vOAn};f`C5p|-0ePJ(@2gAVcxXfgj7ljzI5gom0}v)}B^LDKu5Wsa#B zH|t&;AJ3#-A~?L-G%>OC$4o{j$>yd0h0%gefGz;oBx?6O5;pq|(9ZcIV%q7R0++iP zCrR)k8ZWmvzES@<&+iZS>;S5_a0%FO!trKL!c(sv@z0w_zx%1p6S>n!c0rAoEGj|P zX2U<8qGI1eSchD`_vDufBYi>!E*YhF6{8Q>KgA0B$Dh(7jQD${7g;-&<}Cp>bI-(; zk5NjhQ(Ks9*z24*_W%c|u*dFFym5Q!2UT!8+VOHw>FUMUYmc<4qwiMuZ0#pcNfVB1 zQAd+s*1h{5r{Tz0O8`Oabs_HME7*4U{(M)p#Ffi$stoID`FuMPCTVrf{V-{^>L*_& zL@$^XPZ+e1zD>^9*a+a*H@+!Sg!o>wvaVf(fDn+E;Te#X!5JIPEz=iUJ=DQ`o`W5Y zf2Ek4@|9MzmnM!;6UU$uy?0hE{-{Rvn75bxAzO`3OsEcw;@mb+WfruDD!*vTwzXH>8^b-6mv{5T z*)kBN*grlamfI?rdr_vbNk8~h;1`+y1m@W*oZUzfQHH{sWGr!gPuKBW1&+^^aGZW( zl(iq_r5s=sa{Dlkg0p(^gHq4js1`v4=JAMmH~oxJ8Jh~lcIZ3j()DJUZ^xW`6S!YK z+{#N}hE6yJiL5@_UBZ4wE{@r4=K&#p`V#R$bpE{(_OS=4CC-rpie6q(jvWr?PnZWV z=m@$lSfx}ty6erRUeanbgm!ILSSG z^%D7x)__O?d!&33KNFAP@54|^h%xBF!;4~Up}C&T>!(rzFu9{o{m=uHYsA`r&2dzo zS>8vEoTkJVx^JsnMvdBP1aTQnR2v%3e2$}fJlA`<&JFG!Gna*-0TeM8=m&B8*#5ti z>=++P@@}|NbTfRF$)jXX3cDF5ji<{V`?0#zs&y&yQCuE0ZH#AVujFD0>lNc_V(5VB z)8xt-YCC)VID*>#i^A&RzqCD9PdUcnNnItz=URGll@d+-f>DEtiJa!<3ebJ4=ToDm z`MFn$I(jwkuuJH1U^8BYcg*J`(mQBD?d6*teG(~lPLa<#(_1ozozupY{v%ok)kR>8Fv$oNnKa| zb9D93PLaL}ep6nDE!DPWF=tA%|1=}4pR%LMktBY@9$NiN*raeRIjUQz@xPsY@0zmr z5vA<$ILr^Ri{0?_GO7X;l$h@9weG@z1CBNzQ5xI!ToaiukBjS2xo|8e-m%U(hYU*{ zWKT(zu-WC1!O1m3Sh`RPk}q>$LDMnZw9SIMXtOhmc9l@YIj$G;OK{(t@PWkCedlNsoD zWhH{Nx7vU%>+(Fp{ROrN=k*FZ?XAcTE}&vrQhiF{;2QSk@l!$hIS%mg8h^y3`E3w( zTTooqOgIa;JXS3^Hq1U!90B=Dxj@wf1a1y3-~Nx;X}54~0L=6z+Kiq6ib3e-l<@MK z7q3;S+&5pLf>m}oy;y~6=U`m|0q0|S%U2Z?)4wnU zT31AI{jo=m4$|Im`a)UbY!j0pNEQ5w76x=I*uz?>V$$_%)cqyx5O%~fkb_%U>L-*@n&9yGBADO^_IZ6zJ&&} zrh&ThRG&(ElBfuM&X6qpT&Hpg>I?st!gcoi&oYz^w;RR*dNUOePf^mr;pA19Zd%FJ z3YvKa?SHFsKT3j+E!SfN z&D`a?9;`+S(1_E4dj*-cdswiTf(h$3X51}mC?2pPH(tecMub+1GgK(va9=}0Xss2_ z!G^MW-TB-~;e)~bN5LCeUG)~x3N>|8Q~X>;0rol#X2x6x7|RAkD_V2c`Wl|%t7A(c zPZ(WW*#NaEOZbhuT;&r9jJ@=-g|vjP9WVg1LI6=^qqcOT`pXBQ&S7UaCf_w&Gi)vd zUADH0j&W4jc1l_7jA zHaq7jy_b|29Fc=cgH`VQ%uPVr;gX-G@WiR$3%b_tE2@Tm|5W-2{G7g6*C2i@A^22Vh=mAZdBMu zD@4c0pW)gSRv&1x%*&CECMd5_vd>jCQJX2rEXniihRzV15w~>M@@`;PNg{){AJ~3u zU01!vd-uh;g8lB+)0cSY)luNt6h*b{(lyP9P>f!tP=f=>m`l%$Ut48rGRvZ>I4vRU z+!4&|{N_8}<9h08@dD~W`&h;RB3N%LOqyLZ#MW;YExIgD&B(!?RR4ury48K`jK|ThC?h7r1>Cn}A=e!o7UTQ{>Sdn~N+)KKtH7Bv3((zKm)3>O zD~K)!Rxcv$xH;ukI<8vA4(z+y-?DR$`LW@Bl(R4X2X*k{Yfc+_%~`Ol1Q^GB@!NNM zJvThUF%V4a$p540T>P2r|37~1WCt@F!!T?!%puJo4O80;b8O@sH9~Y8Q99l`VGe0d zg;aBlQmwNN_uVj3QPWX}yG9i5`rfN_-|p(Z{r3ACuIur+uJ`-%dOe?W;$Qw}d380G z;n5DN1d8S0ra!;smE;D$nG!$z&#vyCAA)6?rbl}vb5JLj0FE19iDR6+gxaW(5qcGv zFXNu*e9OFX6t<1MO=N7;?)jfDFI~M6H|u{|iK-3;dn=I(7ot#l*wz)`Kmp9a2Sllj zcXDBCj@m|m#c~UvP=O87vAfE^x*Al%m+Va>7)5~!(R%E~n`S(6%E=-uOcL_ikg`@} zxfv`v!-y+HCOL<$?AkC!I*=!kUDBgI@WGCB5K3gSA(sTEqw*CHZ@MvI0v)4@IZJ|` zHDFP#;IRPYh!QxWO!S?CGU>^!b&xD2~IV*7I|f-sz>h5Sx}q)fv7RGSCADF430 z*~VIb%A!{)4FFd6@%SC)IujoNwhfLvox7W$_A$GHvYm+?uPt*Iz&EHtM#_Y3bZ8W? zuI>vx%AoRM!7U^Zw&m9S}x}=O^VyDd2fE>)Qe2c=f7oQO&j$s6A>(pu#Ig z0Dn!Ytr8jMh6NtjcwoSbLQo+VESUbo$y^=0DtlX{z{a2CbI{64@YOSOZ8={HkHP{e z&K;=DT>5%ofS*2~XMbI5&K-w89LAVBLdyJ-&pkyRRIGt2Ag%H><<8dV3xom| z;w(1kCCBpqxKWS@W*l#ClT|d+y3dIZ8_u`<1%?6Z2+wCtVztQCYK$JbeNmovhYKNe z{c=EH*TJ@Y*;+Bs4;71i;{izTU_gif$jP_%Ub%Cfk6$1aF0aWjh&$@*!ynR(j?lxB z1(1>YHJ7mPEqquY3mjZas0C$MKQRi5uRUDj>@&3S620X+-oc&(dAVqZe`H z4-`tJ&}fqoRl(nJQV0Gwc#nm-*%>xHDmZ_C88Vm-gmYMEM3xkX)927~t4Duqof`6>)lTIG-+`5E4>VuTSL7o$xrfq16#@o#*5 zmoCSpDBxF|&|qa5eX=%#@8mBuPckaD@v2e;7|w8HhQF~xY)~Z*KChzMUD&3y+8LzC z^Zxq)lCa8%j#?{%-vKf_OO1zpmV2`xgufx)YD_UX#i5>@E~FmSZ(Q$XW2D+J+3&y+ z2o0P~FS9jc1+bfY!hd>g&g^Da2?=s9V&{@IEEx+s&9I?h5ve-6jpYaHK5r_;!SyLY zf%TS0@saZ)Gx-H-O2wM*9TW>N%vVLJdIuKn0#P5W1__SlW1Wv;Aqo1!tN69J0nQky zN}+850o0!mV!9gL%z}98Pv!|}y%Z3gA6CPrp74=%xLTdX+7+pck86?T)+(?95R0Ni zM8zrNFlh`c_4P1xf}efD&`a3VOr7Z_ZNi4FDqIU`va9V zGo6(JNQi#<+RYHY(%6Xv;T0n5I$+5xc%i=iwD7905^`Y*oGdblT(>Qpi^5Y~MHeA- z9n?_|W9gyr_+b7Li@rF$=6fOR&@@ot1Q{Plt`-}9>2IHY>{<1+;pE1c17DE0XH6Os zSa?U!>)1l8uaN%W4d{0E40$I?Z=~axFXnhU&0~88E9W@&MrYT_9^@(DB<*4 zgXf8Hb+d1;GO^Q<3C}S2?0{WDC}Ga;HQfLiP7PuuhA4n21<)?2Ek1*xHJL5z2rPZ- z=^6|j`s~x4!D=0cJH7+U=~tT_!37OT2U$uGUFqTHdlFTcCeg+GRD#`*a zVIfon1hM_+p&LoA%MrLcI|3!v{+gvzS zpbzdfgMfEgS$q^(KO$t+-*~74()t6E6mdq%eNj${-rnGBON-hT%g;c@?DMAE&yVF4 zg6?&qR^>o4I}+%+%LYU;tL@meo1%BcxiuMtnU9dy`>&X$s-{UEv%6ysWwd>fq9RF(dlmoG4mT*k;$rbY@Y(w9KOW(63WX&rCN4%Q9 z=7WN?uxTv}lv3tD1-&N*GqsR95$MPD0uvMZX(5Ozh^J12efgwVQq~O9_%RqZ&EHft zlbXX4w+}G9`J~zbX&4F2(ne_fjZ2?4c(xZb$ybl*kwo3<;is}eHs+uL9@)Aky&R+v z+)q*%g6$@6NM||y5U3;csQ=DJ{?n!_{hBuR+_&_=G_S6g8yxog2J4_7g#(a4f7Le& zM>Xh-@Xi7H;3D;QbbC{kI&ZWFzR!o?zas6^K-s6AnqNr6!2)Xo^^)}7ZoIW(#YM== zS~ysZMNC1A45Nhz|BE$CMreEtNEe`3PVWnkO)m$+xLR!3YPEr#O+AK4oBlk71H~ZW4 z@ZousW@jX(PKh~sH;%~4FUVf`Bn0}b4w|k^3c}iLAcLZG&T#-Vo{o&t9gmBJdKWaU z`t8{7X+gz*tnbs_m;V(}>P37xHSyjCA?6zuOjs1?Ng=YBz#PcSwzSzBY zQ6h1tDNrozPkQ+JBPhy01ll&jd6I0e^7_gE^y@-+gbb8K2WN@FXI9i#;{r4p5Kd<3 zRz2#`laloalilGre?CS%ul2L>nsF;oT@pZ!3u*nnbbDX?{9kn=e=HxnKb43DvIUU0 zc@P6em8yJpmNg%fTJ8dgts2_sqcs_`gqdu!qYI&NBv|T!m>Hr@yv)j6gUHmPW0k;h zRju_i7+{~8qO_WtfPc;cdeoplMQ!y%DF$|N=?K(-;IjToH}`7UD zrFgjd zP&a9=#42naiI^dX9y;vM8CZw{>Wni*eEBQ)@2$-Zr0wwM{_1$70J#sfB6zpG`wB%J zzxJKYH8>}0EtoRIhqlf&gII@E4V2*lM)r!;zK~ICNf9qfU-6D`Y zLJVCCeLmoD4Uq=sLlbns(pBosa^rbA>ZmnvVMBh%2g|jQN7lO?Zt}N@7um{rFsc~# zrz&yH(x(58&GqJ0TRwXSna4&x>Us2?>XADsGZc0;f!01*-0_R=YFkpKb8xd9k-C?8 zHZ`5&^{%>$nV&V$xAShP3B1{+c2MEHJ{XL-d-nptCDaO?zExQqTAg;Ekw9b=KbwES z_cxx=cU9(mACQy(-tWrg7gJ#qcIt53Z@kWhO6%+oP74}~kip}L0=qxr+Kp`dV9|w6iBOzxh4(X~-W=(aV-h zFFA?Cu4@wrH$qFg}&%5YUHgZ_( zz*PRtmZKn{-JB{r(wq^Ff*`f^*I)bsk$SW&W;76!twZG0m${ImOsGyMCnqL@Dvl#q zvNDJN1mGiNZ0wpK%x{VTGu(fR90fEKp*uV`F*k@NmnVbjJY@P{xrLk;7f!xN0GrJg zN0ygaEbN@BT%C-=!E8OfAP`DUO}p{MIBRi5d?SfspOIPaaw0kNbAQ?P8#O-2)s}2( zCq8`;f3aflGURQ-xTdOO|COm)Y2k+Yp6iT`M@I`VZP{BWC0)irz`BoA8 z+%Wh6^R5_&m;6%*$iyUjIwL(n&ywtAo?L4@R1RH|W%NgsECeWF?tv|RTa0FB3@n7Sv! zoHdsblo9soJ-HC)ViL8PyGh1u6hoJSEZRe$I^!dJ5rP3gVabyJADXD&)fk>fo2k67 z)`3}c%ZSWDaMYT*i+s0cR_iJUe2V=+Lo`uEfv2$gKc|@=k8FfRCkrIl%+Jdx8VZt2 zDx=Fw+sJ5_TvGaQ<@ zjC=?6n-YMjbqEgP@oBoiDDY}T5d90pR7Uf*zg%DuGSSc5s*U)2?vAO@7j4=ifWb%A zg@ndB(7F6WxCK%aQw@Ex7qBc4Zn3oLWA)v8>RM>+9CdFFjL*@lDe8-GPgXzXvJeK+ z7%-Y6gBer1mMlQs5cfU${s+R=YDOB!$cPTOGn7C)ev-cjJA7>_qvlspu+u%+@F?MYk;W)J)p1)U4^lhz}MvU!QM!iEB zr9)P0+D(%9aDVno2)R!U@+*Gt1fGCJPpDy}LyG6S3d$K8wq0xZI^h1aSpl`Rv= zk%D>7ww!>-F05F1sZs3Q9V*I+Vu79*bMZMf7`V0-Wyq3a_Uc5Qv}N0jYY~y1gZR1b zDR>B>A4ge~Qta4tvoFDs^FB`kM= zfZ1#;U%Gw;&bE<^QjD-|_ba)CWg~03d)ozBLs4G+HLhLF^aPZ5^l6@15GgYFlA@3D`j6Ppcr;#?RjQm(Vi!BWXofRDUMOGY zgqMKO);128DQRFxS%6L5`9zY_J(@aUzR)HYaL@nngm-JqC20KVr-qS?5$}$3tQb7F+feN!L(}Fn6JKSblc++ z3F9G%DhJy!^hg}kkTld)@>Av;g(XHXjN%OA5y=0|>*_rwY&3|+uK3>@@!UijI(cds zYTtn=8XZ*v9tFsAwjzj)TcsoYGu8aS9v|`{d+^4)meX;Ob*djCvqE&Id1#*lpwA+(@-p!^^M z2kQRa|9wgoE_1zg^sO%zg?Ibuvt}I7DH#agM>4u%HBe8utc>)N+xe@oWsE0NetxqL zY7+TtAN^%%^trT|&XFy}gGqgX_)POSp4zHW4Na5-@KCgwsSFs`d*#9os&-k%Pm~c- z%t~q!k72pgHpe^~5?hDx->ciSd>DCm`&Pxu2+7Kfi{!=gsrleQ261~`+xG7+UXk?; zxaGoJ2-gf?y!6u2UHygf6qaXlKLD&Nu~W-9qV~WaZuT?@akexDA=@0N(JdX-Dn8f_84E6}tHeweFBvXPd95?E9=hx|20~4;f}` zTHe5teR8Xdw}scFIFX-RiAX{ zEr|LhVkot$UhgtQsoNJ`wd?EAN;xEuAod|hH`2?JL|soEiQC2Cv%FJp^tS;PT zPtPe=<#xX8HW?_#{kjJp^GHPNme3R+IIql@4oy(Y-?o+y%B@WXfU)l@mw4)$1lGA( zeo14%iI*z;abET7Mo^Ig_}98)y`$;O_v2&2ARpRUkKFLT=fOS->0htT|Gw5V9(P-u z2MJ}+-)&L2&()PWnpe@K>|kZgT%Fx4G#()Xa!c(L5?O#`c`}NJ00?S}duuxv_=ksINTe;BY<55FlQk+r$$O;Tx$AxA3y*aD9haEf}L?UQ!d$_T(U|q z@aZNPKO*_M@n*0qlo?;ojiq{RY0Q|zlj+C8X_iHD^G74Mzc+$-x}KF^jyrO!?B%Fr zAuLG%pVdde!poPx1oiYpyW?WstTT-k0zrH@n|-T_ z?X3hQ3F@0$y`{@-BoFE#csYeEl6^IoaM1)%<*8yGhb#nxgc6Rx&0Wb=S<~P^RShe6 z??$;++ub~S?uHb+OL!u3R+%7zHU~tN|8pWz2w3rIYZT%iysBEkiRv$*7RRqOXrcA= zLz}7~Zdg$5<;4iGL8LfW zRhSt}$Xzr0Qk8L;rj>dc#$3k+Aa@p)0IMnVB6%1@SP*rb>yXR&trXH zNMoC$xF#=KL15Ua8pR$0NyY%kMUNNs)cfZn>}ljXR7>;0r*`{R8_1hKQek9)4C*2C zQ~6QZGSieMXJW|`w;$#`_^fV)h{}@LnM)`tDP`hfKn>?ew<)if;?zT0gEU{AToR)L zlK3LS)yedi2y>3z*ql88xPUa8YR+JaG+3P*GR$B zKy6VNTf$3V1Y|2f{mbj3UIbahc{zQS?&~rC?A^muTr|4Qifj$KaQ(L1>xyQbn$eGc zcF1M_xmI;M8?H^F0-ooqim3pDbz*D!KXgD?^e^Qfa>V zD1`yWSPviPl?S=rn`Ma)Y|{+Ot6zzqy=pRf!Lovh*Wr%vzKI+kr_ifhX((?SkY z^9KI4F8SV0>anY;>Xgz%pg@6)4f5vALV4YZjuNO33kn*m*g79LkauEf`Q(eAlJ5j%AP#7?+nYC&ZgFz<*-tMZA)H=7|ex*yo)0D z$sTsg2Q?*$ypEW^Oe6PLJQi&zXZO_e-IiWi*Ipie_~P1=&{kU*_=V|^gvgpC&abgOyHnI3BDU!P z_m0czwpNylz~^pSZREDPcS_u8AQx}NGgejP2;17wnp07%{i?es#DDmQsRYubVwlwt z+bB-pBLSjJl>ye41Q0+56s7??8rTTsMc#XG%s1CbY$j~%2n@{ati5(gOxlwv$h+-& zmD+XrQ(k9s+8D(1;7w-_sG)EX_BBFwt9GgDqc~x*HU8u6a8u=5%9`cS=$i(qt=SSGv{+4y`>n!$mfz^XX$rIw; z6B(>P733XA`pKD0l6Xvr<6`>(IVfKUaMV(Q!q&eW4$@w3`WYoN&BjM$8vXX z4}GPUK<01*I#(+-1gSmas>o@1h3d_er+b(<4FjqBk)inW(sqM$bKFl0n5Yso`ro%} zL3Sgc00n6CPL!=&Y^MM++|SjemY>-87=4u2eoT(tg}6o9l0({Zb{3p7>#D2@pe>%K z6+cKc*a=wXVUYla1WJtxa5W0ww({>?!5|0$;zgS+x*)EhlwG?o+0L7ERqzHfjFyqk zu#_QJHaq8jxwAPFj!1Hd!uxAA^B82(voX z@2gbH6GSEx%FTBOuTrpE>I5I0pQAZ@DN4zJai7$K);2GQ8CM&o!yZkGxy$)XkV@(( zf{m;=JLoHQ?r|O*k@7LobtU3~giqPr?GH&uRtD5s$Z!5~Dd3vQjA7;w>E8g_4aOiY zI&@pe52b?5(Ujs^j#quLUh2Rn8-whGTygHM7|MwBY_`P64P=V1Ez{aDU=^Eq1qbIE zUKo#z-a9^W-40Z^X_4B;38;0R_A{Hicp_6M`|*+_H9>zz7R-YEb^|MQBR_3S69h&} zwz)U=<Ut8;mAY273&|jtG4fz=Y}r>hs=tlEQ&-bQK!S^S z=g9z#9QW&GaWU?-^8vrUQ%Q+9tKTzcg#sg~8<=o|#g3&uC3y89_Oz^stR~jvpBTHLSdhfg zIGb>kX@Q%G4W>6hm9cRcZR=Uk*Y_kO#tJRhJZPCAJut@*!LX59ooSU_wwJ<@R1bjs z{XAQ-S~nGhnW>2vj}Mj@+wvDP<&WEW^=8HTQHqf5a|t-9y4(14DP(rGgL9?Rk?L}3 zthQ-`Pr|*0gsOOos){ZUwLADgM|uX-yBQl2FlkXug+1@}$(nyIzK?`LiqHk9{Jz2X zuO&O1>+a26k{Cpx+<111=JoZ%)b|_x4-a|U@8Qae1@o~q(>AI+Q7~m7d#N771NS$v z!wjl5GMkY2(eO-|g_rIHZuqILwmzU&OP!mcNssLk^30^pPjF(n5V}|sX1fP58D{nS z@vrEOGetOvJ@+m<-RiU21-)NC6Y?6>OZ*%LoI!iZ%nLjua)*Nm@c?Si$b|va@*5MO zX4??LA*xQ~A5IRz$I1_cN3HBU@?=@TS|%=?6=M~?q#Jf8>8S%}*THOKi6ndcF2IjYy!Nr0H?lR(@GxXN!1*w)7km@jN8u zQW{6?bn?5(#@{i7TB|wBG;e_Jot$&=biu*BE=V zEMK9;gb86Ak4rCvf$d4SDQ_15+`wD6rUz_Ob!0;k2&c%y2!!(_Ex*B5e-e8}|K zU1R_6bxtAwWLSP+z@cb9^zo;UYx5iLIequ-ApOH4DE={b4xI$^3P-||0DQw2MTv(J z2;GC2c)V~_#uQu#in&bwe^ysclNj#KC-2|hR$i>02cK39n)dvCVvY~THBGVGWNHX` znq_oATj@;XgX5yz)^SA|>_rmITEjN2DM#5;0qMcJA2-QHBF|(d*nPk|+szf%0K2ph zYi$RQQ$FUQR9N^kvtqc4V0&lZP7yK#uh=%Zc66yw9Y2p$D|6MyS#}TRY%k*}BqhL}2vfI^;rBp4707KoxZdKisug6^TBS z3lneJTG3>})Tp;7=7pjcu+sKn02ag&n~VwqF7V+fqxJ`wHyH_A4bfQ8q5k;LjdgMB zDS|a2{dWs;Vat-)mS%Ljm3DwdQ}!D3Lz+RK2e@MdsFKk<(s*X`H*~ZdvSiwPiEI;!3~E6w|@D5K|KlaNOhr_=t+4&PW$!tA0+vOT5n7P8N; z!DfbPJP6~U#zEXiz`&9ex!E5CSz9~!wrwPu>~Yq_CVar+*LrA%CKz~Q!>LMcl1=~R zvc_~@Ls6)|F}^V)aeK!J;mF3)$QK`OR*s0xlP^di>6u0WOJ<^ui+TtdJGo;uq1~i9 z99Z*jFYT;i`as6a^nQ%-D#kXRec@B72ZI!|=K5gVz$we+s9{r^yMy@O!kq#cAowm7 z#5|N7xpnf<5$a7aRW6mU?&Vm_T!-49c;UvZ2VnU?9VADuxRl-och7y}luCZVko|#5 zVu3vOsT#AQLvrUBhzAv$lB`3inFE9?0R@Xa6^*?;fBqBA{X#DfzuanaG#S?HaU6no zM4#*I>K?mSS|$%z*tDuHg}^WOttzOe8k1%IJU%QSw-uc|LO||ng_{{vTfVU&4u9t~ z1?c)wQ=}2EKmX9K*gx-mdZIdKfn>~?4TTbgAuR2u@TbWB*_X51Q^lR$D(%XSyMduoCc<%&0Xx3npt#nuk^LVKx?0~yrwwJ>dw!mp`HzJ1)|=$h z`EP$)mWg8;%wB$mcsB`W7Axmi)u;x zs-VB#aEK6tSWUZk05vCL_Ekl2COUzsB_*+7QMcADE8G6Ndu?@8>!|x8Woj?Or9i8` zdpoQVokm}uFg>&ep2pq#ZTm?`CJDY;0CR6-sd_Xdv}0p^rxhEznpT0ZeML4RirzA4 zO*Mg4!Ft7tv=6>#X}|v7;Iif!Z11?v`bP1v`w86s%3{rfZYir?RFTz>n-GKOpkrrW zG+%!~MTlCy0sUyW(a(MdJrJk~_pT{{Q0?rAsMc^|eun5SvoaUzP;_X3`Y}%M@m|M; z*mhSgvHtDDCkfsyQa?lqugZpj7{r)pPG!YR_QiG&aSUl<&s#R0$u`X&@5Lo>iQGr0 zUPp1898@@ykP`7jqDgS^k}NEwgpka(>lRyn6k&2fc2!TVWJIHHiOzI`uiXWPdxxS* z`Yk24_OB-`&#@oM`Z05$t^Oj$tz*@%O^{HF2RtAcVT8&ZjZK$a&41;jVWse=(1mP# zd_P5>f{vH*p?BDd22Fz+AK#Wsk3}G;?iUnq}aTBajA;jIXG`{zFTyAJJ@#(_^ zkp1gK#(_0k=rDgxsn_Px^mJChWpKW>(yfpUJV}8)>-U-_bD|{yzFafZ#;j>udyUvy ze>XeG+^2qn`K;J^B=q9wPX+Mn1S_i}!U}lm zG%a>mSYkWy9NeL-*LPV$Uld+2nw?ce&15+kdH{W#em2KpRD|}O=B^KoeY!3ncOdF# z#7=Ay_)x3|Lycbm>_xAlp1mr^CjBybm-jm4(jo{&8gP5TB2SC3R8Rwb*djjCRMVXO z4=@Bm;d)sgaBPo7z!SkG_KJvzU^C|9)ZC~uz~QDn>084xNVvOoqnOXu58|Od+e5p_k*mHX#cBo*h)O!6 zhc+4{2TZARXYk1;3`)n3XNW|4wJ9EiR<6yb-@3lx)re-7$IxXry7Nim+grpvl`a}t!EnFK176gGY^F#q^3WUh#jR5 zWgCmIVIJIYrtEi`aF9mlprb-@3oHu{DD(5^KF=5X2I?5E+a6AwQiTllfuh^@kaLIn z`}Rl(t86dlu`iFa?Pf*QKikR$8<0;xNzrV=6OaS=sby)u&Bs=kpBWi4kllQ1R6)XD zCAqG@J*NE6=~e>|o%O1GVLYB`ZqoPw@mH*Cvx(cTv6G;N^2P^c-I-&|egv_9VgZPG zfo5Le1bkGS*=nTUI_xq1KDI$rT`&4A0}3KJ6f#3JnhLK6OPnD=X*4>FctefC!tuov zen~}G_h4%A5dlfFIQhhhtJ(1+JxRkd@3VO2QIdxhS=Z(k1Bp{$y@k0b))7%C1L+tKHs`Y~ z1>x=A#0G|HCh>3kG`||@m!Dp#MEwy*z3(mN` zxP$6Qjct06%}^U(-i&1A{r2zlFaoisS7eL_S*V(>q}|6(ur1Ziz=XPURQ<0WMp1)3 z&>&|4n5s0~pC_HESHJHVd7u%A_+>p}@{ndcv~B73Y1UEFq8ylz+nnp(vZfKnY&XDumfz5gYi zv0p1M1;zD51jlN#X9-E!OCd4*HVD)Fqr~dk3-trubIhS(Lxti2v^VKS#Y24*xJr#E zCjR*M)R4z3Otw*x7Wj39RS&l5cz^TLHu*RA>s#hn(0|rHK#$a~%PaMo-;qP&RHq$_{goB_0su{Kwp1gUg=mvTiK671X z(W;=><(D+PHxcD6X+({&Ka(4aF3Hu^KQL$yH&}vL5_9bqW}4KA59;;jeuah>tT))F zNZtG|v(-K!>y4gM9>2H@{+=)s5JsEBcUuZY?;?(s7iS{l+3#N@*^PX8Kkvq$?3~Mt zVmK|;l}Xl>IoC0WPaiy~@_3Rtcn;Qakn+(jE`yNJ>fhs!mVIcBcIcEch`~Gu>EMld zpILT1kF$=n;{~uaWc;_l+2FJCx zH%HA?*L^x>Tn|q>t=OX;oxyQ`eR1?n@4Rj1REKA?XaSUOu_bYsH&!q~iL8H)nP-dJcu32S9_EY5rqiN5GlxXn7JCEZG`wta+abiO zuw%tFSm8vfBiQ@-I-+o^cTHdN&*Aun#54K^@L|&pieSu7Hbx|~lZ!gKr7eH)Vws1C zE$$3S`YnSjXG!H4iOVvrvu+~-^Xcn_on+7=J;ht@B>&| z{^kwkzubzqaX`>bW1lr6|(vN%cgUf`@=8-jzgdN z#`zz$h0>enxgJXOw9U`iX0tsLydB+yXDQ=!gR3Y=QY#Vs+nv z2HPa@y~Z^|IY)Ljy={xlKJh+teff7X`MKD^1iJcugK{v&oj7O{zvPt*cBqhk+jxR; zdC&`h0HR-bo1y}UQWyPcf*e5S&Py{z|GX2g_@D4Z*=0{f@I$*`^THdvuOJpNuq*GG z2Y8yO&ueo%?y}+zb8_4fn|ve1>V)09jWt9gFf<;QJfyLxPbnUd^+?SgMsUDSqBqZo za?r>8?3D8H>?6)_U*Dpp$r{mEt5*brma8Sz5X=y4CvGmPm5?8iR$=jn#(3K*`RKyj+Qu-4D90{Y zk8KwhjX(G^?M6J`JkE?uSNtIvarC!MoSo{CoYF)b$=ddk?(^zlgRILV@NxY>Zpl4HW;4|p)QcTVSk^niHV)V&>@Ovp=DC$d+`sSpAmU2p z*BH*c))Ot+@0Ms9ByZryd{Q-|-0}m0#zCmNkFq)g78+-28wMDmrZhdn`E`JH8}fJO zX5G6++iLc6B6Bpa4YRY_RVt-qvR0O!(5BxNi^f-UZz#IIg>zUmMn*^_>vhjSK}_7K z%)LR#zZ***FNwR$-QM+)Ms^DpK@jx3Uh}$PZ9o?^ZHj)UCHwKVa*x826=kwQBE7xx z;2%O|Wdo0-p6uEyAFT-J<@LBB?v{UdEVy-pMX~*OL*s&{k4Trj-TL)i=#ANcl;ucj zay!&H-FnJ&mn9pD+rr6RJ8u^JmrL6Tbp;Ib`^x{NWx7uC5NXS)VVhG;=8 zEh|39c!+EKzxq%Gy`lXFgmRH` z8W#9ahSN-H?~8KCUM&RQIO)h`j2yjH=nclQG5xW}=Xb$K&vcV!HzQghm^PP-AHyOr zecWrSB%qVL9=N|k3aH{_e%-G2uzWmYzpAT{Co4bV8XL*H;##lxb8UNDW{)qM(x?Ml zt>TwKhZU%Bc`GUbA+kJ;E%8pA3~aS|dP)O!tCvkCO}i&XAUK`RyESVI+M>|ilx3Hr z_U^H_6&Lv1r81SA1#5R5lMaj zV^tHfwr0;(B;DerC<=YqY3YbTTh;}mhS*VajK2{{uk@A|bI_iBYFOh1sWrWQ70v5t z#Dv_lh*zF7H)VNEuReG9X=Kh`t;VT3W4ReRI-@z4U=oirrt~Q>Zsez@PD>~I*?>uSFNwXA#XspRi?B0_m?(bSJvmU@W0@J(>qXAM4zlhpl z7A^c?4$mEMx%vAicJ6@BNg(^$Et3eVTpe)2UjRR#2#%)pz4FxWvV6$D=kqB46~W`0 z1x=_nuK$t#)^nxZK&qwrkM=8(npTT~+#R-i`6XQ|4naScOE8&AY4)d09zTM1{K5}B z&x{_;p`joqx2|x%EJO$(XX+UwVg@2I#BJ?F`BIhT3)pqD%xmX-pSvWOEkBlEcFb>G zxyvxAw0!Q8OFKF^K)d2zO1IgObK}xqClZ!-rhQol7V{!Y=gJ|vKk!OMsm*D=%x+o$ z4**bAIg{mUdnfUy^fJ$V)>E-Y=wDG=B>unMd>a7GzRg)@smwHV?q6rf@{2bSPLr%} z)&r0W%1vvItT5hrYfqBv90xd$EpzXd;$U{BJp#>B(*`w)vIwSP);97s)C2c-_Rmz4 zF}QX^7nkt*J&G)}NI@*Fg<(`~w zgiDgSLswXC>*LsV)qR{N)$Gn+w8frTLUFl^WXxJtg8f#F{htj*e)R7nmtO=>%n}-2 ze;T}(^}E$7dqYOJk!HTZYZ_30w{T6D4<)0+TL*LGoS*9#e*8Ch<@?ZiXu59mkG7rV z+JBHK)5vxx2;k{p<@7%KJ zsY2`tr=v5RV~wiefs=M3BbM+BR@4!1|Ifck2Qh6qO@mCY8OcgJ=9ayWeIh$|IJa8( z)v(cNiub?Y5F1f>JDZ#S0|(Vx-P%hJd%Pq0P1Eu8>-STC-1?vH?510y^_x#xkN!=h zSC%k_J8D@34X&&eBqtuE>(@ZPgfAVN>Cqf=;76Y3m(rs~HxT*;BOZL*5R@jW`H^Dz z%MqttV;g^CDtAn&fBsQesYY7nD1kE>asM7a-eBA`%Qc_x*YW0slvAFZ_6MVa*ggpn8eK3Sc5ePd z!B(C3{$RkF4Xmm}(A)jEE=5sy3V*V?hL>SvqRn4)!u=%Ven2S$!F+gH@Uns@pnPaF zfTwD?XRp?>Ru;3iV}yQ75ua9Gm8igom*8!$!DFYr9pCLG8KY%}5>t_<#`D&e2lF3L zHvqEa&hE?n_<7}0*8mrMm*bp;9{*r=LwSZX-F|~arQHjiHnyFWzP(;4_r#3tRm0pi!reCBR=bb=1-Z4|^Q+>)Cw|XyCX%?1oVbVd(6viA>fgEVSzxYG+H18g1=D&6Y95-bi_e;LS zLL$UsD6Vn8ZUW63(E(x)w`@S(8gd3~$_#AErh10@A~Ht0z^ov0YO=>NZX!Aq2|`Lk ztw;bwa^)mVvIK~aqjIGLssKnX#INdu2+}YRPyrTTAplk(OtMFECImGi!}zFz(a@(3 zGAKkis;@%BgNR@@xP$;uAabe)LrlanqQeG2$D~le1ulUIB5>D;3ZRk$6QIpzFm&)E6GKogtxbynCo{(F zQnFwOeqac~CkOvlfGuSzD=r0ocn3)6a4M?@DUhN?6v-n2#S8)GDsmzx2q?E4#0D;5 z*1qj9I>_YeBl!qOGlWL1a7#1nFM|p}a^fH-TEU)LOU;sH9Xb33_{J1>PhrKnO^1Vv0S&n{s^X2tu5so`io#(NgS1N%fet9Nu>@ls{~qUVN7fp#U-1>aT%}a z%eckM_G|6*;9=fT4`?7_76u;4;akE{LJ0;O1=K<9Wk0S79Dfl{>LB*|V?SV|3-sh3 zZ6Xp6GPnO4aw2W&5*pI@*TDW<$@NyUOkZOEqT zZx0>dIDoW!eC;>dpitYu4t9V^0Yz+}R4guG5o*r68qzXOlTvdc4nYzH806vb>Js{3 zB6T8EIgPCz#5V`7eHhR}Y~XKtAO@E32TUppq9X@TpoMaRHG%Xrqho_c)VuEVPKT6A zg!K|;Kr^OGy^OUB7U7$M;+wSQWN4GL%s_4sK}ZziIGECdzJxa8unR~FM!I#nP9{vo zN(ldK=v-02o@DDdYJ}P<6F@GuVyol}E7lXqqn$WI6D*cI$b-O4H1UpM zhCr`g?By7M;*&lpvj`!}uqj{?Pe21Ek^)8ta5j_HkYH91mYTpI1_oWK;25IGXanYG zleTBoC1-Uul78aG_M_oW0!KaX=7euz8ZjZ6wD`KfMa+;=^R#HVga?GLO?xj+qUK~~ zfos*4Mgc_+(zbx8Bu~BMfoLKCaNq}iAO{R%1|V`sS&kXxBKCUJ27JP%Xs#iJ<|+RN zacXSfe}a?-fK(G$Ge`}tSox9%u<|(UFLXv{1#+TLCt(zvKy6V#dgOq=enxFSGDo{s zEDY`=b8rR1XCi074Di${N02KzBUC*yG(mH#Ttr1OXa};u1ujhnMl&~OU`QR82MVZ1 zgOwtwq(`$CNOKiPu~##GbRy;LWLVRNG$R8+7ZY}aG>Cv5d~gxA$_8pvGc@CyYSdWG z@Dg%B2p~bdrfU{>!XN}O0j1|gZ~{*G!$b0vH9X`IpYy7C=MLWzM1X_{%#DF_q zYK&kosb|MnK+Bk0NPt3fwrIJ9C%%PX5T-x$tBGcmN^jJKajX7U2^bO)FK5+X`595?p7Zj(viQ2|AhV=v7%`RlxH z7f|jgJ;=_~N>*KfA*EM*eboMX<2Y_3s7S{$NMI|ozyRI~fq9_LVdPxpH&7vgpoKLkN)8Si zgtxS2x|r2|Z_DM(0u@9$Y-dH=nkgHje^BfSQcih5kO{iK$2@) z6jUw{c^9a*L-A4b)()%3k!~4DLwN=eLhk~|L0hVrh$-}}Z!E3Znytw(U@$38TGq+p z(2A9|4tN$1bU-ycPxv-jyuizHb;caL)$GDCBx0ct^3m=5>l^>e=^`NM9@lOL)XeSF z%p)#gW?rCZPUZr>D+MTZ;)9BcG($&v z2+K<&Feff&PkgnYB~>i4`*PwrbGdh(BT(Tu=$*YcbL9<42lq&WG+1j+dP7M({@D-S zLV0)~uXdv&6Y)R%s;~NLSA=Ftg}GHlGf!QPp1y<#Qj_Ht*K(!nSS?o*>chA^+_+qh zw|vVdLSjTeytqD`x{M2=zbRdJ>us4;Yns)=0hlu~%Ul0?V#QN@$C0JS86u(``owFF zq*Z|@oAA+581$rkmJY55)Y&;N0vq6whxA%sTYTUI3EBjs!S^&f9#m!+dAL zPPx!LycS&>(*Xp+OB*$T>FxjnK!66g4$~b#WGK8D6!Oz!&(mX%20UFMX)d`?od#?m zxn@8pbSt@#)uwX*(9=pp5@w;1a3;SIP)Za%HcpfJJR)uN#s; z>R>epgpF)sHFUs5T;%_#MwNuuS1ls~FXu82Faila-~pcCeRRFUmo*V#ME^NgDH6Xa za=ft{nVnrH7)h7`WmgxD39}%w7;tjxVhRX^Vog2_EF=t?=0uvN3JAdp@Brr5^FM^< zNka$qx@HZ`Fm z%rK&nHO8A&y^#K!kpAm`^EYRrn`z=V9iZ%0As!xPV&q3g?R$~NuYuBEY9Qn%h=o;=6>!`zh34(&f(n2xyjD~!2zJ)%?rILx&Q>+00eyB z_doQ}NdN@Wp&5w38MN`z(R}%rpSPMH%{>ANnBUefKobJs2Lhlm7J(UNAh}e}0U(_w zJbm$Xh$g@*_BQ+c0o$}q+asK<#HsHJN|p>#G|*0-Y_MsOd&L-&Xh2RV_ZTExUrQmg6lkf z941T*ssu2^(OJ2(=g%b^gsH+Zi~|C4j^V*mr$ogV6)U3jXmS<-A_jBo-pyP0rQX1G zYjW^g6NWCogXg}a=~D7^zkkPZ5Jyj1JZY(8-(Ee=>g}uJ%o;zlIv(oi;}9ZbuE`4; zZp_s=R+)a7W8yr85l4e{%UKv)!jeWVHGxMH85vlI9tJkio_ywH6rn~Ty+)gC4$z=S zXbxOJPDu}OY}NG!cV_Iy9k!CbM)=hYmaT*hCdS9@7L% zYSf`d6>6yAiIT&3;^dN0DtU~PF?6BEF;`|uz-=}(AtWD7fN2gOfSBWmIWL%#PMR;Y z>E;U#q(g(8G|Z_rJJAP^$46eWbaMK%BR6T4ou8wX51>^lVpr}m)N6nOO@gdb*DQN$DjGh7104d*qm zU}5yo1!Ry}@z@lUQHJppLv6WO7@n-5pC=ONw+6{!n7qasF}(cpDW_c`v&$}vQS!;3 z%|Z?ltbM1)Y7`c2G;t`1BvK5r8YI%D4k#V9M(F?;_0>*0ZQan`g$G{O-+AYqCS9** zHX-T}f`{5_t0KoNny{_5b=Wzu8lyA}r>g^KY9yN;G;qY)cwL-SX{Va5srZ_(zKZ6n z4yDu3NfqX85+15#23v@ncOK%<8@d#99i+8XI!mO5p~noR)j`8?^Nq&RF{P_9+LB?| zZo4PPU^)AcEg}CHV~jND2%{b>L2;W$EvYo5MhH4+jt-U{zA2mzFe)nubLRRw0bSGy z-)-a&umcAQ@UV#Zxjot@396>Usu`)S`lkJ?<}W{-7!crs3%1FOS*GKwV99D%%yPgC zqSc2k97hwHAW7aJID-f-OA{4@;3Y5+3vx&cN6pEbw3uT9W<{qtS{ca+wbF$MwvZ$+ zjA0iLfe3QM0(=fc4oNP7oJ(lM23i4FzS3nBuK2-+QQ-<#1X2}y&8uBd1d9}>7?!jU z1z=U&*S-eg2hCWqUnt<$zQWkA9+dHnDCokz1lBLTJj{(H=z&h+*aO>OKmt~%g2ply z2A%cMNfQ5fnH5g4hEtqE5-}i$10+$%na%7CHzTCUO2!NV#G?+fcoNI>^O?@nAq+u- z$ahpSG(4CiHhznZY|euL477r1Li>&^zoWLbt!HiGI2$3vfgN4?QkQrjz$`BDj9vQD zI$946P4dJ6 zoRm2t#DJj$o#d0IbO0>z;YxhqL#6m|12libE{vw zXa+>c0RwzZ>|f1*Fu2lX1w_5X5w*etAl}O>Lk#0r+ESFHq{Xi65&#NT;McFL%ZgbP zOBKP=3NxrHi>Xy@Q8A2`^hlWfe@b*Z_s9`2Xf2;bbl+_DN+AI z-=UpyHTRX}3(S^GLL_rP{_SrV;&6v}z%7}pxn(U00g-Yl&YKVRR643>DF9(0RvAbK zH#e-|H93Ntih2|`A3UM@7VRMiaR3CBl@1SK;0~J5#U0=V!5Z6`#y0+`(;l+QmiPw` z{b5N7X3)x^r6@$QlO5?;Vg=NVhIY-HPZfH1r70n#cfO0!mT&`-!+DBRnL3=8U%*Xo zDoRmqaKj7E+~Lew&m7amfGPs814z(7O>ttCLEuzC_yr58O{-I|e(F6N(7*=$6M_pe zSJ$JcmC(oX-U1catP183gFM7w3rkq7LrY7oYULmi#A*`Gk-&2c32Ru>dRhOjAjQ={ z6apfMiUFLLdSWDhotc|D-9fM#@j(;1wAd zL9w_*tR8e}1cQ;0zphCHMgRMA1;Di^wCNVp?!)=z|VvNGibCC1S^Ui9KY6LRR< zDP2-Z)`0Hh6pF8>CZx3j9?${L;FBhvaR*_J=NWF0G0k=1hG#ru7Iz?NNw?t$qJQ{I zVNQCcba5OFAN|8*=4OV)nT{HyV+rC+bJlqtt2F1y=RJRhF2t@2T>$^R>}4kv24+!q z7;AzQnsB>~H8H7K)P2TrkGt994mTLXJ@1-O1q5NtXtt~34v5dysY3#rDr{(I3tG`h zCWll9R6au%5zdy~dZ)S5{qr@h`=sa&g%*+?f}@9E7oboT7$aU21fc68x}l0giBHfV z$RAQw^(sF%yfq%sDLoA4b{Ubzbl~(hIZYjoUK0zIC(Lb$F0``^`Ja`591~CxxFeOk?ytM`r z5J*ZW0T^RmEP+a8wM@Apa~V=&d6Nzhg<05#e^)19D1A+15S8Z;S(E<}2T>v(acWya4ku`T*N1{x z1w*X2RStw#*w{)?03ch%di`T4t49(TKvat$11-c{CMeXv2XKm>ecL&I{B zH*`Z7nSSZlekQm>T@aBGxIx+2S44F~e)W-;zyp^ck`Tyj5lC4-0 z;0KUJ0GHraH~Eo*B|{%5lqAtWR0WbeG*vMaRhK|oK513e;*eB1mCey<_2)pE=0Xwl zkW={^$Wbk}K@OUr71i>P#9@7))*CUva1M|cZ#4ff595P8$b)GyesAd()1e&8qGC0s zVpynRg82-4LsnU15VIf$y3sUpawm4ei=Y^DdZ>qBh;#5!nec&yd9#Pl03UcVCp8Bk zvk)s_C?{F>Ou%pq2LJ$zh-Fjany}eB^YIJ;Vqb)44ku*}z)&ee_hEr}bc>@Xa&kc7 z)F*wyC!I(tiUc(ou_+R=Al|YXI^hv`z&VUpB1*#%NTms!bBzjdYL<5pr*1?(WBB*6}g5DT#Yq9J;bJerYP;-fygkv}@58F@o`b)*teK0os_%7&!M zW(Io2SFI$ae}#=ynv#C?p(a?Rh~NkMn39Y2kufA#Q>CR?Dp>tEja79VA2<>qsDFr{ z3esYMhW3HY@sL;fkj+9Z&hb^uVO0~LGe5 z`f_?gW60vagTMvBnhwap1=1i5hhVLT zkgbQX4BILV%diZhAPu4buA)$`gCGiA0IY)m3ZS5_2k@@#@U90CuN}3T#{djwhXDs5 z3P@0{{u-{^daczOuF}8-*?_Lu&<@MWJMt z(8>jG(5}S_t)LLBAsehBJFFFD1FE@Eyu+|j)*7hep3_;KJK+&G8w10%5PDD*MDSjp zLn0t?Jr+?`mFGR^7@@0Il6Z9+8>)VMrC0s4ejHh~R(rKotC2%0q{E`M>8G_|yR{st zkwMCl%7&qc;8%ZDkvG&z>qq}rZ|k#6%B0FxS7$4=e%VqSS~1 zDk@bs#2h4%r=^E!owk;_Q6-1UsASvUsdMzZr0S`BA-sg(8nPretSUFQ zWJ_w(1tEvLYcm+9>Pr$Zz5KNv$)pmqbY7>?9C5?EXY(CMpsv8`vF*SGqHw+*i>@Bq zzR(&$t#H2bORU;jzxF!;_N%S5$l)66Un3Nx5gdRq*ObleXyaBP{%pY z4NwCK%6h3ALzU|s zY{f%xwfsf$-RvO^jqyBm}nv{HYdhM%lP6uVn*x3wAG zycu?h9ia-&HzB;TRB{O>OTz><#!E}C0lobtH}TA0t!g&XS)Ce@Dk4E1v!FJmDod`> zyG_spXCe+QGf6I!U2BjZ;?U3wT?buR8BInRz!eG>y#*HiaMpEQ2`33$umvE!1=64h z(l7xfEe#^At=M|4W=9TOkiiYyz$>k-3XH%u-M@M;OxU{9)=I$_9Khj|3xMyu#~iz6Zbu#{dBK+SOa#vNT+%M4$=BP_pbg ztnA7KrvU#A9V-dY5DIY}3K~#cc5T&K5RWuK0##52bYRL`vZYw=4&KFw5$l2T33Y?wtp+rfr$U zE>D3J<|b_o*b2#^%bxtp4pdjh;>r9;68#90)e=_70e_hs6~Da6sLW`ZK!EIGZuf0k z22uZS+`N~(QQbHj0|8<;#tWb34A21W61AkBtD(K5)GKk)hcP!}%n=fxBQEz0i005c zYSML7mnL`+n{|*QqEQDYGbQFV8u-**EYmV1!(BLoU4`@p%T;j8_2iylM{8hR1J|r? zkPXesLp!DepN8_Wed>i}V1uu?4z*&x*)EeTuRv0P59vhW6Z4oQ%7 zVKWrum0Bo7jUOR1ZL0!zEuVqFb1c<>k(&20cZbk zWuOI~K|#&`Yw+vSZb&XbS0zve&n^a9unUMMicwSBq(cW` zKnGT^+r?enkDcu3{@cE71?IlnMIcvtMF-rz+uVNd!maPV?c2Al+*J?-wXFjlLGa7i z$UKmv1wnxZXafjAfXx;aSpjeBA_SLk%esc%x(46l_-pni09q7BTC^_h!jebC%9C~S z#8zxCm=(xTY`=U&J=EZ|l14E(k{M`|E~yoLFtM>GOqoF*`;S1t2$B(`Q3Zx131;v!1W*Uk zE=hy$2>`E0Rp1HmUhZK)?2k?CI^*o+?3=~38%T^X?T;LI8?5f9Lu! z(*;G3!*PYgSuFQ&;5aA**sc3l@LbH1Bh%eH*bF%goiU@Zf%($h$Tr|&wqfJ60~9fA zI8d!Rh6CBS9XODI8%jh?P-a~qpi0%OLJA=S(2YAFBt;ihFn~h7J09prmnG79!5kFpIOZ4?J@I5k7*#aq26KSn zBa9W-cyUJ;J<(CeH^k8;yfxl<<3}TlT%*V%ee^L5C_NEJ$~B-2!xJm9#8Lt*m-KRt zOEBm{mN&?h<;*fAc|%QE);L8LN#2ZeO*rF(Q%*R~)N{`@+9V(r3{bG5Pe}@uM3ypS z@dOVAcjM2|bfA0gwsdIFMU(lA%Wl1pFyILT+(IHLr0Hmw&D7gS00|@+Vo(*N7@{ai z2eVqL!X<-t=;4Y>2q3}?KYB>3imfED!lhg5pw*;R9U%XK2I!o1c2zw{P_P6&1S%mR zLTuov6$vCDB;0TbabUerUA;}Dk=P|^)R5AuwW4FE$YUo09H`QwigfIEDTx65{9?vAi6>AQm$~?&0XXj^4TFkYcND2JL3sja{i>lP!kc zW{Uv>;A9JK76On1J2|mc5%3Nu&|dG3=K>6Hz2MLb?rSmU_KrK@1pK-^%Y7{236$9-uWi#z$1)3^ECg^Gv7S3P&l(;zx_kmKXeTO2r%P{KEJf`7?RHI z$UOiS&Txm*gnW{70aYMS6$DUVM2NsZ49tQ&U04njENH<9UT_u{+)i+oGq)KmX9lww zp=w+pvO?IvS3Kdt2~nb!9h5}}Apr>uOr;63F|atuS&nuzA+=_RWEUe*iMI%Vf-n%m z3ge=PxbU!>bc_TKQ)HB=tjMl(>4sDyDS`hB{J;}(bfE-Ja{B7m+ga%s@7(Nf)f*RRXl&!7bZT%M?_pmKbz_09{C;74UG75`+N{ z7GVo2&vh>UbVq{85lFLIkYJp4}}M?=GmZdGzkSU9Tu@;+a}o>YuGM8LI|>ap#97+NoFY4JHkN@ z1BpYN`h`}sqg`N!IDOxP-gZqK7Gjp_%Mj7c+Nb1F&h*Ji=LoX}JbA0>l)W z^#ko_MXQP~Ah%^&^Vt-pK(7BJLg|ifv?E0-(h34-f@BVu!F0TH9I*+fLl&Im4`bT}Si%2d877<+ciU|W|Fay_O8r=HX*F&nkL~}w&N!oOmyRA`Xt4zs7cBL$gZ$Tw2 zVdV_*uM4!u8r-`f|fXX1+Nd=;~Xd)Cv5n=aM-}6ZxU}?;o9aJVuOtcB5*CZz@|2Q z?TcRv$8@nC+U*9#47 zy*79`yH~Vr5N`i(V_VwR)5FBUcyct>4~T~JY7yaB$2WdJ;i!HAsY^XXIL5ImZhQf% zgXkHmfY$Ahe1a3)fDcht0HpeP zMuBu8_|T0x18+_TULl0nXRw*g4_&h^O1)Ez&VB9~-MxkS(;sr{XE}6jrvN1!@OJyk zucH07do5mVWG{l<$cFET7ies4VxI>>khruFfe32*HaR-P_rl$uUr&KXOuH5D0DXPI z^w7WH?+^bi5n>^2p3@j!4miGSjkSH~@1{13r*4J~#$7ki%nWf+ldo8>qWaKxkCN;vG({n9K$+M9F7M7 zJDC59Abaz@;Sfc8OP~T=#o@rKRXjig#4)OKoEv+E8Z3}2?8Qc_5dUC3azno6U-r_#|8m|0;KZ;vM)zUs{GXw3bFVzaTV0*?3j5!{-q(7-2B3J|>P=#{5FJikd zozphZh_`{;M);~eRbVf6I}QcvI=&LNjgvV3%QjkkMOHLGfh@ouG!AVPw&>fobrh`# z46TN2NQC4-d5gG=+cti5Kj3P>(egn1GOYojq!FTl?$Qn!bifembS&s;jLJ0rC zCx1G=$eFX)iKyKmDm(y%yF-y1P=ixY1F`f3H6Y6-s6#1J5OeT^;BbJPBEC8}krRY#yV;JU9HMSH}_;gFzO z1f0qQ$il%P0OGoV{LFzohgxI<$DyZq(o0YD2&B9qjz}9yVuld1AhZcM3^I;xjJD|$ zM{c~nE}%AJDvb1~FFBa6ZEQ!0jHyLff$|G3M6j=jv%unvi29j6X(I>F0M6EEjV_2O zY!nl0M89dY#@?hLUUNkRdc_#*KG2{}3536S<41cFKzcjR%*@Py{H$w>sT}|8K-HSJ zehf#41kiANpq=m(iR`{-tjPC+!2c{R8LTX>sW5N@Nl4<2*vux-;zx^1FRCOtTpx_Zgu@DBL+CIJ~cy*iv4gAbq_i8zR^IJzn*nWCQ3DF=WS9}UVL#k3NQ zl%_m9b4Uk0Fo#A#QX(x;w>-mizyotQhAFZVXxIWp2nA>Wg*pfYE{Kyw5ue>*wcFSY zJiv}w04BIOyxn0Dq^bfIX@Z8Ip~Q}VQyf6UkXQRLSCgw7V*{*vg$w^6Ro~NvSBOQt zdWFerDgOAUq}vY|TMrsI55!so`T`akFoR2g8JLMALc5MjK)D%+KXLRB4>1EM(7y9% zR8w<}=y;A2G!NpeFHf;nM95WZyhcRmKIrrma%|3s+lg^4Pz)GO`XUUO@zq{+86Id2 zGw1_9=z|sbMtl9nKCpp4ST~G&M;#Iy28vV;v^ezBK(VPe{A8d7syF#;*!V=a=QKzC z>d$_ZHj5q56~Y&Cl{ej_$OR2h2K`Tw$r|{Ns!%mf%QO2Xt|ET#E+v~k4TAwY{4ok$x$dF1cd(}1YKejJs1cly&|^^ zDpeaELYN|`9UnsYTCfeLK3&~CZQaU!hCOwi9`#Wh!bE8CpTw+=xo{1X@q?JL zq?myjKWGj?8=W@G4#Yw%>4>CgrKGm`QAT|Z=|HcRISt-@*KfRpKG0tCh*$01R`=4r zJ~%(}9bb9%13zd5KM;b}z}}aUnR#W`?0uQmu%vsHEKL8%0sR#MNT8XT$xhekgLv%& zd5u?V1WtCKzkTG+-UQBoV<5k}x6k6ihyBM{WY~2?&S0a+i-jg~AXop>SP&jzUn${l zD_2h`VS)oL>10plS#0}@T1o1+)`^y^(^0*)VVO|Sjyh&3BV4D(E zwcS_}90`LZIT9#&fje-U-4LJQaZ6o_6u~?-Jn)WFgIX|V+URoHF^;Y(9iQQ$qVZW; zHeT9s5nFK}TSACqu7z4GRfJr?<1NsDH5iC8-HkXv8R=k5#%u+;kQfM@jn?S^)=S6^xmgap zg&SEVry5qwx>Za|gqv30Sj!oClHI9Il$hBhu=y z3zC@&xQL9AxtY;$jb)`EWmOsaqQ)*rV0!HX9w6WqkXQP}UYZdCAsD}Jd>MO{=X0m;e%NEp9^KId;dXd8e8hJIH9*4A7V;CSr<>vT7A zxBzkhFJJ4m^|V0=y0BGjSc{`JlTKG2@B0T-}>!9WDxm5XdGjhFEhh%3-H*@k>TkPXKUp3dNE$IAbrz!uK75zL^`%E1f_o0y$AVavgnL)sE3 z5+^>B{1FFnkcB&v1+f-u2{@BD?ioPNr8|n_a0!FwdgCMtTd|&FvGxQ>*n&6Mf-RVU3CM*l2!&866YR+zSqOz}2okHpsd5A)^h(QV04z(Z?xZ<;a?Pxfw@@el}3U74e+^;i+*+i zAyDv@c4vUjfh^G92+slvk8qY=X#&em(wL0_hYPHM3*Kmr84%$5=GE-;)vTrC)vz6ZM4FweD^x&&>JYg8IsQ`-#+>S&bYwh9yz z2WW-ol7&>LE<36&auJ8;3Ku2C;sF%`Or$2?aG#6UT;Z$j${;Z*^DCg;?K$SkGfw zzhkteY*aUtH(3g{m4r2rgi!DV-*KxxEs#5?%aP4pMe0qyMhn zmMOvLXk~!+?t0JN>d@j_CJmH9flCN?)*uas2jE_9*I_1L9;nxPwpWXPSO2|d$#OQi zZ~+0wi!wSPB^P;+XK9wMnG5fM9S|8M?}02R1SiM>C#ZQRU;-vMf+JvpnlFMKAeB%d z0X$#{C6|~6LnT21dhP$#ns`AAB}e&%-c?T_P^1p?ooMlMrLQjV-3wQXTcL=ccq5z` zdw%ip)V2sMur7)a`!zxqt+*?C_>XIYtLT$Ovd+s2((1?R6PzMQcuFxMB(I@@W z7Z>M}0MVzT=^E>@-t(|J>o@ju&yJ(g{#s49Yfb<3!v1~WkK?lrk|QB?S;&Sn;eyIO zg*P~b#fEHYVD-nQ_2`fO33%-5p8)HJbv#D(>nRjnj~`S=bqy&0LXo2<^7iJ2c5;I5 zU1n59C7C!#e5C)v5u$LDQwV=a7=zIVh${lr#kmp(1&US(6&^%*snw-R802)36EUJ3 zigG4)xuoghB?liJ#E26kMv0RuSFUv6@+A!imuASc;Q)n7k`8RhuyKip4L_G~-n0?a zj}3$ig$_+x6yZ&rQV|M4A+!%tKRhl8-3s)p4IW>G02N}E2U)Uc&x$n*sVWMySd#Rs1f22XWDguUuk_vrd z;8_308e*inh9{mV*qezxlrV*?J=i+Mak0f#MHO`LS_iM7t#OJcWe_Wds$!gCtg@@E zVXPL#YLSu-!18)6uYKjzlTR-hRg+&;?65->IiRqDA9DC%l^<2PAcSCXxR6C&LI`kH zSYqj`Z(2e?Le*Yzn2T3jbQx@~5P2w^hrtS+)vgd((CZhuyzVMn34fK~7srO7VANh^ zXzglw2C4`)Txg(y&0AnYD5x5Yp@Af%oucfpptV|sC#-rB zMypM`nl!7!4jVI=pNKie7^J3>HL~Jy*PC`<2gjXvWt)v1dBE8>;e8IeU1Wr9yZ!$* z+U&h8UWHK7n0I~{26!af;!RPZgM=3+qKOAdsWYyUi%V}>8Tn4?RwhTrb-hDUG1ZpyRO zigc=h{GWu{=^3HkJZS!43VQR;pfLt!Axl+SD1#?f;~M2KP&v?0PA43Avv+8Kg31}g z10VPfkvWiq7W7#Im$j?|N((fKsX}agb*&iiiVk!zO(#4N!%l$0S9?K-3+Vsg2^S7S zhIA;x4y<6SLI~grJrF<^kZ7;D+)DsW6hIG{n1wvF0R?TygRSf}L;)0{2uCzxbez}* zDB3CxwW>l9tgsjn8p~Kh6HREMg&fcre^e0L>}P z$~+uuCgohD9uc(%MwOca;;#9k7xm{-k~rR`LU%tf{poYrsM3!1!@B=l9@7)zu;+j< z<)tpYlTOf^0G$F#J9eV(o$!Pw=lWT?(IszFUrHw^b;gB>?#!Qk!p5D-_dMoRZ+y!O z-<>l0DL?t?ku#HDpTeXFXbegcoYa8O$`CYV4b5b2Y$FI8_%o9YP!bo^zyo7OnlUV^ zHKkEt1Vz(82)2f)8oKy-EhM!aT0AUyyh7<*6zBNjmmMQE&J zA6Nzf-YhjSlPS>lIH;T1Y_p`iEKo5B)Cy{_3>!SHX;X`Z)pq|CtDU&2H(o2-*S^D& zudQSZy`hCpXd$-Vc%ch{yBI6HPz#D7u4C;O8s0{*j=WvtVxAj-=k6*tvzg6qbd{_2 z^@cp;Sp#suJGWVeCpbn5<}KSMURo09KDj(*FeM~R_r5om##Ecz)+0IfP=}h+td4sm zMV+~!54^h@mMq4wDNQ-F!3vgyf`K*$FiGNngj%Pk!bCbiv2&db{;-sO)T2wSj&&uL zCl|I5zU2utq#=b~F6fjd7Pr`-HU^V40vfvEsdK}F`jgE@D@oMg?0}&&6Pp(T5?n_o|WsG#fSk0Ft{pLm9y2cY5@j?{xb|*qt!!G=BtfPv=-Dj$GMtyl+ehe zCOhGpHLsbhdnPM#qIKp`yV(jS%Bwnxvlv5D0ShA#!x)k?vtyIe9W&Gw`*G2|xf|m~1TsU>oIL2To`w(JU7yqhJ~6Rrq$8ccnZ^VspaWe@J3l)3xJM@JDVeVSX-VV4DTXyDDu?2>qjegZ7X$G!>+sHWEUq2pyxXCH;(&S1^K%hsd8>+Hy2swL za-VI-bt8KRbf`AD#x*W+i7N^{xK^}ALz)DV=2B$Uykagt+(<|I%*HVeZC+mm;mZbF zkgX#g3mEF<`?=74=Bl5SBUQT^TMNLg*y;aGKdvb3U=`e7#SXe1ejxs!2ji#qwY}|x zA~?a>*KYq0auDutTl?GB&I0?@z3#@=o7qLU_x_RIV?EaT5#Rs@oWKpBz;(hEwBKYT zAhMAjvIU%j225&>)GePNr;$rr_WUN`m~zjD`h`fsq{3?1w$!m)+FIkA#BK(TvZ5N+{S*6apbT z$jT}G)`*J)wXi4W5;-O_PSpNQ0&SP%1f9ol8o@}!B2wOAs(Q|*k{eyENlc)}Yb z50}`C*tOj$fPx>wkkKqgCXGf}g&_Z09bzAvM#RNXA+lNGL0rVG0VuEvOTCc>1mfb+ zkqpHi9mNpj^_KO4VxH+5Z@JK7DBH2of#}uICoV?rogVA)N(peEY(&BEMS%-M0WR)^ zF6N>Obb}0Z!!HJ-FGhh2(c%u2Kr#-7VeCapSd8^S)+#PWW9bSCU84|f3}EO5H|mAP zD5Lphf%)}->jjazDb`~tmST+y5UJbhkqa$~i|V<+4&;UFai95(+qjS$xpkYw`~dt} zo42uF09;$NdD|*vfnA724m2daNK8U{n?w%e{!t(dtY5vY-}*7Z0BWQGdZZKFTS#78 z1=brAl;lYUz)7B@y{V*D73BW}!oVL;#viN}WgNk3jlc+C!5Dy5SPc+S4bZYEP^bAG za70?ts9CC1n4shj%4C*;X}>jMFF`v+Y9O9xR~4jDMo=SKBp^QOX~5;4%nhDRzWZ7z%I&wdddJKsHY3C zCog^<_w4{)timd|0A9#|VB{hTT?=s)0UcPuxI8E86~Q&05pSSS4+zn2)QYV<=xjWw zgxX48P^dUg=!NcpgQ6oEb?9RWsDR3f{$*P~N@V+S+qD$|`V}OK7Nm+QBqZJVr^E3pLP3;kx&l*Z$QqR~_g0T?;M(<9fOPB=oDl;)N|Xn_?i# zu~|VH`KQ6jl?1?m1ZY9S7RO@+(eDM(6`&EWq>;g<(PN=e#TqO+YN)#@mN+t&IzHAF z2$o^F*6KGXUvX-k=hE5&<2k0ag;H1q4+$!(@B>cbx zo+Qrdtj!Lsk_sFv?4OVl=}Kb3AB;dv?&J~dB+y>%&R%Uz=4{i-q|FN4Oe$%WR_V>& zY))z*42-}@p6!&TZIJ@0kw)8(B3qw9RiZ)F7>oec^kgc4mBArPs#t-a{R|)356Lv{ z$dJq#q>Lh1P5 ziJ_W|;mmB-;EBrp5avLUjwA$>^H`6HJrC`m4wu*tc#VkMxL50N$>>m6V+vGeHZNy} z$`*_rrjQ-~umH<3cmmP{OR#cpz3KqA&_Nv-Yp)zbuY`dLA!`+=L9(`xV*IA{VWQJq zO49fp)3_O$Azssv6|rbq=M)8f?aX=m2W$0InAImZf0mM z%A`zYl=2yj!5M(A2#oU0II$9YZY57LPr~sScqvZ~&}vNB{`d?Z?Q*BsPoJt({Jic) zZB$kMAckGolQpkOC7DQpY8x`M^E%Y(*vJ~352kDi>L3r0B~p}qiPj0!sAk=&Zow&V zNoT$R`nF2ok;eI;iV6-*QkEbcsIT{e#xWR|4lyhH(t!@}vkr)_KnFChh;KbZ>#sJA zDz)!IBaQo3fwiFTI)4VzyjjF8qC6kVB-S3WypbF6mL^%1$s|V`8JftnE~p4qX{1vB zw%CR&URO#0M#jwIU*rX1yh~N^01D`|QX~Zm$O~_Pp2NjP#RgHk8EA3Lunn^?4X^CV znwqK6aCE@%4L@laG_qFRS{YErRx^-Pi9sqz71oRln|?wrNKYCRYU5h*89>HbTQTI4 zjOL~c2f(T5wsPlsGB2aD&unfgdooaBjbj9^vHVQnqG{m48c&H8a`;)!hA|$ev1NQQ zW&iACx9!fd7SLigArmsw_HCDj_67FYmAV@cF`K&e-vBya^WED8{@;^cU>NgtUY9Z8 zdafF)@!#(D8jk@LOfnn)wi*vMPh!E~2Cm{FH*)hbp-h;XPM9v+?$7w?%`m0^X6^F- zOy!)q)TS8AR9+>gNW!INCGOsjRZ`f6rQPoO80gTBdb@YpZ5ZfyLY+dGno`)8IQK(I zSWvQ2Yp7Y|mDzCV5OL*R0Dzj*z+lp}AaFDd)3ge%Hu#y{Z`80(J6Cwr*+jCi8i8tIeQqwp3*Q~U-G`)Bv{-jJ?L%F4n%pTn}m6Oa9W;xFRYA$?28VvJUe>s-F zHC;z8AhGghJ;5FY?z4ntDxeRkNPrk%h@8*4s>nH>x8SN6E}zTQYV2hH1s+=GU8zMz zA0hv3+d_62yIN;^u^_vx+d7(`xki^h+y7a5y;b#N0pL*|;0qt|07|GhF4hgZb_KSY zt5xzEt8pp-u5l~(Zo@j(z_RFq?$3BG0NwUjo3UOKcC2}6F7H%p2sVU?C9L_Bv4o|v z^fys?bgB%^Rw{>m3rd8^&W1IZ^SU>nWR(8^3ZDR!n79e6iu2Y*GuUlGj>T$)u_a0g z=3jPuOZE4&3{9%MnHUW9cNWmpoU`qyP7Y=Y>p)EnUdmTu3XVVxmCR+Pobw6>o_8x) zVSjjIum)=kP-E=6Cl7Xr<55^e&{u&er8_Lf;#E{H)(#uB7W9Dshy1j>D8)%+3`!8W z8qK^l@`|juo~`gkaX5&pT#DjuF5~ucOzi~(Kg z5YIb>9lDQyNxjLd)`_TW%7ZDG0yPV&ga)!C(7hAvo@v@@2o=GXSUYD5odU!uNdqOx zl62~g!8KvlG+ZO@VMJN7AW8^hF-*oVp2T@-C}vHWQ>R3hF?njtNRuT`$r|a>r9)2| zt<xX_+w^=+@PsRE*tFpET^%z?Uyw4u1!8Fl;!KhBKcMhYF<# zvZBY6B_op@8S~}Lm?vz8JRwbIY`Gva4mB{;7)h%C2@YH%YmFEQ5~dWHeTDYyB2y$- zF_3$9@Y}*A*dBXj%GjE{t%$J=!+DVaMW|QbLH)Y*>f5PnVY}V?_n+UZdmkV4?OQQH z%OqvrzCCmp@XKgvAGbYQD@CmA*x#dy>%@>x3@lQSE0wBXNJWe>9K>P_7{=h>i4o4= zU<@qI7-0+xG5l~s4MdnQ#KJU~i^B==8l#N)5{=s}$x zO17dn?tI=3hHIyjj=G_PR#50`sf(`vsv@GZBIxR@m91Ln)`PA+7USJIDI~|}x{PW0 zU!7@hT;h9x@#8gR$orL(wEtb48mo(XAlgu@-R3uF? zTc2RfI_0$U4Lfz0gbPpVIOZ6JJo1E4gt#EI_cfMh9{T8+mxOs)2({jNh#2a%RgN;M zV~Q|T4WooQ>L8?wI`F6hk2<^}_0$+nHMLcWe!Ykgi}a^e0#@_Cl~%Q~Rk3VkD_MmK zBmTRUv0_y!2c~OT&ce#Ewju!k0puYM0ziQfY+wTv*dPvZK!FS5&;xP#pbhE}mjz3> zpQB``DJ|;6Qe0G^0!>b9N->F3m?D)iyyIRO(xFq5^0pu4P;o3;-DD_by3;6$AQOR2 zMPMVvf*6D#N|NG42C~J8h~tYCvEQqL6$YO5k7p%7P7kI)wwqnyD%{Ef*>q;E?!X`b zMd?m;dgimCZN~}MaY7M(P=rAeZ8`x+BqH(1mH-UMJMDsG)WGAkpgG4odAwxMdLl`y zl_3>#11020sW|FLppG}AqYK=)AE(g>IwL3$70N)%xgn(~b<5Czupl9*6sRh_RFE(U zSCs+-V{!-*X9I0tF}U^UT<+%!p?Yc>~YRsX_Z zD~*JY5LRH7PK{-*DJ07Zcu0<_2oXX7v_SwqP--50kU?>^0jf|vssLJ%hgP&=g;$W! zQru%T85LzfoxqC@S3(rCA`Wr1M9R^MU;vW6RbmM!9NDCzQ?en>UiT_jk*TAu zvvHNHC?bJifef+#gT)_hYQ@;G{4_boYL-uZI)!q@(OldTLb=LCw$7$4Jb6r{Q4}ei zMouSaP6&W%Su35@4)O=8m5vh*ImkmMG5}S{?QT!2$Q|Huk>4>&cZ#DH^Oz@(?i!Fb z>2@RPm@Jia6Midp6v4#wWZJQH-v zOiW#tc_O;ZC5hK;91g815;2@2DI-YSz;nRvGfK}iK=+s6CbD$`Uc13 z2~c^GMxUg?g*Dk}4emRJCkDk&erDqsbc5K2f~Zb4a^%|T zR+q}vkc})@+Gws4PN9U(5?2pUP{IxNx(7B8!e)oP!C~`Y*g{}s4|Z^!9sF@R&yM!c zt~2f2Dh;)>B^uENnVmmwr?iU{w`*Oi$UJuECq@y&BgIe?>g=Z`ZBed_kW!N?SYeH- zl@^z9zp0vesw=rMSXhA^T^aY(vgTPM0@D# z@=2?JEAVxB%2UorZ?1e1E0i(H`;+O~K^m&O`#mG!ldHLC9n_zyQGz8D*Hs`Lhe<$M z9ZGEjo9hhcBnad3Nyvj7lJMp@$N9}|z+fC&A%O4=_U^vIa;&yYcM04Zx~UcbsUMC1 zGgCua)S5P#?qjWcQ)}AMidJ-~i62763qbKg=z#^Zpg|3y0Q#SmwX)iXtjsDN`yy04 zu8Th|=Zmn>0^pXfH`@aj{F;O5w}JV&RRm}M4BSFv>mds;bfz|dB3r^sk2*;RJw^g0{tG3bi3RDRG4vua49o@PD>4)#2IqpAnu(g|BAmQwAdch*SEJ-k!BB`0 z1&a^`Pl3dWFzYC6S0)Tpj-d)lKnJ|SeA1`KIHKxYU0jeHv5+V|+ zu3+{=#%JW?TEZ)sI2dSDVn zCLwbYBl#md*s3bL1KzB_6FlXs+6{BwB{pazB>wA1h_DPk0whR6AW{Mak;K5}A_nCm znoa~ItkRoQ;}ld*2D{{&9D@Z>;uMN%3h==A^dJu0G7L{eF5}=-LWrYS%70o#531l8 zv_J|+r4Hoq3}XNd=dgXg&{T|%ExnK};}Q?#2M^2v57e;BIEpX{vwhA`4^&LWHdB6# z&-fVV$YzC8LgiNss}B{3`&4KV#UXzL>wh5VSZ1@;7I6_1F%f0|QqyR!A6e+AK#{5* zZSr1GsXlMc;sMUy4D;x$I6-gDU~$ft6FG&!7HP3MZxQosQO-WE4LFY$p;H%m(GOa| zgJJ;sK*&5%AO=JT`q-0%OlbK`=+@F@5!tBs>@yx4jk2imD(Evg6i4_(LE%$mcJ0<0)b!X$jq=lGn9+pPXoT=_9G%aCmM?=Y zXsRY{s*vjO6m891QS#Vq@}g=Y)!}7+!!}^XC2iwsLhwh|gC#}qYGz|4X@(K&$`R`d zu#~Y$KNPOu%B@DB5E#ui*1$*I#x}s~xyB5#{A?`P;sIs<#792DAtYcZ8GRSz8CF5}Wv zQYC~^C007(4T=s^g@=7=PJNaRGUM_X8j~*5fi6Ka3`^B~&Tz_hVpL+F3D9sb&rrqK z$9;;*_^|3WSqfFc5LJ+oe3(pyuBsJ$pcQygScTR2f)!D16Eu+z1*od@ezEk1aaySg zgC>s`+l;A{%JaBY7dtOJ-7GxgAs0Ij7s0h$<={GnAs&*TU9&UusFONtu@>jmUgwn- zt!6te62mfkr`n78QbVW zEwYX<)<7@NKo@k53{8OO;efm8IzalA{P=GkuIE!hkT(PzMUL3afAqQN;_r z&{hWsRUAmDj73?DC4@c^`7jNuKCxO`;S^ThRE z1GcK5FJPfB4>l|MkgYv83xljG4^ZH$HY-|FHW-m_7~>#=mQNg)?-$pWg)DN{EGQ3< zYGuQ5f-NY9!%=O|HiL%kf`s6OY4{w=@mXJZ^zuMjXYXs-D1;h~_=s_YsR|%j(>JLK z&mavHvDbozQHoE|s@j)r8%_6+lr~uZjj@8GRzj#1E&+|vIA9S~SUH%3FF{xVwiU+n zSnJr1g%ysyw-+<`d%^d6bMX>*QH|mFR<{>d&Da52K~b+Nksa8KwRc&^7Fm(k&w@ip zjq;VChPxWc{oK!7pw9u?6Cgz>U^f?8*z)j7g)V=}F(p+}NwriTRmv6uc}k3W3T0PB z%IR3Qb;aja!q8L*AyhrrmE#~C@E{$`AyQjc$QZ(msBo8o_jfzf4fnDzi)u0H(plEf zD`6@mZPe{)fQ&DA@GjiiI&4r^;k}2dF9erz%W^| zSybs#Be(}5g6`}7P$Pc-OjTG43>PR?jv<&^8JOd;2}Whdz6TC*A}~2h2i8Xql3NGr zpbFPeRbpV76;-rDSy4UveURl~4f~KI8L@@6qu)7?XL?$}HxD%LeDB%KGFZ>p!2 zob=QIeu-7ThxIqB`ZrH86l?T_fjp{)9IA+VihWTLX!JdrOUk=>ZFLAjLW90d~D zx*cG1`J8M`nRBZJ@3p_-@CRsz@(`?3x%;7O9i=hSxT)jdhEQ6&HzB z+(~g*t9YqZC}~d-g+xyjF{s^95#EhlXipKw?fJaL+N!YC-uc*jYr1ZqB_3DPTJ@XV zi+afO;L*7M{eqJAs`xqI_gJj|^;(Bfh)LYPwYbI6cNSq$U*Sv`d;s&vorPA&6}aUJe48%%9$^AsA72RkB+9*o9Tk6&dW$_@dL8?8`oltvgZkTv6GQ zqd1DvjW-4ypak4L?c=`J)>A!utpu)H`_P^+MJPQF)>&3NwM~2Q4LjLQby63f=HAlM zoorSV=%i4cF;RViz|feDnGhsXnAL~KTz4=*A2Tz8FQ;zDa{Y6^uyZ%P&fSuc=bVs} z{i*=}^0PnN!QGh4du`e^h}p-s*LsnIH<)`PIQV%ur2PO9tiGdBprifR@^sOBi4}jv zSIPHSk4b!>O&rMAo#Cs>#M`&s+xJ-cT0B)euVGrTRcJM%w~C9py>-0(y&q}88inu| z#xr=RN&LvCSla5vQK+z0n}TgL%4y>xPe_pr zOD@F7kl;d%tq^KV2s2MYAt?n2QFsuc5Ss^upfDImz!U*Nff8+XB~DSL0+I?PniFWp zlqxX}%+uR9VfTBbkxpHlwuv?-83I}mw?1g*( z>2DkdmkJv`jM&B{yM^7NXa#q$Ql)(5^6iT!a~wP+@WjzWIYwW~k{yUHjY70&xO`WS zmYcb==FXirXZDPz)nq(;^*8{1o6v3C!|@0Y6NXUo<;n>;Cltqd^vTbkd)}-Rw{YRx zGS|_=`Fo5QddSD9g9kl&J$mXOKOg2;m^#YoCm(K`GG7Of`?GEZV1SpjGT*F2vy$hjZzrR1X}w#e;!eUBZJODe}OB4K4C;6Io;> zA)}0WTyzmeIz}jxMhk63P)R0H6(B|e$>d`~15NnTk^!P1L@NnK=~k3Lp`aB1hEq(z zR8VoK(-KH>97$FjEn(Hsgf3CYl0hvUq!Cj_5w%oHx(RgCjR{@kgB%jc;ZPn)2zsNA zA7vDv02{r;Qc6SWcoL*}#)Lv1d155iO`1k2#HLvBkVloF?&Q`%KMC-Ymy;QUrBSQi z`6i={9+{C?wuS|kt!H(`D_RG(g{50^VJR1|qS@7#V}VKe)?&^YXyUUrFstl{j|J-( zmL5*VZLyRQd);U;=Y%8+d~g=`Q?HOCs&1Y6n6*&0xmr%)B_^M{osW{`Smg<zgW@_o`KC$kTr#_htIjXFZdOK7?6y>VhsJ?kn*#=3T#|p07%DSzWERSm| zyc$StwjEk;*VI$rWrOyG2@%+1emo|G4So#x)`+6DjqqFu6FZszx8G){ZHMje1}y&C zhO3lr^5dT!>NpHL`{I|u3}_vN4aPVE3j-bsrmuO?%Qykz$a_K={ z^0FZz4sAn8a{WCo& zSshkV*T%QW&3YcPo*k>?7^3{ph;)IMbm+DerPM7;U%DXh4&o(L-2_ewX_ZSVwKlc+ z1WKK1MV`d6f*irFQZgZ3gapE^y)Dj82q}o0W^%f+wazC0s%vHKV%I53c8YdFfYB^h zhb5ng=yuoB7E@XU#8lN!cS_lbQ9|`LOWCP)&ASQf!XmpoTp~&bLcug!F|BD)$xa=j z6SYPZnC|(ZdyKK>R?LY46@_mvQgh2X+1IYwY)g>7RLZd2XHU6^hBMgtQ2VsyEiBoP zW(2*VZfs~KLiX=|2-{Z%;~)+^q(e9kct&;%cnsql!#Naem{J;sn|?+oGxB0j6(9z& zhjEZI>?uJV+Es#xfpDhdVGqgXvOWjEWiQ=xfQw>40vXI825{k035-gJDOh0&5X{S# zbY_L4R$*sCB$*S7HlC;vEofZjsttq&R-y3#1zjZnt6R2+RxX~kmXkCcSiXWQO)Y6F ztFvUN1d`6Jq^Nmr8DF-#SG!Kd5}CTYUeZ$IGY_FkZFB5F5`!tCV1?*D^~IqM*QMiH$4}%|<8b3eU1mv8?WtX(cdns+r6! zZ&*OJ0!vyFeC1WA_R_f+DUENM&gz~u$%#$3tYCZTtlnw#*%lj&$XfF>Q*5848*Vw~ zoAw0cQ=?-y#kJ2)s#?n7zGNm*Y8b;94!$$h_RP2hRfuPKWC}u?h78E&p=nnALPaVfZCq0g!&Ix_WG6@U$$6>5 zRExH=5;*aysd1u)uxhlhZW*jYi<(y5A_KcH4Xjs0!B|}&#H3}fSLbA1V9Iwk*S?KT z?X;s(HdG}Wyz;kl6oLy-b?Bk_Y`W9!nWN#1f-DG)x{!@5b%oHgp#>94P}){>OAy^m z3n01z$U<~6O-Wfglhdt3CaDVT7*0WHd~<``h_KSvTDsFQ^NmZe?#aG52%!XK>p^Fe z*}9!z1$msj>w2Zc*s-oCmQd1NW}^%LS?OZi*uf-3oq?Ke znI;i)S#3R^G|@4KJuIVhFkKh_pqjdjHn!t^rb|u>joOM={B(Vih0o_;CxXS}+a_6V z+|7~If=*HG>X+*|vd+z>AC_aD8{*#qGnj4z@3QkWq1!b)ZgDB!3iPU?)!EXyahXC8 zdvJy4W7{T}#+^+>#Hvkmdi%q~`+;Pw=X=jucD(k9psDrF1uJX)jI|bBBs(62vz@4` z*$e%T)|Z{(b24$MUiMb&XM!YvzGQJ8#yJPbVS586eA6Y4vw#(bFqe^Fkbys*Q5b`v zQy4fvpaC49(Hj9IK@6i}3G*B-b!8oc2UgHA4KyDvg&b87RXdg*=)oDBk!2?|LP2I# zNV9fPPy$gf9zF#|RAw*d>a9cKALxeOMvNLPPgHHH$Ul(;$#$#BwWlET3 zWj9q;;AB%(0&8YwTeLku14Kjge0=9rM?^%R=4j3*8dwB5spb=q7c_S`c9IunljatX zR%V_TYmCQzb~H(w*D0endP1;>rH2Bemq*`rDwVf=lSFN{bW2eJBh6%b&7}~x(nzu< zY?NheSVDQM@-`fTd2(bumJ%$BmT5*rUFM@ADl%641tt1MU7IysdS?@?b`zKwSXELx zzu0eik?g#NsXg-oho$5n%_IV28tiheKiY$WREyEh<+U`r#Xdu^$eg2|D$G1L+%| z!574VK-DoFBvoyPE>YMcx6Rn zWkhIoYA{uJU_?U%Y9@qsHO6;q$9Hd7lS$}=VCDc_nRWSew zLwS@=))**D)T#&_ ziLP0RZu5Hjc1N8uO|RD>x(9CHmT8uli*pl1NO)9(7e8H?hCS(q<}w9Xr-XeWh2j`R zHV^~k1Q+DATHVP#ju9CQ^*(jNAy9EM0CHey!z}~FZ~<~MH$)g5!W+C%8U}fv2KgJH z0fHf=Hy?#^#-SYsO^j_ooH60 z*|}QVqo+M2Bnk|5VoAONBmK1G2B=|cLcp8;8r1DS#U z{Mlmp(l8t~QX*I#@S=hq83tAmFb}kX?!ht0p&b8W1z@P40#jxDYBA~&btZa+COB1A zXJtHgF+qT9`m|4*1x;I| zg%DlQXSJg?YG<02QTw#er?pz^GlW@(x><;Kq&88soob6EHXs)p;=YR)cW^|Nf$18Mq`@sD_fZ0>ycEd9#d|ms^>pJwT>mnzTn-rdKcp9{j=3_rX@s z14`w!Q44)1{Inme!Un*?Pip{IU;tJS!-e3rHhcv(tiw?|1?q6Z0^q~{SNpVa5Pe!( z#F@pnbh=s3=dz?*M8pbeO2u~_3%^Sh22WMOB7&w=tHMv~!(2?nP78hNaJ5mwo}Yor4}(wP!htr2 z9nPB{@9Lj~AP$7!9ukm(0rM|wz%lNz1_2W=(<=euFwDFx4r@@%)GGnMJj}ujhSR%| zgs`9l+hkAXbM#wf9EqX#ilX8>u=$#TeU}#lD*+N<1?7CsQ((^jIwOlB0%yFcWkAHh zLs|k?a8w`sR9galJgTGi?0osGGawAY|7^%2GPR*brd^D~Pn(q@e8LXB!dFlPUONRd zjLt4R(GuXo5?#^dtkGAX(IIUB=c6wjIVo`hDaiI_&b)kMLNrfZUKo!8@1@ z9o1Jb2{sYfR}I#JYfNy%#+j!(pf_qevDd4)M^y=Kt2uc8^&~(4LqDEeKilF9xaKWCg@TYW4@g+Wy^`8G$8q+bk-rOPSb64E!P_|>TUChY*%T}Q3&Ky+(+oJXxzeSy*PZihq3+-3H-X!kP z9gV-rEZ;Bu!YADAT^z$*T+uAe-w&=1B#rL>3y$q04dEUw1`;3(+#n9AkP7f#&J>R0 z51#HGo#FOA;pDE-BMrj?z2oiuRAa8r2oK-e&cpi~%ml08=X~wlZO#QR@iTty#a-OY zEDQF2;}~D!3~dlqZPh_;A%N|)Tn*SDzSX7JDPl{BoyNghoWi7*sbbqRf{7|w;L}XL z*MPjjG5o<_E&=K=*Eg=t?(MDzI0_39k8 z?AqD8%cnl-!7bd&%<8?3>bETpk+0qV$Sus2j~v`PA46!OJJ*pvcQJW!#Zr7*I^%W= zdie!w++YZX@q3eMN35sYz;O7_B}~yUEZ|Ac!yvp=UF_Yt-|gRS`(u9J70vDjVDu2K z4*d@B>CWygjo}@?pND>J#yoXJuqOP%Vxsw;tZVVowdLy zS6$n-gbcPFSdft2f(6A9Y^#pYlsI$Y22Oi;3d#~C2)A`ym+s&xf(P%tjCsmlaS||d zw)}Z-Xwi5+nafNC7-K}r00HO1t1q`y@{g#aeiSOfl;-;nIpf$H$T;{0QmQZX zbTlxpq^wAe#m=A{YABy9V(B4_#99aLCk0DZ)x81%d2I9iI#x(8DPJ?5U}gpppu!sa&Wk&Z)c<3s5sp8dIS*%@V*Y zvvdlnE160yETn@9d+adE=wjKdujW*1&XYCPctf~tW0Q5a+kg`;xLZv$5jp0Vqq4Q<>Zl?*c*Cng z2kzh{Z#(?-#cwnJ?WU+Aj41@Btg-!Kh@l6BV~`VtI4OnGVK_yaQ&N#`f>1%IpsENe z$2N9Q%RwI`xx%(=RFLEiuMh}P4PC_0sGmHH5vU>rvSQ}GR!l{lnmeSC#TtjA@Sp1P zD7Ew|nDVqcbi%`e$g5PlBDJfo=35IbRbhpUtvLKTjvHFJ8BP|yNZS=N!2~0SFI}^g ljBLJkRd!hzWocDMSZ06U&J^uGWA diff --git a/wafo/bitwise.py b/wafo/bitwise.py deleted file mode 100644 index beb72fd..0000000 --- a/wafo/bitwise.py +++ /dev/null @@ -1,97 +0,0 @@ -""" -Module extending the bitoperator capabilites of numpy -""" - -from numpy import (bitwise_and, bitwise_or, - bitwise_not, binary_repr, # @UnusedImport - bitwise_xor, where, arange) # @UnusedImport -__all__ = ['bitwise_and', 'bitwise_or', 'bitwise_not', 'binary_repr', - 'bitwise_xor', 'getbit', 'setbit', 'getbits', 'setbits'] - - -def getbit(i, bit): - """ - Get bit at specified position - - Parameters - ---------- - i : array-like of uints, longs - value to - bit : array-like of ints or longs - bit position between 0 and the number of bits in the uint class. - - Examples - -------- - >>> import numpy as np - >>> binary_repr(13) - '1101' - >>> getbit(13,np.arange(3,-1,-1)) - array([1, 1, 0, 1]) - >>> getbit(5, np.r_[0:4]) - array([1, 0, 1, 0]) - """ - return bitwise_and(i, 1 << bit) >> bit - - -def getbits(i, numbits=8): - """ - Returns bits of i in a list - """ - return getbit(i, arange(0, numbits)) - - -def setbit(i, bit, value=1): - """ - Set bit at specified position - - Parameters - ---------- - i : array-like of uints, longs - value to - bit : array-like of ints or longs - bit position between 0 and the number of bits in the uint class. - value : array-like of 0 or 1 - value to set the bit to. - - Examples - -------- - Set bit fifth bit in the five bit binary binary representation of 9 (01001) - yields 25 (11001) - >>> setbit(9,4) - array(25) - """ - val1 = 1 << bit - val0 = bitwise_not(val1) - return where((value == 0) & (i == i) & (bit == bit), bitwise_and(i, val0), - bitwise_or(i, val1)) - - -def setbits(bitlist): - """ - Set bits of val to values in bitlist - - Example - ------- - >>> setbits([1,1]) - 3 - >>> setbits([1,0]) - 1 - """ - val = 0 - for i, j in enumerate(bitlist): - val |= j << i - return val - -if __name__ == '__main__': - from wafo.testing import test_docstrings - test_docstrings(__file__) - -# t = set(np.arange(8),1,1) -# t=get(0x84,np.arange(0,8)) -# t=getbyte(0x84) -# t=get(0x84,[0, 1, 2, 3, 4, 5, 6, 7]) -# t=get(0x20, 6) -# bit = [0 for i in range(8)] -# bit[7]=1 -# t = setbits(bit) -# print(hex(t)) diff --git a/wafo/conftest.py b/wafo/conftest.py deleted file mode 100644 index 6bef122..0000000 --- a/wafo/conftest.py +++ /dev/null @@ -1,3 +0,0 @@ -# TODO Fix doctests in fig.py -collect_ignore = ["fig.py", "MSO.py", "MSPPT.py", "powerpoint.py", - "win32_utils.py"] diff --git a/wafo/definitions.py b/wafo/definitions.py deleted file mode 100644 index d75e648..0000000 --- a/wafo/definitions.py +++ /dev/null @@ -1,310 +0,0 @@ -""" -WAFO defintions and numenclature - - crossings : - cycle_pairs : - turning_points : - wave_amplitudes : - wave_periods : - waves : - -Examples --------- -In order to view the documentation do the following in an ipython window: - -import wafo.definitions as wd -wd.crossings() - -or - -wd.crossings? - - -""" - - -def wave_amplitudes(): - r""" - Wave amplitudes and heights definitions and nomenclature - - Definition of wave amplitudes and wave heights - --------------------------------------------- - - <----- Direction of wave propagation - - - |..............c_..........| - | /| \ | - Hd | _/ | \ | Hu - M | / | \ | - / \ | M / Ac | \_ | c_ - F \ | / \m/ | \ | / \ - ------d----|---u------------------d---|---u----d------ level v - \ | /| \ | / \L - \_ | / | At \_|_/ - \|/..| t - t - - Parameters - ---------- - Ac : crest amplitude - At : trough amplitude - Hd : wave height as defined for down crossing waves - Hu : wave height as defined for up crossing waves - - See also - -------- - waves, crossings, turning_points - """ - print(wave_amplitudes.__doc__) - - -def crossings(): - r""" - Level v crossing definitions and nomenclature - - Definition of level v crossings - ------------------------------- - M - . . M M - . . . . . . - F d . . L - -----------------------u-------d-------o----------------- level v - . . . . u - . m - m - - Let the letters 'm', 'M', 'F', 'L','d' and 'u' in the - figure above denote local minimum, maximum, first value, last - value, down- and up-crossing, respectively. The remaining - sampled values are indicated with a '.'. Values that are identical - with v, but do not cross the level is indicated with the letter 'o'. - We have a level up-crossing at index, k, if - - x(k) < v and v < x(k+1) - or if - x(k) == v and v < x(k+1) and x(r) < v for some di < r <= k-1 - - where di is the index to the previous downcrossing. - Similarly there is a level down-crossing at index, k, if - - x(k) > v and v > x(k+1) - or if - x(k) == v and v > x(k+1) and x(r) > v for some ui < r <= k-1 - - where ui is the index to the previous upcrossing. - - The first (F) value is a up crossing if x(1) = v and x(2) > v. - Similarly, it is a down crossing if x(1) = v and x(2) < v. - - See also - -------- - wave_periods, waves, turning_points, findcross, findtp - """ - print(crossings.__doc__) - - -def cycle_pairs(): - r""" - Cycle pairs definitions and numenclature - - Definition of Max2min and min2Max cycle pair - -------------------------------------------- - A min2Max cycle pair (mM) is defined as the pair of a minimum - and the following Maximum. Similarly a Max2min cycle pair (Mm) - is defined as the pair of a Maximum and the following minimum. - (all turning points possibly rainflowfiltered before pairing into cycles.) - - See also - -------- - turning_points - """ - print(cycle_pairs.__doc__) - - -def wave_periods(): - r""" - Wave periods (lengths) definitions and nomenclature - - Definition of wave periods (lengths) - ------------------------------------ - - - <----- Direction of wave propagation - - <-------Tu---------> - : : - <---Tc-----> : - : : : <------Tcc----> - M : c : : : : - / \ : M / \_ : : c_ c - F \ :/ \m/ \: :/ \ / \ - ------d--------u----------d-------u----d--------u---d-------- level v - \ / \ / :\_ _/: :\_ L - \_ / \_t_/ : \t_/ : : \m/ - \t/ : : : : - : : <---Tt---> : - <--------Ttt-------> : : - <-----Td-----> - Tu = Up crossing period - Td = Down crossing period - Tc = Crest period, i.e., period between up crossing and - the next down crossing - Tt = Trough period, i.e., period between down crossing and - the next up crossing - Ttt = Trough2trough period - Tcc = Crest2crest period - - - <----- Direction of wave propagation - - <--Tcf-> Tuc - : : <-Tcb-> <-> - M : c : : : : - / \ : M / \_ c_ : : c - F \ :/ \m/ \ / \___: :/ \ - ------d---------u----------d---------u-------d--------u---d------ level v - :\_ / \ __/: \_ _/ \_ L - : \_ / \_t_/ : \t_/ \m/ - : \t/ : : - : : : : - <-Ttf-> <-Ttb-> - - - Tcf = Crest front period, i.e., period between up crossing and crest - Tcb = Crest back period, i.e., period between crest and down crossing - Ttf = Trough front period, i.e., period between down crossing and trough - Ttb = Trough back period, i.e., period between trough and up crossing - Also note that Tcf and Ttf can also be abbreviated by their crossing - marker, e.g. Tuc (u2c) and Tdt (d2t), respectively. Similar applies - to all the other wave periods and wave lengths. - - (The nomenclature for wave length is similar, just substitute T and - period with L and length, respectively) - - <----- Direction of wave propagation - - <--TMm--> - <-TmM-> : : - M : : M : - / \ : M /:\_ : M_ M - F \ : / \m/ : \ : /: \ / \ - \ : / : \ : / : \ / \ - \ : / : \ : / : \_ _/ \_ L - \_ : / : \_m_/ : \m_/ \m/ - \m/ : : : : - <-----TMM-----> <----Tmm-----> - - - TmM = Period between minimum and the following Maximum - TMm = Period between Maximum and the following minimum - TMM = Period between Maximum and the following Maximum - Tmm = Period between minimum and the following minimum - - See also - -------- - waves, - wave_amplitudes, - crossings, - turning_points - """ - print(wave_periods.__doc__) - - -def turning_points(): - r""" - Turning points definitions and numenclature - - Definition of turningpoints - --------------------------- - <----- Direction of wave propagation - - M M - / \ .... M /:\_ M_ M - F \ | / \m/ : \ /: \ / \ - \ h | / : \ / : \ / \ - \ | / : \ / : \_ _/ \_ L - \_ | / : \_m_/ : \m_/ \m/ - \m/ : : : : - <------Mw-----> <-----mw-----> - - Local minimum or maximum are indicated with the - letters 'm' or 'M'. Turning points in this connection are all - local max (M) and min (m) and the last (L) value and the - first (F) value if the first local extremum is a max. - - (This choice is made in order to get the exact up-crossing intensity - from rfc by mm2lc(tp2mm(rfc)) ) - - - See also - -------- - waves, - crossings, - cycle_pairs - findtp - - """ - print(turning_points.__doc__) - - -def waves(): - r""" - Wave definitions and nomenclature - - Definition of trough and crest - ------------------------------ - A trough (t) is defined as the global minimum between a - level v down-crossing (d) and the next up-crossing (u) - and a crest (c) is defined as the global maximum between a - level v up-crossing and the following down-crossing. - - Definition of down- and up -crossing waves - ------------------------------------------ - A level v-down-crossing wave (dw) is a wave from a - down-crossing to the following down-crossing. - Similarly, a level v-up-crossing wave (uw) is a wave from an up-crossing - to the next up-crossing. - - Definition of trough and crest waves - ------------------------------------ - A trough-to-trough wave (tw) is a wave from a trough (t) to the - following trough. The crest-to-crest wave (cw) is defined similarly. - - - Definition of min2min and Max2Max wave - -------------------------------------- - A min2min wave (mw) is defined starting from a minimum (m) and - ending in the following minimum. - Similarly a Max2Max wave (Mw) is thus a wave from a maximum (M) - to the next maximum (all waves optionally rainflow filtered). - - <----- Direction of wave propagation - - - <------Mw-----> <----mw----> - M : : c : - / \ M : / \_ : c_ c - F \ / \m/ \ : /: \ /:\ - ------d--------u----------d-------u----d--------u---d------ level v - \ /: \ : /: : :\_ _/ : :\_ L - \_ / : \_t_/ : : : \t_/ : : \m/ - \t/ <-------uw---------> : <-----dw-----> - : : : : - <--------tw--------> <------cw-----> - - (F=first value and L=last value). - - See also - -------- - turning_points, - crossings, - wave_periods - findtc, - findcross - """ - print(waves.__doc__) - -if __name__ == '__main__': - import doctest - doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE) diff --git a/wafo/demos.py b/wafo/demos.py deleted file mode 100644 index f1dfbcc..0000000 --- a/wafo/demos.py +++ /dev/null @@ -1,146 +0,0 @@ -""" -Created on 20. jan. 2011 - -@author: pab -""" -import numpy as np -from numpy import exp, meshgrid -__all__ = ['peaks', 'humps', 'magic'] - - -def _magic_odd_order(n): - ix = np.arange(n) + 1 - J, I = np.meshgrid(ix, ix) - A = np.mod(I + J - (n + 3) / 2, n) - B = np.mod(I + 2 * J - 2, n) - M = n * A + B + 1 - return M - - -def _magic_doubly_even_order(n): - M = np.arange(1, n * n + 1).reshape(n, n) - ix = np.mod(np.arange(n) + 1, 4) // 2 - J, I = np.meshgrid(ix, ix) - iz = np.flatnonzero(I == J) - M.put(iz, n * n + 1 - M.flat[iz]) - return M - - -def _magic_even_order(n): - p = n // 2 - M0 = magic(p) - M = np.hstack((np.vstack((M0, M0 + 3 * p * p)), - np.vstack((M0 + 2 * p * p, M0 + p * p)))) - if n > 2: - k = (n - 2) // 4 - jvec = np.hstack((np.arange(k), np.arange(n - k + 1, n))) - for i in range(p): - for j in jvec: - temp = M[i][j] - M[i][j] = M[i + p][j] - M[i + p][j] = temp - - i = k - j = 0 - temp = M[i][j] - M[i][j] = M[i + p][j] - M[i + p][j] = temp - j = i - temp = M[i + p][j] - M[i + p][j] = M[i][j] - M[i][j] = temp - return M - - -def magic(n): - """ - Return magic square for n of any orders > 2. - - A magic square has the property that the sum of every row and column, - as well as both diagonals, is the same number. - - Examples - -------- - >>> np.allclose(magic(3), - ... [[8, 1, 6], - ... [3, 5, 7], - ... [4, 9, 2]]) - True - - >>> np.allclose(magic(4), - ... [[16, 2, 3, 13], - ... [ 5, 11, 10, 8], - ... [ 9, 7, 6, 12], - ... [ 4, 14, 15, 1]]) - True - - >>> np.allclose(magic(6), - ... [[35, 1, 6, 26, 19, 24], - ... [ 3, 32, 7, 21, 23, 25], - ... [31, 9, 2, 22, 27, 20], - ... [ 8, 28, 33, 17, 10, 15], - ... [30, 5, 34, 12, 14, 16], - ... [ 4, 36, 29, 13, 18, 11]]) - True - """ - if (n < 3): - raise ValueError('n must be greater than 2.') - - if np.mod(n, 2) == 1: - return _magic_odd_order(n) - elif np.mod(n, 4) == 0: - return _magic_doubly_even_order(n) - return _magic_even_order(n) - - -def peaks(x=None, y=None, n=51): - """ - Return the "well" known MatLab (R) peaks function - evaluated in the [-3,3] x,y range - - Example - ------- - >>> import matplotlib.pyplot as plt - >>> x,y,z = peaks() - - h = plt.contourf(x,y,z) - - """ - if x is None: - x = np.linspace(-3, 3, n) - if y is None: - y = np.linspace(-3, 3, n) - - [x1, y1] = meshgrid(x, y) - - z = (3 * (1 - x1) ** 2 * exp(-(x1 ** 2) - (y1 + 1) ** 2) - - 10 * (x1 / 5 - x1 ** 3 - y1 ** 5) * exp(-x1 ** 2 - y1 ** 2) - - 1. / 3 * exp(-(x1 + 1) ** 2 - y1 ** 2)) - - return x1, y1, z - - -def humps(x=None): - """ - Computes a function that has three roots, and some humps. - - Example - ------- - >>> import matplotlib.pyplot as plt - >>> x = np.linspace(0,1) - >>> y = humps(x) - - h = plt.plot(x,y) - """ - if x is None: - y = np.linspace(0, 1) - else: - y = np.asarray(x) - - return 1.0 / ((y - 0.3) ** 2 + 0.01) + 1.0 / ((y - 0.9) ** 2 + 0.04) + \ - 2 * y - 5.2 - - -if __name__ == '__main__': - from wafo.testing import test_docstrings - test_docstrings(__file__) diff --git a/wafo/f2py_tools.py b/wafo/f2py_tools.py deleted file mode 100644 index 74b0e97..0000000 --- a/wafo/f2py_tools.py +++ /dev/null @@ -1,65 +0,0 @@ -# -*- coding: utf-8 -*- -""" -f2py c_library.pyf c_functions.c -c - -See also http://www.scipy.org/Cookbook/CompilingExtensionsOnWindowsWithMinGW -""" -import os -import sys - - -def which(program): - """ - Return filepath to program if it exists - - In order to test if a certain executable exists, it will search for the - program name in the environment variables. - If program is a full path to an executable, it will check it exists - - Copied from: - http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python/ - It is supposed to mimic the UNIX command "which" - """ - - def is_exe(fpath): - return os.path.exists(fpath) and os.access(fpath, os.X_OK) - - fpath, unused_fname = os.path.split(program) - if fpath: - if is_exe(program): - return program - else: - for path in os.environ["PATH"].split(os.pathsep): - exe_file = os.path.join(path, program) - if is_exe(exe_file): - return exe_file - - return None - - -def f2py_call_str(): - '''Return which f2py callable is in the path regardless of platform''' - - # define possible options: - # on Arch Linux, python and f2py are the calls corresponding to python 3 - # and python2/f2py2 for python 2 - # other Linux versions might still use python/f2py for python 2 - - if os.path.basename(sys.executable).endswith('2'): - options = ('f2py2', 'f2py2.6', 'f2py2.7',) - else: # on Windows and other Linux using python/f2py - options = ('f2py.exe', 'f2py.bat', 'f2py', 'f2py2.6', 'f2py2.7', - 'f2py.py',) - for k in options: - if which(k): - # Found the f2py path, no need to look further - f2py_call = k - f2py_path = which(k) - break - - try: - print('found f2py in:', f2py_path) - return f2py_call - except NameError: - raise UserWarning('Couldn\'t locate f2py. ' - 'Should be part of NumPy installation.') diff --git a/wafo/fig.py b/wafo/fig.py deleted file mode 100644 index f700103..0000000 --- a/wafo/fig.py +++ /dev/null @@ -1,908 +0,0 @@ -# /usr/bin/env python -''' -Module FIG ------------- -Module for manipulating windows/figures created using -pylab or enthought.mayavi.mlab on the windows platform. - -Figure manipulation involves -maximization, minimization, hiding, closing, stacking or tiling. - -It is assumed that the figures are uniquely numbered in the following way: -Figure 1 -Figure 2 -.... -or -TVTK scene 1 -TVTK scene 2 -TVTK scene 3 -... - -Example -------- ->>> import pylab as p ->>> import wafo.fig as fig ->>> for ix in range(6): -... f = p.figure(ix) ->>> fig.stack('all') ->>> fig.stack(1,2) ->>> fig.hide(1) ->>> fig.restore(1) ->>> fig.tile() ->>> fig.pile() ->>> fig.maximize(4) ->>> fig.close('all') -''' - -from __future__ import absolute_import, division, print_function -# import win32api -import win32gui -import win32con -import wx -import numpy - -from win32gui import (EnumWindows, MoveWindow, GetWindowRect, FindWindow, - ShowWindow, BringWindowToTop) - -__all__ = ['close', 'cycle', 'hide', 'keep', 'maximize', 'minimize', 'pile', - 'restore', 'stack', 'tile', 'find_all_figure_numbers', 'set_size'] - -# Figure format strings to recognize in window title -FIGURE_TITLE_FORMATS = ('Figure', 'TVTK Scene', 'Chaco Plot Window: Figure') -_SCREENSIZE = None - - -class CycleDialog(wx.Dialog): - - def _get_buttons(self): - hbox = wx.BoxSizer(wx.HORIZONTAL) - buttons = ['Forward', 'Back', 'Cancel'] - callbacks = [self.on_forward, self.on_backward, self.on_cancel] - for button, callback in zip(buttons, callbacks): - button = wx.Button(self, -1, button, size=(70, 30)) - self.Bind(wx.EVT_BUTTON, callback, button) - hbox.Add(button, 1, wx.ALIGN_CENTER) - return hbox - - def _get_message(self): - label = ('Press back or forward to display previous or next figure(s),' - ' respectively. Press cancel to quit.') - message = wx.StaticText(self, label=label, size=(240, 25)) - return message - - def __init__(self, parent, interval=None, title='Cycle dialog'): - super(CycleDialog, self).__init__(parent, title=title, size=(260, 130)) - if isinstance(interval, (float, int)): - self.interval_milli_sec = interval * 1000 - else: - self.interval_milli_sec = 30 - - self.timer = wx.Timer(self) - self.Bind(wx.EVT_TIMER, self.on_forward, self.timer) - - vbox = wx.BoxSizer(wx.VERTICAL) - vbox.Add(self._get_message(), 0, wx.ALIGN_CENTER | wx.TOP, 20) - vbox.Add(self._get_buttons(), 1, wx.ALIGN_CENTER | wx.TOP | wx.BOTTOM, 10) - self.SetSizer(vbox) - - def ShowModal(self, *args, **kwargs): - self.timer.Start(self.interval_milli_sec, oneShot=True) - return super(CycleDialog, self).ShowModal(*args, **kwargs) - - def on_forward(self, evt): - self.EndModal(wx.ID_FORWARD) - - def on_backward(self, evt): - self.EndModal(wx.ID_BACKWARD) - - def on_cancel(self, evt): - self.EndModal(wx.ID_CANCEL) - - -def _get_cycle_dialog(parent=None, interval=None): - app = wx.GetApp() - if not app: - app = wx.App(redirect=False) - frame = wx.Frame(None) - app.SetTopWindow(frame) - dlg = CycleDialog(parent, interval) - return dlg - - -def get_window_position_and_size(window_handle): - pos = GetWindowRect(window_handle) - return pos[0], pos[1], pos[2] - pos[0], pos[3] - pos[1] - - -def get_screen_position_and_size(window_handles): - """Return screen position; X, Y and size; width, height. - - Parameters - ---------- - window_handles: list of handles to open window figures - (Note: only needed the first time) - - Returns - -------- - X : coordinate of the left side of the screen. - Y : coordinate of the top of the screen. - width : screen horizontal size - height : screen vertical size - - """ - # pylint: disable=global-statement - global _SCREENSIZE - if _SCREENSIZE is None: - window_handle = window_handles[0] - pos = get_window_position_and_size(window_handle) - _show_windows((window_handle,), win32con.SW_SHOWMAXIMIZED) - _SCREENSIZE = get_window_position_and_size(window_handle) - MoveWindow(window_handle, pos[0], pos[1], pos[2], pos[3], 1) - return _SCREENSIZE - - -def _get_screen_size(wnds): - screen_width, screen_height = get_screen_position_and_size(wnds)[2:4] - return screen_width, screen_height - - -def _windowEnumerationHandler(handle, result_list): - """Pass to win32gui.EnumWindows() to generate list of window handle, window - text tuples.""" - # pylint: disable=no-member - if win32gui.IsWindowVisible(handle): - result_list.append((handle, win32gui.GetWindowText(handle))) - - -def _find_window_handles_and_titles(wantedTitle=None): - """Return list of window handle and window title tuples. - - Parameter - --------- - wantedTitle: - - """ - handles_n_titles = [] - EnumWindows(_windowEnumerationHandler, handles_n_titles) - if wantedTitle is None: - return handles_n_titles - else: - return [(handle, title) - for handle, title in handles_n_titles - if title.startswith(wantedTitle)] - - -def find_figure_handles(*figure_numbers): - """Find figure handles from figure numbers.""" - wnd_handles = [] - for figure_number in _parse_figure_numbers(*figure_numbers): - for format_ in FIGURE_TITLE_FORMATS: - winTitle = format_ + ' %d' % figure_number - handle = FindWindow(None, winTitle) - if not handle == 0: - wnd_handles.append(handle) - return wnd_handles - - -def find_all_figure_numbers(): - """Return list of all figure numbers. - - Example - ------- - >>> import fig - >>> import pylab as p - >>> for ix in range(5): - ... f = p.figure(ix) - ... p.draw() - - fig.find_all_figure_numbers() - [0, 1, 2, 3, 4] - - >>> fig.close() - - """ - figure_numbers = [] - for wantedTitle in FIGURE_TITLE_FORMATS: - handles_n_titles = _find_window_handles_and_titles(wantedTitle) - for _handle, title in handles_n_titles: - try: - number = int(title.split()[-1]) - figure_numbers.append(number) - except (TypeError, ValueError): - pass - # pylint: disable=no-member - return numpy.unique(figure_numbers).tolist() - - -def _parse_figure_numbers(*args): - figure_numbers = [] - for arg in args: - if isinstance(arg, (list, tuple, set)): - for val in arg: - figure_numbers.append(int(val)) - elif isinstance(arg, int): - figure_numbers.append(arg) - elif arg == 'all': - figure_numbers = find_all_figure_numbers() - break - else: - raise TypeError('Only integers arguments accepted!') - - if len(figure_numbers) == 0: - figure_numbers = find_all_figure_numbers() - return figure_numbers - - -def _show_figure(figure_numbers, command): - """Sets the specified figure's show state. - - Parameters - ---------- - figure_numbers: list of figure numbers - command: one of following commands: - SW_FORCEMINIMIZE: - Minimizes a window, even if the thread that owns the window is not - responding. This flag should only be used when minimizing windows - from a different thread. - SW_HIDE: - Hides the window and activates another window. - SW_MAXIMIZE: - Maximizes the specified window. - SW_MINIMIZE: - Minimizes the specified window and activates the next top-level window - in the Z order. - SW_RESTORE: - Activates and displays the window. If the window is minimized or - maximized, the system restores it to its original size and position. - An application should specify this flag when restoring a minimized - window. - SW_SHOW: - Activates the window and displays it in its current size and position. - SW_SHOWDEFAULT: - Sets the show state based on the SW_ value specified in the STARTUPINFO - structure passed to the CreateProcess function by the program that - started the application. - SW_SHOWMAXIMIZED: - Activates the window and displays it as a maximized window. - SW_SHOWMINIMIZED: - Activates the window and displays it as a minimized window. - SW_SHOWMINNOACTIVE: - Displays the window as a minimized window. This value is similar to - SW_SHOWMINIMIZED, except the window is not activated. - SW_SHOWNA: - Displays the window in its current size and position. This value is - similar to SW_SHOW, except the window is not activated. - SW_SHOWNOACTIVATE: - Displays a window in its most recent size and position. This value is - similar to SW_SHOWNORMAL, except the window is not actived. - SW_SHOWNORMAL: - Activates and displays a window. If the window is minimized or - maximized, the system restores it to its original size and position. - An application should specify this flag when displaying the window for - the first time. - - """ - for number in _parse_figure_numbers(*figure_numbers): - for format_ in FIGURE_TITLE_FORMATS: - title = format_ + ' %d' % number - handle = FindWindow(None, title) - if not handle == 0: - BringWindowToTop(handle) - ShowWindow(handle, command) - - -def _show_windows(handles, command, redraw_now=False): - """Sets the specified window's show state. - - Parameters - ---------- - handles: list of window handles - command: one of following commands: - SW_FORCEMINIMIZE: - Minimizes a window, even if the thread that owns the window is not - responding. This flag should only be used when minimizing windows - from a different thread. - SW_HIDE: - Hides the window and activates another window. - SW_MAXIMIZE: - Maximizes the specified window. - SW_MINIMIZE: - Minimizes the specified window and activates the next top-level window - in the Z order. - SW_RESTORE: - Activates and displays the window. If the window is minimized or - maximized, the system restores it to its original size and position. - An application should specify this flag when restoring a minimized - window. - SW_SHOW: - Activates the window and displays it in its current size and position. - SW_SHOWDEFAULT: - Sets the show state based on the SW_ value specified in the STARTUPINFO - structure passed to the CreateProcess function by the program that - started the application. - SW_SHOWMAXIMIZED: - Activates the window and displays it as a maximized window. - SW_SHOWMINIMIZED: - Activates the window and displays it as a minimized window. - SW_SHOWMINNOACTIVE: - Displays the window as a minimized window. This value is similar to - SW_SHOWMINIMIZED, except the window is not activated. - SW_SHOWNA: - Displays the window in its current size and position. This value is - similar to SW_SHOW, except the window is not activated. - SW_SHOWNOACTIVATE: - Displays a window in its most recent size and position. This value is - similar to SW_SHOWNORMAL, except the window is not actived. - SW_SHOWNORMAL: - Activates and displays a window. If the window is minimized or - maximized, the system restores it to its original size and position. - An application should specify this flag when displaying the window for - the first time. - - redraw_now : - - """ - # pylint: disable=no-member - for handle in handles: - if not handle == 0: - BringWindowToTop(handle) - ShowWindow(handle, command) - if redraw_now: - rect = GetWindowRect(handle) - win32gui.RedrawWindow(handle, rect, None, win32con.RDW_UPDATENOW) - - -def keep(*figure_numbers): - """Keeps figure windows of your choice and closes the rest. - - Parameters - ---------- - figure_numbers : list of integers specifying which figures to keep. - - Example: - -------- - # keep only figures 1,2,3,5 and 7 - >>> import pylab as p - >>> import wafo.fig as fig - >>> for ix in range(10): - ... f = p.figure(ix) - >>> fig.keep( range(1,4), 5, 7) - - or - fig.keep([range(1,4), 5, 7]) - >>> fig.close() - - See also - -------- - fig.close - - """ - figs2keep = [] - for fig in figure_numbers: - if isinstance(fig, (list, tuple, set)): - for val in fig: - figs2keep.append(int(val)) - elif isinstance(fig, int): - figs2keep.append(fig) - else: - raise TypeError('Only integers arguments accepted!') - - if len(figs2keep) > 0: - allfigs = set(find_all_figure_numbers()) - figs2delete = allfigs.difference(figs2keep) - close(figs2delete) - - -def close(*figure_numbers): - """ Close figure window(s) - - Parameters - ---------- - figure_numbers : list of integers or string - specifying which figures to close (default 'all'). - - Examples - -------- - >>> import pylab as p - >>> import wafo.fig as fig - >>> for ix in range(5): - ... f = p.figure(ix) - >>> fig.close(3,4) # close figure 3 and 4 - >>> fig.close('all') # close all remaining figures - - or even simpler - fig.close() # close all remaining figures - - See also - -------- - fig.keep - - """ - # pylint: disable=no-member - for handle in find_figure_handles(*figure_numbers): - if win32gui.SendMessage(handle, win32con.WM_CLOSE, 0, 0): - win32gui.SendMessage(handle, win32con.WM_DESTROY, 0, 0) - - -def restore(*figure_numbers): - """Restore figures window size and position to its default value. - - Parameters - ---------- - figure_numbers : list of integers or string - specifying which figures to restor (default 'all'). - - Description - ----------- - RESTORE Activates and displays the window. If the window is minimized - or maximized, the system restores it to its original size and position. - - Examples - --------- - >>> import pylab as p - >>> import wafo.fig as fig - >>> for ix in range(5): - ... f = p.figure(ix) - >>> fig.restore('all') #Restores all figures - >>> fig.restore() #same as restore('all') - >>> fig.restore(p.gcf().number) #Restores the current figure - >>> fig.restore(3) #Restores figure 3 - >>> fig.restore([2, 4]) #Restores figures 2 and 4 - - or alternatively - fig.restore(2, 4) - >>> fig.close() - - See also - -------- - fig.close, - fig.keep - - """ - SW_RESTORE = win32con.SW_RESTORE - # SW_RESTORE = win32con.SW_SHOWDEFAULT - # SW_RESTORE = win32con.SW_SHOWNORMAL - _show_figure(figure_numbers, SW_RESTORE) - - -def hide(*figure_numbers): - """hide figure(s) window. - - Parameters - ---------- - figure_numbers : list of integers or string - specifying which figures to hide (default 'all'). - - Examples: - -------- - >>> import wafo.fig as fig - >>> import pylab as p - >>> for ix in range(5): - ... f = p.figure(ix) - >>> fig.hide('all') #hides all unhidden figures - >>> fig.hide() #same as hide('all') - >>> fig.hide(p.gcf().number) #hides the current figure - >>> fig.hide(3) #hides figure 3 - >>> fig.hide([2, 4]) #hides figures 2 and 4 - - or alternatively - fig.hide(2, 4) - >>> fig.restore(list(range(5))) - >>> fig.close() - - See also - -------- - fig.cycle, - fig.keep, - fig.restore - - """ - _show_figure(figure_numbers, win32con.SW_HIDE) - - -def minimize(*figure_numbers): - """Minimize figure(s) window size. - - Parameters - ---------- - figure_numbers : list of integers or string - specifying which figures to minimize (default 'all'). - - Examples: - --------- - >>> import wafo.fig as fig - >>> import pylab as p - >>> for ix in range(5): - ... f = p.figure(ix) - >>> fig.minimize('all') #Minimizes all unhidden figures - >>> fig.minimize() #same as minimize('all') - >>> fig.minimize(p.gcf().number) #Minimizes the current figure - >>> fig.minimize(3) #Minimizes figure 3 - >>> fig.minimize([2, 4]) #Minimizes figures 2 and 4 - - or alternatively - fig.minimize(2, 4) - >>> fig.close() - - See also - -------- - fig.cycle, - fig.keep, - fig.restore - - """ - _show_figure(figure_numbers, win32con.SW_SHOWMINIMIZED) - - -def maximize(*figure_numbers): - """Maximize figure(s) window size. - - Parameters - ---------- - figure_numbers : list of integers or string - specifying which figures to maximize (default 'all'). - - Examples: - --------- - >>> import pylab as p - >>> import wafo.fig as fig - >>> for ix in range(5): - ... f = p.figure(ix) - >>> fig.maximize('all') #Maximizes all unhidden figures - >>> fig.maximize() #same as maximize('all') - >>> fig.maximize(p.gcf().number) #Maximizes the current figure - >>> fig.maximize(3) #Maximizes figure 3 - >>> fig.maximize([2, 4]) #Maximizes figures 2 and 4 - - or alternatively - fig.maximize(2, 4) - >>> fig.close() - - See also - -------- - fig.cycle, - fig.keep, - fig.restore - - """ - _show_figure(figure_numbers, win32con.SW_SHOWMAXIMIZED) - - -def pile(*figure_numbers, **kwds): - """Pile figure windows. - - Parameters - ---------- - figure_numbers : list of integers or string - specifying which figures to pile (default 'all'). - kwds : dict with the following keys - position : - width : - height : - - Description - ------------- - PILE piles all open figure windows on top of eachother - with complete overlap. PILE(FIGS) can be used to specify which - figures that should be piled. Figures are not sorted when specified. - - Example: - -------- - >>> import pylab as p - >>> import wafo.fig as fig - >>> for ix in range(7): - ... f = p.figure(ix) - >>> fig.pile() # pile all open figures - >>> fig.pile(range(1,4), 5, 7) # pile figure 1,2,3,5 and 7 - >>> fig.close() - - See also - -------- - fig.cycle, fig.keep, fig.maximize, fig.restore, - fig.stack, fig.tile - - """ - wnds = find_figure_handles(*figure_numbers) - numfigs = len(wnds) - if numfigs > 0: - screen_width, screen_height = _get_screen_size(wnds) - pos = kwds.get( - 'position', (int(screen_width / 5), int(screen_height / 4))) - width = kwds.get('width', int(screen_width / 2.5)) - height = kwds.get('height', int(screen_height / 2)) - - for wnd in wnds: - MoveWindow(wnd, pos[0], pos[1], width, height, 1) - BringWindowToTop(wnd) - - -def set_size(*figure_numbers, **kwds): - """Set size for figure windows. - - Parameters - ---------- - figure_numbers : list of integers or string - specifying which figures to pile (default 'all'). - kwds : dict with the following keys - width : - height : - - Description - ------------- - Set size sets the size of all open figure windows. SET_SIZE(FIGS) - can be used to specify which figures that should be resized. - Figures are not sorted when specified. - - Example: - -------- - >>> import pylab as p - >>> import fig - >>> for ix in range(7): - ... f = p.figure(ix) - >>> fig.set_size(7, width=150, height=100) - >>> fig.set_size(range(1,4), 5,width=250, height=170) - >>> fig.close() - - See also - -------- - fig.cycle, fig.keep, fig.maximize, fig.restore, - fig.stack, fig.tile - - """ - handles = find_figure_handles(*figure_numbers) - numfigs = len(handles) - if numfigs > 0: - screen_width, screen_height = _get_screen_size(handles) - width = kwds.get('width', int(screen_width / 2.5)) - height = kwds.get('height', int(screen_height / 2)) - new_pos = kwds.get('position', None) - pos = new_pos - for handle in handles: - if not new_pos: - pos = get_window_position_and_size(handle) - MoveWindow(handle, pos[0], pos[1], width, height, 1) - BringWindowToTop(handle) - - -def stack(*figure_numbers, **kwds): - """Stack figure windows. - - Parameters - ---------- - figure_numbers : list of integers or string - specifying which figures to stack (default 'all'). - kwds : dict with the following keys - figs_per_stack : - number of figures per stack (default depends on screenheight) - - Description - ----------- - STACK stacks all open figure windows on top of eachother - with maximum overlap. STACK(FIGS) can be used to specify which - figures that should be stacked. Figures are not sorted when specified. - - Example: - -------- - >>> import pylab as p - >>> import wafo.fig as fig - >>> for ix in range(7): - ... f = p.figure(ix) - >>> fig.stack() # stack all open figures - >>> fig.stack(range(1,4), 5, 7) # stack figure 1,2,3,5 and 7 - >>> fig.close() - - See also - -------- - fig.cycle, fig.keep, fig.maximize, fig.restore, - fig.pile, fig.tile - - """ - wnds = find_figure_handles(*figure_numbers) - numfigs = len(wnds) - if numfigs > 0: - screenpos = get_screen_position_and_size(wnds) - y_step = 25 - x_step = border = 5 - - figs_per_stack = kwds.get( - 'figs_per_stack', - int(numpy.fix(0.7 * (screenpos[3] - border) / y_step))) - - for iy in range(numfigs): - pos = get_window_position_and_size(wnds[iy]) - # print('[x, y, w, h] = ', pos) - ix = iy % figs_per_stack - ypos = int(screenpos[1] + ix * y_step + border) - xpos = int(screenpos[0] + ix * x_step + border) - MoveWindow(wnds[iy], xpos, ypos, pos[2], pos[3], 1) - BringWindowToTop(wnds[iy]) - - -def tile(*figure_numbers, **kwds): - """Tile figure windows. - - Parameters - ---------- - figure_numbers : list of integers or string - specifying which figures to tile (default 'all'). - kwds : dict with key pairs - specifying how many pairs of figures that are tiled at a time - - Description - ----------- - TILE places all open figure windows around on the screen with no - overlap. TILE(FIGS) can be used to specify which figures that - should be tiled. Figures are not sorted when specified. - - Example: - -------- - >>> import pylab as p - >>> import wafo.fig as fig - >>> for ix in range(7): - ... f = p.figure(ix) - >>> fig.tile() # tile all open figures - >>> fig.tile( range(1,4), 5, 7) # tile figure 1,2,3,5 and 7 - >>> fig.tile(range(1,11), pairs=2) # tile figure 1 to 10 two at a time - >>> fig.tile(range(1,11), pairs=3) # tile figure 1 to 10 three at a time - >>> fig.close() - - See also - -------- - fig.cycle, fig.keep, fig.maximize, fig.minimize - fig.restore, fig.pile, fig.stack - - """ - wnds = find_figure_handles(*figure_numbers) - - nfigs = len(wnds) - # Number of windows. - - if nfigs > 0: - nfigspertile = kwds.get('pairs', nfigs) - - ceil = numpy.ceil - sqrt = numpy.sqrt - maximum = numpy.maximum - - nlayers = int(ceil(nfigs / nfigspertile)) - - # Number of figures horisontally. - nh = maximum(int(ceil(sqrt(nfigspertile))), 2) - # Number of figures vertically. - nv = maximum(int(ceil(nfigspertile / nh)), 2) - - screenpos = get_screen_position_and_size(wnds) - screen_width, screen_heigth = screenpos[2:4] - - hspc = 10 # Horisontal space. - topspc = 20 # Space above top figure. - medspc = 10 # Space between figures. - botspc = 20 # Space below bottom figure. - - figwid = (screen_width - (nh + 1) * hspc) / nh - fighgt = (screen_heigth - (topspc + botspc) - (nv - 1) * medspc) / nv - - figwid = int(numpy.round(figwid)) - fighgt = int(numpy.round(fighgt)) - - idx = 0 - for unused_ix in range(nlayers): - for row in range(nv): - figtop = int(screenpos[1] + topspc + row * (fighgt + medspc)) - for col in range(nh): - if (row) * nh + col < nfigspertile: - if idx < nfigs: - figlft = int( - screenpos[0] + (col + 1) * hspc + col * figwid) - fighnd = wnds[idx] - MoveWindow(fighnd, figlft, figtop, figwid, fighgt, - 1) - # Set position. - BringWindowToTop(fighnd) - idx += 1 - - -class _CycleGenerator(object): - - """Cycle through figure windows. - - Parameters - ---------- - figure_numbers : list of integers or string - specifying which figures to cycle through (default 'all'). - kwds : dict with the following keys - pairs : number of figures to cycle in pairs (default 1) - maximize: If True maximize figure when viewing (default False) - interval : pause interval in seconds - - Description - ----------- - CYCLE brings up all open figure in ascending order and pauses after - each figure. Press escape to quit cycling, backspace to display previous - figure(s) and press any other key to display next figure(s) - When done, the figures are sorted in ascending order. - - CYCLE(maximize=True) does the same thing, except figures are maximized. - CYCLE(pairs=2) cycle through all figures in pairs of 2. - - Examples: - >>> import pylab as p - >>> import wafo.fig as fig - >>> for ix in range(4): - ... f = p.figure(ix) - - fig.cycle(range(3), interval=1) # Cycle trough figure 0 to 2 - - # Cycle trough figure 0 to 2 with figures maximized - fig.cycle(range(3), maximize=True, interval=1) - fig.cycle(interval=1) # Cycle through all figures one at a time - fig.tile(pairs=2, interval=1) - fig.cycle(pairs=2, interval=2) # Cycle through all figures two at a time - - fig.cycle(pairs=2) # Manually cycle through all figures two at a time - >>> fig.close() - - See also - -------- - fig.keep, fig.maximize, fig.restore, fig.pile, - fig.stack, fig.tile - - """ - escape_key = chr(27) - backspace_key = chr(8) - - def __init__(self, **kwds): - self.dialog = None - maximize = kwds.get('maximize', False) - pairs = kwds.get('pairs', 1) - self.interval = kwds.get('interval', 'user_defined') - self.nfigspercycle = 1 - if maximize: - self.command = win32con.SW_SHOWMAXIMIZED - else: - self.command = win32con.SW_SHOWNORMAL - if pairs is not None: - self.nfigspercycle = pairs - - def _set_options(self, kwds): - self.__init__(**kwds) - - def _iterate(self, handles): - i = 0 - numfigs = len(handles) - self.dialog = _get_cycle_dialog(parent=None, interval=self.interval) - while 0 <= i and i < numfigs: - iu = min(i + self.nfigspercycle, numfigs) - yield handles[i:iu] - i = self.next_index(i) - self.dialog.Destroy() - raise StopIteration - - def next_index(self, i): - result = self.dialog.ShowModal() - if result == wx.ID_FORWARD: - i += self.nfigspercycle - elif result == wx.ID_BACKWARD: - i -= self.nfigspercycle - else: - i = -1 - return i - - def __call__(self, *figure_numbers, **kwds): - handles = find_figure_handles(*figure_numbers) - numfigs = len(handles) - if numfigs > 0: - self._set_options(kwds) - for handle in self._iterate(handles): - _show_windows(handle, self.command, redraw_now=True) - - _show_windows(handles, win32con.SW_SHOWNORMAL) - -cycle = _CycleGenerator() - - -if __name__ == '__main__': - from wafo.testing import test_docstrings - import matplotlib - matplotlib.interactive(True) - test_docstrings(__file__) diff --git a/wafo/gaussian.py b/wafo/gaussian.py deleted file mode 100644 index d2cc947..0000000 --- a/wafo/gaussian.py +++ /dev/null @@ -1,1040 +0,0 @@ -from __future__ import absolute_import -from numpy import (r_, minimum, maximum, atleast_1d, atleast_2d, mod, ones, - floor, random, eye, nonzero, where, repeat, sqrt, exp, inf, - diag, zeros, sin, arcsin, nan) -from numpy import triu -from scipy.special import ndtr as cdfnorm, ndtri as invnorm -from scipy.special import erfc -import warnings -import numpy as np - -try: - from wafo import mvn # @UnresolvedImport -except ImportError: - warnings.warn('mvn not found. Check its compilation.') - mvn = None -try: - from wafo import mvnprdmod # @UnresolvedImport -except ImportError: - warnings.warn('mvnprdmod not found. Check its compilation.') - mvnprdmod = None -try: - from wafo import rindmod # @UnresolvedImport -except ImportError: - warnings.warn('rindmod not found. Check its compilation.') - rindmod = None - - -__all__ = ['Rind', 'rindmod', 'mvnprdmod', 'mvn', 'cdflomax', 'prbnormtndpc', - 'prbnormndpc', 'prbnormnd', 'cdfnorm2d', 'prbnorm2d', 'cdfnorm', - 'invnorm'] - - -class Rind(object): - - """ - RIND Computes multivariate normal expectations - - Parameters - ---------- - S : array-like, shape Ntdc x Ntdc - Covariance matrix of X=[Xt,Xd,Xc] (Ntdc = Nt+Nd+Nc) - m : array-like, size Ntdc - expectation of X=[Xt,Xd,Xc] - Blo, Bup : array-like, shape Mb x Nb - Lower and upper barriers used to compute the integration limits, - Hlo and Hup, respectively. - indI : array-like, length Ni - vector of indices to the different barriers in the indicator function. - (NB! restriction indI(1)=-1, indI(NI)=Nt+Nd, Ni = Nb+1) - (default indI = 0:Nt+Nd) - xc : values to condition on (default xc = zeros(0,1)), size Nc x Nx - Nt : size of Xt (default Nt = Ntdc - Nc) - - Returns - ------- - val: ndarray, size Nx - expectation/density as explained below - err, terr : ndarray, size Nx - estimated sampling error and estimated truncation error, respectively. - (err is with 99 confidence level) - - Notes - ----- - RIND computes multivariate normal expectations, i.e., - E[Jacobian*Indicator|Condition ]*f_{Xc}(xc(:,ix)) - where - "Indicator" = I{ Hlo(i) < X(i) < Hup(i), i = 1:N_t+N_d } - "Jacobian" = J(X(Nt+1),...,X(Nt+Nd+Nc)), special case is - "Jacobian" = |X(Nt+1)*...*X(Nt+Nd)|=|Xd(1)*Xd(2)..Xd(Nd)| - "condition" = Xc=xc(:,ix), ix=1,...,Nx. - X = [Xt, Xd, Xc], a stochastic vector of Multivariate Gaussian - variables where Xt,Xd and Xc have the length Nt,Nd and Nc, respectively - (Recommended limitations Nx,Nt<=100, Nd<=6 and Nc<=10) - - Multivariate probability is computed if Nd = 0. - - If Mb>> import wafo.gaussian as wg - >>> import numpy as np - >>> n = 5 - >>> Blo =-np.inf; Bup=-1.2; indI=np.array([-1, n-1], dtype=int) # Barriers - >>> m = np.zeros(n); rho = 0.3; - >>> Sc =(np.ones((n,n))-np.eye(n))*rho+np.eye(n) - >>> rind = wg.Rind() - >>> E0, err0, terr0 = rind(Sc,m,Blo,Bup,indI) # exact prob. 0.001946 - - >>> A = np.repeat(Blo,n); B = np.repeat(Bup,n) # Integration limits - >>> E1 = rind(np.triu(Sc),m,A,B) #same as E0 - - Compute expectation E( abs(X1*X2*...*X5) ) - >>> xc = np.zeros((0,1)) - >>> infinity = 37 - >>> dev = np.sqrt(np.diag(Sc)) # std - >>> ind = np.nonzero(indI[1:])[0] - >>> Bup, Blo = np.atleast_2d(Bup,Blo) - >>> Bup[0,ind] = np.minimum(Bup[0,ind] , infinity*dev[indI[ind+1]]) - >>> Blo[0,ind] = np.maximum(Blo[0,ind] ,-infinity*dev[indI[ind+1]]) - >>> val, err, terr = rind(Sc,m,Blo,Bup,indI, xc, nt=0) - >>> np.allclose(val, 0.05494076, rtol=4e-2) - True - >>> err[0] < 5e-3, terr[0] < 1e-7 - (True, True) - - Compute expectation E( X1^{+}*X2^{+} ) with random - correlation coefficient,Cov(X1,X2) = rho2. - >>> m2 = [0, 0]; rho2 = np.random.rand(1) - >>> Sc2 = [[1, rho2], [rho2 ,1]] - >>> Blo2 = 0; Bup2 = np.inf; indI2 = [-1, 1] - >>> rind2 = wg.Rind(method=1) - >>> def g2(x): - ... return (x*(np.pi/2+np.arcsin(x))+np.sqrt(1-x**2))/(2*np.pi) - >>> E2 = g2(rho2) # exact value - >>> E3 = rind(Sc2,m2,Blo2,Bup2,indI2,nt=0) - >>> E4 = rind2(Sc2,m2,Blo2,Bup2,indI2,nt=0) - >>> E5 = rind2(Sc2,m2,Blo2,Bup2,indI2,nt=0,abseps=1e-4) - - See also - -------- - prbnormnd, prbnormndpc - - References - ---------- - Podgorski et al. (2000) - "Exact distributions for apparent waves in irregular seas" - Ocean Engineering, Vol 27, no 1, pp979-1016. - - P. A. Brodtkorb (2004), - Numerical evaluation of multinormal expectations - In Lund university report series - and in the Dr.Ing thesis: - The probability of Occurrence of dangerous Wave Situations at Sea. - Dr.Ing thesis, Norwegian University of Science and Technolgy, NTNU, - Trondheim, Norway. - - Per A. Brodtkorb (2006) - "Evaluating Nearly Singular Multinormal Expectations with Application to - Wave Distributions", - Methodology And Computing In Applied Probability, Volume 8, Number 1, - pp. 65-91(27) - """ - - def __init__(self, **kwds): - """ - Parameters - ---------- - method : integer, optional - defining the integration method - 0 Integrate by Gauss-Legendre quadrature (Podgorski et al. 1999) - 1 Integrate by SADAPT for Ndim<9 and by KRBVRC otherwise - 2 Integrate by SADAPT for Ndim<20 and by KRBVRC otherwise - 3 Integrate by KRBVRC by Genz (1993) (Fast Ndim<101) (default) - 4 Integrate by KROBOV by Genz (1992) (Fast Ndim<101) - 5 Integrate by RCRUDE by Genz (1992) (Slow Ndim<1001) - 6 Integrate by SOBNIED (Fast Ndim<1041) - 7 Integrate by DKBVRC by Genz (2003) (Fast Ndim<1001) - - xcscale : real scalar, optional - scales the conditinal probability density, i.e., - f_{Xc} = exp(-0.5*Xc*inv(Sxc)*Xc + XcScale) (default XcScale=0) - abseps, releps : real scalars, optional - absolute and relative error tolerance. - (default abseps=0, releps=1e-3) - coveps : real scalar, optional - error tolerance in Cholesky factorization (default 1e-13) - maxpts, minpts : scalar integers, optional - maximum and minimum number of function values allowed. The - parameter, maxpts, can be used to limit the time. A sensible - strategy is to start with MAXPTS = 1000*N, and then increase MAXPTS - if ERROR is too large. - (Only for METHOD~=0) (default maxpts=40000, minpts=0) - seed : scalar integer, optional - seed to the random generator used in the integrations - (Only for METHOD~=0)(default floor(rand*1e9)) - nit : scalar integer, optional - maximum number of Xt variables to integrate. This parameter can be - used to limit the time. If NIT is less than the rank of the - covariance matrix, the returned result is a upper bound for the - true value of the integral. (default 1000) - xcutoff : real scalar, optional - cut off value where the marginal normal distribution is truncated. - (Depends on requested accuracy. A value between 4 and 5 is - reasonable.) - xsplit : real scalar - parameter controlling performance of quadrature integration: - if Hup>=xCutOff AND Hlo<-XSPLIT OR - Hup>=XSPLIT AND Hlo<=-xCutOff then - do a different integration to increase speed - in rind2 and rindnit. This give slightly different results - if XSPILT>=xCutOff => do the same integration always - (Only for METHOD==0)(default XSPLIT = 1.5) - quadno : scalar integer - Quadrature formulae number used in integration of Xd variables. - This number implicitly determines number of nodes - used. (Only for METHOD==0) - speed : scalar integer - defines accuracy of calculations by choosing different parameters, - possible values: 1,2...,9 (9 fastest, default []). - If not speed is None the parameters, ABSEPS, RELEPS, COVEPS, - XCUTOFF, MAXPTS and QUADNO will be set according to - INITOPTIONS. - nc1c2 : scalar integer, optional - number of times to use the regression equation to restrict - integration area. Nc1c2 = 1,2 is recommended. (default 2) - (note: works only for method >0) - """ - self.method = 3 - self.xcscale = 0 - self.abseps = 0 - self.releps = 1e-3, - self.coveps = 1e-10 - self.maxpts = 40000 - self.minpts = 0 - self.seed = None - self.nit = 1000, - self.xcutoff = None - self.xsplit = 1.5 - self.quadno = 2 - self.speed = None - self.nc1c2 = 2 - - self.__dict__.update(**kwds) - self.initialize(self.speed) - self.set_constants() - - def initialize(self, speed=None): - """ - Initializes member variables according to speed. - - Parameter - --------- - speed : scalar integer - defining accuracy of calculations. - Valid numbers: 1,2,...,10 - (1=slowest and most accurate,10=fastest, but less accuracy) - - - Member variables initialized according to speed: - ----------------------------------------------- - speed : Integer defining accuracy of calculations. - abseps : Absolute error tolerance. - releps : Relative error tolerance. - covep : Error tolerance in Cholesky factorization. - xcutoff : Truncation limit of the normal CDF - maxpts : Maximum number of function values allowed. - quadno : Quadrature formulae used in integration of Xd(i) - implicitly determining # nodes - """ - if speed is None: - return - self.speed = min(max(speed, 1), 13) - - self.maxpts = 10000 - self.quadno = r_[1:4] + (10 - min(speed, 9)) + (speed == 1) - if speed in (11, 12, 13): - self.abseps = 1e-1 - elif speed == 10: - self.abseps = 1e-2 - elif speed in (7, 8, 9): - self.abseps = 1e-2 - elif speed in (4, 5, 6): - self.maxpts = 20000 - self.abseps = 1e-3 - elif speed in (1, 2, 3): - self.maxpts = 30000 - self.abseps = 1e-4 - - if speed < 12: - tmp = max(abs(11 - abs(speed)), 1) - expon = mod(tmp + 1, 3) + 1 - self.coveps = self.abseps * ((1.0e-1) ** expon) - elif speed < 13: - self.coveps = 0.1 - else: - self.coveps = 0.5 - - self.releps = min(self.abseps, 1.0e-2) - - if self.method == 0: - # This gives approximately the same accuracy as when using - # RINDDND and RINDNIT - # xCutOff= MIN(MAX(xCutOff+0.5d0,4.d0),5.d0) - self.abseps = self.abseps * 1.0e-1 - trunc_error = 0.05 * max(0, self.abseps) - self.xcutoff = max(min(abs(invnorm(trunc_error)), 7), 1.2) - self.abseps = max(self.abseps - trunc_error, 0) - - def set_constants(self): - if self.xcutoff is None: - trunc_error = 0.1 * self.abseps - self.nc1c2 = max(1, self.nc1c2) - xcut = abs(invnorm(trunc_error / (self.nc1c2 * 2))) - self.xcutoff = max(min(xcut, 8.5), 1.2) - # self.abseps = max(self.abseps- truncError,0); - # self.releps = max(self.releps- truncError,0); - - if self.method > 0: - names = ['method', 'xcscale', 'abseps', 'releps', 'coveps', - 'maxpts', 'minpts', 'nit', 'xcutoff', 'nc1c2', 'quadno', - 'xsplit'] - - constants = [getattr(self, name) for name in names] - constants[0] = mod(constants[0], 10) - rindmod.set_constants(*constants) # @UndefinedVariable - - def __call__(self, cov, m, ab, bb, indI=None, xc=None, nt=None, **kwds): - if any(kwds): - self.__dict__.update(**kwds) - self.set_constants() - if xc is None: - xc = zeros((0, 1)) - - big, b_lo, b_up, xc = atleast_2d(cov, ab, bb, xc) - b_lo = b_lo.copy() - b_up = b_up.copy() - - Ntdc = big.shape[0] - Nc = xc.shape[0] - if nt is None: - nt = Ntdc - Nc - - unused_Mb, Nb = b_lo.shape - Nd = Ntdc - nt - Nc - Ntd = nt + Nd - - if indI is None: - if Nb != Ntd: - raise ValueError('Inconsistent size of b_lo and b_up') - indI = r_[-1:Ntd] - - Ex, indI = atleast_1d(m, indI) - if self.seed is None: - seed = int(floor(random.rand(1) * 1e10)) # @UndefinedVariable - else: - seed = int(self.seed) - - # INFIN = INTEGER, array of integration limits flags: size 1 x Nb - # if INFIN(I) < 0, Ith limits are (-infinity, infinity); - # if INFIN(I) = 0, Ith limits are (-infinity, Hup(I)]; - # if INFIN(I) = 1, Ith limits are [Hlo(I), infinity); - # if INFIN(I) = 2, Ith limits are [Hlo(I), Hup(I)]. - infinity = 37 - dev = sqrt(diag(big)) # std - ind = nonzero(indI[1:] > -1)[0] - infin = repeat(2, len(indI) - 1) - infin[ind] = (2 - (b_up[0, ind] > infinity * dev[indI[ind + 1]]) - - 2 * (b_lo[0, ind] < -infinity * dev[indI[ind + 1]])) - - b_up[0, ind] = minimum(b_up[0, ind], infinity * dev[indI[ind + 1]]) - b_lo[0, ind] = maximum(b_lo[0, ind], -infinity * dev[indI[ind + 1]]) - ind2 = indI + 1 - - return rindmod.rind(big, Ex, xc, nt, ind2, b_lo, b_up, infin, seed) - - -def test_rind(): - """ Small test function - """ - n = 5 - Blo = -inf - Bup = -1.2 - indI = [-1, n - 1] # Barriers - # A = np.repeat(Blo, n) - # B = np.repeat(Bup, n) # Integration limits - m = zeros(n) - rho = 0.3 - Sc = (ones((n, n)) - eye(n)) * rho + eye(n) - rind = Rind() - E0 = rind(Sc, m, Blo, Bup, indI) # exact prob. 0.001946 A) - print(E0) - - A = repeat(Blo, n) - B = repeat(Bup, n) # Integration limits - _E1 = rind(triu(Sc), m, A, B) # same as E0 - - xc = zeros((0, 1)) - infinity = 37 - dev = sqrt(diag(Sc)) # std - ind = nonzero(indI[1:])[0] - Bup, Blo = atleast_2d(Bup, Blo) - Bup[0, ind] = minimum(Bup[0, ind], infinity * dev[indI[ind + 1]]) - Blo[0, ind] = maximum(Blo[0, ind], -infinity * dev[indI[ind + 1]]) - _E3 = rind(Sc, m, Blo, Bup, indI, xc, nt=1) - - -def cdflomax(x, alpha, m0): - """ - Return CDF for local maxima for a zero-mean Gaussian process - - Parameters - ---------- - x : array-like - evaluation points - alpha, m0 : real scalars - irregularity factor and zero-order spectral moment (variance of the - process), respectively. - - Returns - ------- - prb : ndarray - distribution function evaluated at x - - Notes - ----- - The cdf is calculated from an explicit expression involving the - standard-normal cdf. This relation is sometimes written as a convolution - - M = sqrt(m0)*( sqrt(1-a^2)*Z + a*R ) - - where M denotes local maximum, Z is a standard normal r.v., - R is a standard Rayleigh r.v., and "=" means equality in distribution. - - Note that all local maxima of the process are considered, not - only crests of waves. - - Example - ------- - >>> import pylab - >>> import wafo.gaussian as wg - >>> import wafo.spectrum.models as wsm - >>> import wafo.objects as wo - >>> import wafo.stats as ws - >>> S = wsm.Jonswap(Hm0=10).tospecdata(); - >>> xs = S.sim(10000) - >>> ts = wo.mat2timeseries(xs) - >>> tp = ts.turning_points() - >>> mM = tp.cycle_pairs() - >>> m0 = S.moment(1)[0] - >>> alpha = S.characteristic('alpha')[0] - >>> x = np.linspace(-10,10,200); - >>> mcdf = ws.edf(mM.data) - - h = mcdf.plot(), pylab.plot(x,wg.cdflomax(x,alpha,m0)) - - See also - -------- - spec2mom, spec2bw - """ - c1 = 1.0 / (sqrt(1 - alpha ** 2)) * x / sqrt(m0) - c2 = alpha * c1 - return cdfnorm(c1) - alpha * exp(-x ** 2 / 2 / m0) * cdfnorm(c2) - - -def prbnormtndpc(rho, a, b, d=None, df=0, abseps=1e-4, ierc=0, hnc=0.24): - """ - Return Multivariate normal or T probability with product correlation. - - Parameters - ---------- - rho : array-like - vector of coefficients defining the correlation coefficient by: - correlation(I,J) = rho[i]*rho[j]) for J!=I - where -1 < rho[i] < 1 - a,b : array-like - vector of lower and upper integration limits, respectively. - Note: any values greater the 37 in magnitude, are considered as - infinite values. - d : array-like - vector of means (default zeros(size(rho))) - df = Degrees of freedom, NDF<=0 gives normal probabilities (default) - abseps = absolute error tolerance. (default 1e-4) - ierc = 1 if strict error control based on fourth derivative - 0 if error control based on halving the intervals (default) - hnc = start interval width of simpson rule (default 0.24) - - Returns - ------- - value = estimated value for the integral - bound = bound on the error of the approximation - inform = INTEGER, termination status parameter: - 0, if normal completion with ERROR < EPS; - 1, if N > 1000 or N < 1. - 2, IF any abs(rho)>=1 - 4, if ANY(b(I)<=A(i)) - 5, if number of terms exceeds maximum number of evaluation points - 6, if fault accurs in normal subroutines - 7, if subintervals are too narrow or too many - 8, if bounds exceeds abseps - - PRBNORMTNDPC calculates multivariate normal or student T probability - with product correlation structure for rectangular regions. - The accuracy is as best around single precision, i.e., about 1e-7. - - Example: - -------- - >>> import wafo.gaussian as wg - >>> rho2 = np.random.rand(2) - >>> a2 = np.zeros(2) - >>> b2 = np.repeat(np.inf,2) - >>> [val2,err2, ift2] = wg.prbnormtndpc(rho2,a2,b2) - >>> def g2(x): - ... return 0.25+np.arcsin(x[0]*x[1])/(2*np.pi) - >>> E2 = g2(rho2) # exact value - >>> np.abs(E2-val2)>> rho3 = np.random.rand(3) - >>> a3 = np.zeros(3) - >>> b3 = np.repeat(inf,3) - >>> [val3, err3, ift3] = wg.prbnormtndpc(rho3,a3,b3) - >>> def g3(x): - ... return 0.5-sum(np.sort(np.arccos([x[0]*x[1], - ... x[0]*x[2],x[1]*x[2]])))/(4*np.pi) - >>> E3 = g3(rho3) # Exact value - >>> np.abs(E3-val3) < 5 * err2 - True - - - See also - -------- - prbnormndpc, prbnormnd, Rind - - Reference - --------- - Charles Dunnett (1989) - "Multivariate normal probability integrals with product correlation - structure", Applied statistics, Vol 38,No3, (Algorithm AS 251) - """ - - if d is None: - d = zeros(len(rho)) - # Make sure integration limits are finite - aa = np.clip(a - d, -100, 100) - bb = np.clip(b - d, -100, 100) - - return mvnprdmod.prbnormtndpc(rho, aa, bb, df, abseps, ierc, hnc) - - -def prbnormndpc(rho, a, b, abserr=1e-4, relerr=1e-4, usesimpson=True, - usebreakpoints=False): - """ - Return Multivariate Normal probabilities with product correlation - - Parameters - ---------- - rho = vector defining the correlation structure, i.e., - corr(Xi,Xj) = rho(i)*rho(j) for i~=j - = 1 for i==j - -1 <= rho <= 1 - a,b = lower and upper integration limits respectively. - tol = requested absolute tolerance - - Returns - ------- - value = value of integral - error = estimated absolute error - - PRBNORMNDPC calculates multivariate normal probability - with product correlation structure for rectangular regions. - The accuracy is up to almost double precision, i.e., about 1e-14. - - Example: - ------- - >>> import wafo.gaussian as wg - >>> rho2 = np.random.rand(2) - >>> a2 = np.zeros(2) - >>> b2 = np.repeat(np.inf,2) - >>> [val2,err2, ift2] = wg.prbnormndpc(rho2,a2,b2) - >>> g2 = lambda x : 0.25+np.arcsin(x[0]*x[1])/(2*np.pi) - >>> E2 = g2(rho2) #% exact value - >>> np.abs(E2-val2)>> rho3 = np.random.rand(3) - >>> a3 = np.zeros(3) - >>> b3 = np.repeat(inf,3) - >>> [val3,err3, ift3] = wg.prbnormndpc(rho3,a3,b3) - >>> def g3(x): - ... return 0.5-sum(np.sort(np.arccos([x[0]*x[1], - ... x[0]*x[2],x[1]*x[2]])))/(4*np.pi) - >>> E3 = g3(rho3) # Exact value - >>> np.abs(E3-val3) 0: - warnings.warn('Abnormal termination ier = %d\n\n%s' % - (ier, _ERRORMESSAGE[ier])) - return val, err, ier - -_ERRORMESSAGE = {} -_ERRORMESSAGE[0] = '' -_ERRORMESSAGE[1] = """ - Maximum number of subdivisions allowed has been achieved. one can allow - more subdivisions by increasing the value of limit (and taking the - according dimension adjustments into account). however, if this yields - no improvement it is advised to analyze the integrand in order to - determine the integration difficulties. if the position of a local - difficulty can be determined (i.e. singularity discontinuity within - the interval), it should be supplied to the routine as an element of - the vector points. If necessary an appropriate special-purpose - integrator must be used, which is designed for handling the type of - difficulty involved. - """ -_ERRORMESSAGE[2] = """ - the occurrence of roundoff error is detected, which prevents the requested - tolerance from being achieved. The error may be under-estimated.""" - -_ERRORMESSAGE[3] = """ - Extremely bad integrand behaviour occurs at some points of the integration - interval.""" -_ERRORMESSAGE[4] = """ - The algorithm does not converge. Roundoff error is detected in the - extrapolation table. It is presumed that the requested tolerance cannot be - achieved, and that the returned result is the best which can be obtained. - """ -_ERRORMESSAGE[5] = """ - The integral is probably divergent, or slowly convergent. - It must be noted that divergence can occur with any other value of ier>0. - """ -_ERRORMESSAGE[6] = """the input is invalid because: - 1) npts2 < 2 - 2) break points are specified outside the integration range - 3) (epsabs<=0 and epsrel EPS and MAXPTS - function vaules used; increase MAXPTS to - decrease ERROR; - if INFORM = 2, N > NMAX or N < 1. where NMAX depends on the - integration method - Example - ------- - Compute the probability that X1<0,X2<0,X3<0,X4<0,X5<0, - Xi are zero-mean Gaussian variables with variances one - and correlations Cov(X(i),X(j))=0.3: - indI=[0 5], and barriers B_lo=[-inf 0], B_lo=[0 inf] - gives H_lo = [-inf -inf -inf -inf -inf] H_lo = [0 0 0 0 0] - - >>> Et = 0.001946 # # exact prob. - >>> n = 5; nt = n - >>> Blo =-np.inf; Bup=0; indI=[-1, n-1] # Barriers - >>> m = 1.2*np.ones(n); rho = 0.3; - >>> Sc =(np.ones((n,n))-np.eye(n))*rho+np.eye(n) - >>> rind = Rind() - >>> E0, err0, terr0 = rind(Sc,m,Blo,Bup,indI, nt=nt) - - >>> A = np.repeat(Blo,n) - >>> B = np.repeat(Bup,n)-m - >>> val, err, inform = prbnormnd(Sc,A,B) - >>> np.allclose([val, err, inform], - ... [0.0019456719705212067, 1.0059406844578488e-05, 0]) - True - - >>> np.allclose(np.abs(val-Et) < err0+terr0, True) - True - >>> 'val = %2.5f' % val - 'val = 0.00195' - - See also - -------- - prbnormndpc, Rind - """ - - m, n = correl.shape - Na = len(a) - Nb = len(b) - if (m != n or m != Na or m != Nb): - raise ValueError('Size of input is inconsistent!') - - if maxpts is None: - maxpts = 1000 * n - - maxpts = max(round(maxpts), 10 * n) - -# % array of correlation coefficients; the correlation -# % coefficient in row I column J of the correlation matrix -# % should be stored in CORREL( J + ((I-2)*(I-1))/2 ), for J < I. -# % The correlation matrix must be positive semidefinite. - - D = np.diag(correl) - if (any(D != 1)): - raise ValueError('This is not a correlation matrix') - - # Make sure integration limits are finite - A = np.clip(a, -100, 100) - B = np.clip(b, -100, 100) - ix = np.where(np.triu(np.ones((m, m)), 1) != 0) - L = correl[ix].ravel() # % return only off diagonal elements - - infinity = 37 - infin = np.repeat(2, n) - (B > infinity) - 2 * (A < -infinity) - - err, val, inform = mvn.mvndst(A, B, infin, L, maxpts, abseps, releps) - - return val, err, inform - - # CALL the mexroutine -# t0 = clock; -# if ((method==0) && (n<=100)), -# %NMAX = 100 -# [value, err,inform] = mexmvnprb(L,A,B,abseps,releps,maxpts); -# elseif ( (method<0) || ((method<=0) && (n>100)) ), -# % NMAX = 500 -# [value, err,inform] = mexmvnprb2(L,A,B,abseps,releps,maxpts); -# else -# [value, err,inform] = mexGenzMvnPrb(L,A,B,abseps,releps,maxpts,method); -# end -# exTime = etime(clock,t0); -# ' - -# gauss legendre points and weights, n = 6 -_W6 = [0.1713244923791705e+00, 0.3607615730481384e+00, 0.4679139345726904e+00] -_X6 = [-0.9324695142031522e+00, - - 0.6612093864662647e+00, -0.2386191860831970e+00] -# gauss legendre points and weights, n = 12 -_W12 = [0.4717533638651177e-01, 0.1069393259953183e+00, 0.1600783285433464e+00, - 0.2031674267230659e+00, 0.2334925365383547e+00, 0.2491470458134029e+00] -_X12 = [-0.9815606342467191e+00, -0.9041172563704750e+00, - -0.7699026741943050e+00, - - 0.5873179542866171e+00, -0.3678314989981802e+00, - -0.1252334085114692e+00] -# gauss legendre points and weights, n = 20 -_W20 = [0.1761400713915212e-01, 0.4060142980038694e-01, - 0.6267204833410906e-01, 0.8327674157670475e-01, - 0.1019301198172404e+00, 0.1181945319615184e+00, - 0.1316886384491766e+00, 0.1420961093183821e+00, - 0.1491729864726037e+00, 0.1527533871307259e+00] -_X20 = [-0.9931285991850949e+00, -0.9639719272779138e+00, - - 0.9122344282513259e+00, -0.8391169718222188e+00, - - 0.7463319064601508e+00, -0.6360536807265150e+00, - - 0.5108670019508271e+00, -0.3737060887154196e+00, - - 0.2277858511416451e+00, -0.7652652113349733e-01] - - -def cdfnorm2d(b1, b2, r): - """ - Returnc Bivariate Normal cumulative distribution function - - Parameters - ---------- - - b1, b2 : array-like - upper integration limits - r : real scalar - correlation coefficient (-1 <= r <= 1). - - Returns - ------- - bvn : ndarray - distribution function evaluated at b1, b2. - - Notes - ----- - CDFNORM2D computes bivariate normal probabilities, i.e., the probability - Prob(X1 <= B1 and X2 <= B2) with an absolute error less than 1e-15. - - This function is based on the method described by Drezner, z and - G.O. Wesolowsky, (1989), with major modifications for double precision, - and for |r| close to 1. - - Example - ------- - >>> import wafo.gaussian as wg - >>> x = np.linspace(-5,5,20) - >>> [B1,B2] = np.meshgrid(x, x) - >>> r = 0.3; - >>> F = wg.cdfnorm2d(B1,B2,r) - - surf(x,x,F) - - See also - -------- - cdfnorm - - Reference - --------- - Drezner, z and g.o. Wesolowsky, (1989), - "On the computation of the bivariate normal integral", - Journal of statist. comput. simul. 35, pp. 101-107, - """ - # Translated into Python - # Per A. Brodtkorb - # - # Original code - # by alan genz - # department of mathematics - # washington state university - # pullman, wa 99164-3113 - # email : alangenz@wsu.edu - - b1, b2, r = np.broadcast_arrays(b1, b2, r) - cshape = b1.shape - h, k, r = -b1.ravel(), -b2.ravel(), r.ravel() - - bvn = where(abs(r) > 1, nan, 0.0) - - two = 2.e0 - twopi = 6.283185307179586e0 - - hk = h * k - - k0, = nonzero(abs(r) < 0.925e0) - if len(k0) > 0: - hs = (h[k0] ** 2 + k[k0] ** 2) / two - asr = arcsin(r[k0]) - k1, = nonzero(r[k0] >= 0.75) - if len(k1) > 0: - k01 = k0[k1] - for i in range(10): - for sign in - 1, 1: - sn = sin(asr[k1] * (sign * _X20[i] + 1) / 2) - bvn[k01] = bvn[k01] + _W20[i] * \ - exp((sn * hk[k01] - hs[k1]) / (1 - sn * sn)) - - k1, = nonzero((0.3 <= r[k0]) & (r[k0] < 0.75)) - if len(k1) > 0: - k01 = k0[k1] - for i in range(6): - for sign in - 1, 1: - sn = sin(asr[k1] * (sign * _X12[i] + 1) / 2) - bvn[k01] = bvn[k01] + _W12[i] * \ - exp((sn * hk[k01] - hs[k1]) / (1 - sn * sn)) - - k1, = nonzero(r[k0] < 0.3) - if len(k1) > 0: - k01 = k0[k1] - for i in range(3): - for sign in - 1, 1: - sn = sin(asr[k1] * (sign * _X6[i] + 1) / 2) - bvn[k01] = bvn[k01] + _W6[i] * \ - exp((sn * hk[k01] - hs[k1]) / (1 - sn * sn)) - - bvn[k0] *= asr / (two * twopi) - bvn[k0] += fi(-h[k0]) * fi(-k[k0]) - - k1, = nonzero((0.925 <= abs(r)) & (abs(r) <= 1)) - if len(k1) > 0: - k2, = nonzero(r[k1] < 0) - if len(k2) > 0: - k12 = k1[k2] - k[k12] = -k[k12] - hk[k12] = -hk[k12] - - k3, = nonzero(abs(r[k1]) < 1) - if len(k3) > 0: - k13 = k1[k3] - a2 = (1 - r[k13]) * (1 + r[k13]) - a = sqrt(a2) - b = abs(h[k13] - k[k13]) - bs = b * b - c = (4.e0 - hk[k13]) / 8.e0 - d = (12.e0 - hk[k13]) / 16.e0 - asr = -(bs / a2 + hk[k13]) / 2.e0 - k4, = nonzero(asr > -100.e0) - if len(k4) > 0: - bvn[k13[k4]] = (a[k4] * exp(asr[k4]) * - (1 - c[k4] * (bs[k4] - a2[k4]) * - (1 - d[k4] * bs[k4] / 5) / 3 + - c[k4] * d[k4] * a2[k4] ** 2 / 5)) - - k5, = nonzero(hk[k13] < 100.e0) - if len(k5) > 0: - # b = sqrt(bs); - k135 = k13[k5] - bvn[k135] = bvn[k135] - exp(-hk[k135] / 2) * sqrt(twopi) * \ - fi(-b[k5] / a[k5]) * b[k5] * \ - (1 - c[k5] * bs[k5] * (1 - d[k5] * bs[k5] / 5) / 3) - - a /= two - for i in range(10): - for sign in - 1, 1: - xs = (a * (sign * _X20[i] + 1)) ** 2 - rs = sqrt(1 - xs) - asr = -(bs / xs + hk[k13]) / 2 - k6, = nonzero(asr > -100.e0) - if len(k6) > 0: - k136 = k13[k6] - bvn[k136] += (a[k6] * _W20[i] * exp(asr[k6]) * - (exp(-hk[k136] * (1 - rs[k6]) / - (2 * (1 + rs[k6]))) / rs[k6] - - (1 + c[k6] * xs[k6] * - (1 + d[k6] * xs[k6])))) - - bvn[k3] = -bvn[k3] / twopi - - k7, = nonzero(r[k1] > 0) - if len(k7): - k17 = k1[k7] - bvn[k17] += fi(-np.maximum(h[k17], k[k17])) - - k8, = nonzero(r[k1] < 0) - if len(k8) > 0: - k18 = k1[k8] - bvn[k18] = -bvn[k18] + np.maximum(0, fi(-h[k18]) - fi(-k[k18])) - - bvn.shape = cshape - return bvn - - -def fi(x): - return 0.5 * (erfc((-x) / sqrt(2))) - - -def prbnorm2d(a, b, r): - """ - Returns Bivariate Normal probability - - Parameters - --------- - a, b : array-like, size==2 - vector with lower and upper integration limits, respectively. - r : real scalar - correlation coefficient - - Returns - ------- - prb : real scalar - computed probability Prob(A[0] <= X1 <= B[0] and A[1] <= X2 <= B[1]) - with an absolute error less than 1e-15. - - Example - ------- - >>> import wafo.gaussian as wg - >>> a = [-1, -2] - >>> b = [1, 1] - >>> r = 0.3 - >>> np.allclose(wg.prbnorm2d(a,b,r), 0.56659121350428077) - True - - See also - -------- - cdfnorm2d, - cdfnorm, - prbnormndpc - """ - infinity = 37 - lower = np.asarray(a) - upper = np.asarray(b) - if np.all((lower <= -infinity) & (infinity <= upper)): - return 1.0 - if (lower >= upper).any(): - return 0.0 - correl = r - infin = np.repeat(2, 2) - (upper > infinity) - 2 * (lower < -infinity) - - if np.all(infin == 2): - return (bvd(lower[0], lower[1], correl) - - bvd(upper[0], lower[1], correl) - - bvd(lower[0], upper[1], correl) + - bvd(upper[0], upper[1], correl)) - elif (infin[0] == 2 and infin[1] == 1): - return (bvd(lower[0], lower[1], correl) - - bvd(upper[0], lower[1], correl)) - elif (infin[0] == 1 and infin[1] == 2): - return (bvd(lower[0], lower[1], correl) - - bvd(lower[0], upper[1], correl)) - elif (infin[0] == 2 and infin[1] == 0): - return (bvd(-upper[0], -upper[1], correl) - - bvd(-lower[0], -upper[1], correl)) - elif (infin[0] == 0 and infin[1] == 2): - return (bvd(-upper[0], -upper[1], correl) - - bvd(-upper[0], -lower[1], correl)) - elif (infin[0] == 1 and infin[1] == 0): - return bvd(lower[0], -upper[1], -correl) - elif (infin[0] == 0 and infin[1] == 1): - return bvd(-upper[0], lower[1], -correl) - elif (infin[0] == 1 and infin[1] == 1): - return bvd(lower[0], lower[1], correl) - elif (infin[0] == 0 and infin[1] == 0): - return bvd(-upper[0], -upper[1], correl) - return 1 - - -def bvd(lo, up, r): - return cdfnorm2d(-lo, -up, r) - - -if __name__ == '__main__': - from wafo.testing import test_docstrings - test_docstrings(__file__) -# if __name__ == '__main__': -# if False: #True: # -# test_rind() -# else: -# import doctest -# doctest.testmod() diff --git a/wafo/integrate.py b/wafo/integrate.py deleted file mode 100644 index 779fbcf..0000000 --- a/wafo/integrate.py +++ /dev/null @@ -1,1476 +0,0 @@ -from __future__ import absolute_import, division, print_function -import warnings -import numpy as np -from numpy import pi, sqrt, ones, zeros -from scipy import integrate as intg -import scipy.special.orthogonal as ort -from scipy import special as sp - -from scipy.integrate import simps, trapz -from wafo.plotbackend import plotbackend as plt -from wafo.demos import humps -from numdifftools.extrapolation import dea3 -# from wafo.dctpack import dct -from collections import defaultdict -# from pychebfun import Chebfun - -_EPS = np.finfo(float).eps -_NODES_AND_WEIGHTS = defaultdict(list) - -__all__ = ['dea3', 'clencurt', 'romberg', - 'h_roots', 'j_roots', 'la_roots', 'p_roots', 'qrule', - 'gaussq', 'richardson', 'quadgr', 'qdemo'] - - -def _assert(cond, msg): - if not cond: - raise ValueError(msg) - - -def _assert_warn(cond, msg): - if not cond: - warnings.warn(msg) - - -def clencurt(fun, a, b, n=5, trace=False): - """ - Numerical evaluation of an integral, Clenshaw-Curtis method. - - Parameters - ---------- - fun : callable - a, b : array-like - Lower and upper integration limit, respectively. - n : integer - defines number of evaluation points (default 5) - - Returns - ------- - q_val = evaluated integral - tol = Estimate of the approximation error - - Notes - ----- - CLENCURT approximates the integral of f(x) from a to b - using an 2*n+1 points Clenshaw-Curtis formula. - The error estimate is usually a conservative estimate of the - approximation error. - The integral is exact for polynomials of degree 2*n or less. - - Example - ------- - >>> import numpy as np - >>> val, err = clencurt(np.exp, 0, 2) - >>> np.allclose(val, np.expm1(2)), err[0] < 1e-10 - (True, True) - - - See also - -------- - simpson, - gaussq - - References - ---------- - [1] Goodwin, E.T. (1961), - "Modern Computing Methods", - 2nd edition, New yourk: Philosophical Library, pp. 78--79 - - [2] Clenshaw, C.W. and Curtis, A.R. (1960), - Numerische Matematik, Vol. 2, pp. 197--205 - """ - # make sure n_2 is even - n_2 = 2 * int(n) - a, b = np.atleast_1d(a, b) - a_shape = a.shape - a = a.ravel() - b = b.ravel() - - a_size = np.prod(a_shape) - - s = np.c_[0:n_2 + 1:1] - s_2 = np.c_[0:n_2 + 1:2] - x = np.cos(np.pi * s / n_2) * (b - a) / 2. + (b + a) / 2 - - if hasattr(fun, '__call__'): - f = fun(x) - else: - x_0 = np.flipud(fun[:, 0]) - n_2 = len(x_0) - 1 - _assert(abs(x - x_0) <= 1e-8, - 'Input vector x must equal cos(pi*s/n_2)*(b-a)/2+(b+a)/2') - - f = np.flipud(fun[:, 1::]) - - if trace: - plt.plot(x, f, '+') - - # using a Gauss-Lobatto variant, i.e., first and last - # term f(a) and f(b) is multiplied with 0.5 - f[0, :] = f[0, :] / 2 - f[n_2, :] = f[n_2, :] / 2 - - # x = cos(pi*0:n_2/n_2) - # f = f(x) - # - # N+1 - # c(k) = (2/N) sum f''(n)*cos(pi*(2*k-2)*(n-1)/N), 1 <= k <= N/2+1. - # n=1 - n = n_2 // 2 - fft = np.fft.fft - tmp = np.real(fft(f[:n_2, :], axis=0)) - c = 2 / n_2 * (tmp[0:n + 1, :] + np.cos(np.pi * s_2) * f[n_2, :]) - c[0, :] = c[0, :] / 2 - c[n, :] = c[n, :] / 2 - - c = c[0:n + 1, :] / ((s_2 - 1) * (s_2 + 1)) - q_val = (a - b) * np.sum(c, axis=0) - - abserr = (b - a) * np.abs(c[n, :]) - - if a_size > 1: - abserr = np.reshape(abserr, a_shape) - q_val = np.reshape(q_val, a_shape) - return q_val, abserr - - -def romberg(fun, a, b, releps=1e-3, abseps=1e-3): - """ - Numerical integration with the Romberg method - - Parameters - ---------- - fun : callable - function to integrate - a, b : real scalars - lower and upper integration limits, respectively. - releps, abseps : scalar, optional - requested relative and absolute error, respectively. - - Returns - ------- - Q : scalar - value of integral - abserr : scalar - estimated absolute error of integral - - ROMBERG approximates the integral of F(X) from A to B - using Romberg's method of integration. The function F - must return a vector of output values if a vector of input values is given. - - - Example - ------- - >>> import numpy as np - >>> [q,err] = romberg(np.sqrt,0,10,0,1e-4) - >>> np.allclose(q, 21.08185107) - True - >>> err[0] < 1e-4 - True - """ - h = b - a - h_min = 1.0e-9 - # Max size of extrapolation table - table_limit = max(min(np.round(np.log2(h / h_min)), 30), 3) - - rom = zeros((2, table_limit)) - - rom[0, 0] = h * (fun(a) + fun(b)) / 2 - ipower = 1 - f_p = ones(table_limit) * 4 - - # q_val1 = 0 - q_val2 = 0. - q_val4 = rom[0, 0] - abserr = q_val4 - # epstab = zeros(1,decdigs+7) - # newflg = 1 - # [res,abserr,epstab,newflg] = dea(newflg,q_val4,abserr,epstab) - two = 1 - one = 0 - converged = False - for i in range(1, table_limit): - h *= 0.5 - u_n5 = np.sum(fun(a + np.arange(1, 2 * ipower, 2) * h)) * h - - # trapezoidal approximations - # T2n = 0.5 * (Tn + Un) = 0.5*Tn + u_n5 - rom[two, 0] = 0.5 * rom[one, 0] + u_n5 - - f_p[i] = 4 * f_p[i - 1] - # Richardson extrapolation - for k in range(i): - rom[two, k + 1] = (rom[two, k] + - (rom[two, k] - rom[one, k]) / (f_p[k] - 1)) - - q_val1 = q_val2 - q_val2 = q_val4 - q_val4 = rom[two, i] - - if 2 <= i: - res, abserr = dea3(q_val1, q_val2, q_val4) - # q_val4 = res - converged = abserr <= max(abseps, releps * abs(res)) - if converged: - break - - # rom(1,1:i) = rom(2,1:i) - two = one - one = (one + 1) % 2 - ipower *= 2 - _assert(converged, "Integral did not converge to the required accuracy!") - return res, abserr - - -def _h_roots_newton(n, releps=3e-14, max_iter=10): - # pim4=0.7511255444649425 - pim4 = np.pi ** (-1. / 4) - - # The roots are symmetric about the origin, so we have to - # find only half of them. - m = int(np.fix((n + 1) / 2)) - - # Initial approximations to the roots go into z. - anu = 2.0 * n + 1 - rhs = np.arange(3, 4 * m, 4) * np.pi / anu - theta = _get_theta(rhs) - z = sqrt(anu) * np.cos(theta) - - p = zeros((3, len(z))) - k_0 = 0 - k_p1 = 1 - - for _i in range(max_iter): - # Newtons method carried out simultaneously on the roots. - p[k_0, :] = 0 - p[k_p1, :] = pim4 - - for j in range(1, n + 1): - # Loop up the recurrence relation to get the Hermite - # polynomials evaluated at z. - k_m1 = k_0 - k_0 = k_p1 - k_p1 = np.mod(k_p1 + 1, 3) - - p[k_p1, :] = (z * sqrt(2 / j) * p[k_0, :] - - sqrt((j - 1) / j) * p[k_m1, :]) - - # p now contains the desired Hermite polynomials. - # We next compute p_deriv, the derivatives, - # by the relation (4.5.21) using p2, the polynomials - # of one lower order. - - p_deriv = sqrt(2 * n) * p[k_0, :] - d_z = p[k_p1, :] / p_deriv - - z = z - d_z # Newtons formula. - - converged = not np.any(abs(d_z) > releps) - if converged: - break - - _assert_warn(converged, 'Newton iteration did not converge!') - weights = 2. / p_deriv ** 2 - return _expand_roots(z, weights, n, m) - - -def h_roots(n, method='newton'): - """ - Returns the roots (x) of the nth order Hermite polynomial, - H_n(x), and weights (w) to use in Gaussian Quadrature over - [-inf,inf] with weighting function exp(-x**2). - - Parameters - ---------- - n : integer - number of roots - method : 'newton' or 'eigenvalue' - uses Newton Raphson to find zeros of the Hermite polynomial (Fast) - or eigenvalue of the jacobi matrix (Slow) to obtain the nodes and - weights, respectively. - - Returns - ------- - x : ndarray - roots - w : ndarray - weights - - Example - ------- - >>> import numpy as np - >>> x, w = h_roots(10) - >>> np.allclose(np.sum(x*w), -5.2516042729766621e-19) - True - - See also - -------- - qrule, gaussq - - References - ---------- - [1] Golub, G. H. and Welsch, J. H. (1969) - 'Calculation of Gaussian Quadrature Rules' - Mathematics of Computation, vol 23,page 221-230, - - [2]. Stroud and Secrest (1966), 'gaussian quadrature formulas', - prentice-hall, Englewood cliffs, n.j. - """ - - if not method.startswith('n'): - return ort.h_roots(n) - return _h_roots_newton(n) - - -def _j_roots_newton(n, alpha, beta, releps=3e-14, max_iter=10): - # Initial approximations to the roots go into z. - alfbet = alpha + beta - - z = np.cos(np.pi * (np.arange(1, n + 1) - 0.25 + 0.5 * alpha) / - (n + 0.5 * (alfbet + 1))) - - p = zeros((3, len(z))) - k_0 = 0 - k_p1 = 1 - for _i in range(max_iter): - # Newton's method carried out simultaneously on the roots. - tmp = 2 + alfbet - p[k_0, :] = 1 - p[k_p1, :] = (alpha - beta + tmp * z) / 2 - - for j in range(2, n + 1): - # Loop up the recurrence relation to get the Jacobi - # polynomials evaluated at z. - k_m1 = k_0 - k_0 = k_p1 - k_p1 = np.mod(k_p1 + 1, 3) - - a = 2. * j * (j + alfbet) * tmp - tmp = tmp + 2 - c = 2 * (j - 1 + alpha) * (j - 1 + beta) * tmp - b = (tmp - 1) * (alpha ** 2 - beta ** 2 + tmp * (tmp - 2) * z) - - p[k_p1, :] = (b * p[k_0, :] - c * p[k_m1, :]) / a - - # p now contains the desired Jacobi polynomials. - # We next compute p_deriv, the derivatives with a standard - # relation involving the polynomials of one lower order. - - p_deriv = ((n * (alpha - beta - tmp * z) * p[k_p1, :] + - 2 * (n + alpha) * (n + beta) * p[k_0, :]) / - (tmp * (1 - z ** 2))) - d_z = p[k_p1, :] / p_deriv - z = z - d_z # Newton's formula. - - converged = not any(abs(d_z) > releps * abs(z)) - if converged: - break - - _assert_warn(converged, 'too many iterations in jrule') - - x = z # Store the root and the weight. - f = (sp.gammaln(alpha + n) + sp.gammaln(beta + n) - - sp.gammaln(n + 1) - sp.gammaln(alpha + beta + n + 1)) - weights = (np.exp(f) * tmp * 2 ** alfbet / (p_deriv * p[k_0, :])) - return x, weights - - -def j_roots(n, alpha, beta, method='newton'): - """ - Returns the roots of the nth order Jacobi polynomial, P^(alpha,beta)_n(x) - and weights (w) to use in Gaussian Quadrature over [-1,1] with weighting - function (1-x)**alpha (1+x)**beta with alpha,beta > -1. - - Parameters - ---------- - n : integer - number of roots - alpha,beta : scalars - defining shape of Jacobi polynomial - method : 'newton' or 'eigenvalue' - uses Newton Raphson to find zeros of the Hermite polynomial (Fast) - or eigenvalue of the jacobi matrix (Slow) to obtain the nodes and - weights, respectively. - - Returns - ------- - x : ndarray - roots - w : ndarray - weights - - - Example - -------- - >>> [x,w]= j_roots(10,0,0) - >>> sum(x*w) - 2.7755575615628914e-16 - - See also - -------- - qrule, gaussq - - - Reference - --------- - [1] Golub, G. H. and Welsch, J. H. (1969) - 'Calculation of Gaussian Quadrature Rules' - Mathematics of Computation, vol 23,page 221-230, - - [2]. Stroud and Secrest (1966), 'gaussian quadrature formulas', - prentice-hall, Englewood cliffs, n.j. - """ - _assert((-1 < alpha) & (-1 < beta), - 'alpha and beta must be greater than -1') - if not method.startswith('n'): - return ort.j_roots(n, alpha, beta) - return _j_roots_newton(n, alpha, beta) - - -def la_roots(n, alpha=0, method='newton'): - """ - Returns the roots (x) of the nth order generalized (associated) Laguerre - polynomial, L^(alpha)_n(x), and weights (w) to use in Gaussian quadrature - over [0,inf] with weighting function exp(-x) x**alpha with alpha > -1. - - Parameters - ---------- - n : integer - number of roots - method : 'newton' or 'eigenvalue' - uses Newton Raphson to find zeros of the Laguerre polynomial (Fast) - or eigenvalue of the jacobi matrix (Slow) to obtain the nodes and - weights, respectively. - - Returns - ------- - x : ndarray - roots - w : ndarray - weights - - Example - ------- - >>> import numpy as np - >>> [x,w] = h_roots(10) - >>> np.allclose(np.sum(x*w) < 1e-16, True) - True - - See also - -------- - qrule, gaussq - - References - ---------- - [1] Golub, G. H. and Welsch, J. H. (1969) - 'Calculation of Gaussian Quadrature Rules' - Mathematics of Computation, vol 23,page 221-230, - - [2]. Stroud and Secrest (1966), 'gaussian quadrature formulas', - prentice-hall, Englewood cliffs, n.j. - """ - _assert(-1 < alpha, 'alpha must be greater than -1') - - if not method.startswith('n'): - return ort.la_roots(n, alpha) - return _la_roots_newton(n, alpha) - - -def _get_theta(rhs): - r_3 = rhs ** (1. / 3) - r_2 = r_3 ** 2 - c = [9.084064e-01, 5.214976e-02, 2.579930e-03, 3.986126e-03] - theta = r_3 * (c[0] + r_2 * (c[1] + r_2 * (c[2] + r_2 * c[3]))) - return theta - - -def _la_roots_newton(n, alpha, releps=3e-14, max_iter=10): - - # Initial approximations to the roots go into z. - anu = 4.0 * n + 2.0 * alpha + 2.0 - rhs = np.arange(4 * n - 1, 2, -4) * np.pi / anu - theta = _get_theta(rhs) - z = anu * np.cos(theta) ** 2 - - d_z = zeros(len(z)) - p = zeros((3, len(z))) - p_previous = zeros((1, len(z))) - p_deriv = zeros((1, len(z))) - k_0 = 0 - k_p1 = 1 - k = slice(len(z)) - for _i in range(max_iter): - # Newton's method carried out simultaneously on the roots. - p[k_0, k] = 0. - p[k_p1, k] = 1. - - for j in range(1, n + 1): - # Loop up the recurrence relation to get the Laguerre - # polynomials evaluated at z. - km1 = k_0 - k_0 = k_p1 - k_p1 = np.mod(k_p1 + 1, 3) - - p[k_p1, k] = ((2 * j - 1 + alpha - z[k]) * p[k_0, k] - - (j - 1 + alpha) * p[km1, k]) / j - # end - # p now contains the desired Laguerre polynomials. - # We next compute p_deriv, the derivatives with a standard - # relation involving the polynomials of one lower order. - - p_previous[k] = p[k_0, k] - p_deriv[k] = (n * p[k_p1, k] - (n + alpha) * p_previous[k]) / z[k] - - d_z[k] = p[k_p1, k] / p_deriv[k] - z[k] = z[k] - d_z[k] # Newton?s formula. - # k = find((abs(d_z) > releps.*z)) - - converged = not np.any(abs(d_z) > releps) - if converged: - break - - _assert_warn(converged, 'too many iterations!') - - nodes = z - weights = -np.exp(sp.gammaln(alpha + n) - - sp.gammaln(n)) / (p_deriv * n * p_previous) - return nodes, weights - - -def _p_roots_newton_start(n): - m = int(np.fix((n + 1) / 2)) - t = (np.pi / (4 * n + 2)) * np.arange(3, 4 * m, 4) - a = 1 - (1 - 1 / n) / (8 * n * n) - x = a * np.cos(t) - return m, x - - -def _p_roots_newton(n): - """ - Algorithm given by Davis and Rabinowitz in 'Methods - of Numerical Integration', page 365, Academic Press, 1975. - """ - m, x = _p_roots_newton_start(n) - - e_1 = n * (n + 1) - for _j in range(2): - p_km1 = 1 - p_k = x - for k in range(2, n + 1): - t_1 = x * p_k - p_kp1 = t_1 - p_km1 - (t_1 - p_km1) / k + t_1 - p_km1 = p_k - p_k = p_kp1 - - den = 1. - x * x - d_1 = n * (p_km1 - x * p_k) - d_pn = d_1 / den - d_2pn = (2. * x * d_pn - e_1 * p_k) / den - d_3pn = (4. * x * d_2pn + (2 - e_1) * d_pn) / den - d_4pn = (6. * x * d_3pn + (6 - e_1) * d_2pn) / den - u = p_k / d_pn - v = d_2pn / d_pn - h = -u * (1 + (.5 * u) * (v + u * (v * v - u * d_3pn / (3 * d_pn)))) - p = p_k + h * (d_pn + (.5 * h) * (d_2pn + (h / 3) * - (d_3pn + .25 * h * d_4pn))) - d_p = d_pn + h * (d_2pn + (.5 * h) * (d_3pn + h * d_4pn / 3)) - h = h - p / d_p - x = x + h - - nodes = -x - h - f_x = d_1 - h * e_1 * (p_k + (h / 2) * (d_pn + (h / 3) * - (d_2pn + (h / 4) * - (d_3pn + (.2 * h) * d_4pn)))) - weights = 2 * (1 - nodes ** 2) / (f_x ** 2) - return _expand_roots(nodes, weights, n, m) - - -def _p_roots_newton1(n, releps=1e-15, max_iter=100): - m, x = _p_roots_newton_start(n) - # Compute the zeros of the N+1 Legendre Polynomial - # using the recursion relation and the Newton-Raphson method - - # Legendre-Gauss Polynomials - p = zeros((3, m)) - - # Derivative of LGP - p_deriv = zeros((m,)) - d_x = zeros((m,)) - - # Compute the zeros of the N+1 Legendre Polynomial - # using the recursion relation and the Newton-Raphson method - - # Iterate until new points are uniformly within epsilon of old - # points - k = slice(m) - k_0 = 0 - k_p1 = 1 - for _ix in range(max_iter): - p[k_0, k] = 1 - p[k_p1, k] = x[k] - - for j in range(2, n + 1): - k_m1 = k_0 - k_0 = k_p1 - k_p1 = np.mod(k_0 + 1, 3) - p[k_p1, k] = ((2 * j - 1) * x[k] * p[k_0, k] - - (j - 1) * p[k_m1, k]) / j - - p_deriv[k] = n * (p[k_0, k] - x[k] * p[k_p1, k]) / (1 - x[k] ** 2) - - d_x[k] = p[k_p1, k] / p_deriv[k] - x[k] = x[k] - d_x[k] - k, = np.nonzero((abs(d_x) > releps * np.abs(x))) - converged = len(k) == 0 - if converged: - break - - _assert(converged, 'Too many iterations!') - - nodes = -x - weights = 2. / ((1 - nodes ** 2) * (p_deriv ** 2)) - return _expand_roots(nodes, weights, n, m) - - -def _expand_roots(x, w, n, m): - if (m + m) > n: - x[m - 1] = 0.0 - if not (m + m) == n: - m = m - 1 - x = np.hstack((x, -x[m - 1::-1])) - w = np.hstack((w, w[m - 1::-1])) - return x, w - - -def p_roots(n, method='newton', a=-1, b=1): - """ - Returns the roots (x) of the nth order Legendre polynomial, P_n(x), - and weights to use in Gaussian Quadrature over [-1,1] with weighting - function 1. - - Parameters - ---------- - n : integer - number of roots - method : 'newton' or 'eigenvalue' - uses Newton Raphson to find zeros of the Hermite polynomial (Fast) - or eigenvalue of the jacobi matrix (Slow) to obtain the nodes and - weights, respectively. - - Returns - ------- - nodes : ndarray - roots - weights : ndarray - weights - - - Example - ------- - Integral of exp(x) from a = 0 to b = 3 is: exp(3)-exp(0)= - >>> import numpy as np - >>> nodes, weights = p_roots(11, a=0, b=3) - >>> np.allclose(np.sum(np.exp(nodes) * weights), 19.085536923187668) - True - >>> nodes, weights = p_roots(11, method='newton1', a=0, b=3) - >>> np.allclose(np.sum(np.exp(nodes) * weights), 19.085536923187668) - True - >>> nodes, weights = p_roots(11, method='eigenvalue', a=0, b=3) - >>> np.allclose(np.sum(np.exp(nodes) * weights), 19.085536923187668) - True - - See also - -------- - quadg. - - - References - ---------- - [1] Davis and Rabinowitz (1975) 'Methods of Numerical Integration', - page 365, Academic Press. - - [2] Golub, G. H. and Welsch, J. H. (1969) - 'Calculation of Gaussian Quadrature Rules' - Mathematics of Computation, vol 23,page 221-230, - - [3] Stroud and Secrest (1966), 'gaussian quadrature formulas', - prentice-hall, Englewood cliffs, n.j. - """ - - if not method.startswith('n'): - nodes, weights = ort.p_roots(n) - else: - if method.endswith('1'): - nodes, weights = _p_roots_newton1(n) - else: - nodes, weights = _p_roots_newton(n) - - if (a != -1) | (b != 1): - # Linear map from[-1,1] to [a,b] - d_h = (b - a) / 2 - nodes = d_h * (nodes + 1) + a - weights = weights * d_h - - return nodes, weights - - -def q5_roots(n): - """ - 5 : p(x) = 1/sqrt((x-a)*(b-x)), a =-1, b = 1 Chebyshev 1'st kind - """ - j = np.arange(1, n + 1) - weights = ones(n) * np.pi / n - nodes = np.cos((2 * j - 1) * np.pi / (2 * n)) - return nodes, weights - - -def q6_roots(n): - """ - 6 : p(x) = sqrt((x-a)*(b-x)), a =-1, b = 1 Chebyshev 2'nd kind - """ - j = np.arange(1, n + 1) - x_j = j * np.pi / (n + 1) - weights = np.pi / (n + 1) * np.sin(x_j) ** 2 - nodes = np.cos(x_j) - return nodes, weights - - -def q7_roots(n): - """ - 7 : p(x) = sqrt((x-a)/(b-x)), a = 0, b = 1 - """ - j = np.arange(1, n + 1) - x_j = (j - 0.5) * pi / (2 * n + 1) - nodes = np.cos(x_j) ** 2 - weights = 2 * np.pi * nodes / (2 * n + 1) - return nodes, weights - - -def q8_roots(n): - """ - 8 : p(x) = 1/sqrt(b-x), a = 0, b = 1 - """ - nodes_1, weights_1 = p_roots(2 * n) - k, = np.where(0 <= nodes_1) - weights = 2 * weights_1[k] - nodes = 1 - nodes_1[k] ** 2 - return nodes, weights - - -def q9_roots(n): - """ - 9 : p(x) = sqrt(b-x), a = 0, b = 1 - """ - nodes_1, weights_1 = p_roots(2 * n + 1) - k, = np.where(0 < nodes_1) - weights = 2 * nodes_1[k] ** 2 * weights_1[k] - nodes = 1 - nodes_1[k] ** 2 - return nodes, weights - - -def qrule(n, wfun=1, alpha=0, beta=0): - """ - Return nodes and weights for Gaussian quadratures. - - Parameters - ---------- - n : integer - number of base points - wfun : integer - defining the weight function, p(x). (default wfun = 1) - 1 : p(x) = 1 a =-1, b = 1 Gauss-Legendre - 2 : p(x) = exp(-x^2) a =-inf, b = inf Hermite - 3 : p(x) = x^alpha*exp(-x) a = 0, b = inf Laguerre - 4 : p(x) = (x-a)^alpha*(b-x)^beta a =-1, b = 1 Jacobi - 5 : p(x) = 1/sqrt((x-a)*(b-x)), a =-1, b = 1 Chebyshev 1'st kind - 6 : p(x) = sqrt((x-a)*(b-x)), a =-1, b = 1 Chebyshev 2'nd kind - 7 : p(x) = sqrt((x-a)/(b-x)), a = 0, b = 1 - 8 : p(x) = 1/sqrt(b-x), a = 0, b = 1 - 9 : p(x) = sqrt(b-x), a = 0, b = 1 - - Returns - ------- - bp = base points (abscissas) - wf = weight factors - - The Gaussian Quadrature integrates a (2n-1)th order - polynomial exactly and the integral is of the form - b n - Int ( p(x)* F(x) ) dx = Sum ( wf_j* F( bp_j ) ) - a j=1 - where p(x) is the weight function. - For Jacobi and Laguerre: alpha, beta >-1 (default alpha=beta=0) - - Examples: - --------- - >>> import numpy as np - - # integral of x^2 from a = -1 to b = 1 - >>> bp, wf = qrule(10) - >>> np.allclose(sum(bp**2*wf), 0.66666666666666641) - True - - # integral of exp(-x**2)*x**2 from a = -inf to b = inf - >>> bp, wf = qrule(10,2) - >>> np.allclose(sum(bp ** 2 * wf), 0.88622692545275772) - True - - # integral of (x+1)*(1-x)**2 from a = -1 to b = 1 - >>> bp, wf = qrule(10,4,1,2) - >>> np.allclose((bp * wf).sum(), 0.26666666666666755) - True - - See also - -------- - gaussq - - Reference - --------- - Abromowitz and Stegun (1954) - (for method 5 to 9) - """ - - if wfun == 3: # Generalized Laguerre - return la_roots(n, alpha) - if wfun == 4: # Gauss-Jacobi - return j_roots(n, alpha, beta) - - _assert(0 < wfun < 10, 'unknown weight function') - - root_fun = [None, p_roots, h_roots, la_roots, j_roots, q5_roots, q6_roots, - q7_roots, q8_roots, q9_roots][wfun] - return root_fun(n) - - -class _Gaussq(object): - """ - Numerically evaluate integral, Gauss quadrature. - - Parameters - ---------- - fun : callable - a,b : array-like - lower and upper integration limits, respectively. - releps, abseps : real scalars, optional - relative and absolute tolerance, respectively. - (default releps=abseps=1e-3). - wfun : scalar integer, optional - defining the weight function, p(x). (default wfun = 1) - 1 : p(x) = 1 a =-1, b = 1 Gauss-Legendre - 2 : p(x) = exp(-x^2) a =-inf, b = inf Hermite - 3 : p(x) = x^alpha*exp(-x) a = 0, b = inf Laguerre - 4 : p(x) = (x-a)^alpha*(b-x)^beta a =-1, b = 1 Jacobi - 5 : p(x) = 1/sqrt((x-a)*(b-x)), a =-1, b = 1 Chebyshev 1'st kind - 6 : p(x) = sqrt((x-a)*(b-x)), a =-1, b = 1 Chebyshev 2'nd kind - 7 : p(x) = sqrt((x-a)/(b-x)), a = 0, b = 1 - 8 : p(x) = 1/sqrt(b-x), a = 0, b = 1 - 9 : p(x) = sqrt(b-x), a = 0, b = 1 - trace : bool, optional - If non-zero a point plot of the integrand (default False). - gn : scalar integer - number of base points to start the integration with (default 2). - alpha, beta : real scalars, optional - Shape parameters of Laguerre or Jacobi weight function - (alpha,beta>-1) (default alpha=beta=0) - - Returns - ------- - val : ndarray - evaluated integral - err : ndarray - error estimate, absolute tolerance abs(int-intold) - - Notes - ----- - GAUSSQ numerically evaluate integral using a Gauss quadrature. - The Quadrature integrates a (2m-1)th order polynomial exactly and the - integral is of the form - b - Int (p(x)* Fun(x)) dx - a - GAUSSQ is vectorized to accept integration limits A, B and - coefficients P1,P2,...Pn, as matrices or scalars and the - result is the common size of A, B and P1,P2,...,Pn. - - Examples - --------- - integration of x**2 from 0 to 2 and from 1 to 4 - - >>> import numpy as np - >>> A = [0, 1] - >>> B = [2, 4] - >>> fun = lambda x: x**2 - >>> val1, err1 = gaussq(fun,A,B) - >>> np.allclose(val1, [ 2.6666667, 21. ]) - True - >>> np.allclose(err1, [ 1.7763568e-15, 1.0658141e-14]) - True - - Integration of x^2*exp(-x) from zero to infinity: - >>> fun2 = lambda x : np.ones(np.shape(x)) - >>> val2, err2 = gaussq(fun2, 0, np.inf, wfun=3, alpha=2) - >>> val3, err3 = gaussq(lambda x: x**2,0, np.inf, wfun=3, alpha=0) - >>> np.allclose(val2, 2), err2[0] < 1e-14 - (True, True) - >>> np.allclose(val3, 2), err3[0] < 1e-14 - (True, True) - - Integrate humps from 0 to 2 and from 1 to 4 - >>> val4, err4 = gaussq(humps, A, B, trace=True) - - See also - -------- - qrule - gaussq2d - """ - - @staticmethod - def _get_dx(wfun, jacob, alpha, beta): - def fun1(x): - return x - if wfun == 4: - d_x = jacob ** (alpha + beta + 1) - else: - d_x = [None, fun1, fun1, fun1, None, lambda x: ones(np.shape(x)), - lambda x: x ** 2, fun1, sqrt, - lambda x: sqrt(x) ** 3][wfun](jacob) - return d_x.ravel() - - @staticmethod - def _nodes_and_weights(num_nodes, wfun, alpha, beta): - global _NODES_AND_WEIGHTS - name = 'wfun{:d}_{:d}_{:g}_{:g}'.format(wfun, num_nodes, alpha, beta) - nodes_and_weights = _NODES_AND_WEIGHTS[name] - if len(nodes_and_weights) == 0: - nodes_and_weights.extend(qrule(num_nodes, wfun, alpha, beta)) - nodes, weights = nodes_and_weights - return nodes, weights - - def _initialize_trace(self, max_iter): - if self.trace: - self.x_trace = [0] * max_iter - self.y_trace = [0] * max_iter - - def _plot_trace(self, x, y): - if self.trace: - self.x_trace.append(x.ravel()) - self.y_trace.append(y.ravel()) - hfig = plt.plot(x, y, 'r.') - plt.setp(hfig, 'color', 'b') - - def _plot_final_trace(self): - if self.trace > 0: - plt.clf() - plt.plot(np.hstack(self.x_trace), np.hstack(self.y_trace), '+') - - @staticmethod - def _get_jacob(wfun, a, b): - if wfun in [2, 3]: - jacob = ones((np.size(a), 1)) - else: - jacob = (b - a) * 0.5 - if wfun in [7, 8, 9]: - jacob *= 2 - return jacob - - @staticmethod - def _warn_msg(k, a_shape): - n = len(k) - if n > 1: - if n == np.prod(a_shape): - msg = 'All integrals did not converge' - else: - msg = '%d integrals did not converge' % (n, ) - return msg + '--singularities likely!' - return 'Integral did not converge--singularity likely!' - - @staticmethod - def _initialize(wfun, a, b, args): - args = np.broadcast_arrays(*np.atleast_1d(a, b, *args)) - a_shape = args[0].shape - args = [np.reshape(x, (-1, 1)) for x in args] - a_out, b_out = args[:2] - args = args[2:] - if wfun in [2, 3]: - a_out = zeros((a_out.size, 1)) - return a_out, b_out, args, a_shape - - @staticmethod - def _revert_nans_with_old(val, val_old): - if any(np.isnan(val)): - val[np.isnan(val)] = val_old[np.isnan(val)] - - @staticmethod - def _update_error(i, abserr, val, val_old, k): - if i > 1: - abserr[k] = abs(val_old[k] - val[k]) # absolute tolerance - - def __call__(self, fun, a, b, releps=1e-3, abseps=1e-3, alpha=0, beta=0, - wfun=1, trace=False, args=(), max_iter=11): - self.trace = trace - num_nodes = 2 - - a_0, b_0, args, a_shape = self._initialize(wfun, a, b, args) - - jacob = self._get_jacob(wfun, a_0, b_0) - shift = int(wfun in [1, 4, 5, 6]) - d_x = self._get_dx(wfun, jacob, alpha, beta) - - self._initialize_trace(max_iter) - - # Break out of the iteration loop for three reasons: - # 1) the last update is very small (compared to int and to releps) - # 2) There are more than 11 iterations. This should NEVER happen. - dtype = np.result_type(fun((a_0 + b_0) * 0.5, *args)) - n_k = np.prod(a_shape) # # of integrals we have to compute - k = np.arange(n_k) - opt = (n_k, dtype) - val, val_old, abserr = zeros(*opt), np.nan * ones(*opt), 1e100 * ones(*opt) - nodes_and_weights = self._nodes_and_weights - for i in range(max_iter): - x_n, weights = nodes_and_weights(num_nodes, wfun, alpha, beta) - x = (x_n + shift) * jacob[k, :] + a_0[k, :] - - params = [xi[k, :] for xi in args] - y = fun(x, *params) - self._plot_trace(x, y) - val[k] = np.sum(weights * y, axis=1) * d_x[k] # do the integration - self._revert_nans_with_old(val, val_old) - self._update_error(i, abserr, val, val_old, k) - - k, = np.where(abserr > np.maximum(abs(releps * val), abseps)) - converged = len(k) == 0 - if converged: - break - val_old[k] = val[k] - num_nodes *= 2 # double the # of basepoints and weights - - _assert_warn(converged, self._warn_msg(k, a_shape)) - - # make sure int is the same size as the integration limits - val.shape = a_shape - abserr.shape = a_shape - - self._plot_final_trace() - return val, abserr - - -gaussq = _Gaussq() - - -def richardson(q_val, k): - # license BSD - # Richardson extrapolation with parameter estimation - c = np.real((q_val[k - 1] - q_val[k - 2]) / (q_val[k] - q_val[k - 1])) - 1. - # The lower bound 0.07 admits the singularity x.^-0.9 - c = max(c, 0.07) - return q_val[k] + (q_val[k] - q_val[k - 1]) / c - - -class _Quadgr(object): - """ - Gauss-Legendre quadrature with Richardson extrapolation. - - [q_val,ERR] = QUADGR(FUN,A,B,TOL) approximates the integral of a function - FUN from A to B with an absolute error tolerance TOL. FUN is a function - handle and must accept vector arguments. TOL is 1e-6 by default. q_val is - the integral approximation and ERR is an estimate of the absolute - error. - - QUADGR uses a 12-point Gauss-Legendre quadrature. The error estimate is - based on successive interval bisection. Richardson extrapolation - accelerates the convergence for some integrals, especially integrals - with endpoint singularities. - - Examples - -------- - >>> import numpy as np - >>> q_val, err = quadgr(np.log,0,1) - >>> q, err = quadgr(np.exp,0,9999*1j*np.pi) - >>> np.allclose(q, -2.0000000000122662), err < 1.0e-08 - (True, True) - - >>> q, err = quadgr(lambda x: np.sqrt(4-x**2), 0, 2, abseps=1e-12) - >>> np.allclose(q, 3.1415926535897811), err < 1.0e-12 - (True, True) - - >>> q, err = quadgr(lambda x: np.sqrt(4-x**2), 0, 0, abseps=1e-12) - >>> np.allclose(q, 0), err < 1.0e-12 - (True, True) - - >>> q, err = quadgr(lambda x: x**-0.75, 0, 1) - >>> np.allclose(q, 4), err < 1.e-13 - (True, True) - - >>> q, err = quadgr(lambda x: 1./np.sqrt(1-x**2), -1, 1) - >>> np.allclose(q, 3.141596056985029), err < 1.0e-05 - (True, True) - - >>> q, err = quadgr(lambda x: np.exp(-x**2), -np.inf, np.inf, 1e-9) - >>> np.allclose(q, np.sqrt(np.pi)), err < 1e-9 - (True, True) - - >>> q, err = quadgr(lambda x: np.cos(x)*np.exp(-x), 0, np.inf, 1e-9) - >>> np.allclose(q, 0.5), err < 1e-9 - (True, True) - >>> q, err = quadgr(lambda x: np.cos(x)*np.exp(-x), np.inf, 0, 1e-9) - >>> np.allclose(q, -0.5), err < 1e-9 - (True, True) - >>> q, err = quadgr(lambda x: np.cos(x)*np.exp(x), -np.inf, 0, 1e-9) - >>> np.allclose(q, 0.5), err < 1e-9 - (True, True) - - See also - -------- - QUAD, - QUADGK - """ - # Author: jonas.lundgren@saabgroup.com, 2009. license BSD - # Order limits (required if infinite limits) - - def _change_variable_and_integrate(self, fun, a, b, abseps, max_iter): - isreal = np.isreal(a) & np.isreal(b) & ~np.isnan(a) & ~np.isnan(b) - _assert(isreal, 'Infinite intervals must be real.') - integrate = self._integrate - # Change of variable - if np.isfinite(a) & np.isinf(b): # a to inf - val, err = integrate(lambda t: fun(a + t / (1 - t)) / (1 - t) ** 2, - 0, 1, abseps, max_iter) - elif np.isinf(a) & np.isfinite(b): # -inf to b - val, err = integrate(lambda t: fun(b + t / (1 + t)) / (1 + t) ** 2, - -1, 0, abseps, max_iter) - else: # -inf to inf - val1, err1 = integrate(lambda t: fun(t / (1 - t)) / (1 - t) ** 2, - 0, 1, abseps / 2, max_iter) - val2, err2 = integrate(lambda t: fun(t / (1 + t)) / (1 + t) ** 2, - -1, 0, abseps / 2, max_iter) - val = val1 + val2 - err = err1 + err2 - return val, err - - @staticmethod - def _nodes_and_weights(): - # Gauss-Legendre quadrature (12-point) - x = np.asarray( - [0.12523340851146894, 0.36783149899818018, 0.58731795428661748, - 0.76990267419430469, 0.9041172563704748, 0.98156063424671924]) - w = np.asarray( - [0.24914704581340288, 0.23349253653835478, 0.20316742672306584, - 0.16007832854334636, 0.10693932599531818, 0.047175336386511842]) - nodes = np.hstack((x, -x)) - weights = np.hstack((w, w)) - return nodes, weights - - @staticmethod - def _get_best_estimate(k, vals0, vals1, vals2): - if k >= 6: - q_v = np.hstack((vals0[k], vals1[k], vals2[k])) - q_w = np.hstack((vals0[k - 1], vals1[k - 1], vals2[k - 1])) - elif k >= 4: - q_v = np.hstack((vals0[k], vals1[k])) - q_w = np.hstack((vals0[k - 1], vals1[k - 1])) - else: - q_v = np.atleast_1d(vals0[k]) - q_w = vals0[k - 1] - # Estimate absolute error - errors = np.atleast_1d(abs(q_v - q_w)) - j = errors.argmin() - err = errors[j] - q_val = q_v[j] -# if k >= 2: # and not iscomplex: -# _val, err1 = dea3(vals0[k - 2], vals0[k - 1], vals0[k]) - return q_val, err - - def _extrapolate(self, k, val0, val1, val2): - # Richardson extrapolation - if k >= 5: - val1[k] = richardson(val0, k) - val2[k] = richardson(val1, k) - elif k >= 3: - val1[k] = richardson(val0, k) - q_val, err = self._get_best_estimate(k, val0, val1, val2) - return q_val, err - - def _integrate(self, fun, a, b, abseps, max_iter): - dtype = np.result_type(fun((a + b) / 2), fun((a + b) / 4)) - - # Initiate vectors - val0 = zeros(max_iter, dtype=dtype) # Quadrature - val1 = zeros(max_iter, dtype=dtype) # First Richardson extrapolation - val2 = zeros(max_iter, dtype=dtype) # Second Richardson extrapolation - - x_n, weights = self._nodes_and_weights() - n = len(x_n) - # One interval - d_x = (b - a) / 2 # Half interval length - x = (a + b) / 2 + d_x * x_n # Nodes - # Quadrature - val0[0] = d_x * np.sum(weights * fun(x), axis=0) - - # Successive bisection of intervals - for k in range(1, max_iter): - - # Interval bisection - d_x = d_x / 2 - x = np.hstack([x + a, x + b]) / 2 - # Quadrature - val0[k] = np.sum(np.sum(np.reshape(fun(x), (-1, n)), axis=0) * - weights, axis=0) * d_x - - q_val, err = self._extrapolate(k, val0, val1, val2) - - converged = (err < abseps) | ~np.isfinite(q_val) - if converged: - break - - _assert_warn(converged, 'Max number of iterations reached without ' - 'convergence.') - _assert_warn(np.isfinite(q_val), - 'Integral approximation is Infinite or NaN.') - - # The error estimate should not be zero - err = err + 2 * np.finfo(q_val).eps - return q_val, err - - @staticmethod - def _order_limits(a, b): - if np.real(a) > np.real(b): - return b, a, True - return a, b, False - - def __call__(self, fun, a, b, abseps=1e-5, max_iter=17): - a = np.asarray(a) - b = np.asarray(b) - if a == b: - q_val = b - a - err = np.abs(b - a) - return q_val, err - - a, b, reverse = self._order_limits(a, b) - - improper_integral = np.isinf(a) | np.isinf(b) - if improper_integral: # Infinite limits - q_val, err = self._change_variable_and_integrate(fun, a, b, abseps, - max_iter) - else: - q_val, err = self._integrate(fun, a, b, abseps, max_iter) - - # Reverse direction - if reverse: - q_val = -q_val - - return q_val, err - - -quadgr = _Quadgr() - - -def boole(y, x): - a, b = x[0], x[-1] - n = len(x) - h = (b - a) / (n - 1) - return (2 * h / 45) * (7 * (y[0] + y[-1]) + 12 * np.sum(y[2:n - 1:4]) + - 32 * np.sum(y[1:n - 1:2]) + - 14 * np.sum(y[4:n - 3:4])) - - -def _plot_error(neval, err_dic, plot_error): - if plot_error: - plt.figure(0) - for name in err_dic: - plt.loglog(neval, err_dic[name], label=name) - - plt.xlabel('number of function evaluations') - plt.ylabel('error') - plt.legend() - - -def _print_headers(formats_h, headers, names): - print(''.join(fi % t for (fi, t) in zip(formats_h, - ['ftn'] + names))) - print(' '.join(headers)) - - -def _stack_values_and_errors(neval, vals_dic, err_dic, names): - data = [neval] - for name in names: - data.append(vals_dic[name]) - data.append(err_dic[name]) - - data = np.vstack(tuple(data)).T - return data - - -def _print_data(formats, data): - for row in data: - print(''.join(fi % t for (fi, t) in zip(formats, row.tolist()))) - - -def _print_values_and_errors(neval, vals_dic, err_dic): - names = sorted(vals_dic.keys()) - num_cols = 2 - formats = ['%4.0f, '] + ['%10.10f, '] * num_cols * 2 - formats[-1] = formats[-1].split(',')[0] - formats_h = ['%4s, '] + ['%20s, '] * num_cols - formats_h[-1] = formats_h[-1].split(',')[0] - headers = ['evals'] + ['%12s %12s' % ('approx', 'error')] * num_cols - while len(names) > 0: - names_c = names[:num_cols] - _print_headers(formats_h, headers, names_c) - data = _stack_values_and_errors(neval, vals_dic, err_dic, names_c) - _print_data(formats, data) - names = names[num_cols:] - - -def _display(neval, vals_dic, err_dic, plot_error): - # display results - _print_values_and_errors(neval, vals_dic, err_dic) - _plot_error(neval, err_dic, plot_error) - - -def chebychev(y, x, n=None): - if n is None: - n = len(y) - c_k = np.polynomial.chebyshev.chebfit(x, y, deg=min(n - 1, 36)) - c_ki = np.polynomial.chebyshev.chebint(c_k) - q = np.polynomial.chebyshev.chebval(x[-1], c_ki) - return q - - -def qdemo(f, a, b, kmax=9, plot_error=False): - """ - Compares different quadrature rules. - - Parameters - ---------- - f : callable - function - a,b : scalars - lower and upper integration limits - - Details - ------- - qdemo(f,a,b) computes and compares various approximations to - the integral of f from a to b. Three approximations are used, - the composite trapezoid, Simpson's, and Boole's rules, all with - equal length subintervals. - In a case like qdemo(exp,0,3) one can see the expected - convergence rates for each of the three methods. - In a case like qdemo(sqrt,0,3), the convergence rate is limited - not by the method, but by the singularity of the integrand. - - Example - ------- - >>> import numpy as np - >>> qdemo(np.exp,0,3, plot_error=True) - true value = 19.08553692 - ftn, Boole, Chebychev - evals approx error approx error - 3, 19.4008539142, 0.3153169910, 19.5061466023, 0.4206096791 - 5, 19.0910191534, 0.0054822302, 19.0910191534, 0.0054822302 - 9, 19.0856414320, 0.0001045088, 19.0855374134, 0.0000004902 - 17, 19.0855386464, 0.0000017232, 19.0855369232, 0.0000000000 - 33, 19.0855369505, 0.0000000273, 19.0855369232, 0.0000000000 - 65, 19.0855369236, 0.0000000004, 19.0855369232, 0.0000000000 - 129, 19.0855369232, 0.0000000000, 19.0855369232, 0.0000000000 - 257, 19.0855369232, 0.0000000000, 19.0855369232, 0.0000000000 - 513, 19.0855369232, 0.0000000000, 19.0855369232, 0.0000000000 - ftn, Clenshaw-Curtis, Gauss-Legendre - evals approx error approx error - 3, 19.5061466023, 0.4206096791, 19.0803304585, 0.0052064647 - 5, 19.0834145766, 0.0021223465, 19.0855365951, 0.0000003281 - 9, 19.0855369150, 0.0000000082, 19.0855369232, 0.0000000000 - 17, 19.0855369232, 0.0000000000, 19.0855369232, 0.0000000000 - 33, 19.0855369232, 0.0000000000, 19.0855369232, 0.0000000000 - 65, 19.0855369232, 0.0000000000, 19.0855369232, 0.0000000000 - 129, 19.0855369232, 0.0000000000, 19.0855369232, 0.0000000000 - 257, 19.0855369232, 0.0000000000, 19.0855369232, 0.0000000000 - 513, 19.0855369232, 0.0000000000, 19.0855369232, 0.0000000000 - ftn, Simps, Trapz - evals approx error approx error - 3, 19.5061466023, 0.4206096791, 22.5366862979, 3.4511493747 - 5, 19.1169646189, 0.0314276957, 19.9718950387, 0.8863581155 - 9, 19.0875991312, 0.0020622080, 19.3086731081, 0.2231361849 - 17, 19.0856674267, 0.0001305035, 19.1414188470, 0.0558819239 - 33, 19.0855451052, 0.0000081821, 19.0995135407, 0.0139766175 - 65, 19.0855374350, 0.0000005118, 19.0890314614, 0.0034945382 - 129, 19.0855369552, 0.0000000320, 19.0864105817, 0.0008736585 - 257, 19.0855369252, 0.0000000020, 19.0857553393, 0.0002184161 - 513, 19.0855369233, 0.0000000001, 19.0855915273, 0.0000546041 - """ - true_val, _tol = intg.quad(f, a, b) - print('true value = %12.8f' % (true_val,)) - neval = zeros(kmax, dtype=int) - vals_dic = {} - err_dic = {} - - # try various approximations - methods = [trapz, simps, boole, chebychev] - - for k in range(kmax): - n = 2 ** (k + 1) + 1 - neval[k] = n - x = np.linspace(a, b, n) - y = f(x) - for method in methods: - name = method.__name__.title() - q = method(y, x) - vals_dic.setdefault(name, []).append(q) - err_dic.setdefault(name, []).append(abs(q - true_val)) - - name = 'Clenshaw-Curtis' - q = clencurt(f, a, b, (n - 1) // 2)[0] - vals_dic.setdefault(name, []).append(q[0]) - err_dic.setdefault(name, []).append(abs(q[0] - true_val)) - - name = 'Gauss-Legendre' # quadrature - q = intg.fixed_quad(f, a, b, n=n)[0] - vals_dic.setdefault(name, []).append(q) - err_dic.setdefault(name, []).append(abs(q - true_val)) - - _display(neval, vals_dic, err_dic, plot_error) - - -def main(): - # val, err = clencurt(np.exp, 0, 2) - # valt = np.exp(2) - np.exp(0) - # [Q, err] = quadgr(lambda x: x ** 2, 1, 4, 1e-9) - # [Q, err] = quadgr(humps, 1, 4, 1e-9) - # - # [x, w] = h_roots(11, 'newton') - # sum(w) - # [x2, w2] = la_roots(11, 1, 't') - # - # from scitools import numpyutils as npu #@UnresolvedImport - # fun = npu.wrap2callable('x**2') - # p0 = fun(0) - # A = [0, 1, 1]; B = [2, 4, 3] - # area, err = gaussq(fun, A, B) - # - # fun = npu.wrap2callable('x**2') - # [val1, err1] = gaussq(fun, A, B) - # - # - # Integration of x^2*exp(-x) from zero to infinity: - # fun2 = npu.wrap2callable('1') - # [val2, err2] = gaussq(fun2, 0, np.inf, wfun=3, alpha=2) - # [val2, err2] = gaussq(lambda x: x ** 2, 0, np.inf, wfun=3, alpha=0) - # - # Integrate humps from 0 to 2 and from 1 to 4 - # [val3, err3] = gaussq(humps, A, B) - # - # [x, w] = p_roots(11, 'newton', 1, 3) - # y = np.sum(x ** 2 * w) - - x = np.linspace(0, np.pi / 2) - _q0 = np.trapz(humps(x), x) - [q, err] = romberg(humps, 0, np.pi / 2, 1e-4) - print(q, err) - - -if __name__ == '__main__': - from wafo.testing import test_docstrings - test_docstrings(__file__) - # qdemo(np.exp, 0, 3, plot_error=True) - # plt.show('hold') - # main() diff --git a/wafo/integrate_oscillating.py b/wafo/integrate_oscillating.py deleted file mode 100644 index 81217ef..0000000 --- a/wafo/integrate_oscillating.py +++ /dev/null @@ -1,538 +0,0 @@ -""" -Created on 20. aug. 2015 - -@author: pab -""" -from __future__ import division -from collections import namedtuple -import warnings -import numdifftools as nd -import numdifftools.nd_algopy as nda -from numdifftools.extrapolation import dea3 -from numdifftools.limits import Limit -import numpy as np -from numpy import linalg -from numpy.polynomial.chebyshev import chebval, Chebyshev -from numpy.polynomial import polynomial -from wafo.misc import piecewise, findcross, ecross - -_FINFO = np.finfo(float) -EPS = _FINFO.eps -_EPS = EPS -_TINY = _FINFO.tiny -_HUGE = _FINFO.max - - -def _assert(cond, msg): - if not cond: - raise ValueError(msg) - - -def _assert_warn(cond, msg): - if not cond: - warnings.warn(msg) - - -class PolyBasis(object): - @staticmethod - def _derivative(c, m): - return polynomial.polyder(c, m) - - @staticmethod - def eval(t, c): - return polynomial.polyval(t, c) - - @staticmethod - def _coefficients(k): - c = np.zeros(k + 1) - c[k] = 1 - return c - - def derivative(self, t, k, n=1): - c = self._coefficients(k) - d_c = self._derivative(c, m=n) - return self.eval(t, d_c) - - def __call__(self, t, k): - return t**k - - -poly_basis = PolyBasis() - - -class ChebyshevBasis(PolyBasis): - - @staticmethod - def _derivative(c, m): - cheb = Chebyshev(c) - dcheb = cheb.deriv(m=m) - return dcheb.coef - - @staticmethod - def eval(t, c): - return chebval(t, c) - - def __call__(self, t, k): - c = self._coefficients(k) - return self.eval(t, c) - - -chebyshev_basis = ChebyshevBasis() - - -def richardson(q_val, k): - # license BSD - # Richardson extrapolation with parameter estimation - c = np.real((q_val[k - 1] - q_val[k - 2]) / (q_val[k] - q_val[k - 1])) - 1. - # The lower bound 0.07 admits the singularity x.^-0.9 - c = max(c, 0.07) - return q_val[k] + (q_val[k] - q_val[k - 1]) / c - - -def evans_webster_weights(omega, g, d_g, x, basis, *args, **kwds): - - def psi(t, k): - return d_g(t, *args, **kwds) * basis(t, k) - - j_w = 1j * omega - n = len(x) - a_matrix = np.zeros((n, n), dtype=complex) - rhs = np.zeros((n,), dtype=complex) - - dbasis = basis.derivative - lim_g = Limit(g) - b_1 = np.exp(j_w * lim_g(1, *args, **kwds)) - if np.isnan(b_1): - b_1 = 0.0 - a_1 = np.exp(j_w * lim_g(-1, *args, **kwds)) - if np.isnan(a_1): - a_1 = 0.0 - - lim_psi = Limit(psi) - for k in range(n): - rhs[k] = basis(1, k) * b_1 - basis(-1, k) * a_1 - a_matrix[k] = (dbasis(x, k, n=1) + j_w * lim_psi(x, k)) - - solution = linalg.lstsq(a_matrix, rhs) - return solution[0] - - -def osc_weights(omega, g, d_g, x, basis, a_b, *args, **kwds): - def _g(t): - return g(scale * t + offset, *args, **kwds) - - def _d_g(t): - return scale * d_g(scale * t + offset, *args, **kwds) - - w = [] - - for a, b in zip(a_b[::2], a_b[1::2]): - scale = (b - a) / 2 - offset = (a + b) / 2 - - w.append(evans_webster_weights(omega, _g, _d_g, x, basis)) - - return np.asarray(w).ravel() - - -class _Integrator(object): - info = namedtuple('info', ['error_estimate', 'n']) - - def __init__(self, f, g, dg=None, a=-1, b=1, basis=chebyshev_basis, s=1, - precision=10, endpoints=True, full_output=False): - self.f = f - self.g = g - self.dg = nd.Derivative(g) if dg is None else dg - self.basis = basis - self.a = a - self.b = b - self.s = s - self.endpoints = endpoints - self.precision = precision - self.full_output = full_output - - -class QuadOsc(_Integrator): - def __init__(self, f, g, dg=None, a=-1, b=1, basis=chebyshev_basis, s=15, - precision=10, endpoints=False, full_output=False, maxiter=17): - self.maxiter = maxiter - super(QuadOsc, self).__init__(f, g, dg=dg, a=a, b=b, basis=basis, s=s, - precision=precision, endpoints=endpoints, - full_output=full_output) - - @staticmethod - def _change_interval_to_0_1(f, g, d_g, a, _b): - def f_01(t, *args, **kwds): - den = 1 - t - return f(a + t / den, *args, **kwds) / den ** 2 - - def g_01(t, *args, **kwds): - return g(a + t / (1 - t), *args, **kwds) - - def d_g_01(t, *args, **kwds): - den = 1 - t - return d_g(a + t / den, *args, **kwds) / den ** 2 - return f_01, g_01, d_g_01, 0., 1. - - @staticmethod - def _change_interval_to_m1_0(f, g, d_g, _a, b): - def f_m10(t, *args, **kwds): - den = 1 + t - return f(b + t / den, *args, **kwds) / den ** 2 - - def g_m10(t, *args, **kwds): - return g(b + t / (1 + t), *args, **kwds) - - def d_g_m10(t, *args, **kwds): - den = 1 + t - return d_g(b + t / den, *args, **kwds) / den ** 2 - return f_m10, g_m10, d_g_m10, -1.0, 0.0 - - @staticmethod - def _change_interval_to_m1_1(f, g, d_g, _a, _b): - def f_m11(t, *args, **kwds): - den = (1 - t**2) - return f(t / den, *args, **kwds) * (1 + t**2) / den ** 2 - - def g_m11(t, *args, **kwds): - den = (1 - t**2) - return g(t / den, *args, **kwds) - - def d_g_m11(t, *args, **kwds): - den = (1 - t**2) - return d_g(t / den, *args, **kwds) * (1 + t**2) / den ** 2 - return f_m11, g_m11, d_g_m11, -1., 1. - - def _get_functions(self): - a, b = self.a, self.b - reverse = np.real(a) > np.real(b) - if reverse: - a, b = b, a - f, g, dg = self.f, self.g, self.dg - - if a == b: - pass - elif np.isinf(a) | np.isinf(b): - # Check real limits - if ~np.isreal(a) | ~np.isreal(b) | np.isnan(a) | np.isnan(b): - raise ValueError('Infinite intervals must be real.') - # Change of variable - if np.isfinite(a) & np.isinf(b): - f, g, dg, a, b = self._change_interval_to_0_1(f, g, dg, a, b) - elif np.isinf(a) & np.isfinite(b): - f, g, dg, a, b = self._change_interval_to_m1_0(f, g, dg, a, b) - else: # -inf to inf - f, g, dg, a, b = self._change_interval_to_m1_1(f, g, dg, a, b) - - return f, g, dg, a, b, reverse - - def __call__(self, omega, *args, **kwds): - f, g, dg, a, b, reverse = self._get_functions() - - val, err = self._quad_osc(f, g, dg, a, b, omega, *args, **kwds) - - if reverse: - val = -val - if self.full_output: - return val, err - return val - - @staticmethod - def _get_best_estimate(k, q_0, q_1, q_2): - if k >= 5: - q_v = np.hstack((q_0[k], q_1[k], q_2[k])) - q_w = np.hstack((q_0[k - 1], q_1[k - 1], q_2[k - 1])) - elif k >= 3: - q_v = np.hstack((q_0[k], q_1[k])) - q_w = np.hstack((q_0[k - 1], q_1[k - 1])) - else: - q_v = np.atleast_1d(q_0[k]) - q_w = q_0[k - 1] - errors = np.atleast_1d(abs(q_v - q_w)) - j = np.nanargmin(errors) - return q_v[j], errors[j] - - def _extrapolate(self, k, q_0, q_1, q_2): - if k >= 4: - q_1[k] = dea3(q_0[k - 2], q_0[k - 1], q_0[k])[0] - q_2[k] = dea3(q_1[k - 2], q_1[k - 1], q_1[k])[0] - elif k >= 2: - q_1[k] = dea3(q_0[k - 2], q_0[k - 1], q_0[k])[0] - # # Richardson extrapolation - # if k >= 4: - # q_1[k] = richardson(q_0, k) - # q_2[k] = richardson(q_1, k) - # elif k >= 2: - # q_1[k] = richardson(q_0, k) - q, err = self._get_best_estimate(k, q_0, q_1, q_2) - return q, err - - def _quad_osc(self, f, g, dg, a, b, omega, *args, **kwds): - if a == b: - q_val = b - a - err = np.abs(b - a) - return q_val, err - - abseps = 10**-self.precision - max_iter = self.maxiter - basis = self.basis - if self.endpoints: - x_n = chebyshev_extrema(self.s) - else: - x_n = chebyshev_roots(self.s) - # x_n = tanh_sinh_open_nodes(self.s) - - # One interval - hh = (b - a) / 2 - x = (a + b) / 2 + hh * x_n # Nodes - - dtype = complex - val0 = np.zeros((max_iter, 1), dtype=dtype) # Quadrature - val1 = np.zeros((max_iter, 1), dtype=dtype) # First extrapolation - val2 = np.zeros((max_iter, 1), dtype=dtype) # Second extrapolation - - lim_f = Limit(f) - a_b = np.hstack([a, b]) - wq = osc_weights(omega, g, dg, x_n, basis, a_b, *args, **kwds) - val0[0] = hh * np.sum(wq * lim_f(x, *args, **kwds)) - - # Successive bisection of intervals - nq = len(x_n) - n = nq - for k in range(1, max_iter): - n += nq * 2**k - - hh = hh / 2 - x = np.hstack([x + a, x + b]) / 2 - a_b = np.hstack([a_b + a, a_b + b]) / 2 - wq = osc_weights(omega, g, dg, x_n, basis, a_b, *args, **kwds) - - val0[k] = hh * np.sum(wq * lim_f(x, *args, **kwds)) - - q_val, err = self._extrapolate(k, val0, val1, val2) - - converged = (err <= abseps) | ~np.isfinite(q_val) - if converged: - break - _assert_warn(converged, 'Max number of iterations reached ' - 'without convergence.') - _assert_warn(np.isfinite(q_val), - 'Integral approximation is Infinite or NaN.') - - # The error estimate should not be zero - err += 2 * np.finfo(q_val).eps - return q_val, self.info(err, n) - - -def adaptive_levin_points(m, delta): - m_1 = m - 1 - prm = 0.5 - while prm * m_1 / delta >= 1: - delta = 2 * delta - k = np.arange(m) - x = piecewise([k < prm * m_1, k == np.ceil(prm * m_1)], - [-1 + k / delta, 0 * k, 1 - (m_1 - k) / delta]) - return x - - -def open_levin_points(m, delta): - return adaptive_levin_points(m + 2, delta)[1:-1] - - -def chebyshev_extrema(m, delta=None): - k = np.arange(m) - x = np.cos(k * np.pi / (m - 1)) - return x - - -def tanh_sinh_nodes(m, delta=None, tol=_EPS): - tmax = np.arcsinh(np.arctanh(1 - _EPS) * 2 / np.pi) - # tmax = 3.18 - m_1 = int(np.floor(-np.log2(tmax / max(m - 1, 1)))) - 1 - h = 2.0**-m_1 - t = np.arange((m + 1) // 2 + 1) * h - x = np.tanh(np.pi / 2 * np.sinh(t)) - k = np.flatnonzero(np.abs(x - 1) <= 10 * tol) - y = x[:k[0] + 1] if len(k) else x - return np.hstack((-y[:0:-1], y)) - - -def tanh_sinh_open_nodes(m, delta=None, tol=_EPS): - return tanh_sinh_nodes(m + 1, delta, tol)[1:-1] - - -def chebyshev_roots(m, delta=None): - k = np.arange(1, 2 * m, 2) * 0.5 - x = np.cos(k * np.pi / m) - return x - - -class AdaptiveLevin(_Integrator): - """Return integral for the Levin-type and adaptive Levin-type methods""" - - @staticmethod - def _a_levin(omega, f, g, d_g, x, s, basis, *args, **kwds): - - def psi(t, k): - return d_g(t, *args, **kwds) * basis(t, k) - - j_w = 1j * omega - nu = np.ones((len(x),), dtype=int) - nu[0] = nu[-1] = s - S = np.cumsum(np.hstack((nu, 0))) - S[-1] = 0 - n = int(S[-2]) - a_matrix = np.zeros((n, n), dtype=complex) - rhs = np.zeros((n,)) - dff = Limit(nda.Derivative(f)) - d_psi = Limit(nda.Derivative(psi)) - dbasis = basis.derivative - for r, t in enumerate(x): - for j in range(S[r - 1], S[r]): - order = ((j - S[r - 1]) % nu[r]) # derivative order - dff.fun.n = order - rhs[j] = dff(t, *args, **kwds) - d_psi.fun.n = order - for k in range(n): - a_matrix[j, k] = (dbasis(t, k, n=order + 1) + - j_w * d_psi(t, k)) - k1 = np.flatnonzero(1 - np.isfinite(rhs)) - if k1.size > 0: # Remove singularities - warnings.warn('Singularities detected! ') - a_matrix[k1] = 0 - rhs[k1] = 0 - solution = linalg.lstsq(a_matrix, rhs) - v = basis.eval([-1, 1], solution[0]) - - lim_g = Limit(g) - g_b = np.exp(j_w * lim_g(1, *args, **kwds)) - if np.isnan(g_b): - g_b = 0 - g_a = np.exp(j_w * lim_g(-1, *args, **kwds)) - if np.isnan(g_a): - g_a = 0 - return v[1] * g_b - v[0] * g_a - - def _get_integration_limits(self, omega, args, kwds): - a, b = self.a, self.b - M = 30 - ab = [a] - scale = (b - a) / 2 - n = 30 - x = np.linspace(a, b, n + 1) - dg_x = np.asarray([scale * omega * self.dg(xi, *args, **kwds) - for xi in x]) - i10 = findcross(dg_x, M) - i1 = findcross(dg_x, 1) - i0 = findcross(dg_x, 0) - im1 = findcross(dg_x, -1) - im10 = findcross(dg_x, -M) - x10 = ecross(x, dg_x, i10, M) if len(i10) else () - x1 = ecross(x, dg_x, i1, 1) if len(i1) else () - x0 = ecross(x, dg_x, i0, 0) if len(i0) else () - xm1 = ecross(x, dg_x, im1, -1) if len(im1) else () - xm10 = ecross(x, dg_x, im10, -M) if len(im10) else () - - for i in np.unique(np.hstack((x10, x1, x0, xm1, xm10))): - if x[0] < i < x[n]: - ab.append(i) - ab.append(b) - return ab - - def __call__(self, omega, *args, **kwds): - ab = self._get_integration_limits(omega, args, kwds) - s = self.s - val = 0 - n = 0 - err = 0 - for ai, bi in zip(ab[:-1], ab[1:]): - vali, infoi = self._QaL(s, ai, bi, omega, *args, **kwds) - val += vali - err += infoi.error_estimate - n += infoi.n - if self.full_output: - info = self.info(err, n) - return val, info - return val - - @staticmethod - def _get_num_points(s, prec, betam): - return 1 if s > 1 else int(prec / max(np.log10(betam + 1), 1) + 1) - - def _QaL(self, s, a, b, omega, *args, **kwds): - """if s>1,the integral is computed by Q_s^L""" - scale = (b - a) / 2 - offset = (a + b) / 2 - prec = self.precision # desired precision - - def ff(t, *args, **kwds): - return scale * self.f(scale * t + offset, *args, **kwds) - - def gg(t, *args, **kwds): - return self.g(scale * t + offset, *args, **kwds) - - def dgg(t, *args, **kwds): - return scale * self.dg(scale * t + offset, *args, **kwds) - dg_a = abs(omega * dgg(-1, *args, **kwds)) - dg_b = abs(omega * dgg(1, *args, **kwds)) - g_a = abs(omega * gg(-1, *args, **kwds)) - g_b = abs(omega * gg(1, *args, **kwds)) - delta, alpha = min(dg_a, dg_b), min(g_a, g_b) - - betam = delta # * scale - if self.endpoints: - if delta < 10 or alpha <= 10 or s > 1: - points = chebyshev_extrema - else: - points = adaptive_levin_points - elif delta < 10 or alpha <= 10 or s > 1: - points = chebyshev_roots - else: - points = open_levin_points # tanh_sinh_open_nodes - - m = self._get_num_points(s, prec, betam) - abseps = 10 * 10.0**-prec - num_collocation_point_list = m * 2**np.arange(1, 5) + 1 - basis = self.basis - - q_val = 1e+300 - num_function_evaluations = 0 - n = 0 - for num_collocation_points in num_collocation_point_list: - n_old = n - q_old = q_val - x = points(num_collocation_points, betam) - n = len(x) - if n > n_old: - q_val = self._a_levin(omega, ff, gg, dgg, x, s, basis, *args, - **kwds) - num_function_evaluations += n - err = np.abs(q_val - q_old) - if err <= abseps: - break - info = self.info(err, num_function_evaluations) - return q_val, info - - -class EvansWebster(AdaptiveLevin): - """Return integral for the Evans Webster method""" - - def __init__(self, f, g, dg=None, a=-1, b=1, basis=chebyshev_basis, s=8, - precision=10, endpoints=False, full_output=False): - super(EvansWebster, - self).__init__(f, g, dg=dg, a=a, b=b, basis=basis, s=s, - precision=precision, endpoints=endpoints, - full_output=full_output) - - def _a_levin(self, omega, ff, gg, dgg, x, s, basis, *args, **kwds): - w = evans_webster_weights(omega, gg, dgg, x, basis, *args, **kwds) - - f = Limit(ff)(x, *args, **kwds) - return np.sum(f * w) - - def _get_num_points(self, s, prec, betam): - return 8 if s > 1 else int(prec / max(np.log10(betam + 1), 1) + 1) - - -if __name__ == '__main__': - tanh_sinh_nodes(16) diff --git a/wafo/padua.py b/wafo/padua.py deleted file mode 100644 index a372248..0000000 --- a/wafo/padua.py +++ /dev/null @@ -1,532 +0,0 @@ -''' - -All the software contained in this library is protected by copyright. -Permission to use, copy, modify, and distribute this software for any -purpose without fee is hereby granted, provided that this entire notice -is included in all copies of any software which is or includes a copy -or modification of this software and in all copies of the supporting -documentation for such software. - -THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED -WARRANTY. IN NO EVENT, NEITHER THE AUTHORS, NOR THE PUBLISHER, NOR ANY -MEMBER OF THE EDITORIAL BOARD OF THE JOURNAL "NUMERICAL ALGORITHMS", -NOR ITS EDITOR-IN-CHIEF, BE LIABLE FOR ANY ERROR IN THE SOFTWARE, ANY -MISUSE OF IT OR ANY DAMAGE ARISING OUT OF ITS USE. THE ENTIRE RISK OF -USING THE SOFTWARE LIES WITH THE PARTY DOING SO. - -ANY USE OF THE SOFTWARE CONSTITUTES ACCEPTANCE OF THE TERMS OF THE -ABOVE STATEMENT. - - -AUTHORS: -Per A Brodtkorb -Python code Based on matlab code written by: - -Marco Caliari -University of Verona, Italy -E-mail: marco.caliari@univr.it - -Stefano de Marchi, Alvise Sommariva, Marco Vianello -University of Padua, Italy -E-mail: demarchi@math.unipd.it, alvise@math.unipd.it, - marcov@math.unipd.it - -Reference ---------- -Padua2DM: fast interpolation and cubature at the Padua points in Matlab/Octave -NUMERICAL ALGORITHMS, 56 (2011), PP. 45-60 - - -Padua module ------------- -In polynomial interpolation of two variables, the Padua points are the first -known example (and up to now the only one) of a unisolvent point set -(that is, the interpolating polynomial is unique) with minimal growth of their -Lebesgue constant, proven to be O(log2 n). -This module provides all the functions needed to perform interpolation and -cubature at the Padua points, together with the functions and the demos used -in the paper. - -pdint.m : main function for interpolation at the Padua points -pdcub.m : main function for cubature at the Padua points -pdpts.m : function for the computation of the Padua points -padua_fit.m : function for the computation of the interpolation - coefficients by FFT (recommended) -pdcfsMM.m : function for the computation of the interpolation - coefficients by matrix multiplications -pdval.m : function for the evaluation of the interpolation - polynomial -pdwtsFFT.m : function for the computation of the cubature - weights by FFT -pdwtsMM.m : function for the computation of the cubature - weights by matrix multiplications (recommended) -funct.m : function containing some test functions -demo_pdint.m : demo script for pdint -demo_cputime_pdint.m : demo script for the computation of CPU time for - interpolation -demo_errors_pdint.m : demo script for the comparison of interpolation with - coefficients computed by FFT or by matrix - multiplications -demo_pdcub : demo script for pdcub -demo_cputime_pdcub.m : demo script for the computation of CPU time for - cubature -demo_errors_pdcub.m : demo script for the comparison of cubature with - weights computed by FFT or by matrix multiplications -demo_errors_pdcub_gl.m : demo script for the comparison of different cubature - formulas -cubature_square.m : function for the computation of some cubature - formulas for the square -omelyan_solovyan_rule.m : function for the computation of Omelyan-Solovyan - cubature points and weights -Contents.m : Contents file for Matlab - - -''' -from __future__ import absolute_import, division -import numpy as np -from numpy.fft import fft -from wafo.dctpack import dct -from wafo.polynomial import map_from_interval, map_to_interval -# from scipy.fftpack.realtransforms import dct - - -class _ExampleFunctions(object): - ''' - Computes test function in the points (x, y) - - Parameters - ---------- - x,y : array-like - evaluate the function in the points (x,y) - i : scalar int (default 0) - defining which test function to use. Options are - 0: franke - 1: half_sphere - 2: poly_degree20 - 3: exp_fun1 - 4: exp_fun100 - 5: cos30 - 6: constant - 7: exp_xy - 8: runge - 9: abs_cubed - 10: gauss - 11: exp_inv - - Returns - ------- - z : array-like - value of the function in the points (x,y) - ''' - @staticmethod - def franke(x, y): - '''Franke function. - - The value of the definite integral on the square [-1,1] x [-1,1], - obtained using a Padua Points cubature formula of degree 500, is - 2.1547794245591083e+000 with an estimated absolute error of 8.88e-016. - - The value of the definite integral on the square [0,1] x [0,1], - obtained using a Padua Points cubature formula of degree 500, is - 4.06969589491556e-01 with an estimated absolute error of 8.88e-016. - - Maple: 0.40696958949155611906 - ''' - def _exp(x, y, loc, scale, p2=2): - return np.exp(- (x - loc[0])**2 / scale[0] - (y - loc[1])**p2 / scale[1]) - # exp = np.exp - x9, y9 = 9. * x, 9. * y - return (3. / 4 * _exp(x9, y9, [2, 2], [4, 4]) + - 3. / 4 * _exp(x9, y9, [-1, -1], [49, 10], p2=1) + - 1. / 2 * _exp(x9, y9, [7, 3], [4, 4]) - - 1. / 5 * _exp(x9, y9, [4, 7], [1, 1])) - - @staticmethod - def half_sphere(x, y): - '''The value of the definite integral on the square [-1,1] x [-1,1], - obtained using a Padua Points cubature formula of degree 2000, is - 3.9129044444568244e+000 with an estimated absolute error of 3.22e-010. - ''' - return ((x - 0.5)**2 + (y - 0.5)**2)**(1. / 2) - - @staticmethod - def poly_degree20(x, y): - ''''Bivariate polynomial having moderate degree. - The value of the definite integral on the square [-1,1] x - [-1,1], up to machine precision, is 18157.16017316017 (see ref. 6). - The value of the definite integral on the square [-1,1] x [-1,1], - obtained using a Padua Points cubature formula of degree 500, - is 1.8157160173160162e+004. - - 2D modification of an example by L.N.Trefethen (see ref. 7), f(x)=x^20. - ''' - return (x + y)**20 - - @staticmethod - def exp_fun1(x, y): - ''' The value of the definite integral on the square [-1,1] x [-1,1], - obtained using a Padua Points cubature formula of degree 2000, - is 2.1234596326670683e+001 with an estimated absolute error of - 7.11e-015. - ''' - return np.exp((x - 0.5)**2 + (y - 0.5)**2) - - @staticmethod - def exp_fun100(x, y): - '''The value of the definite integral on the square [-1,1] x [-1,1], - obtained using a Padua Points cubature formula of degree 2000, - is 3.1415926535849605e-002 with an estimated absolute error of - 3.47e-017. - ''' - return np.exp(-100 * ((x - 0.5)**2 + (y - 0.5)**2)) - - @staticmethod - def cos30(x, y): - ''' The value of the definite integral on the square [-1,1] x [-1,1], - obtained using a Padua Points cubature formula of degree 500, - is 4.3386955120336568e-003 with an estimated absolute error of - 2.95e-017. - ''' - return np.cos(30 * (x + y)) - - @staticmethod - def constant(x, y): - '''Constant. - To test interpolation and cubature at degree 0. - The value of the definite integral on the square [-1,1] x [-1,1] - is 4. - ''' - return np.ones(np.shape(x + y)) - - @staticmethod - def exp_xy(x, y): - '''The value of the definite integral on the square [-1,1] x [-1,1] - is up to machine precision is 5.524391382167263 (see ref. 6). - 2. The value of the definite integral on the square [-1,1] x [-1,1], - obtained using a Padua Points cubature formula of degree 500, - is 5.5243913821672628e+000 with an estimated absolute error of - 0.00e+000. - 2D modification of an example by L.N.Trefethen (see ref. 7), - f(x)=exp(x). - ''' - return np.exp(x + y) - - @staticmethod - def runge(x, y): - ''' Bivariate Runge function: as 1D complex function is analytic - in a neighborhood of [-1; 1] but not throughout the complex plane. - - The value of the definite integral on the square [-1,1] x [-1,1], - up to machine precision, is 0.597388947274307 (see ref. 6). - The value of the definite integral on the square [-1,1] x [-1,1], - obtained using a Padua Points cubature formula of degree 500, - is 5.9738894727430725e-001 with an estimated absolute error of - 0.00e+000. - - 2D modification of an example by L.N.Trefethen (see ref. 7), - f(x)=1/(1+16*x^2). - ''' - return 1. / (1 + 16 * (x**2 + y**2)) - - @staticmethod - def abs_cubed(x, y): - '''Low regular function. - The value of the definite integral on the square [-1,1] x [-1,1], - up to machine precision, is 2.508723139534059 (see ref. 6). - The value of the definite integral on the square [-1,1] x [-1,1], - obtained using a Padua Points cubature formula of degree 500, - is 2.5087231395340579e+000 with an estimated absolute error of - 0.00e+000. - - 2D modification of an example by L.N.Trefethen (see ref. 7), - f(x)=abs(x)^3. - ''' - return (x**2 + y**2)**(3 / 2) - - @staticmethod - def gauss(x, y): - '''Bivariate gaussian: smooth function. - The value of the definite integral on the square [-1,1] x [-1,1], - up to machine precision, is 2.230985141404135 (see ref. 6). - The value of the definite integral on the square [-1,1] x [-1,1], - obtained using a Padua Points cubature formula of degree 500, - is 2.2309851414041333e+000 with an estimated absolute error of - 2.66e-015. - - 2D modification of an example by L.N.Trefethen (see ref. 7), - f(x)=exp(-x^2). - ''' - return np.exp(-x**2 - y**2) - - @staticmethod - def exp_inv(x, y): - '''Bivariate example stemming from a 1D C-infinity function. - The value of the definite integral on the square [-1,1] x [-1,1], - up to machine precision, is 0.853358758654305 (see ref. 6). - The value of the definite integral on the square [-1,1] x [-1,1], - obtained using a Padua Points cubature formula of degree 2000, - is 8.5335875865430544e-001 with an estimated absolute error of - 3.11e-015. - - 2D modification of an example by L.N.Trefethen (see ref. 7), - f(x)=exp(-1/x^2). - ''' - arg_z = (x**2 + y**2) - # Avoid cases in which "arg_z=0", setting only in those instances - # "arg_z=eps". - arg_z = arg_z + (1 - np.abs(np.sign(arg_z))) * 1.e-100 - arg_z = 1. / arg_z - return np.exp(-arg_z) - - def __call__(self, x, y, i=0): - s = self - test_function = [s.franke, s.half_sphere, s.poly_degree20, s.exp_fun1, - s.exp_fun100, s.cos30, s.constant, s.exp_xy, s.runge, - s.abs_cubed, s.gauss, s.exp_inv] - return test_function[i](x, y) - - -example_functions = _ExampleFunctions() - - -def _find_m(n): - ix = np.r_[1:(n + 1) * (n + 2):2] - if np.mod(n, 2) == 0: - n2 = n // 2 - offset = np.array([[0, 1] * n2 + [0, ]] * (n2 + 1)) - ix = ix - offset.ravel(order='F') - return ix - - -def padua_points(n, domain=(-1, 1, -1, 1)): - ''' Return Padua points - - Parameters - ---------- - n : scalar integer - interpolation degree - domain : vector [a,b,c,d] - defining the rectangle [a,b] x [c,d]. (default domain = (-1,1,-1,1)) - - Returns - ------- - pad : array of shape (2 x (n+1)*(n+2)/2) such that - (pad[0,:], pad[1,: ]) defines the Padua points in the domain - rectangle [a,b] x [c,d]. - or - X1,Y1,X2,Y2 : arrays - Two subgrids X1,Y1 and X2,Y2 defining the Padua points - ------------------------------------------------------------------------------- - ''' - a, b, c, d = domain - t0 = [np.pi] if n == 0 else np.linspace(0, np.pi, n + 1) - t1 = np.linspace(0, np.pi, n + 2) - zn = map_to_interval(np.cos(t0), a, b) - zn1 = map_to_interval(np.cos(t1), c, d) - - Pad1, Pad2 = np.meshgrid(zn, zn1) - ix = _find_m(n) - return np.vstack((Pad1.ravel(order='F')[ix], - Pad2.ravel(order='F')[ix])) - - -def error_estimate(C0f): - ''' Return interpolation error estimate from Padua coefficients - ''' - n = C0f.shape[1] - C0f2 = np.fliplr(C0f) - errest = sum(np.abs(np.diag(C0f2))) - if (n >= 1): - errest = errest + sum(np.abs(np.diag(C0f2, -1))) - if (n >= 2): - errest = errest + sum(np.abs(np.diag(C0f2, -2))) - return 2 * errest - - -def padua_fit(Pad, fun, *args): - ''' - Computes the Chebyshevs coefficients - - so that f(x, y) can be approximated by: - - f(x, y) = sum cjk*Tjk(x, y) - - Parameters - ---------- - Pad : array-like - Padua points, as computed with padua_points function. - fun : function to be interpolated in the form - fun(x, y, *args), where *args are optional arguments for fun. - - Returns - ------- - coefficents: coefficient matrix - abs_err : interpolation error estimate - - Example - ------ - >>> import numpy as np - >>> import wafo.padua as wp - >>> domain = [0, 1, 0, 1] - >>> a, b, c, d = domain - >>> points = wp.padua_points(21, domain) - >>> C0f, abs_error = wp.padua_fit(points, wp.example_functions.franke) - >>> x1 = np.linspace(a, b, 100) - >>> x2 = np.linspace(c, d, 101) - >>> val = wp.padua_val(x1, x2, C0f, domain, use_meshgrid=True) - >>> X1, X2 = np.meshgrid(x1, x2) - >>> true_val = wp.example_functions.franke(X1, X2) - - >>> np.allclose(val, true_val, atol=10*abs_error) - True - >>> np.allclose(np.abs(val-true_val).max(), 0.0073174614275738296) - True - >>> np.allclose(abs_error, 0.0022486904061664046) - True - - import matplotlib.pyplot as plt - plt.contour(x1, x2, val) - - ''' - - N = np.shape(Pad)[1] - # recover the degree n from N = (n+1)(n+2)/2 - n = int(round(-3 + np.sqrt(1 + 8 * N)) / 2) - C0f = fun(Pad[0], Pad[1], *args) - if (n > 0): - ix = _find_m(n) - GfT = np.zeros((n + 2) * (n + 1)) - GfT[ix] = C0f * 2 / (n * (n + 1)) - GfT = GfT.reshape(n + 1, n + 2) - GfT = GfT.T - GfT[0] = GfT[0] / 2 - GfT[n + 1] = GfT[n + 1] / 2 - GfT[:, 0] = GfT[:, 0] / 2 - GfT[:, n] = GfT[:, n] / 2 - Gf = GfT.T - # compute the interpolation coefficient matrix C0f by FFT - Gfhat = np.real(fft(Gf, 2 * n, axis=0)) - Gfhathat = np.real(fft(Gfhat[:n + 1, :], 2 * (n + 1), axis=1)) - C0f = 2 * Gfhathat[:, 0:n + 1] - C0f[0] = C0f[0, :] / np.sqrt(2) - C0f[:, 0] = C0f[:, 0] / np.sqrt(2) - C0f = np.fliplr(np.triu(np.fliplr(C0f))) - C0f[n] = C0f[n] / 2 - - return C0f, error_estimate(C0f) - - -def paduavals2coefs(f): - m = len(f) - n = int(round(-1.5 + np.sqrt(.25 + 2 * m))) - x = padua_points(n) - idx = _find_m(n) - w = 0 * x[0] + 1. / (n * (n + 1)) - idx1 = np.all(np.abs(x) == 1, axis=0) - w[idx1] = .5 * w[idx1] - idx2 = np.all(np.abs(x) != 1, axis=0) - w[idx2] = 2 * w[idx2] - - G = np.zeros(idx.max() + 1) - G[idx] = 4 * w * f - - use_dct = 100 < n - if use_dct: - C = np.rot90(dct(dct(G.T).T)) # , axis=1) - else: - t1 = np.r_[0:n + 1].reshape(-1, 1) - Tn1 = np.cos(t1 * t1.T * np.pi / n) - t2 = np.r_[0:n + 2].reshape(-1, 1) - Tn2 = np.cos(t2 * t2.T * np.pi / (n + 1)) - C = np.dot(Tn2, np.dot(G, Tn1)) - - C[0] = .5 * C[0] - C[:, 1] = .5 * C[:, 1] - C[0, -1] = .5 * C[0, -1] - del C[-1] - - # Take upper-left triangular part: - return np.fliplr(np.triu(np.fliplr(C))) - # C = triu(C(:,end:-1:1)); - # C = C(:,end:-1:1); - - -# TODO: padua_fit2 does not work correctly yet. -def padua_fit2(Pad, fun, *args): - # N = np.shape(Pad)[1] - # recover the degree n from N = (n+1)(n+2)/2 - # _n = int(round(-3 + np.sqrt(1 + 8 * N)) / 2) - C0f = fun(Pad[0], Pad[1], *args) - return paduavals2coefs(C0f) - - -def _compute_moments(n): - k = np.r_[0:n:2] - mom = 2 * np.sqrt(2) / (1 - k ** 2) - mom[0] = 2 - return mom - - -def padua_cubature(coefficients, domain=(-1, 1, -1, 1)): - ''' - Compute the integral through the coefficient matrix. - ''' - n = coefficients.shape[1] - mom = _compute_moments(n) - M1, M2 = np.meshgrid(mom, mom) - M = M1 * M2 - C0fM = coefficients[0:n:2, 0:n:2] * M - a, b, c, d = domain - integral = (b - a) * (d - c) * C0fM.sum() / 4 - return integral - - -def padua_val(X, Y, coefficients, domain=(-1, 1, -1, 1), use_meshgrid=False): - ''' - Evaluate polynomial in padua form at X, Y. - - Evaluate the interpolation polynomial defined through its coefficient - matrix coefficients at the target points X(:,1),X(:,2) or at the - meshgrid(X1,X2) - - Parameters - ---------- - X, Y: array-like - evaluation points. - coefficients : array-like - coefficient matrix - domain : a vector [a,b,c,d] - defining the rectangle [a,b] x [c,d] - use_meshgrid: bool - If True interpolate at the points meshgrid(X, Y) - - Returns - ------- - fxy : array-like - evaluation of the interpolation polynomial at the target points - ''' - def transform(tn, x, a, b): - xn = map_from_interval(x, a, b).clip(min=-1, max=1).reshape(1, -1) - tx = np.cos(tn * np.arccos(xn)) * np.sqrt(2) - tx[0] = 1 - return tx - - X, Y = np.atleast_1d(X, Y) - original_shape = X.shape - a, b, c, d = domain - n = np.shape(coefficients)[1] - - tn = np.r_[0:n][:, None] - tx1 = transform(tn, X.ravel(), a, b) - tx2 = transform(tn, Y.ravel(), c, d) - - if use_meshgrid: # eval on meshgrid points - return np.dot(tx1.T, np.dot(coefficients, tx2)).T - # scattered points - val = np.sum(np.dot(tx1.T, coefficients) * tx2.T, axis=1) - return val.reshape(original_shape) - - -if __name__ == '__main__': - from wafo.testing import test_docstrings - test_docstrings(__file__) diff --git a/wafo/setup.py b/wafo/setup.py deleted file mode 100644 index a535100..0000000 --- a/wafo/setup.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Sun Oct 25 14:55:34 2015 - -@author: dave -""" - - -def configuration(parent_package='', top_path=None): - from numpy.distutils.misc_util import Configuration - config = Configuration('wafo', parent_package, top_path) - config.add_subpackage('source') - config.make_config_py() - return config - -if __name__ == "__main__": - from numpy.distutils.core import setup - setup(**configuration(top_path='').todict()) diff --git a/wafo/wavemodels.py b/wafo/wavemodels.py deleted file mode 100644 index 36a77c1..0000000 --- a/wafo/wavemodels.py +++ /dev/null @@ -1,268 +0,0 @@ -''' -Created on 13. mar. 2018 - -@author: pab -''' -import numpy as np -from numpy import pi, sqrt -import wafo.transform.estimation as te -import wafo.transform as wt -from wafo.containers import PlotData -from wafo.kdetools.kernels import qlevels -from wafo.misc import tranproc -import warnings - - - -def _set_default_t_h_g(t, h, g, m0, m2): - if g is None: - y = np.linspace(-5, 5) - x = sqrt(m0) * y + 0 - g = wt.TrData(y, x) - if t is None: - tt1 = 2 * pi * sqrt(m0 / m2) - t = np.linspace(0, 1.7 * tt1, 51) - if h is None: - px = g.gauss2dat([0, 4.]) - px = abs(px[1] - px[0]) - h = np.linspace(0, 1.3 * px, 41) - return h, t, g - -def lh83pdf(t=None, h=None, mom=None, g=None): - """ - LH83PDF Longuet-Higgins (1983) approximation of the density (Tc,Ac) - in a stationary Gaussian transform process X(t) where - Y(t) = g(X(t)) (Y zero-mean Gaussian, X non-Gaussian). - - CALL: f = lh83pdf(t,h,[m0,m1,m2],g); - - f = density of wave characteristics of half-wavelength - in a stationary Gaussian transformed process X(t), - where Y(t) = g(X(t)) (Y zero-mean Gaussian) - t,h = vectors of periods and amplitudes, respectively. - default depending on the spectral moments - m0,m1,m2 = the 0'th,1'st and 2'nd moment of the spectral density - with angular frequency. - g = space transformation, Y(t)=g(X(t)), default: g is identity - transformation, i.e. X(t) = Y(t) is Gaussian, - The transformation, g, can be estimated using lc2tr - or dat2tr or given apriori by ochi. - - Example - ------- - >>> import wafo.spectrum.models as sm - >>> Sj = sm.Jonswap() - >>> w = np.linspace(0,4,256) - >>> S = Sj.tospecdata(w) #Make spectrum object from numerical values - >>> S = sm.SpecData1D(Sj(w),w) # Alternatively do it manually - >>> mom, mom_txt = S.moment(nr=2, even=False) - >>> f = lh83pdf(mom=mom) - >>> f.plot() - - See also - -------- - cav76pdf, lc2tr, dat2tr - - References - ---------- - Longuet-Higgins, M.S. (1983) - "On the joint distribution wave periods and amplitudes in a - random wave field", Proc. R. Soc. A389, pp 24--258 - - Longuet-Higgins, M.S. (1975) - "On the joint distribution wave periods and amplitudes of sea waves", - J. geophys. Res. 80, pp 2688--2694 - """ - - # tested on: matlab 5.3 - # History: - # Revised pab 01.04.2001 - # - Added example - # - Better automatic scaling for h,t - # revised by IR 18.06.2000, fixing transformation and transposing t and h to fit simpson req. - # revised by pab 28.09.1999 - # made more efficient calculation of f - # by Igor Rychlik - - m0, m1, m2 = mom - h, t, g = _set_default_t_h_g(t, h, g, m0, m2) - - L0 = m0 - L1 = m1 / (2 * pi) - L2 = m2 / (2 * pi)**2 - eps2 = sqrt((L2 * L0) / (L1**2) - 1) - - if np.any(~np.isreal(eps2)): - raise ValueError('input moments are not correct') - - const = 4 / sqrt(pi) / eps2 / (1 + 1 / sqrt(1 + eps2**2)) - - a = len(h) - b = len(t) - der = np.ones((a, 1)) - - h_lh = g.dat2gauss(h.ravel(), der.ravel()) - - der = abs(h_lh[1]) # abs(h_lh[:, 1]) - h_lh = h_lh[0] - - # Normalization + transformation of t and h ??????? - # Without any transformation - - t_lh = t / (L0 / L1) - #h_lh = h_lh/sqrt(2*L0) - h_lh = h_lh / sqrt(2) - t_lh = 2 * t_lh - - # Computation of the distribution - T, H = np.meshgrid(t_lh[1:b], h_lh) - f_th = np.zeros((a, b)) - tmp = const * der[:, None] * (H / T)**2 * np.exp(-H**2. * - (1 + ((1 - 1. / T) / eps2)**2)) / ((L0 / L1) * sqrt(2) / 2) - f_th[:, 1:b] = tmp - - f = PlotData(f_th, (t, h), - xlab='Tc', ylab='Ac', - title='Joint density of (Tc,Ac) - Longuet-Higgins (1983)', - plot_kwds=dict(plotflag=1)) - - return _add_contour_levels(f) - - -def cav76pdf(t=None, h=None, mom=None, g=None): - """ - CAV76PDF Cavanie et al. (1976) approximation of the density (Tc,Ac) - in a stationary Gaussian transform process X(t) where - Y(t) = g(X(t)) (Y zero-mean Gaussian, X non-Gaussian). - - CALL: f = cav76pdf(t,h,[m0,m2,m4],g); - - f = density of wave characteristics of half-wavelength - in a stationary Gaussian transformed process X(t), - where Y(t) = g(X(t)) (Y zero-mean Gaussian) - t,h = vectors of periods and amplitudes, respectively. - default depending on the spectral moments - m0,m2,m4 = the 0'th, 2'nd and 4'th moment of the spectral density - with angular frequency. - g = space transformation, Y(t)=g(X(t)), default: g is identity - transformation, i.e. X(t) = Y(t) is Gaussian, - The transformation, g, can be estimated using lc2tr - or dat2tr or given a priori by ochi. - [] = default values are used. - - Example - ------- - >>> import wafo.spectrum.models as sm - >>> Sj = sm.Jonswap() - >>> w = np.linspace(0,4,256) - >>> S = Sj.tospecdata(w) #Make spectrum object from numerical values - >>> S = sm.SpecData1D(Sj(w),w) # Alternatively do it manually - >>> mom, mom_txt = S.moment(nr=4, even=True) - >>> f = cav76pdf(mom=mom) - >>> f.plot() - - See also - -------- - lh83pdf, lc2tr, dat2tr - - References - ---------- - Cavanie, A., Arhan, M. and Ezraty, R. (1976) - "A statistical relationship between individual heights and periods of - storm waves". - In Proceedings Conference on Behaviour of Offshore Structures, - Trondheim, pp. 354--360 - Norwegian Institute of Technology, Trondheim, Norway - - Lindgren, G. and Rychlik, I. (1982) - Wave Characteristics Distributions for Gaussian Waves -- - Wave-lenght, Amplitude and Steepness, Ocean Engng vol 9, pp. 411-432. - """ - # tested on: matlab 5.3 NB! note - # History: - # revised pab 04.11.2000 - # - fixed xlabels i.e. f.labx={'Tc','Ac'} - # revised by IR 4 X 2000. fixed transform and normalisation - # using Lindgren & Rychlik (1982) paper. - # At the end of the function there is a text with derivation of the density. - # - # revised by jr 21.02.2000 - # - Introduced cell array for f.x for use with pdfplot - # by pab 28.09.1999 - - m0, m2, m4 = mom - h, t, g = _set_default_t_h_g(t, h, g, m0, m2) - - eps4 = 1.0 - m2**2 / (m0 * m4) - alfa = m2 / sqrt(m0 * m4) - if np.any(~np.isreal(eps4)): - raise ValueError('input moments are not correct') - - a = len(h) - b = len(t) - der = np.ones((a, 1)) - - h_lh = g.dat2gauss(h.ravel(), der.ravel()) - der = abs(h_lh[1]) - h_lh = h_lh[0] - - # Normalization + transformation of t and h - - pos = 2 / (1 + alfa) # inverse of a fraction of positive maxima - cons = 2 * pi**4 * pos / sqrt(2 * pi) / m4 / sqrt((1 - alfa**2)) - # Tm=2*pi*sqrt(m0/m2)/alpha; #mean period between positive maxima - - t_lh = t - h_lh = sqrt(m0) * h_lh - - # Computation of the distribution - T, H = np.meshgrid(t_lh[1:b], h_lh) - f_th = np.zeros((a, b)) - - f_th[:, 1:b] = cons * der[:, None] * (H**2 / (T**5)) * np.exp(-0.5 * ( - H / T**2)**2. * ((T**2 - pi**2 * m2 / m4)**2 / (m0 * (1 - alfa**2)) + pi**4 / m4)) - f = PlotData(f_th, (t, h), - xlab='Tc', ylab='Ac', - title='Joint density of (Tc,Ac) - Cavanie et al. (1976)', - plot_kwds=dict(plotflag=1)) - return _add_contour_levels(f) - -def _add_contour_levels(f): - p_levels = np.r_[10:90:20, 95, 99, 99.9] - try: - c_levels = qlevels(f.data, p=p_levels) - f.clevels = c_levels - f.plevels = p_levels - except ValueError as e: - msg = "Could not calculate contour levels!. ({})".format(str(e)) - warnings.warn(msg) - return f - - # Let U,Z be the height and second derivative (curvature) at a local maximum in a Gaussian proces - # with spectral moments m0,m2,m4. The conditional density ($U>0$) has the following form - #$$ - # f(z,u)=c \frac{1}{\sqrt{2\pi}}\frac{1}{\sqrt{m0(1-\alpha^2)}}\exp(-0.5\left(\frac{u-z(m2/m4)} - # {\sqrt{m0(1-\alpha^2)}}\right)^2)\frac{|z|}{m4}\exp(-0.5z^2/m4), \quad z<0, - #$$ - # where $c=2/(1+\alpha)$, $\alpha=m2/\sqrt{m0\cdot m4}$. - # - # The cavanie approximation is based on the model $X(t)=U \cos(\pi t/T)$, consequently - # we have $U=H$ and by twice differentiation $Z=-U(\pi^2/T)^2\cos(0)$. The variable change has Jacobian - # $2\pi^2 H/T^3$ giving the final formula for the density of $T,H$ - #$$ - # f(t,h)=c \frac{2\pi^4}{\sqrt{2\pi}}\frac{1}{m4\sqrt{m0(1-\alpha^2)}}\frac{h^2}{t^5} - # \exp(-0.5\frac{h^2}{t^4}\left(\left(\frac{t^2-\pi^2(m2/m4)} - # {\sqrt{m0(1-\alpha^2)}}\right)^2+\frac{\pi^4}{m4}\right)). - #$$ - # - # - - -def test_docstrings(): - import doctest - print('Testing docstrings in %s' % __file__) - doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE) - - -if __name__ == '__main__': - test_docstrings() diff --git a/wafo/win32_utils.py b/wafo/win32_utils.py deleted file mode 100644 index ace64e4..0000000 --- a/wafo/win32_utils.py +++ /dev/null @@ -1,258 +0,0 @@ -from __future__ import division -from numpy import round -from threading import Thread -from time import sleep -from win32gui import (InitCommonControls, CallWindowProc, CreateWindowEx, - CreateWindow, SetWindowLong, SendMessage, ShowWindow, - PumpWaitingMessages, PostQuitMessage, DestroyWindow, - MessageBox, EnumWindows, GetClassName) -from win32api import GetModuleHandle, GetSystemMetrics # @UnresolvedImport -from win32api import SetWindowLong as api_SetWindowLong # @UnresolvedImport -from commctrl import (TOOLTIPS_CLASS, TTM_GETDELAYTIME, TTM_SETDELAYTIME, - TTDT_INITIAL, TTDT_AUTOPOP) -import win32con - -WM_USER = win32con.WM_USER -PBM_SETRANGE = (WM_USER + 1) -PBM_SETPOS = (WM_USER + 2) -PBM_DELTAPOS = (WM_USER + 3) -PBM_SETSTEP = (WM_USER + 4) -PBM_STEPIT = (WM_USER + 5) -PBM_SETRANGE32 = (WM_USER + 6) -PBM_GETRANGE = (WM_USER + 7) -PBM_GETPOS = (WM_USER + 8) -PBM_SETBARCOLOR = (WM_USER + 9) -PBM_SETMARQUEE = (WM_USER + 10) -PBM_GETSTEP = (WM_USER + 13) -PBM_GETBKCOLOR = (WM_USER + 14) -PBM_GETBARCOLOR = (WM_USER + 15) -PBM_SETSTATE = (WM_USER + 16) -PBM_GETSTATE = (WM_USER + 17) -PBS_SMOOTH = 0x01 -PBS_VERTICAL = 0x04 -PBS_MARQUEE = 0x08 -PBS_SMOOTHREVERSE = 0x10 -PBST_NORMAL = 1 -PBST_ERROR = 2 -PBST_PAUSED = 3 -WC_DIALOG = 32770 -WM_SETTEXT = win32con.WM_SETTEXT - - -def MAKELPARAM(a, b): - return (a & 0xffff) | ((b & 0xffff) << 16) - - -def _get_tooltip_handles(hwnd, resultList): - ''' - Adds a window handle to resultList if its class-name is 'tooltips_class32', - i.e. the window is a tooltip. - ''' - if GetClassName(hwnd) == TOOLTIPS_CLASS: - resultList.append(hwnd) - - -def set_max_pop_delay_on_tooltip(tooltip): - ''' - Sets maximum auto-pop delay (delay before hiding) on an instance of - wx.ToolTip. - NOTE: The tooltip's SetDelay method is used just to identify the correct - tooltip. - ''' - test_value = 12345 - # Set initial delay just to identify tooltip. - tooltip.SetDelay(test_value) - handles = [] - EnumWindows(_get_tooltip_handles, handles) - for hwnd in handles: - if SendMessage(hwnd, TTM_GETDELAYTIME, TTDT_INITIAL) == test_value: - SendMessage(hwnd, TTM_SETDELAYTIME, TTDT_AUTOPOP, 32767) - tooltip.SetDelay(500) # Restore default value - - -class Waitbar(Thread): - - def __init__(self, title='Waitbar', can_abort=True, max_val=100): - Thread.__init__(self) # Initialize thread - self.title = title - self.can_abort = can_abort - self.max_val = max_val - InitCommonControls() - self.hinst = GetModuleHandle(None) - self.started = False - self.position = 0 - self.do_update = False - self.start() # Run the thread - while not self.started: - sleep(0.1) # Wait until the dialog is ready - - def DlgProc(self, hwnd, uMsg, wParam, lParam): - if uMsg == win32con.WM_DESTROY: - api_SetWindowLong(self.dialog, - win32con.GWL_WNDPROC, - self.oldWndProc) - if uMsg == win32con.WM_CLOSE: - self.started = False - if uMsg == win32con.WM_COMMAND and self.can_abort: - self.started = False - return CallWindowProc(self.oldWndProc, hwnd, uMsg, wParam, lParam) - - def BuildWindow(self): - width = 400 - height = 100 - self.dialog = CreateWindowEx( - win32con.WS_EX_TOPMOST, - WC_DIALOG, - self.title + ' (0%)', - win32con.WS_VISIBLE | win32con.WS_OVERLAPPEDWINDOW, - int(round( - GetSystemMetrics(win32con.SM_CXSCREEN) * .5 - width * .5)), - int(round( - GetSystemMetrics(win32con.SM_CYSCREEN) * .5 - height * .5)), - width, - height, - 0, - 0, - self.hinst, - None) - self.progbar = CreateWindow( - # win32con.WS_EX_DLGMODALFRAME, - 'msctls_progress32', - '', - win32con.WS_VISIBLE | win32con.WS_CHILD, - 10, - 10, - width - 30, - 20, - self.dialog, - 0, - 0, - None) - if self.can_abort: - self.button = CreateWindow( - # win32con.WS_EX_DLGMODALFRAME, - 'BUTTON', - 'Cancel', - win32con.WS_VISIBLE | win32con.WS_CHILD | win32con.BS_PUSHBUTTON, # @IgnorePep8 - int(width / 2.75), - 40, - 100, - 20, - self.dialog, - 0, - 0, - None) - self.oldWndProc = SetWindowLong( - self.dialog, - win32con.GWL_WNDPROC, - self.DlgProc) - SendMessage(self.progbar, PBM_SETRANGE, 0, MAKELPARAM(0, self.max_val)) -# win32gui.SendMessage(self.progbar, PBM_SETSTEP, 0, 10) -# win32gui.SendMessage(self.progbar, PBM_SETMARQUEE, 0, 0) - ShowWindow(self.progbar, win32con.SW_SHOW) - - def run(self): - self.BuildWindow() - self.started = True - while self.started: - PumpWaitingMessages() - if self.do_update: - SendMessage(self.progbar, PBM_SETPOS, - int(self.position % self.max_val), 0) - percentage = int(round(100.0 * self.position / self.max_val)) - SendMessage(self.dialog, WM_SETTEXT, 0, - self.title + ' (%d%%)' % percentage) - # SendMessage(self.progbar, PBM_STEPIT, 0, 0) - self.do_update = False - sleep(0.1) - PostQuitMessage(0) - DestroyWindow(self.dialog) - - def update(self, pos): - if self.started: - if not self.do_update: - self.position = pos - self.do_update = True - return True - return False - - def close(self): - self.started = False - - -# class Waitbar2(Dialog, Thread): -# def __init__(self, title='Waitbar'): -# template = [[title, (0, 0, 215, 36), -# (win32con.DS_MODALFRAME | win32con.WS_POPUP | -# win32con.WS_VISIBLE | win32con.WS_CAPTION | -# win32con.WS_SYSMENU | win32con.DS_SETFONT | -# win32con.WS_GROUP | win32con.WS_EX_TOPMOST), -# | win32con.DS_SYSMODAL), -# None, (8, "MS Sans Serif")], ] -# Dialog.__init__(self, id=template) -# Thread.__init__(self) # Initialize thread -# self.started = False -# self.start() # Run the thread -# while not self.started: -# sleep(0.1) # Wait until the dialog is ready -# -# def OnInitDialog(self): -# rc = Dialog.OnInitDialog(self) -# self.pbar = CreateProgressCtrl() -# self.pbar.CreateWindow (win32con.WS_CHILD | win32con.WS_VISIBLE, -# (10, 10, 310, 24), self, 1001) -# self.started = True -# return rc -# -# def run(self): -# self.DoModal() -# -# def update(self, pos): -# self.pbar.SetPos(int(pos)) -# -# def close(self): -# self.OnCancel() - - -class WarnDlg(Thread): - - def __init__(self, message='', title='Warning!'): - Thread.__init__(self) # Initialize thread - self.title = title - self.message = message - self.start() # Run the thread - - def run(self): - # MessageBox(self.message, self.title, win32con.MB_ICONWARNING) - MessageBox(0, self.message, self.title, - win32con.MB_ICONWARNING | win32con.MB_SYSTEMMODAL) - - -class ErrorDlg(Thread): - - def __init__(self, message='', title='Error!', blocking=False): - Thread.__init__(self) # Initialize thread - self.title = title - self.message = message - if blocking: - self.run() # Run without threading - else: - self.start() # Run in thread - - def run(self): - # MessageBox(self.message, self.title, win32con.MB_ICONERROR) - MessageBox(0, self.message, self.title, - win32con.MB_ICONERROR | win32con.MB_SYSTEMMODAL) - - -if __name__ == '__main__': - WarnDlg('This is an example of a warning', 'Warning!') - ErrorDlg('This is an example of an error message') - wb = Waitbar('Waitbar example') -# wb2 = Waitbar2('Waitbar example') - for i in range(20): - print(wb.update(i * 5)) -# wb2.update(i) - sleep(0.1) - wb.close() -# wb2.close()