From 6a36fa1b466b3b00c9894ceb13a2df9bd260afd8 Mon Sep 17 00:00:00 2001 From: Paul Hobson Date: Thu, 19 Oct 2017 11:58:52 -0700 Subject: [PATCH] Backport PR #9121: Remove old normalising code from plt.hist --- lib/matplotlib/axes/_axes.py | 40 +++++++----------- .../test_axes/hist_density.png | Bin 0 -> 17433 bytes lib/matplotlib/tests/test_axes.py | 8 ++++ 3 files changed, 24 insertions(+), 24 deletions(-) create mode 100644 lib/matplotlib/tests/baseline_images/test_axes/hist_density.png diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 6b53165ca296..429c77f8b24d 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -6105,13 +6105,6 @@ def hist(self, x, bins=None, range=None, density=None, weights=None, -------- hist2d : 2D histograms - Notes - ----- - Until numpy release 1.5, the underlying numpy histogram function was - incorrect with ``normed=True`` if bin sizes were unequal. MPL - inherited that error. It is now corrected within MPL when using - earlier numpy versions. - """ # Avoid shadowing the builtin. bin_range = range @@ -6204,8 +6197,10 @@ def hist(self, x, bins=None, range=None, density=None, weights=None, else: hist_kwargs = dict(range=bin_range) - n = [] + # List to store all the top coordinates of the histograms + tops = [] mlast = None + # Loop through datasets for i in xrange(nx): # this will automatically overwrite bins, # so that each histogram uses the same bins @@ -6213,29 +6208,26 @@ def hist(self, x, bins=None, range=None, density=None, weights=None, m = m.astype(float) # causes problems later if it's an int if mlast is None: mlast = np.zeros(len(bins)-1, m.dtype) - if density and not stacked: - db = np.diff(bins) - m = (m.astype(float) / db) / m.sum() if stacked: - if mlast is None: - mlast = np.zeros(len(bins)-1, m.dtype) m += mlast mlast[:] = m - n.append(m) + tops.append(m) + # If a stacked density plot, normalize so the area of all the stacked + # histograms together is 1 if stacked and density: db = np.diff(bins) - for m in n: - m[:] = (m.astype(float) / db) / n[-1].sum() + for m in tops: + m[:] = (m.astype(float) / db) / tops[-1].sum() if cumulative: slc = slice(None) if cbook.is_numlike(cumulative) and cumulative < 0: slc = slice(None, None, -1) if density: - n = [(m * np.diff(bins))[slc].cumsum()[slc] for m in n] + tops = [(m * np.diff(bins))[slc].cumsum()[slc] for m in tops] else: - n = [m[slc].cumsum()[slc] for m in n] + tops = [m[slc].cumsum()[slc] for m in tops] patches = [] @@ -6253,7 +6245,7 @@ def hist(self, x, bins=None, range=None, density=None, weights=None, if rwidth is not None: dr = np.clip(rwidth, 0, 1) - elif (len(n) > 1 and + elif (len(tops) > 1 and ((not stacked) or rcParams['_internal.classic_mode'])): dr = 0.8 else: @@ -6279,7 +6271,7 @@ def hist(self, x, bins=None, range=None, density=None, weights=None, _barfunc = self.bar bottom_kwarg = 'bottom' - for m, c in zip(n, color): + for m, c in zip(tops, color): if bottom is None: bottom = np.zeros(len(m)) if stacked: @@ -6323,7 +6315,7 @@ def hist(self, x, bins=None, range=None, density=None, weights=None, # For data that is normed to form a probability density, # set to minimum data value / logbase # (gives 1 full tick-label unit for the lowest filled bin) - ndata = np.array(n) + ndata = np.array(tops) minimum = (np.min(ndata[ndata > 0])) / logbase else: # For non-normed (density = False) data, @@ -6346,7 +6338,7 @@ def hist(self, x, bins=None, range=None, density=None, weights=None, fill = (histtype == 'stepfilled') xvals, yvals = [], [] - for m in n: + for m in tops: if stacked: # starting point for drawing polygon y[0] = y[1] @@ -6409,9 +6401,9 @@ def hist(self, x, bins=None, range=None, density=None, weights=None, p.set_label('_nolegend_') if nx == 1: - return n[0], bins, cbook.silent_list('Patch', patches[0]) + return tops[0], bins, cbook.silent_list('Patch', patches[0]) else: - return n, bins, cbook.silent_list('Lists of Patches', patches) + return tops, bins, cbook.silent_list('Lists of Patches', patches) @_preprocess_data(replace_names=["x", "y", "weights"], label_namer=None) def hist2d(self, x, y, bins=10, range=None, normed=False, weights=None, diff --git a/lib/matplotlib/tests/baseline_images/test_axes/hist_density.png b/lib/matplotlib/tests/baseline_images/test_axes/hist_density.png new file mode 100644 index 0000000000000000000000000000000000000000..d75fc1fd8849cb99aad6f782c1d9596f90f80079 GIT binary patch literal 17433 zcmeHv2VB!+zin{P7v?gogem_|JEf)ou9uW|uQYI1GmCGWvf_ zx@wvod{WmUCQ9|M$j}&)ywUy|dt9*>X2x2r&eWULcKiNlc z>6pJUGQ%yo$Nk0M{2dIpXznmld%|{NX!e+CnWRr$w9C=TwsvcuI2V6i^ya(`8zE^?0D5#!_IrhfBnJgWY_I%aUS=QRCx2&nj$v<4k&eykSc z`r~$atInsFGcq!&B?!#g*49?5sqW`I%3hx~CnQ%?V0RrnTSfC{l=;pj3)C;oPbfJ$ zJ2^E_R99xoKfT(@?4+nfahrR6rQ|tX$3b z;ftL5VlQSHST8TlcUAiN3^yeByc!`*TC16lZ|v;tYt20SB5P`j`~BoDzxuwlz1^ld?0}u4 zBX(K=UN3cMx{TJaj!XGIm+$*^W<}(s@hrQmSI;;)Ivzax@V-z+c6MEYXMaplQIYa& z)qbqc1q`MsDB@xOx|VHiZ9MW$rfD;FEvYGR5$@f)*T+wQ*U6r@;JD|KhGW@pEZA=@ zFzg&0>R#U5i0iVBcHb)i581GNZ-lIUdpS7>11~l^oBxFKwQDuEckV9@7T~eJc5QrN zkw)OKx=P*c4YDu2o8om=9Z?z?a|#(A9#)=j)#H)8a;iavHR;r`7IS>YoUlCaK&`~K zr0J-B7zrH9&R+ZE`E%Kmx3-N*^^*ylkSR*OB_)I%%9&AhrTQ_fn;w1B*YIF4otW7M zU!Lr*U_GR$z|)czy6rl(}7H zI8)^1V&B320@agU1))lmohw zYF2;MEsy^60sQVz8zr{-GnbsWwa*%@uX^;&&3sQivyt}AA=+s-f&y=UJtRXZ|TbtR`2(a#m|kNjXyT?T4GYh z@Z!ZG|MHtY&5^6WVp#8f`XJKB)vaHg(;wM(a@6u|u!f$VUUzr5;yvg7a*`$MU14FN zkcLyme0yEILczeqP_#t@XPL~Am$q%F3p=2tm@rVK5PHnz{qZ8l9*;T&SjD`sB24|6 zLw3&2jk80wO7|p8ibPKa?wDFUHzXz|)T(oZ7{t!mh%F41{+@7~onFtGXb z{-wf5JT6RV_wL=KsiK~Ir@qo&*IF?3oZX^bINOT)o{Wa|W^9MtTO)X2jDzhrdQU#7ZMR3)vTGKCNWM(QJ#!dDV zOEju-d^5AMq+JKA2ByiEf4p@zR^~8yWj+r(xgO)PWp=rnWmu#dqWVD4i=3I6Ddjyo z7_I^@cy5pN{5FIe#%n*rU=9Ui)?hGO_8*6x_G;7L;AS2DZ~ydJ>kMv8Q_ocAv;Fn; z^(p43L(x5GQ01_7CDsMBL}1o<33yC)J_r)un^08Lp;-~Zk83v?86=Gq-ToU!d&`=& zpHyVzww>;!{^1Up3fYSW{5&wg*Tb@F`})4}{$MG?c?x~8O)N(&XN=`wnd1^aQW zLM3}hVk_M48e^l1_4XaPW*J#owR2-F1@05=*~ZV0OmyTmE==`EdrtQ{g(kqdMmPfF z)uFraumqXy%8wsSa_GuGP~7KX61}WCpP@7K{^iYt$|x}tk9_g%7!3Z0{4Mw21aYV3 zbt9XgvK6$6fd;(F$ zPuIw(Yb@*W<7_8+494w(0d;5I?}G|$+&3pDr>nqLXJxW+Wiq`7UUQ5s(N8X~Vxil| zTpELk*RC1oxu2Sv8vLc?L`!rp;8ErTa9HFxM8B#9qUohO^y*0%}UJNKKDzd4%|CQNW7K288w(Nx_Vu+z8 zY_-`J>$nDAZIzfTY;4WY(=#!N3lc9q1mD)E<3AhT+R-sW8cD1zb)P8pz1FT&A0sV% z@#4jVx7Y0L;d_00=htAGr1$RK+uYRDWCy_Icfh!QEEzy6KVQnZl4%n?v)@uZaqCz^ zO{7Rme}7_vlIJjs%JGNC(_!L!;BPN0QJLClmbvA#HQRWkgs98Yp7g-u=@!~Z{j*FAovxUXQw#?a~gtyURCQ(Tz z18rbuXoLYzo9rdgOY*MqDtjHZZ_n0%D+NQZtdH@G!mkw;vWhN|ZPJ2x zVbmiC{5uS+ffXCGTg1SsJ=-Wo((-iJ6K85=jJ&fsu*XttQD){50;`x1w{GJOx8Ut? zTRf?Lo~w)Ing8;VH7rJ>d@BvgB{em*+>(!Xd*RCp^g3yuMZ^Ochq5plVE||{a&k63 zMUHlMcGd6}OMM3&fr^YzOeo!xm5~{QP1J~(5yA)fIdxSJ_Ls3e=!f-E2Z0CFH6$n% zz>S4%E(~<@as!sp8}9Fj!MJ3KlwlOE3|2j$Ej=t~R8iu#@SWK_r3Axf+djETvqpf3 zw1Ry6CO!ZRvHwQ7@vuf$0_asEOcBkB@A+lDKE018tT0o|H()^7xXtQ@-8J=@dY)o_ zCRA}E8#mjFGdZ>C#o^-tm``$?#KH4nOG3$7|qGL)DC|>n=TUNpK zfw#awm0-PAEzS(!+AbOn1xq)K=5tn-S@cgoa@hh-WaQ>Hv>93?%nVS7*;;FXGbjC5 zL5Ab+=@j}%W8>d-%6iiSu#IDD#>FmyzR)x?GfUMWCgzwF+q7j~G$Q-^6**HANw^UY zpUG^af_#7%fNu1n5z^6{PI6fzmJ3u%aSG&5FCyv)donL(q3^AGD7hb`PZ!`^b@?e6 zE-5g1Ma|2PfdWCYN7sni9;6EL3Q3YEQKPW-_I68tpRtr^8(7T=Z*$2jOQtR_*CWiO zbY|sM#@@Ph3#l9cB8{+`nwnnkkpv`z_J=CFexADxa4QgS3w~T`X{jOr`Gky$V|O7; zr?h9!X3P@uKscZ~LtO46x(Cb3$qfVQktXwN;nh3!mY~TAQ_7ph4Pv~))Cjw-xwSQ7 z=l;`fJgQRdt*vgoxNP$ZMf41{66AO^PWT!J@r`sB%z04Iv~Ko#bl%2M!y`3!`0xL%$*Ddlf9S%v$m&xqt|-QCku zfE#J><*=waa5c?+XWoPac810eT%yNU@owECTJ`$QuFx_83`V%|oj<1hC(4;|N<Haps;F;GlA8k;JfIOhU2wQ+!eD9 zgV8p$-YxiBl~Lvn_s~N*cx3^{t1z;2;||^`kQ4nayfCdwVHlFwv$Y8PhH9fd_gWM= z7~R^z*F6(gV`6Na4{svGP&Nb+5~Bi}bAZUYW@ZUONWC{G(aPD26xHcM+AbaC2QVWC z=|qk%m-$X0#^Ufw5RQlg!$&ycJ)V(Dw`@ocvRf$s)eLU ztDes4H=rNqJEmoEr26?fP%@7u`A=9pyP{@O9~%k6T}WeTVJZ$FG$l7Tx5qLI=tVK$ zhyv&3~bNpCJ9Z^-4(Tmdwv#N)91hQaj(KFbQ}FoZU&)j&Fpo}sw(0ys zpvj!up$Lj9;`wI_go-0UiZt18`rD(=P7B9e8dsb9oAb-H0iHje9Q}{Db%$#$PL%*0 zh?@nhsop{+~zVF9f#L;}(-Q6Oy zv$YbQJbBF)F-z!KviKEkJrvSy@@{(WF3ES_Q-AX9G(zG)~d| zT6>-a5%v)*dSxY#$tpySV7?502o%t^9^#NA5tjk=ZsDdti6*nHfg&6?68SUhs%Pq% zUh3Iups@wuY9M6+Q>+0A0T|NCb4@4B7C5bGDv>uga(OHn7ddoQm&#x;qq~7J?vXH$ z2h*w7y~B(z@6y?aN56Xh{5j%J#wI4A-jhfgA=l~g#~c%nb|c#%A1cfI$dMznu-VIN zSNxXdG{CY+%iB+Z7fL#kMY|0OC=OP2@ILw6mPNQe%`jWuzJ2TIUMbzEEDde|^TkFL zmsW&Pb-<9~I?R2huz5T%zl33G0M$jF6JqA@AqbKnZi$9{&gBmzd_Qb8E5a_%weYC; zdYumCN2+ho-hySkFx|&8j{-4~b`OYE#jg!1;cN8adeTso$!s)%8O^LQtZcUH`C~1y zDj|KQ!BYZ+$ZWX;6C4DAj+Y+>Q?3dd8*IB#8NlMo&vS<7E*PwmRe7p!0g^+-gs_XA zXel@PP2-qNfhrLI%I@Ap1FJfM;|E$2Ngd|2Cpk`-=qqJt?rmK>V)69bZw_k5dz}E0 z`hM_OH&=kXL+5>s@Pm<8)zSj<@mt%$uL@a`O9$QS=AfDwZH~_vxI71Mh@dboazq{X zZ@OWZ#Zll8HgI3x2J?i2I4gYq+xNt_iHScyMdN$LWAtDEuYx5vYZ z69f%c-o8h_`jWF|A*0GR@E zDb-RH$hA5wrpU-hqklU8L(9)iz>`eoPbCX1Usb<^P&UgjuK^ivMTYwNgLg%8tNa*! z(Xea_(!@bx;S+$+2!S=NVQFaz7z!64DtNDKX03XEdq+oFWo2c{B^-{vIe`Fh;XU() z8<7A+IboMn|G;hj5Z8z;rsTqv!Dr=fy}$o-2(Pzpqw3Gv;7J2~q2ip;D#ZL>JLUh& zpyK=%@Gt6`Q?y!|o5P-2Qfw9`yT&^5EQ%?-if)IEP*i~q!2MQNA-)3kF8d!M173Orup)$kcd&G<*V0R6H@~uT92-(N8 zgVlCUPSXn|8G32MyNHXYD(ML{tNK`3a2R}Mt9AUPI!tlr`n?A3X|v>jcf?@N;DtWrE3>$NK60eL)Y>+|-Jp_D zK}&i3_-kZ(D=qlI^=WBpx(`GbO@9rfy@A_F!`Sm4e4wuVaW`^>b0Fsc97FmDkW=xV zPMn*l4vAQd$*6}V`)3-!AV9KwAkn8GUIEODaTx=+67bG;nFHCT>HIl= zrxZYd;X92Z)&{D~C5f68Wer0SuhCAt&^FRB$3?+ z#!#pt#2((SZ>-yx5BBu{niJq5Y`G7@M;Y#cQKheU+6>@~HF!aMi-UIUA-AleMVFsrH_H|3ece(gFE?FUv%5 zCLj)=R-w#6!f#CLjm0sz!e0Z79T5>Jxbo(1U97AKxI|~d=B9e&0nxR9p%+v5y|vnI za;bD$_o%Bby$b?raI1d{k{?pBA05`=WWwcw6dNp@;K7=co z0v9Uz^u6)f2gQ&jW#r}2WZHXs*}21{<%LzhR++=5qZJS450%lq23Q_)cOKssOb1_V zusU34Nf|6mlL$z6U}f8F1{e5$+w|9u!mq)c|6a_bC<4D3yBedwtI(?07Qi?afN_cS zIjo_U3wEro#1l%qd%J@7G)e61&qgD`n@J-PbX*T<_=UYYV6LUp8CFze-_qMFdOW~f zBLH*$;7^Ph6M^MQ0=4*mIN)yCq3!keF2HXiW_UAyPvcYbTelwi;od%Zo3Z8;w3<7g zSxSTK2e_t{Q1}1~Kt@y}HC(>3G(q}!S47IH>b^KD=hCyUk-Z*00}AnMoLr9jD)1%) z@Tvvv8M?L4sp{$FA9eNg!UOs7hZy}n&h0>4Av_hJm!uK>6%9?Vt1Zx|R7nqz&-}8- zrz=_0?2p{!QK^+72?E$*nDgy_#j1f2EPNu5tb%wfm0eHe^~}}r8`nbto(+I6FE%c2#oW3$U<=|%n6aCg}f>+SO@+LK4t!$!{pJ3J%f z@cz@mqhMiV1G}LNLHPi_Z15*Ez)Veqj1I|k+xY9Jiz$u2cISKcPpredU;J}--kXe&*lmf5 zxH8x{VJQCho~;(f0h#vjVSl%NtJL+6ulbF(!i2B?jh$lh6f$tP*5YrbR?U=Z*MH;6 z;d00}AOBsh96nT)B@(!UPtgv_F)uQ5Arl47rvuk9O2VSw&bKSynn%&?DhgAD(4quC z7`OQ81AiRrzralogH>P+F_lIbME61({@|<+7n7GA8(=M=3``^cT3aSEf?^bKHsU4k zzng@DMX2hE*B)_GfRwjZK$8FB1f8am$+arrLh6M1e!3|zx#|8d9dv(`-NKGSS^iL+ zbmL_8swJ9|y;ex$+8>QkIk1~|;kDX<JtHQ?jIQc_Y&XQdxYvoN+r{WtxXS^p6)mI76w@lM^dZ(n|g>L`ABFx45;S5-0n zPcNT5crI4|@$LkEgjBz_m3?&T9t=LD&%Fj8xXA>vfZqmh=M@Ck5C?hSgM!s_9o~di~0cLY_rT(NE7{iC3{Gl-nAvD#R$fS=5Yp5X00fZ;t z07NI=upgudE9_p7@fu-}1X@AC3p@KrX>|=S`dr}E1IqrQVq&H;TU1%80^~B`?FKG> zc5Z)|JH+C))4e2bfNwqU(jV+sU#MCFYAOHw)Y38FxHG8V5QuuB@jTco5b>m#uf?3d zvi39W%g8`fpEfGmx_+#^|T%kz&!IRcVT zs9tCd;+#3ALx^q5GPGS`Gyj_5>l_z*^zsRCHw$1bLk)wU-bq*tBvi%NCdQCiW#ox3 zSwMLoh7#BVOi*x5)|~$c-z>v=fbRkVYT9)YIq8r{R@6%V!uQQlZ%2gE4CWd%<4y;E z`OcbMbqPKURxSPPL?Wz#}oDK_76V`uFxQl=`1h znGK$bQ;3NE*43Rb{mIqsoKk^TZ2J3dLDL25hUcr@5OqE9U0|{>uzWtR!Hkal8eGsT2113nKvZRL;T7Cl6LKyjO zm{F_MfpH>q?>~BBhmJ!55|(tLI={D2ZL~xq1m1m;l|Uu7@hQr{+|~($41Ex8x+Pd3 zTq!z46+TKoOx7*{6iQDrq?>f84O)%2X7GSnTZ~f$|4XA;awDc(UgAJT)$lkp$s z(hC|Cg~9Mt`~El&GL=y|>!16;N>>KZoKFr_L6zc=rzPM9(JN?v5*DoPj@g?6?A25h zSnyQ&;>RH7yHNjDNeV>Uv(TbJrZDOKcUzJ6P+nOaFe-7mjO=gl=b{F?*Bmor`-Gj; z7!MB?pE1VQL=`?aiyI!cS+myq(N9$%5rgb1NYteuI~CG^mXI{mGh5r*+YY%62ykzJIPzw{*(-5(YHLRtS$V7UK; zg0Hq$@XaB7O3l5!rsLLg4}bDQFc_?6fJ--60P5nUSKYe1%|+(nn8UFRYhKwUlSoX} zkI5?4qq-7lfo#!g#}xC=U_0*=jKB4Zun?my!G8j1+kdL4xoXZ}H1a{W>q;c4Z|7G& z1|-uzBYI6*eEzokzwc6fAF|v*Sng0}4u+!}tFAKpz!X<6n~^<<-v?ZS2<+t;IKY}f zF>))H#=)AaOp{0vMeGlp!PeSiZ)Ak7>nP%MN?mmnS!qJMv?^}v)n&|j4yFk0My+P8 ziu?TTKi4|vmNw0Bew-`(Q=7xnXA)(Pz5cAJ)fu~k_aVeG!(gOcKqOiLh94|&5=j9O zI68Fj1}z0xm(0CB{D4w%Xd-Z-)G1+5M0t6Ui~2792vsItvo}1qH@qQHbGA6e{Pp2s zeWubZO=HJ_3?L(~?PJ2NzTt|u)#~ofJ%_^;U~WJq9|L_9Lr4pyARcqmlr7 zgu^DH$|N*Y79Ubp#tq3eQ^nLoNCG9%1`D%-ircE$g9sVSCO#HOaCs;TH$v%08VdNx zP9{O%rDtdu-RQqi0CIg)gWSIBA7qO195OuEB_B#y2~HAy>tM4UUe40LnD%1t`#FPO z`7z^OJ*_|6>J)w-Q7UJJ(E>3;GCzxp^N9?4#H?X z2Uvm{?!PL^FfBL}grNuO{M7^wjk7FdF*buryxe9oijIzXk@&;HsI`rlUb%hRk6h5H z7i^Lin~MM_`uB|*B;`P$pkU9h&XNL-1nLw}{8>HJ2Gl#f^7=MZ-Tu+8k^e`#M&ZC( z$l_tw4Cs52SYFz5L!XETNK+*~YhF});;|j5%Gfd-vqv-UHzrY!C17XQ)HCE89iu!O zh9d(V76hz@q^cN`gDZDw9>H^r!{e*4UGoBjmC4T-wC(;g0)$F>tj9s`!o{I-XG&>e z;`vM;SE;Z?IhL(Xa|PBOV*heFikX7uMAY2_1i}?|3%%0UDcC|bQj+A7t}y06gxZeY@x5h zhauTf469t|@M7A5ilN;%J#jktTG@(y>Sd|@Y`y2<^Nr~d@UoVD80NI<3_O-b!HxBC z`pflnmZcRVr>iq&8M(r=>QMYA)08>iu*YO|h3Ae?y3$M27MqvCr~H~W@J#`2Q1Sno z!tYGAtbZT`Q(Ol;G9Wz<(3mgN0uAulFAi8p%Yjxxt#&Ut#u^G1=AfZ22k} z;y7e&H$78dQEsoK#P0W=;NIgmpJjnXa>7?97n?k7i{Sd<;_Yjm=LWtjoAGj5l zRqn#~p3_n1P;zG5|j+r>QKx3mx8Sv3MdQ`psb{a7mb5js8(UlWK2{ zmOF!sP;Eke-3Uns8OBAJ5UkC5c`~!U_d11-kHsr?JZunnc{QRU06G)lf=dh^AN!f7}pGK6AHe`c)(YV?7}GU21BmaGEqQ|i7z2D6|NoLm;GBzO!hxwLF$CwRO;Cn)JqO|21N9U1Np{McSmIu zko0(5g917L29YQjQt{-)AaWHPc0tQN3V-K^9x{P|w!Q^tsRL;Ti{p- zp=5K&m!GGvd-8C@7gug&yY{6<$s50<40Z2=-c0LZdVGsFxrpA#@cxzvZPEt1!U#*5dSl&g z0fD^MR{c<4u8R9W3a`Pbm@V74U$nGL?z=A9(b<{)-FM&7oyusHEE%`a^Fg~v3Ij>7 z($3o1Wx#o`iYH_!1QbH;EC4*w;<3@ulF>@2-KQ27wt^Tj)7G~PmIT%={ouiagDNWh z(6s-U&mk%qm%3#$=U%hs?JFL@WT%tl>Ad39z`=VGm=ok$$=wg z@j&PU?gRx%?+E;H`f3qaQL^9+Nd*%=x8EFlN`K(}*21~x3o1c%# z&KBKY4a9&t?6y$V&>$Cf*2U%NozPJE3l}b&4%^JdB@Znj4+?HGRKJGDv-0FLG&By% z$h1x$D>@`5CL7kkT3YCFo(dW9P%a863E!_C^6=3k!2-LMgE%;~gm+j2dC8;05)w4| zC?e6>*VnfWhJ>@;k&c$09{aWH*3|<#PljA61M9NYa?2S%zlzP9HXW_5u5LI{>cemv zpwXPcP`r#&?05>YJ5)lD`*VJNClCpip4&{I&e91z?>s6j%AQ~{nT-0d4w^%XygLFn zZ`~>lf?hUUSZ85z?JQ&`F^P$Z{t~8&p{1Mq%pgLv>n*visiE;q>2A))k00Z8_9+eA z*vQ`mr=!p@gE(Chzq7M5lg09xER@lS3=dCkXwVijEot&58eO^a7y_v0Q2*R2UbyAV z>?k7`LR)({oV5HF`atPQ(_h|6&@Z1dz?SNBL)}CKPzn_{Cv#_9|m$2n_5DNz6 z92C9mfe(48U)O+KRMDSZa>deeD&(WoES=ug+dC=AP=3z^eFWVzXKq7ts?V7XhY<}t zJ&XO>GwN|+FWdZ}L7bVBGlU%w1x!-J&!tlcMGpPtM&91u#ufPI<>lp*Ap@V6mX%#J zH_wH;)5-TH=R%L@mEi0B_g6TJELLr8trm>An!37H;Alzqa42z$u$zD?`_oPB_+wuM z{+Pt2vUt3rqQW@e>Q3J?@g7wL^_9%rTy02CG|!%G1y`FhbvueBA95!xJvZ0D&23I$ z!1gVqSUKB2EB*vlhaITAyZ7#0w6RI;yY4U#<;jWBcgZM*fRWtV)bt2U!!EvBIboed zeLTJt^*3=g0$%wL?^Th`p48Wm*du!B5%fSi<7<}B9~YhN^Q4YJi+5N>A zY~fTr(`m^WAxPsvXn#@|_~x5$8m3-!ftw`bKCTbUKBJ`M(v2H8Jk;~spwluBbwAB8 zfXqj5u4e+`@B)QMKXdP)-LOt3fHOWf zRX!FUdF2WQ_W1O4dmecub8^xF3wkp%BLgrvC|BQ9%XD19wWz(_;9RVX1`PNmXl<=X zlOLKjNY2PW!3mv@uw~bMNsqW*1U%=kf`SnoPVIhX83=2CGQ_G36057Q6cw+3{9a{c z(Xs+MVVUXaO`y~#Lu^Q~v3qk&NxHD0yYsDsaOFu!-}LqM9XWL9JlvkJurPJ;y{C);`?8vVoHAm7n7- z6jS}ncy~|~20+$d02!pIso9Ia@dWBES7Cv3YB*>i`un3Rjde=Armh|s79Q^Y{>7Tz z+}wI9%AGL$pI;w1?e5`mL{RXBLM4IYKjQJItjy%_;loQSEZRkV{Zq`6+uwix8IPsD zq2b8&_2{tUNW}(J<|%~N36Xg^l@%%SaJ0SH+Qn zfl&JE+S-Y7F3-h0`pk?1&HWaUNQ8k^vVn;Xj6o{!#m=2caD6-ZC^<*h*Ve;%bpsGg zfXMkucZcANMJ{Bfha@F0T)uo+(PQ!<1ngK8e9pTS)?SC4Y68lUBYkpLUT+Fj))6xM zWOqqLMP+iMyIvUndKI0t-HR$hJr0Lk#|*TR5S@?JI=4dNmy)12JtYGIS1%-@SWR3RP7Z=mzkq`kN{!DAd%} zTE@P!I2$9Srn)>AuAV3i(0(^KxD^tU?53vkXe>aC)?MsOg!9`;a5|)$?_JLMW(+c63x;7=fP)rOtKKQDIBMFrZ)__=rL7j<>N9t#z&swb*izJ{ZEk-2{{6RaUcauQP$<)v0<_?q!c(Y@ez9v;GJK(I03)84mZlEZ