GUniFrac/0000755000176200001440000000000014142662222011711 5ustar liggesusersGUniFrac/NAMESPACE0000644000176200001440000000137414141354572013142 0ustar liggesusersimportFrom(vegan, adonis, vegdist) importFrom(ape, is.rooted, drop.tip) import(statmod) import(matrixStats) import(stats) importFrom(Rcpp, evalCpp) importFrom(rmutil, dbetabinom) importFrom(Matrix, nearPD) importFrom(MASS, rnegbin) importFrom(parallel, mclapply, makeCluster, stopCluster, clusterEvalQ, parApply, parLapply, parSapply, parRapply, parCapply) importFrom(utils, getFromNamespace) import(foreach) import(ggplot2) import(ggrepel) importFrom(lmerTest, lmer) importFrom(modeest, mlv) importFrom("grDevices", "dev.off", "hcl", "pdf") export(GUniFrac) export(Rarefy) export(PermanovaG) export(PermanovaG2) export(SimulateMSeq) export(dmanova) export(adonis3) export(ZicoSeq) export(GMPR) export(linda) export(linda.plot) useDynLib(GUniFrac) GUniFrac/data/0000755000176200001440000000000014141323303012613 5ustar liggesusersGUniFrac/data/vaginal.otu.tab.rda0000644000176200001440000021270414142647423016322 0ustar liggesusers7zXZi"6!Xt=])ThnRʠD5=g8Mr7? 0#^v(.٤=nJ oƘ OZK07YxҼې!~qenF1n1 U-mz>-hh"s~QiIu*6uzKazu:2eTw0ZRt *ɛ/(?D (enҠi_^U)Y;:A]‘LOLXf4B$ʰCKKd;zӺڒ!ɝ\rxr3:"<Kj٠Ⱦ-O >{d//6_wn6p}_άq9~mD)=tPEW^E*"o78ZVs(Eߞ]:rAs\2 x䛃evxfN6)lE_A-ZBx?GCt18!ҽwꡥV fYF1aov-Y/eҺyV[anօH \z.Sa\]7}80n oOB8}ɯ~$(=Z*LD2pEtJK9bzm: WPI,pNRJz$O H_$Sg)y3y( _Z%U눲C%t2굁ƪ 7Ď@iB>7͑t"?lZ9$XԿQGeٳ=^3cwÀ媬KP(ڛp~"BPq3CBoZu(ԉ睴Uܥ\@G< 7އ-kSіa^'#6\x˦/<:ԟL1{hJԎ%0C|@Kh!s!ב#%s7 j8۸6 g_LExȨֵYJom u)2X#g1ЌrL>T޾ (2>Jc9gU&7$@syɂXOWζb$qRv\\@FpB$ \WˌOiQSxj|goM'Y>|3BSlqa·;Z*8 t źUt!:QWzz/աgmГ~ ȯAn0x2Fvt*}f>8%Y|CU U%/D(震s;Jblt﹆/đ,O c6pΕebdt]mځ_(xe̘ a7(| n3LȄaӫ}hBjQ>ă2;¦o^cNѨNkxKӥl@%q is *N/\LNmAhiOYFo#%hdf;(OkGYpB*b߲Iƴc4}'Gx\uA[1/uM4߉{40F_%*b1Ƃs 0N/ ^I8zFy8Pl^u'6Iʗ]}(BSs6M-*w0,ݪݽA5Ÿu ݙs/]uuZL3`!pR(`9ޙ8D4w`l~nUEu]Ogu C A&*T'&ug5,{A М7 z*nH-ROl#" 򭣏rg1WH]{CAh'sR%Vh!T^V]d#m;~geV&7S NmSJ/t}%7l=$0Cm0ӏVVq{UQ ~D+"xT?꘡a@7{չV?T7E;y܀ZQnd\(r=~ԬIk蹑8< $FZ.*?_;&mfc X4̶I֌K6"3!/?8ǛVyZQ'U_Bƍnd nUP%(1c9],EA& ns':Lm:N8\d7!pY0ﻝvQ}*cWٿO'08tV⹕8IH.“5GWƬ4CbOc+E?IټC~^Wo]~VѬRi6i,&"q{g;f;$#!yZ3n#{] U0s|J`:(bsD`akA1#3[PN .;vU{N&P7@4J_V1؇Y&j.6SEpA$a?"` &S"*~XH\#nvqozAiKo~{ey9fL)V,* E([OP-5(@AFKsF˛Oݜg`Lh8R? + $($ al{C{Fe^r^:k-L^|1,_w7f[O R XkLP Ga#!󩭂8 :H'ZOqƬ} }b0bBOS|KvB~\3 2܋J=M-7]s2 }Snnrm"AK/iMJu NmI%!c"nI Tp+)0msN;"%^cŕ4HS<# Q2L1]aKྎ`/MX_+{+ZW@@dgQrvj_Qi2+x8abXK4`'z8e(ёATjolky V)$c\h(c7:l2Z}I\y h6ʫ7ZMFsK%9-^Dj3al7M;Y]pHX5yP; }oZn !`. Y ,AԆ-[F`0Rk ו&sapv6]-$L{aٟһ!L yVd³,}8А4Y,e>ܣKxKyfrQW K¤K)J͚AQ3~ 4 m$tEjaT h~{=_))`$B4m_JQ7c_c#F^ ;>%cb#.c{t呓bryL@H (?ͤ΁&tc8^ 9 t}4zijW3vڰ0 h6C2g<`G]] &H" %#Ԩ+18 =nH/szo>BĒ pa /{ٸ5ݍT!Q}aSCEb %'l=3Ї]o\3QL8҉al~p|uXo1^x}nChu!%dV,JK% (aX9iTHxJpdI5RC_ {_^^By"Z܂mY7~`b]YXNu@O@ kqt:-{ }o[@_3QpfaaTd8KxOF !wp6PW`LYM`>Z{r(`ҩTjѨ h;Pxѫ]*xQ.х|19mjtZP3T8Z9EbA&id2̘i j|B28cѲ0)'v|rCo#IUcz)u}n hV'_u|kӵTӻGq4B];'3Figܯ\9ew ]0-eH/߬L0y+JNww0О@`Ԃ}y/o׆ b%:B267doH@靸kﲚ0#BrL''QBY5 W;-2 |=|X-)LL;tz!cU&@!:1ϢȖw괅ed*HX33m)Z{e&A/眓LMI<5JH<=7ABA>/Arb0Sx:Ln^pI52#Q<ړ~]$FVlO]yd%hjۮ9$&eBV&wRj6W_uFS179APZ)*)K91{<_ex`j>Oo.hSF@ cKp?"ל7a %#QB5ϟoBx!H#%aeqdRvۥR82ņV٪ȼk%zAbP5ͬH{Bl%Rd=Miݝu]1RVT7Ì# 1rzFoT!D҆aF.X`; 1 3/I[$;TIh u+5]v dlq?wxc^BfbR{t  {{A)2m D \IyhE0UU=9g3Ef%[ '.w( ȯR*ܸVcG06\I{i4=X_N/a9hHD~O 5)"`b0+HZWJӅ%D B 81o"QQ}_ef9H$*Igf*`b 4 X-{≠EWI9^?+|@cƽrZ ~xvunJ0H3O&/HhED} D,Ksݝ6p@Uˤ2fJ5]f1K*/RqdAzYi$L$wt]875qqb68.Lxw/8Ma2D;PwQ$~Vi~Ј2!Ccl:2aojGl2L$h$|~h_ 1h3QyuրJXٚd9cګKRRCxYӤ$ffܨT)ϣ}9Z UFPc 8Zʜ1OwA߿hoxPiekށ ˄ ʺU68^R}6zZ3>7;ѤWׂTdUx\ðߩSY#^9)<0rdk==c0o%.|ۮ/FABxp߁]@p$ (E'_e$y BA4 |gQOOIU qWZ '}jsr-qU<5$ы5T9pjrPQ F--w6fX8f5Yoy UR;*}ŒIWI̦=ӏfhBNy e[XL<Y($l#Ga^(t!|cKܴw %=;#YH8g?@sCd:m;% =7GlW+Bk(2zةmD'.}`,_Q8ĽFHTܵy }Z}1A579?6h|漽rוG|抻$(c)+'V ZrSKJ@lj}yN !=f[S ΡL~7&CMePf\fY gb2Rvzp@ǃKw4*%mj "dI<㸕gHy]ʕ{9q$4 ު)o"B3Qܲp[<(_GѽꯈO1;@AG*};ufL +ֵm$kԶ*EKGmXl7s NoZ) uB^`{[/ nd6@Ҹ" :R*\LDW8-uܦ N~ϱs{ %ۻ gv( u̠X&A t=Wev{S'q; 0E[joDvmp+06M@Uj&X{kȀmU$+yPގř1> %$E^Hl&B.oKNg ˍPHg{kpF"۶^gi.1uQ%j'zR8c0Q n/ AصG11FVIGU{>FL>3T()ezAT}vú(_{lUJ)of'MLJP4+tKJ|YOGԳ&uJr@%u@"rZF#1mKQ7_Z{O:[K> b]%F ~ͼꨧP7MV ) mtWOe T]%"1=[>;)c`dCg|*0 w5 hի5ΞFbDGw&>-;`I0'Sa |IJhŦ7c.f52n"3+"QK+!!M`Pli_>?S-4>?CW)s͆~nq Kh6#ۚrvS[~$)ޝm_1iAGNbS~ǔ7ݓlTr`2q/UXJSK^TlTn 6r9mNB{00ǻ-lcǨDu޲ؘ}?BaضB_ I"YQ`թ,пYB.0Iry+}t[){FIڼV+~źP?k}o@~~.R 'c"9)} s"?B~D<|XmcW&Gb]0qR54q@|TqN\J1I)3tvi@\'c]LgF{ia{b 5Hn sax/v`L']ÆIщcG8V83?HGVE G'hinNaKSOjr>(KIpצINK(y<ʙg -w'/}h{!K'F/ѣDqָoYLe gxx>tu]Cz n]a6V6!0ڃ)cdq_}z!@F\]lLKf[Dj.V ß7mpz3jhZg})Tp|AzF cW-uU;[cƀ~hZk`μ.-P{V*<#e6pDM6БnZo0јL/BdP8!_@T#:} $$CUrDY$ K"N׷&zK<'R)J>CsV{Jn<5gNƚ\Hw.3X_qhI$)oeĂϮOR/͢?XhvElshb;[ ̯Ѯ<@\ k&r'q|Qfӑ%mLwn/hd^ b+) \ᵗsR:HOTBi{WI&0`p-'kcX`fVxNQΛNԈ܉ekGENͳ:$z&r4CF0fiIut3/.LhnL;d-^gb\G*>BgOB +3*y'=3O<d 4ՌusxhRV6-,Rx*7I._w U )8$8W>ͮ͹]\n=N`NC;RSxLKOj[A16GtÑ .$%OK SW3.Cj⹚<~>jku1' D.vtTL /1m$j e[6wUF@~; ش ӟP(%7M.M3L[B/,v jcnEzF:] LcE~'8by#^#ڱVyRP/l=8ONzGK fz_B=♥Gg)wF2T*S ΁PZa.yݑ1F R>ԥ8V+\N@|`'XύƷ۩ tCnj~s=9d)`E7Rjυ^ӕM\$j{|E -,M4is8u@om[UZC qb(4&e9c ~sJb EVX7t_*^[5Jw7E+ 7 |ؙuK0'k@MFwD|'qBlU"TMH*PڊF}@R@2TG 0H"R&SCV].B+yf ^2c_DAF|MJNoY_ 8~N Ik٧7bҞVw=p 'Ou$zhHo/1 =rRcӪYMymK8?)0eN`' †Ks~, ;g)ˆca HxMp1I AE00 ?x./ȃU?(N><9jhg0ћ'ҏ˨J;+YXHcZ/8 d~B ^kI=-%ۖY~ZkŞrM׹2! 'ԶyR*oTR{VI WY}DCඖBG@ۺ&8Li6D싸AZZ/6\S8jU(xr OaH#jIL=e|L.xvKf"! [.O@wÚ5`k8na0J%6 DI+w>$Oi$dlḾˢJщZyL;#^/@B]x9W gvch%fN`ogk V|mvmpz=Nd oEec[C)_xBt!p -c3#W)ˌf s2ၑdKq>Cr|PzAm _VCf#4f{X #3RFtY^7oR<߶ ̖8$%LZ4$M"RmI;MI20=Dmz`qISynVڳ;u1,QO'WScrO $bŅS"'r!ͭ2^\@oygۊ{65 5WdG$iz{Vdx4y8#}); 7_W~ej R#`gȈ3ߌ rZqUvQ"u Iq3/OEò h >"e&{î7 _$1ɺajк:B%!4xipz{əU*`F JmnERSg#Hvme%_3ؖs0}q{b.p)C9`I\a+' e fpGŨz?^[ dQ0ScBGg7HG κHnEنq͐i> 5jnoP̮x*PjBJv[kg t_Dֈ`'HYGŻm"$"7!9s2 AZ5Jrp: F&F˪;ke2ȁZ(zQĄysW9qҰ9/N! #`\?B`5(UQ,"s>6 e+ζǐVf=NVbn 8F)%$~J~x\~DQ5dX "D}OWhgSL XDV0*iɒSuvˏX-M-eWT2 JV!wBZR4 ejFON= !: ש_gͷ݌P4m~Ns 7l,"9㛇.K\*K*8GD$ke&6!'Fo'> ƴ1`&"$%)](sܔ-6`ÅJX_/bɓI|3t~p{;9 G$*;)*Jy*c+~E n 8IG4pk{8*"ɶf{zK+5cKCUO:ЋAIYF?!cc=3Lq(]hA$%&:"n0Y`W0`^qqXwH?>@2zRlR֤Ct_bXDFe {-*5k}spFHh(Htb(TQԡfyvuZ[t&.i>z8ɬ EXZ3]d:wHN\˛U~DMav4"ݺ􇼍nXHm['1wlti\rfp 7?w'-jҭnfe{vc|\!80ŸsiF=pgt_l%v&/mwy6oA$qРgNWoW'^ Gc(fTE&cI(':oԁ 1ğtlnaXgD@ճc>Q tiVX ;|MUl .3PQwv xV-SfPyS;'e¶| O# <;nVl_ @3S7}|{b_"c G֌;lї)X@ Lxu3t':=hR7\a}uam( aʚ@Wj{@2zH|(1`{e\?Y$4pi#".MGUS&K40,2a3Wػ+&2 #hJXi}PBn- @Eɉe]ߕxѩ汹Y14Yzv `i{hJ-M``M{in̎~DltvF(D]6z9j944vqpꌠ~4SB ck93L2~g%AqX!%ijI.|IlQ~mOk`h:0dlX`?1*gSB򓺜ń]Ozw zQnpU@30Add$l-ekÎQ SKݮl߂*~| "݁"܄]M;gH\gsKm*|j"/ կʄ-a#W\sǙl}+-NǕהCC[$v2| 3$9BjhQ$nE-3wl-J5';vP%>[@POǭ9jk=R[ xAFnHXcO\S!Aʍ} *d8|2܇eQ,k!CZY8RLB* e"^v:)Gŝg~ڰ4iZW_ǑI,&Kona/oEØD0j.\\}Zs|.\{}1ձa%-X1_KK8SKE[tYl[gM⻘F]Dglx\(ȓIkU:NJD+"U\t  l,UsxO]|({;˦؍2%F\`vӘ.OA5x7:9XGxsoK9#4e>F JX_E78Ag{Lќih=8V1n-^QM=S]ƅ-''4P%+O׻$>!HŢlA}DkybR} 4@nr@k2;~97vw@:3,O_C$" 凵9^̏151nnРf26֣ hƛen&pPx2Ort .^Y]&rp^Llϳv3B@*E2+*~ڱGXk4Ҫ܋[XMC̱HH'5 Oƙ'=^6|V+lYS BWJm fOsm y1/Cjv?eEG 0Q7֒mk>aO?sW1-?YK%0vOo9#K9 ~$3S{s4+"}OGxoepvyo *84EZ7gΐ\5⥰݌NjJvSfwl9HV*2-FjGE⏄auYCY a^}Wi=ׄ3uarܜGd7[ύ.~NCKd~ZznƒAd?"jqfJuۇ¹ɟh 1+q)epsp&@\_Uf`d@4BAg''Cy6 =Dv0E.QGY:Djh%hCYޕ-F mwi'`80F>cT@fDbHsPvIyw s5ݼ/O 6DǡE7f -1 רҪ7xCv Go Ov ցlF/?͵Z-:zA¥hfRJM%9U;.tFٟۏ)g.£Jir:i'%"r0Yh@6P Po].UOJOFVT\ΪsLe˜rZ{h*6a1WcnJY)r[U.c$AŋUϢ3%C !,͍57?ӊvO ֯R'Ŋ5K"}[Z_QȊ)=50 :bO/QfpĦZ79O>MLd| 'i[;ozICme/#\9 5`}ӄfu*\G s|YV *A2~Ud)w u3'*ldsǓ p*R;s(qLc49| B.6X'!Ԙ peZ.S}D#y^`p Oi`V0c7ɯev,V_mAlV3iH8Bx ?r7 *'tFɅOLUsښD1V$^éjdi9iSFzzy"Px<%9cwGSG%9r(CD^wF~ Z&o"mUAd\!*' ΍.܀\99޾l, AHS'5&յXf=N4I`U(ZI봒!pI%~$fWJ}@1WU4?Tn_? 4?H%ߚU:Y( V-~rsƐm >{B![VbA6?%1!&1+"Z ҫƢ̠:J,YлGM=:9xպ"FA5s:X™b p kV8穋WVo\o_4̡? 䄧kRReZ4S_j hFSC}6~[8L+u9!մX4D]4K+-x' &.&ݲ<[ L/ AVtJ?D3>'&u9 YZ'%Ŵp(ǙbuLk2b+ KE6)"tND(%F[Ϗҹ#08?xdp8GXp 3%Ve KOs%C^0=Rwۻ@n|a~ gJ|yK-s0 _KPL4 eEA ?FZ?fIqӻSQ7:ңLW>_m)o4ZexnKR]q\(I:HҖ`z2hȏ{TjaR)WR47INy::#qa J< ʽ$zwU fݍ*ǛHY_ԹAa݆j7 Yx^.6R֐亭u[+QޯTakWH}kq(tY NבJVY; F}c71G56>80e_@̊w6CfyM4 ׶2Aҟbj(}gyw iX0:$}8ўܮN8Ȕc)A3ƚ Ji Cž#s%i,M|7v()k_1r ӫ?b(\ sRz47:;i\O@ѕby .[L倫-VDvwXXy-ĬIK;-Z1 2 lM."?#R?u8e|%&B1 V/\2NAQ 3Jd^ҝY[;$zU iq K=(ikg*7̄RMyo'OT,|*}@tt,f]q\fd`O&oh$&z_ StmD9h3xSsW)_N%?^w~ i'jK *es-l ^c)C%Ukg ~AC;]Y8҆٣Iy4'+0$sn4rd űG1EMbF3Y~g ppQpp3%Q."چ?8臿*Ya|ZqWBȋaƓgrcFp[JJg6X*w=A][ʍ숥jXn~>"T4x6&:hJ,Ml SV=Am!BJlv_5y4Ssa[{OySye; / ;Hl'EҕTADPJfKmqlV}#KpmowZ9+pR MiAb%rұ:Pf,QۏIF?Wf'i הspLHJKdua  d佛.HܜEPvH3;Lkq4 z\]cKh(zq0INJqeʅUJXp`SWEM0{$OPg?QX4‚l%VuGU:kDzap4hA?#¤țKF^.]aͤ0Q}1x Gw4nMnUEٷ}`0}]?KM̲YFyˀ1TN91mS!玥K[EWG[纯,<弩y K3Z4z}'Nf[$xIB>> 6>{Fv8,?q*}X?i80LzQA1@ޱfyJqW9Mx> //jmb uݿƷ2!^Y. (fǰ>JN^7͜+JP7%O=66 J7&PNPWVntfL f-vZK6\7rk{tw鸊 7FJV/(W)i*}_wٲGTE*l!?x-Rq-@8,r8 ?Sp.#瘝F~UՁ`XU-8e>٭egViyN*OIt ʷ.\[%0^v[6 Ip6&yQ-|p a4ԥfd'fKPB!`GFA$\Kz4rdJa`{>Tv^5I "LH׵2[7Q?43jոW6e~eY$r& w KiI9-:^J_I[9tZWl]0'ÇvK&H,LN45qZ9t fSi1:? ^rd^qv">s2>'7^C_J{4`[bo‡(՘D6țذ&Af_'Hpl > LuE19$ Ddyb;%H)j:P5Vy%Dg>H d]ۃ/!5e5> nBN];/5+p3̇%n^@/LJ '}t<_yuL2jrvH)mTS$ ʝzzO I_fںXgw":KϷ/HmǠM|1ZZT᠈~q5wcV ;23i|_?~•]ꗋL,negYN"vwiO?x_WgXKɠ'ᮅ8m+Adu<ek3ػTHً+OD;ާux|~eWG0KJb.ix™.W ipm4295Ǽ(ozcIcmvt3Ѕz?m l+mФԇMƫj"]"VCڷ TcWx>jT$&-J*]@kf6JNNp!ߌt4E嵭4aHB]#Cv T3, H̵m ʹ20!tn~qQf] --+r#uU_ILHQ?y@C,o.@+ "u{XK9:ʧƹj=lQ%mڋsc j@CpyhLQ$ 'QYM}AikB/^ޥPi1ocg+'m{,74f#7Z,qC PB>?BJC:$\.Q;ROUúI)Mic 9N(HQvgkV Nh/j]NrI$ى DE~?0Yb;5ѴTR8őS%HWWd~$ZJɂx ]gD͍HR>a=~;w%$Qц+ybߍ66hOZkm.2蛦`y`J|hB3S* ~<{~H9nak9O3Ƿ~ZXB,/aҝZӫLy e\3gxD+cu#v䖎>CÒX/zxL,%揭GQw, _9Rz!W:E= X-̲?j4ڡSnRt+knA 8T9Ϸ{%),ْ5 WsW\mG2l[z|x"oV%"7o]{|{B,9dɘJqAO1)۝C@:j؃*8R]s26#NAg8PKe9FY_a7JXNdaQћBg#񳪵z <&?aHMH4eZ@Pq5p1O|=;/Zp^Չeƙi$/~,T7uΞ<-`ގ&9 `طtcm&|j0q?I9 ܶ,e9psԂ.29W[g #lj$R#Sŭ$'X^m}_/b/LU`فD /yС`ݢ?Z`xX~;)>̼_: - fbe #@i܋}B5[$i̎9P7֩Lc29MIO N 'D8?xQ搫HNq%->YCGUOKHu:XoM~öqұM?[ PTr>l̖L:: VԫKh=ԶCku < N1xu0L(YKh[j~_!L8T-1rUqrkxeY4j|!V^;8ƈ}  juF`gOk^ b"knNJJEn[IosgwGA@Y⏡*3ٹշnUH(?)I8}M0R v>6ppxÇLбgq[V&ښ-:.89*(\9<9WY]}{?O詳vw,I /@6VC8wZXFvBƗ>1+dgS E~9t&ogttTdf U0y :%%}9bjR8D2h.t؂1rtCPUJu Hn[g;㤃O[ ? fLN;{g<E[ mwzHpM-L2^Rsn`BM4av8rΊ[FB`]7pI{>} Bke'oha cn9q=fz ksgAt<ɭ`\Yaljoy>u<ə ΐ0@0o{lb3b6)$g馩, B-=nrA$#xFJߣ `ؕ}BDof__ )|c#v!!O#E /_vGQL)~ye[ !1A;%me~'Ҳ>mz,KH!\%qL^wN)InY3Aq`I.&]ֶs`bh1c5=D*5 [X/hr򉲒.!E΅:4<`qNb`ۋgx@s޸"F@߆nd/{șƳ?#.3dv|B g;Um!#gxUB=^z/NƬZAis]PvKKDMmѤ š~I'VͼcpB|9Sqi ػ3jFĀaZ)yaN@ްIxDDϗsxڞdp:ԅEK@"6 gʓB}N1{x6`Qh+h\qYU*Q#Py"y( *`(6寮BaÕ/k-o TR";#e҅Z^iȾe>iqFy磼yw=IC)rl`|i-Ծ95Qg*\ѝLqa扖]2_1oPYt+lg_.n>MSB>'elryQK Nel/'O; ύUY, v;g.*Vu - ReQnE/@HX\Ꮕjȧ[ j2CQ1IC[+W'Va/On[/d8[Ւ)֋\YݏѬ6p`jDi9,eUX:|g(nj3hɝOz{> yd܆EmdN L6)]jSHsM>ʾ4:#wUlv;H?BRTgmoVAS.CORֱ=sF+0y*~]9VGOfvWW6T ߌ1Uz5CnAe? nB͹?<,uo K/D#Ǎ rfLΕ䎎E@uaz/F\Ԣ"_xChi.1V^qԙYRg9'Kc;DG^ 6- 21k>&k[LtD\"-Bt=_YTb'%$ >U+`k0κ+ %Rn(#ϑ}@T;ws[F)0%R^ e8:Xٝ9ŹY4hhʒ kRSM 5O%Z[e[:[%6xy4͊}#0gq!B9f|U&@#J*{̒n RKxBG^gM'1Y ;xo# KO^:EúAez'2cQ!D Q/d$*݈λ)ly)ّ*]o ׍(Wo2m- =bNB-J4s-qqc _[g?f{hE|U470m-q5W *r%}@|_CtV78SRD^bTfʯQH}@5SM?qVCЫ&B`LI%rԺREk}<6wA[lHWŲUs|?ʌ! BhE;0= )PM5E;ƭbNg(Sݹ. IH~ Yϋ%% cuFMT{Y:-D5 P"N U$۾)6I`-Gl}~݃/G"D`&t(+9da6N/ >@:X$d| P`ZG٩9H54ڄl^F'L (!'#!V`J?pL L2lts(jǫ]ʨT^瀑75h[E`2Pi~GMHVʥuMhW\̏ etPzVc-޳3 x<dN:XTjs&|d(4㩁-\F7֥q4L7,b%cj 8ֻ!WCYؘ15m9ɩ3*`aS$fE1X%; fg_4QqS[Ū _i>/Q䒌GR04欀A*J"gI2hK a|,$iĭǾs19P}Lj\,"ނuKhEoßꍥgHo[VLEJNxb϶ C]b t.y>pڪrKw+?qc C4yI٪EjeĸmWL,HɂjuڠqӇoVĵ,5 9EȉpkMlM+JqL6/ZSќ]s4Mܦ)KuUoPё޴0i> Wj% '}ia'ad7.X/sx9;|~/bJ-!kPRaRK5S(b4|yQy.p%\ј?bp.rX^K5 3^tƞruZ5g3C:`U$^CB_B[ HӖ?`+73NsWTYӧ{D^,7h']q*cb;5P:$F)|8 )CV`,Md wyFejYnTC#neqp-*oz={}@&!HO4Q7s*9f -C4xup$ tWEW?A]Lj0S}XYDždQP7oY5V^BEsӅiEMxo^䴫5%uo<#)2(!MYiFOf<{1ܭ.Id#֤J^YCCڴ٥XDղ-?#~y؆7a@ (*0X &^3am#EUMGUJ,Q_KXCCN%YЭbt?4z -ko0בZ4) Ju&1-NN)HσSyF$f{nFL0 DAY)2;j5#n,QQ/#\ݖJŅ7-3ύ.2Fd7zёJQkN.ɛ.LQw|5UYLF5pSM>PKH(rȔrCʬ}쨌_$gn!ij_Nw sA47&H<}M s`V(鬵bTIȜ7t)H=\B DĔ#e3UɖLLՈZ-8TNPrv>}3.lvߪH8og2'<X뉗;bt^;2'QnBm Kj¾l6b54Aw5IZHWqU3甽-d A`spbu*[3Xޚ-%'O w=[, >8Q鈺]!Oj4 27{(حSJH{]{);b{M$n.)e<x3_W߈Ndt=t -x<7bv'1Ts[h z NIs> YZ'N[)H S-n)p 9{Bz8|_H#Q sXh 㵠li(tv\R){Fg^EA,p,9H n[~o*^J"VODcs#| >@ DdA}!K.#5InQf|c;2åН 8`۹*-[oeKol2ǐML܈MtD*oBz؇.' u *FH9m =s^6 +ɬR'^[|3LpJ~w\y/1 4庄<"!dv5!Ȣ2u1i4A\)2֬iK;TݗA=ڃ2V5aj(2q0x[&c-/DjCsf-׻A͜]hQ%ą4ϷE`/eN^BW{l?t5}.L;% ̊r )Yg'?^ȸD-S{&>f`iRI"ڽ ;qPnFm 絷K&TyɧA)紆Vd6#D~حyne'=ev3(ժp\{ MO8}R;7Z ]I@=^4ΐ` )D*ٵ/=âap*'{{K0-kq9H2Oc]+ndn9% 찲a?9bA78т)8dxN!`Lh5gNGCxؗڥuLV? IY :~iIBwbH@8yX-9_Dߖ2{*{f } :̕v'M݂pyt$qϤ z&zq! zVr|Qd[lm=qC :@hu`>0@A‚ RKB[J)Fy,3RtB$5K,\;LzEE~J !T 4y;3yhjƲgEjThS(TaьIد$ܸaM!¤ Lzk_=ڢt8՟NlcnSɢq(O RH2MnD= W'D-/^gM2(`6rٯů݀@ @=8~r~h4,*k?ݭa m}/JSȰv,ש5VHܖKwwҊ SZ{aȻ" T{H~ߜU}l]!@$*qd .rb"dv{5{^4 ԼWʢ8vSpsac+oO4[u|+/ZeOK..8]JJ~R7nC" F_R^b㱔{5k߄蛤쒫r";|`aה~YQ.1!? )I AGvִd=ɅwMcEnF8B(;@ۅQ0Sa"L!Mg~TA 2.! PkrE'Wl?!;]&&U?OfNo[#H 0h8{bTI!9)XT#8Um=^S[j Øo,KASA1޲:9YrpÒ|PytB8~,Fl/u(M+^x3g%p3t Hiί=?>#Λi?H Yny L0LĠ\tr:Xs8 w/9K;cxt+4w:H:h+HEk t\_A3mڞeIn3 QEzcKn#"mwG XoDЅ=*J>[K3?+0o0%@|,.@c-%{Z"D[am_a8G"#`saG(؊{q-@? -0w\02ZΒ?0ؓ -KxL_`"bQbxcN⪆شbv .IɆ[_br{WYس6֣zwEx;9D.8c=_˰vˢ;m#7$􀣿]62 =>T>8`1==T0'}h M^Ű.F!~fsu!BG[;{p+XdqXQQ<=AR !,=OȲ,gxE?]A}smcHH)9%Rl[ik&x /\YȲꕠﰢg%KZa_\PuR1έK#̅mJY2/BSa ٖt۬E2Bu]}|iG#?jߙ@OUNc@V !wxͪB[Xsÿ $Vp]*rs<6- ASB`FRN8vp䥛ZٚT{U%Wqzl#0SU6 3_Ȥw&(AY$MmMG!0<`la+]rG V8~$ w <"&+yfq}C#v* ufGCg šHf><F|/b!6+|Fv2 b=O9wLB`>$mOq BWG3^j='<\X67pQ%Qܴ~€'0zg:fU-Le3j0Jz~Dxܪߡ7ӚO]@ pj˫875q9 }%'5KAW!AL&F̽7F *-ޞ ͊pqtz&POw50kC^^@?+Cb -Nh0mJrkrsӤ.LTZ/ՙ83-=^4JqBa)(6>A a w)<G ۰Rؙ Bp\h(4ks K>j!fD (p}7k[K8˪m^D෬ЂV*ͧųzXr\s4S&i&2EpNDQY23DhIA =@fc;;I=vRͅP8g;.!۳^ȲL:J9À@>սԕyK͞ՙHW5&P2lUѢƜ~7`H`)E-tmc_yԺ@x.)A)Z`@+QP5qt- {_ed3Sb3Zm44X{* -5Ƴp9Dov\}Qp/r#)$/Y)Ni)WoFl)gl= aSC9ՍPLVyAUOYl@`VN]6.V!5ծY.[V8%Wy#2~zJ(1]u~/>rBtsJh?8Q23dZfmz]IRƝՅH*aYn7͊i|t䒬/B;{gxkayZOȒ{m̼6f,iGiQ~G |_4$б墀8vdlдlY]Y+ ϪٯdRK{*lx )2Ot5`[V=_]ǔሧ&G8\;8TWpN %ϯ[-3+djL|]8Yqdý(`}7|2>|c0dnZpe8rQ)ٟI"E/ikY[Fh+l +֒VZvWĐ"Ӯ+]51%B>V$<=Bb@ yz:^4.h1/.cl^*D*Kip r}RN4[=O-\:]SMoQs(_b v9M"ͦߢf1i ׉_CS|d*܍p 1I FLnϮ=kVS /Owa ]G/66}RzN]n אp>6DlKjGЯnvY9sK@dp Bu_0+z*M᭨A,6 OoIoǰ#IIyI+P֎ {_٭!kͰ,${v.&bg4O hK`$бc^Fj6WqB_GUywlKzr3^a8N_Ee \>fwpaxRsuEt ͑lͪ\"I\ @3.W*%CEb>sa$rU2RLnhsޚigLK1-HtgvVçAl{_wk}uAAN}exupU 8 !Ƹ3>5/vV IV#k!_!W86R|gzUQjV}[5[Syӝhjm\^ejɗ 82d-nnYl7+ne$|q *}P /qCh£k-IUv=NLXǘsw:{vDGb`?, |dQ$zz\^4϶YuB,|GH0z'ڀj9e ؉J3<}|^|`4S04}cD0\$&X)#0cUu@ծ}sb &Z[dMUqf p^!`nl$N6C8a6FAϷ l<Ƞ(?}t'kdՑ,l6vjgjae> U,5< `-7R䇊!B颁Q;sjref[͝P 8{G(5>:5\S xSr>.>fķg,SE#UX%䄓?7iE` :Emϟc`&,4LO YcpiBP 7_GŎiK N#T3$B]]>|JU (2!/EѦ]=9I 2<oc}sB9LStJ5u]sRkI=a]L deϷ@ye-Aoo"-]9Iư%ʪ2LLe*{yAi g}!c$|M](Q0Z$1?l gh li bz(N`w~󺴋uy{#eĔ*J"`\\,z97U`{'MoaOB4& g_IV:ok4nl̺YZ fY6ʡ\y"C((\`, L@GT{6 @ZT|C(H킟(X#AmbՇz1`RUidG5 Ż-1:L7ӟy09c}'nEϒ>D-l~z 7{oMcPbA}H1<ٍu8%CMHfBtY`weE߭]\2X^L=|orї *f-'+e]t|BhߞH𲘅)%aQmOAv_V.\xnwnxEybWhݷt#;>)SZRǘ0H˒ K}!Ƽ @Z)Zίr,}K6^'l-C5Q{0CP}/AĩC6۱B f͍cim32,k:$z%' 6~o;lvgT ͔mihl,(lP*ebDg8~LMMȐH]$C&,T@7SVb/h'KKо5E" XBPZPіP;asLG}wTkSI7 h>,^ ;jnx$|vAe)!K-:t`%mȞ̆bqN?qӲ9 @>ĈlyiFïtzpFt\p \PU!yWNA Da~Ӿ5Ru#-jYvw& @) }-g/؇Ro4)j<[ܩ9eO~EcXm'Űb:9hmKU\}jTHf]W4-)<4/V[p<{m5O#87*gj$cJ{*α a 1 )4O[vM.4 W;#0pYQr!m:ӛT*$y/؈C !xZ C L92P^_э@2u ˼ bEGV@ p<2:@ #Fc'canvf|dz \sstmROs8Rt}x)s]PP DJ=\ 큇!YNڍnJc m*i/0π{*#d߈}0j586 ,Gc vTD֜P♪+[XBk-޸k<?b]ߎElu´c>K'%8NƴD{;컚0Ȝe #ͩ)iR :)'#g_VzcZU*,{+'h?(CUp5TL2fy% V&?;ض $8yx:!g8%02(;*f!/W²ISM.sv#nS;☄%1ς;ȭ_Z1‡iLgl.Mw&RKo|4/z2& SmD2SVVE:vOjw14 C0F0|X[lIČKdo8 vVQ?rࡖ/_c ^ץo; iESz=keu/}_quihyíuG t Ao# d$<+ 7/- 뛆 ]ȲNZq^Ga 1ı m%Sj?xzCd;K6vtaB)_;/̧J2޻ 15cM\G*IdvcJg`fgpr^Ŏs5E ̺J[G&*؎0SOطClK4Y=T#keaBfzQxnk"o0ʞ9zF-X0MwC Sq5uuZ} -&?)\(s oɓ|\3|̄aE=TE@M7zzo]k,)a)<Mm8{ CfJ=ywMU` 5e?t~I aڂ'} T `fSr7'ߴgZo8gG-o焵( Z6U1Ƙ38AWAMynE`:)a2SҹPB9ZK{7_R.M{~b93y`yHOڥ*dd/kmi]sM 'Lшpqa(}5ּtg+RY'Uge} WpƬXzzg{9z)MJ#=k5 %7槚Y |LRUxe'm{7$N(E~ڦD/W#h|$G⩎y-}Oibx[61\q4V>> Ǘv6=YRSz}IkrydybHnQ ԖvU- 89=(ԭTv (Dp^Ù]d$#in7Ī.}U}jrf " A`͕Oʾȷ0M#&OBηPrX;d_> 3n~&Mv固7.2o?ŁuxT9LEo-۲*AGpt!Ba &4"zy:<͉Өk.dapw@_v05zd'je\ D_sOvw3:О죊 Ii'13)IjMhUQd9Y!IoE9VfR-`7z*ZN]t41P"HzU}yi/FoѬV0='؜^l:> ýPT#< f|rm|BkOj"|S:7wQ6!V:1=Nx?'<¢ңu֖-wbەrg->gwFQC\֠ǣr6r K`Pk bqh꽠ϴCҔ|c]Ma*ŵO}TܠpWO $/_nVwJaH-2zpx89J6^*UL3v]bOo̝:"S]1>7Uh6~Q-hQa4|vIJ!'ݭl/n\U ^8U@SӽHɘOJXg7,wg~#܇7Nݽ~_ȣ;sG^ka~8MMR։fJt9loiPܩCC4Z]Lq ~H*mT]Zs:# ؋_M%Y6>*뤆P\1dңmԡ#0 0ע r=ʿm 54ǁdnfؔKVo\1_dpol/`"&hH+~Ϳ>OxS:(λ>ְt+nC\ۻNфʪS~Sg2pC0NO7'`C9yL!#J&Ind@܍ʯdA5&m#d'曇bA)X$6mR=c2gQC{@׿mZXwS # ́q0sr`# T6m]ݝU0sK1%Xcgɫc{h5zdkr?'Au dеuaAMBmU6'3QVrM 9W& J|gy=6oSdU;cZՈm Zdu,~X)(G;:$焀DT :_>c4ËT X'O&sMkxԊyѺ" ,zZ]rURS%zcA_A% K.5D`aဍ ~oL-D3gۛ/܋' Xݯ zkxZűEj7:~skԡ0I^(Ϳȳ1kmWy _ly@8I9u8Eؾf9g`T$۳7Ƈh5ΘPHiAs]<*+2ֱ~SZX< Ed4Z c b7O;-q`'9`9RGqL 0~L,pmΦscIhE^ATiՕX*QQ["d7绿yd\: yL ʒ+mt~usWFPiK3ń <!,AN*6^̄ITl,<fKGj.p\dP1F<8^cU}Wi7wN艹 8Y&X6fD%fz!Oi͓;}n;ҁՁ\ ʖ*.&5CeRIrWSyHZauuj{__QC6?)ӞNoZΦ5fav.vaڸCc"&3u2.B*{IFҽ|?Is"x OH%/Dv( c54-)ٳ30z$'8Dn.`l'Q~e8؝M*7l;#8tPG7)KVEF5HViFj@0sTM[¼@IyL\ICQAB3gƩIŐ)AeFʸ kz|h{4ߢ2Իe_HMILjtGЍОD6j<ǣA㌼ZOb[m9,uaɮ$Qb |􃸣[+P_|`JMH]kh:X7{VP6%Rt5Dnߡg gs}Bi|>mMmgh\nDx܊M暋pֲ@ LD◑ҳbⴖl1TĂ `D O_`{1͸?o=eaM3U(qX=XiIjk Zt[MB"(:Bצ #~W1aGe3ڄkȣ,Tq?f3O5&\/F1^sol<}(sv-$"ݺWxe#x }yl )_Q\A*/( (Ah"TK8U9C6ϥXpkcoᵐІ@GuõhA@:IA01]q9EGw^hK\S5[֨w=JYy+_=UzS~'ozW[Ko wiU%d\Amy 0z%tE V^l=sXՕ4W8> [ ͊U\E)؅3l%f`g 3Q;f!:yL{IS' komlM@O@QKɲ,T0aL$^P5)ָuͼ0R^D&4A,עk%M6p=T{8GL^.Wiv1ΒkpH$[ "]Hei:HQ ȫBwÊ.j-`Nݵ#!4ɚ2c>Gwy!@c# ݣ<5:F sybhJM\G y]9EdRW]kXÁ#*߮Uls+Ƨs;S\+cGͨ.*FхD#:Hjvx,|(lԁwT4m-3_(:, /ǂ:.31SFֹ#Pc-zS`F!4f(~G  ICg>ezGœn$O͓O%Ԧ*:kA2K7Ncjl;-9BuKXQ.pt E_o*xL!5Jր~ckEdM2Pg3o^UA0E:;o<) {wMTV&oс̐"1ٺ;;7м2"s${au*hn!rPŶ_դWS `󹆔k [}DëS0k$r\8ɇOxntR(caﶢ OJ A;SpȩBZ:hb*""Τ`tA/#AR0ɴ9'hH? qލ(ΓbOX1V"` sxnQӂZh-3>qj2#M[yL5a+l?urەV1j h K-7 Gi+.pS6{oJ3.y̯{8eަȟSme߿Ȧ{xF>Nx[_L il V?*@:?Y!N{P,Zh4l+_<_8m Jc3CȪ<)B$oa1h  ޘqF]f F٢amyӰ?3Q*MY&**|"wrp !.cHrߔdsH Qz[Ue|940\e =Ƅo}], u0"g)Z_*C@}BM+^q *MsX!Bɭ  0;SPJ >pu6!b~1W\?}#*)ζ9͂sbӈ:cr'ۋbVCۼ)8]sZC4ޙuKɏj `dc|43<.|vecyCMy%s 4 X޶S'pH uc֛@e@=䦋/FxiFBwi _f7 Z]!1M` <ILS-pX&Bϊ 2P^xnΡfX[bܮS1: 6{QWbU2։\o ۀIKQԟP>pV S7;ɍΤSIR6Iy;̣ cU4pѭۏ~KIi =_^ ֆ3 6v2Nz;//&r+>$*0 ִ-l-\ŎwkSq]{/N $ BC%'uiV}dr쟖>,ލ,(|Ft|)hi;;8 VX*=j'O9ݺYゝJ[k71AY',N0#ȬHgDGe"ɷdx}IYCiPc0Y@Rd 0.AGԝ"/AR54b_& p?L;Nԍeon? :ERb<îH&vtż"Zz0x.ܷꂖ(@wt;^WÇ/4%3>g}IZ@x]'ېZ_ }?G?_V&3|E],UF*;V:癶X-R̥r`1\2*QLSE(Fםeu0LNs$.[v,[㲷b9棉6@fD?s[*|03CJDc#U9m[HVMV*,wJ`P{ +Rrӓ}C&{Sl>ם[IUknJIcI֏aXAPafrɟh?-o /hs@_qV$ߵ%eeS8dabdXw2nK\.xnJ,c@bc8LF8|=4P^KP[@+T<{AUĦ=ZCU|uA@siDa.:1P<\<=sso^sw-()7a, 2gp?kݻR۴FC}G78˜*ˁ9F G[I,Khtqeҧ`rd#Sٵzumge0:jGW#,4fFž9PwҼ#IwnN+3Eew2P. E 0g3$@`Gcc <=0|jn0|n1IqþfKyv~hZt0gY!NVU~k\`S΀4_J}ǔ4{w7HY3-rZB&.wUEYF2zczFCy!KY \6& {}̥h[f+.|aek!x$EM4C6Â::<V+a xdI+baϒWlX+cb]x([FrKrdN܍nVW!`%Vroi 8p(!]}Y-J$_Vڸ||Wl|חHh {)n/3"&yR+ eXF8bXm61K IZǦa`F"=)K}c7=T5!"JiSSHwBCb _u< 4\XDSMQ^/GaPUr;$QtKNR 93A `,`rKaj|"HOx/{D'Z9(*Nɱtf$#1zkU9e=]i Jm޲e"FV_7mO2l:WjQ :N,DVܪI5o" XwZ.Q1*/ אa& k^3_ ^f8l,- r}_a->/ԿRCӵqR4#@xZ+X mG(4KA}rٻLJOZotAr*i 5S eZѷK&Uv$/a=,$EGA5D7|/ `>!PMAO[ qn]>n| ef$i([-:\C Q0ɦ681`V謷i]]?hP* W4OLɱx3u[Y-G8C._YN^xit-e߹Xye㽄xa̋% 1҈2nY:aL2Zfk`܌#<ݸ\&yZm!wIg5rD_ѵTsWll%]<_]/H#iƋr^XJ^G)sUl-`1e&? 6 /a-zVg Jn*YCfÙVLmx] 9($x> )FM}nTݮjw^i*`2Ef }G[mSJib/Jř¨[m>)zyȵbbr͢6s[i4n6 h?2 [/܍/}~'54dj>yA])bhso\,AHag*4 }iٕ,9PTv5kyy. )n𤉲s.~7%l;Xh X#eFО.7RKzaFO~#+Fcb<:XF)x| L,HZZcy6>ٙ{*cj, K$eEΩ5@U;KHachP *jEb9'h|T:;\͵Bi'xZt0:e 4 aW^Ҭw2;QF:j }5הH^JsR4LL"ٛrMmK{HSr; WڅBYOO)&+[F"s@Q'rp /@oE&"m]\.hןh$>KF+g:\sc%R=z@Qc C^HV Vs9SONMĖUsMDeStgɈDd>̷UNQ^W&Q|{ZL|Nw2e@if:g.lK5i1*n]ml$Zn Id-;\Bo%x09eh,8N*rZ? fͬXٛnd!!gո/uM-Y}NKQ3h1(|R˥qS@1\$+cv kE<Y 'O=rp8ʰOWӟ5&*Q-dTV$ 7Q3OƊY2w0Y\b~Y?X\Wc1\`Xߝ r=8:j'9EosFaoq<":|17%_ĠM~PwTpS0깂D,ʑGPs +Mp[?Y26X@׆cLA_DS( = [PQ6OŖ}l>}V7Ɋ\1 5 {de*hɴ_pS‡//;o0gb1hsn f=^O2yxPnmزJXDBAI/ Mۦ^:(IՌ.0_K?eTh4\M=1A3^,(N?vw(M=輭.nL>Kb,rl𝒫9ot!7>{o. IbQȟ_BNJF8 O--9/c =~wQGOBkvӫp\*Bx2 %ᓜ589Bu&tg>YƳ1aW5:nw#8Zs?_hC Qvt\Hd7VWxr*rӑKK<#n\~7E*.׺u+ˣ;Ʀ+{{E$F1_Ƌe+ ξ)ȿ$1᭻?B6 D"żdGohfh<7d1"GhP`zt@7MVbDqY '[z!L~\#+Z\=ECkV) 7y-$v ?C fwH)çԢeM) x;,H--8j #13Kڸ,W ZeLLeŐ1ӮODK ̣Y엓VgN[ÖȜZؚr@䬭h,*$G a -X~@G|DN3@3͓*e?48a]0O ySo̓S20V }<iIϤR~s6`/O-sQa TrdrXJ\ιL,Q4Q5#R<6`IYԛU@!#kXt= ͍KQLj^dN5D>S7 ak1[FMgG9Otx`\{lh) WrD1fRǧe2Sp}f_Wŷ`irUi #[P];"am1oBJ2}[&wJ ˱a:B+4}OˆX H YY,xV8()(ҋkoNt|ÙNۍ0gj(aмxoޡO xx"N%VzAr@ZxWb t軚#_!ן͹ S$4c:> a6=bIW/P4u|E*L,Gˤ;igo4vT9ٮID瓣zӾs_<>Dѭ`e,X S_$z>?̤_ P12* 3i8=`S], N Ofo79v[up! %wVJ .K/׿gI]YB󁨻& ~8ƻB\Ipjaא[.$TҧSKht@.2̑Ԙ3fmɏPA(`*(o8.q,`^* *7(k4NmUm`c߁Dͪ+VzSpmth`g0M:;4M0Eΐ»e̳sH?}{5+[ӊޢg.jɁ7SbΆ#5IS/]=+CЍ&ϽFĀoW%09|-w)_yߠGV:uƮauqǸI`-gJ.S x4 "yOSفTw}mP"V+'1᳼}fY^6y좑W e6,:]`+pyjN$ꉕf7 aCd*fסCόeXImT,Sz椸a@o] MQ ] FLo8l}vFP ]t׭&,Cp#o+h}M֟)/ 8Yo(Zhn6ٻq1ߏUʉG)x\1gq;DR3tԳ:NA]Rd݆UO^ Pɧ!46*422hL<:^)!Y uWtKa^ (KOnaڙ,HwwҺ]'=dԄ/V P-Ѷ!?Qlf`H< u?4hl*ߌL ]R?DDY7ԦrbTNhtXkҫ$ܫSU!;x/ʜreBeo $f4mɁ:0ϰA=#~*?*-nak\A65r8ZƋ+cͣn`.Z*#E}*kS^"[~ʁO A%> m> Wc>{ýsU3yQ3;"\2)bN~W6?+HPKk֬#ը}=.!7xm[nan։i\>u#1%PG ͪHVMXKS4y8r,ΛJ/ 9acBOPskp毑-8/ӓrB^էv" li %v'>si[`l ?F_nBej:jtkH 8A:V-D½16NMAvy{{~bancI1?.P%(Lum7#vh:K5+Y5D9.x \:,_$a` e~Ba\lhW$D{%1,e[j Zm G,Dу䋄1 i @_,my;/:=ÃĥFrZ-i s/*t8Y(8PiC~B? ')wsKƂpѓ|M;I6`ٹFv=ēv&]Bk5fT 7gVycXm[cVB:4ctֲ_&xzɪ6 geʟ6H[ MP]ׅ rv^e\**.pX)-xrdšߟحKzfT0%Nn!Hk0EWFoxd$i5iFw{X]^ԼZJj0zO6&[V)k1W% 5:.C$Ɍ/h̪_#\Zb&:fDq6<$2~ֽ 33PSb8E2 _;?wZ$X7X/{̢eԖa{0Pv*:sܚx͔{.[H?2-.=I3F"9oB"o"%Cyc"O?Z8yx ,EFn.Pʳ$Єn* F*>7exeEZhY;!3 iAz A:ɿktZx8HZ'[&9:Dq[kҿ8`мD{wF  n (5WI7/p ]Q|c#oPǻG~JK!;yH\seD(")ߺNޯ_DAR ؄F].C8O5<׼_ )YS.kܰ50su|cUmt1"&d&V@Ϲ Zp~k lP9*FDԞ6\C\ffI)',vqYbm䬣n {3Xb, Π UvXft ^vѣ@%KLE48:u9u9n$=T.&D5al=ֵyV \p-=l ;fd FA3ʴfQN{70ZA} ie.3_̗Hn~xuyG+%]μk$"& Ie '{r wfA2sVNn^kʌ#A񌁙B}R'9EACC61դIJ\otW)K&RObnT1x|H*hXd@ҨXzuRUgB+r\m:0n{BgZЙQZM$bf2F2؏P-#)qA2\&UF*Ih]RLVzG!"oWǞ1~S!4EAG%o4Tq[^iRM2*fm\y1pU+OJ86Bďڷ9+5YF9rGnH7]o!W% K %R|nu`Q+9P!l n9 Vy#ZN)zLi(V:ĚpɓBAC' 3E[|jz[zU H( mz)}qw)l);e$9OkHi ! wg~ Bqg 5Lj8 D罗9\kio¥r*֋!g-UZ[;;X(h,M$]~rdNcb$6(< yyr<흠\1CױpGhcan?M|#%Mf7=&MA3A?s|>7J,iU K4a!Q]gP#n, D15dP *j,rrb,l~t5`I)Pweš1ɶ4R]"k@L0sW8zxk9CzU]s%l URLIF\HZrA4q˯Nz{0?JХ %NsxɊ@8ʶkfy-8XTOxKw.аrQάAU4Ye@/B!.L4[/$k+̤2[zr Ƥ8 (HYi,?S֗n 뗸IH `LmXvN2"f.ֺ}zcru6"Y v$A{߶po?]@ajaСP8|7.l>)fiuZ~ętrrr:G38ֺBxׯr\2e*?{PM=^{ ^vW@)~,}mOHA  *[RUC/Mb]Žޖbu~%1톂!qKȬV&$_|+ yf[ 79RsiuzM/?wa'ו2 ]p!eĩ[=a @~%K&SaHLb/|0ziИӽcZtAfH{(f\advxoBof.D\qG=tkS6cľ#l; 7*T$2CZL< |ed^ܖp+X|m m FHX@ sƵkR&^ ^`Byd=7\3_#(MA kwҜ&t @Z5+OV2s+Ny?Oga3<\2 "J%o*I8)OV| I c({r9Ț i7BjMwܖ*,h}׮^E_y[EQʽӲ rLM11MwOZ*XwEɒ㛙LޅmYfw'L 1G%~+ 0!3!E.DktKrk菶Qnp72lLcbOxfJiq0_b u_?*g8:sNU/?TpdΛ??<~a[[)jS YD\`r>S}=n0~ J9ԅuaBEQH 9۵33V4:#/mgZT..W?1Z^%h&#( 3'Aκn!{TM(mUmuʬO8e>ӆxtwhmwJ4ܿB`#YMj6};lVloU @_F㏡OH9}e(|f 6TjVG~&TgA`|n!%eitGI{Z׳w6GhC@q0*u^0u;2>TB(MXG^ rϑ*vY~@OUδ~yrB)$>`%`H]3t}#X%[~8#nrx*AwdӿRhjrmFC$M5>e;}`Zϱ2E|f !sTx{SͰkd3f7CyڻH癱Ykd"Vq6-hUG,ǘ} `D9M)Mʱ! pgw4;9BFeq[T|Q:]t<(j=sdɦc: eˍTx L IF+̩y^f" H۫ KƐR8 >|IXLTkk}4nԁQ2c>5K{J1zag\Tr5# NS< BUPt8=ZVߣKЗ` ^).n4k$M/si^=Pk>LjK,o|RW{GCz770dߴ38e~ڡytӮN(=SDN?( L'\961GEad>:dca+/z6Ps!K2薯囅OXʾ/׷!5}_n'n?\j5DF֕Aճʔ8VZ4`^P+@PRMzףDȬ5F F?.dN2 K#OFNi{Znͥ` ?MV0x1ӐdeϾd aBC)Fm0\Y,aגڦcdu*o:Ga/x[[B{t>Fdtn˾s26-d{Ϫ8tމ'[1M9wUx5&9@c4NwY%5 k/]9'$`EO">ns.%F $fPdbq^[' rEF`?ă/q ܜV@g4y[ ~8l Lt**@&IYе>0 YZGUniFrac/data/throat.tree.rda0000644000176200001440000003613014142647423015562 0ustar liggesusers7zXZi"6!Xd<])TW"nRʟoÞug7 ð"=%E uCTՈZEς`415&O8,:FpũCi]6Mfbo$LOu]rCg5Jsg`j/l'x_ fF\NTKav3(2i9#;VJG/뙩c|+ h2&=}ks`u6lLgvjБk[U jaxTuEVi:CX$1ܥ3,BfX ʹSЀxuP!tb%}mNcYW+]>ۋ4/- `B#9 4^+uiq fK?XDnqa[~lhtΕoot3yxPՈCE!@KlrG3[_A-LW _jS+9=*!7baV; SQ}{l8?ZV$ݫ<#j 5{SEA픶`wSqoL+G̞SsQQKm@쇋FIz!k'iDEX(~!Pq{*bS2XTJALQ M:ԡVb<4画C1JOKe23+슿Bт[;dž ]Ԡc_1eL 6 [c4l0y,F]0ߊdDCLgsn]/!4R~=1wpsx$usKR컢neykDV+@z)n twt-US ϿJK_(|)]!{[)Qy^i<*ƑCoM]!LfZsА8׮؉+F־DGPV- ~GIގc^ kdž˧)40OF0U~*KokRP%O %-iCXD% w7P~Vzs"/~#qAwa_bZCp )*vAŭ y8E$TzznɷÈAg=!}*?AޥU>P(1qޠc*GLgEz|gOL<(oƩs,X $?%;kKt&FspM"^FDh" G2M-uA<NKXEg2R?4oUL(!t/3#hEIQG´c)?`M&aZR4;:Nz}Ժ*6+ж!Sp}{ɚYS;~NTF|(¢6^oVҰ9G.{e -tx>A+jH5wFnY$UjKN{mVC@R}W5NS0,,SSG@@}m226cxc:|}OaiJh.4 >xTvUj5`d,JY 54DPYM xZߒ!:Ff ю^]@)jĦ981Asf7Q4ON_GC% REbGlpXt Gf)|bQ>~zSA].1m.7 ޱ8vel5|F*gC xSb =YKtyId& 3%qHAY |r,~JH9.$Y4m)@PEд%!f+,MVH!+I 6]I9YŃBOrl]wi.<<ȼ~J]qYE䐗nּ17} !iFwnǨnb ^@/EqǏcVLwr\k߆+X#Z;D-jˎWBrĩi<G 6҉^)46v9XBL"4ɡ瀢'/> 4cُ X&qF%y k:648 *6Xi : E5 w_o+ :JѸLS~BK)DNŅ,GZȶۈuol^ݐf%r)]/zsIټ8589nT3gDy'YQwiu{l$ H@M[[aw$[I#E;[}mՍ}ZUz\C)ЋPPXb+XG]];j98*y \:a{Pߝ[-|p`ߓӶGNhWt?pÉ}$(̸bt/:E鞛i5w  %4kr =!ǃ*(8;%=#G,U,޵6\AZiã]%uybxύĥ}#3I-R`͚;@Yf"rLv &':fX K .wXDp3(I3"C.eK"0r 4{e!c3TvGof O!pyonʺط`Ru_@JpEw*⃨=eM+R nA_HG+p9! ߰ʏmka3n76gOVITj߈MH\#=*ޔ"5G!Me,j)f"'] Q2`egQ2<;ov| fC:n'PY&r@;#45kC J2ybxBh zR,?@_Ќ u:!U4n|~Y8^y ݢT¡SsK^ÒpcpsP6j8y#?Ju[ #60FÀHyU} .y!_jw49q2QԷY \ynjD`,]NCEE[E! kn×DX }oFs\VB͗Bm-zJ5uͺ8҉@D+ƫo0 ^#\Kg"IH3҄럑.?BU梵>Ub˷8xnbjO#:xlRt[aUwg^r$Oy"`\zEGL80)kT7 C̽Ŕ!-7JCd(#GOa˅C4*^aC2yXP[:U;4-c5(Q6d b!&% 8鵅@i1BF|l0H%&!nuׂd3. 8`}ωKOiDU,.,44Dv2[gy0w|ƋN3< ̎H=.]>. ģZg|+BƘ hx.&Y(/EG/\wbo ;9|d',%ϊWMnb坋lK 7 QT`F$--n]\+>«.xȢID>:<$mJn; yQ|ۅgKbx;)&Vy:,J\ify덢YYeb\AV98\/<&h&$Sb ڕFխtx4AJΪg#tC3$ښZߏd8Dj3u T~ Zf("ȋ'Ơ Ͽ⠗~@Ӂ#}ZvW]SvO)vBp{HpF-M xN*.WxRV#4SnPL;P+8ZHin.eGM*[FX&3`Hqoa 8^X(T5\zcNFu#$W;|K\!V%,V.ZQҐ7͊Lt:I׋/Mc^!I涽Wݏ;6 Q|޿4{D&K дScB;Jzq[6Fg nW5:/RIjCt o?EH+^GWR*?'HxLVہo/ޗ̢r+^yyU7hA_ŌN:cqTG - ᖾAf4ԁ/չUTFgvKȰ 1/h$1ZwN9YO|&Ȕ#?OsTdxtJz.;u >^@B-]pwt{2QG3,]T8cV /vۿK,Kn{8y4/_xaޤ%HS;_ ?Q WpdBz+Q ċXS3#P@tW1?h zpY_%}#[tU睪 aÛ*S"- K7'9r3 wdFNm Ӟ5A-ZmxJk"Lc7A=Tg`׿҇IN!a͚"3;BnsK"?E!?۾(0q($[>c`tYRԳ}*buMVk#cEH&XeB;XJ}8`j$95veo0jW,D١+Pk 8wQ {.&&ݪ;[C0 dN^ δƀ&rXnY+NZhLY-^y/{cYԬ!!`{h\'N,TD)\P%0v.alr5`jfc={{Ys, KE&f3q k*ÿ;S_sSl~KVҩ[GI$].(2  ٗî5 C3 0/5p&qP¨b* R@<.r>Q {dqsVIU5"-li\Pتp KMm,g(ʧH7-Uȯ*6WSn}{9rN[;=} X5Q<5SS$@y HiFKL1VpuRǔ5uL$GQb䪊F|P8k>Yƴ㗭YRbZZuc'o#l4va9efh_F+BkL4}XaL^8@gFdiGt*1υ撝2Aj\7Qo̭@[>[mPG&\pc:ڬ!tMlW+=ESiNb"b8R(ZDMqNau0,]!y!vB26- ak, ѓ1^0=v!! :#x*a`Y2ƳvoPv 搶~<+pDe9V g#{t] G ftJhkkwB!A,-12 NǍ6Z"?h~3$'du lϑir[O6L@nNqwApIJ oDV5KfIT=tq2n\dv)n*޳rd ;Ee]%7a'/S|fLX|@<p*u['9GԾd/|H'Dž8u>(sʹif9Ce!X0FCÑ/*ϣֶ1>moҘ4ϙϳxgdq|98Nr390BPpB.$sU#HYFo4i")k^,+v@d |Jjބ zɀͳ2]46)ڏ߹c|v߿3oѦet M=2 7ec?W"אd Mm!\AM_an`M"T7lɊ&x̙pQne2Nsً\&x䣓 j32 ;26I iˑo $*M-Q!P9/D6 u3GQna߯'g-@WԣC>C4= >[*t'8l.lUkX*i{V+ ߿c(;_H"-Nu,H&={GPq(R tpNfTo{3; k#@Us$|| F%e_% wA1C&w^`^ g)}p)KfeO AJ'h՞aRU{X,5eQIcF3CQjT^*qUJ7OoL)z \] r OLE/n?AN2@؋\ZfSzݤĖ߂`҄$6B3>waIm~TEiS(>;HEQFq&,+^ D\B?\vL*O"oՈH=jBT+n԰q$,‡5igff4*Am5Tɖ 7:}ؽAq.<3ˣGkzB[(VkkPa ږRx|]{Mf\ h{(4R6ʏɺU Ov$~%zƽ܉S!N< D _rA4N, 6lYpQ$c-Tj1M0BNc,/f+ihn9ѫ5&ًp=LVB;!4K(k|+ \8N w5c#})_r~0P"}qUt f+CA2|h(4pGecy!@4DE9s6D-Z - !ئ@Rz&.SwGW|7q{3̬ l>r`J/g^PBYOT\ r{*W(4r@:rg#y{qGh/>Jf,|~IcTԫ[(t{G&~<%}iΚ>>MFq G?u߽fǴ)_/զ'[ nJUUav,&?Ge(LE]zc^ =#R M>)A&QiNP!^v/Y(rj7HG{f Z% rx0mO7yvDt2 n(z B}//$xt1EAM +^To[)IڋT[kY%^sAƊg6g0@jSokSya#Arm-3=T_3[3e+Ps!^a/ݰK<ujl}>JۃDI<)n G4Hr }^9vQS1 HܟosyneiÜU$[6?4QB1T5aY@yB1{`F,)>N]d)·Uok `BΣwb/nJbT Z7 ABDd0mw3_de MLP^qCZF=:߷vP+{]\9*Qݠp.ʂf͂wd& Y 6yoB7_9N|Q1'#Q}JLո8R(UŨD$𨹂Ѱѡ@xn:G^;ĂƢFQi8/1aVcğlƈ-pYXِ,ɁyG2- &[SsX/Աv_χQeʇ S.q2"VL?#2Cx"֦]1x^3Rj$5xX}gbK4lxsq Kz;:\nkF#W8~xFiGZ* :pğyH0xuNʡY:etGM1ZĞ+QN'̒fK 2E3LyZEz|UmӼ-хԇ7lkv;9SȁIzIoIg97nsߛ~ 1דdHgPAmEY,2Q o][Y\L[_cYƂjnES 80BCCidFCiz7!D\o͋XlK53|  ,3` ߓIFOb:\ZHY\95 RS)JJ T==OM D7"WDw H {XZHMYk'QpEF\7VG E!D?y)).Ƒæc]a9_m%~&c(xc[35,㐛 iWU]o|lig  _FX-6#6ԩ$3oZ3e.08'=#Vۊx!nv0:bG-}|hPTWmz,NՕȜgb:=Nipxv 'HWbT:!µdHədR`*%w<}9f)qi:ILqn{Ijᖈ)cLTq\.xK,*.7ɻ4YcP8sJDlNEȃ R x:, t}Վ;Mvl_ғG#y+D촱.e^HAETxʀ+4.R3UcvKLq7cUL21-`^bN?Kd~嵬?_)3w}C Xeq T/xEĽ늪ecZ: ^S OXT#j~Bd I#feK6Lx ҔFApt?8e1ڎqGLx%ηڦ+qaAw1#_EљTbȗE#*ިhGTl5 Gm{&ׂLAά9ϧx*cZ 7TH_1 %HNEGq$9^`{lTmͪy c{ix7K 0T҆cx\ר币VVߐu$%>&ϔ͖d6<e`k?*,%Sv ѐh~Q^-.Dz.੹-D߀O1o<*뛪w2wY -xpZ8m)P6,Tt)OIYiNŭҽ͢/emAFcPX D㒮/s | sgxi͈36}5ܾn_;{Ξs @S^tNdn+Q/Ύp)r%(Th:?7ZȌ ^B%P_8azI4!U!(fLէ1ّ2O]UG%z,]!|oOU|͙ۧ'iZQl|Ar,m{TmϝD]1zf 6/ bP9+vvg"n@s 0@SI.q8w"c"EXtsu_cJRs )w`8)ـ9&A]?? de8$6SMȤ[u<VÂBQYTAG8c~|9\u_kZ>ШK({6$Ͱ5;9G~*0|AX="dY6*u VLD)ʲqx'L@7n|h@֎YQt9;.ܷCϢlo=SϾ= ~5bꏦQP/w"sҧVQL~۵TR%_ @~-U9?Yy:ע9 7ǫ #E{zMx FL%uR'#iGhB:\;|WR˄#fSʀo. WnvMf&^ʎ0TS7 oNH&z!D ~ /dznV'N}2M\=N  1$aJ. *eenabco_8A2uL1XOیci`vD!Qi,RiJ_`~VĆ.v>01 !˘yGN/g{2[.2{\', tZbxG/UOT3QRxhWQ~'3VxJfXPCTrdIJd~ܫ5>(cq!c,);?~?3H*lЃR}8]HQ;~6PEAdEK-;e2Rºcq<%>8 VuWiK>+ !' er Ck].|" PDpkpq-7ə`h(Vs0brEvaF}U _9gçKS, ^>%UscyW_.޲M[[T;}gy%!O<BO)WOM9tn@G?;ܣV[>jAi Z'U0 YZGUniFrac/data/throat.otu.tab.rda0000644000176200001440000002352714142647423016205 0ustar liggesusersBZh91AY&SYXdZκ̞q%)܈.tŰuIT D\ ERV}ڠn;wt ܠ>IhkZt) @jM4mLORi~='Q@4S53(44 hhSЀ e0~=OPOQM 4hhi=!0 `CɈɀ5P<w2eYeuMڏe$:MCajwe]Վ(9jW( >R)K "q>~dY6d9*e B7Xq\~Fl<V J 6$f$-yO+Qz<$?!Qlhub, yBJ @G Fa@cQ'r XK0HvNU{qYC5a R|$՝$oQn_w>GxbFsH%:7RauE!Bkgg<xSŽM ۟qϷMf9AI[춓ROh,|iԕR 4YA%dJxX>>;~!ܓR&CvXdA2,SpFr6a%u6f|; lDD_D_.7V9 Y.VZ@syjQi*v]̙ ‘>y(囈mh{ ;vH0ZhЊ>9ist9ãX0!Bn#M`F}cq'Z=x[(OFKтG>g{Gs#^|'MbHJj3se9A{&rٺzsbwZসZ"YFGl& I$LT @\!K%>@j.?.sVmaA*0?GQ>M@dF}uz+!$F$B8Q~>3U?ٛ3zE<* #L&P) iJ L#Hg*l!q690ЍQF)a 1uHlca0h" {YB߳#rFX, kV[KT=S$T9+ $$-ԙfSǗ=jД"+(WAI+@ .9쩡WK#QjRme%i;he [w >;"Af#'{ Xߦ\gLY'rY$BdyO̫JgxZa5uKb6E7ZգRH6H$# 9xM D A 4Š G`V0[JW1ɮ,Tf*kaYE_1,I FI$ByF[x~"Al;4ĥb-t髻YF*(4Z׌b]P%C,cLDe0JYPu)өq:I8<țԱFF%WB"AH Ud`I@9 `^b!&8J̀t/V"ݦ;s>ZQ!$24aXiܵ8n>푳@8>lfO /ĸ#HGȡfqDVyDFY,lApa^/(땢)<,1BJ@M,9KLǴtwgVKdii+&rkE[*ߓpoX7;&Aa%^Lul#zokR@墷,`dxNёpq<>ELγraq&4MPx) % C*ev.nD +¯9rɆ$@|؞soO_}':lk D;{*._0^;2X#jLE;K}Zݧ΢;Dn1 }^I]d U:z+PS,N~'l)_=MnBfwڂ(:{ B<&L?PE}'`WәhI]n .gɳC//5gn6f5=_~ynu~oz qǻtlxX=XM5g(B.׊4]St$BZ߃ba RiQb(Aq/g/+3hƢ)q -e_UrE)VqO<&_{w j-ۧ5|d=*bkT Ȼ.Wqqς$v~Z$dF=xͻw.;ݿ8.zxh #imR_GׂߚGqW8Ix^|]sU-d sÓ?8 ;|XBO/R4 fv;G%dqݘ~8tBZ"*MڬKhDW`qYx`<ro70+>NG'N3x[}gezjwCz*JU+] h*}1wD2@Ʒ4+_?8C+r2P'1ڇTsǘ;7ǯPfv.I$hMLF]aD͵o~I!H@?y@!;HzO-+kAX&+ҝuqh5ؔ.KϺ{*$hlѬI}US>.)ɭc{ q,!z50a5r&`|tI%Nh#Tb IIU$Jme+am2I}yIau7o҉7d@k 1#z JrTmX<,|0: 4(ŀ t_$A)&J$0cuGbHk z5ʐC?Ɗ=2@ؾCɐ$=DA B dV@N2| 4*>K۞<Ϡy۩St.9MHgZ2<gC;LW UGJN%C,׷ n>'dn*uQ!| )>XG+<F#!bv R\ʵ;7vY&X_ cB 1Γ6 [^3V995wmrfOj'w20<`þˑ8Ji$ցڼ"->U~YׅI"DF4rRnwKܻ1S yb⠸ڭvXY asb2<][&im&C$#yT9qMk$/i,0UXKP, iBG56; RxHOY*b$Ģq%Mpr<.Hd1YY-fe@J<46gM49"]vV4N<2Vi8ˌ%L׬uxxÞjFI$# aj{P{_JWՎsHLr\GG,_N3m[ll0KDp (=LQXHtpz^]8д80p6D.BI)N$]H`(VB: (qڞ($5<9*K`I^njJJ(<{D=(thキkϾξh:ZS͹)W]V:zZW[Hnөuhs˅ @N0Cvn\#YxL> `@c P-bq\xә/аC#A xADʗr u3ikagmq]hL¨fzדH( 4*b0Zc$: VFCT0߂-rSbC1rL ׋- 䟐 MTpe0D_ 0IE )H O?3HN=APg)}uB#c?Y%^ M]5L>s$ zUpe,aQEPڲQ7'?6TKl}1 ˚CE.pI/~(WVhktAIF *0m؈wt(V;VEZag3/~lUxYI O~H! 4)<N.ɤ:$ `̠ T`T,޶X,ACMT#i=·95y~./,ލ?1E bT8ilɳZH'ؙXN0p[,,% u|%DV11(W:p űBD 0D6;%$-8Pc9LEHthHk2pI@!HSI0Bd Iy285P:3mZs˻qҸW[Hp -*nd0uMM_/g5o"tHBUIQi+Uo;cyI߮krp#b2ipHApƮb7;u(X|\Y $J j9v+[ uI)iԠIoWfKrB\޷F<_z1a)y3fS nzvҔ-dG3_ĖI Dśs6zK豷DtO~rbN8:3]ݢ3'OeelX6Z ߇ĨYYprN% y#4ܗ:lDiM1dzB3b`ࣛ ra Z5ъPlxn̘kkT FgN}#J%gY/Bi/0mX:z-1ǩfn˟,.8M g)%-jZ( |n\2c)r:@I+Nϡa)põN)u>ū=& qcLPnO^f}Y'ƕuA.%bl\=|p;ۋlJoL[dKw'k\{_ĝ֒"`3DO#GU-hzunjV j\<¾S0ع_}"֫1TZHpvv.SRD4(ؒhSlgC0ȕ2׬,&,n up-sc GTGNHL;N`N>F\3[U&Ӓ|OYuJy"xtAjCRO̊. ݩas70x$qJ6構`VD,M^+Ҹc3wBf^ c}@8?wHW 0o)#.5!G3\'Y:X'ha;ۣO6@YFƇ9u7"K΢8 P Y1So HvU-6G΁e(jKhh8)#Q2Va.4w2!`p# (rƕVbIv~ͩݍbŃd鉾wשv8"6rrwp7\I $\jļ<7v$^ ,TQ¯дi6A#9#9yڌ 0gW/UCza`>uHDYޮ#I跩CQy,ȚO6rXd*."e/W33 'fF`@t S:mC2: Fw9"2B".ҲkY:OքZBQq*I&RhlN0{ s qfZJ9ے"qm)NBhd<5 Y0 ѰFAbsD&#m 3;pęяg",HV%ץOvSSڎU»s2۷=kJݱWYBbtz߻]O !EI-R(pkkM Dk'Qv@,31"uo gX-: :G0@}+3䉿|߻p =r֩~E];`AVchl~5K1bDv:i]ߥcM? `*X@TЫeE%%NT+].mwҏ.$owz-'ehkR$TJHT "(Hw/ɞGUniFrac/data/stool.otu.tab.rda0000644000176200001440000051117014142647423016040 0ustar liggesusers7zXZi"6!XH])ThnRʠD5=g8Mr7-bgLE(vI/}k6"2Wuݸv>;LˆI2Il@2H"GiP,ϩ &}0~Vd@XKY@Er}K^ՏPid_qI)yݗ[4@P1^&vv}6*'2S"ß]7YKXtƲb`mTur1G^OfewJ[MYh1Ok⪔ipeJ0 #yEUH rH¬ZT@b :FyBa}1ު*(\ \D_ڻ9G&XfW 5(Gл 4 C⍩n0w9E:P  d)sD>l^Uߋ(rCgt iPX܌gbf@Ml*rU}.CNJ<;ϖ5.+VqMyr 'q0]l$b-'dc|pMi\V/ 2Z;CY>%Iɯ5 e⡑ZoMkAc&I>/䒻u$TO%;TT016KYi;<˜bg θL)^ ttNR|·L^"*B EȩbRp68fՕV̰y%5nqǤ{pe)ApH)רr%H %Chs`QQ`DfFyțqY>׽OǖFl/2'|OF(IL`a@Ghwa+ 5/ ^*l2ӳ#N\ݨj>b鏓@%(ajPB`kg@ȼM7g?-)+(j~1[n.ɚ\#1 fJ |/ya*Xkr،N?eEShC 5z6@YEu>/#-tuFM~^`|_ᅯCB?PSśBp9aRL6Xi&Ȏwe3mFȬ[ͷ'{P ."Y*L׶uHOcIMb\_D-D[ؐDK_TI#b(cYM(^[rf1!:tJD*cXs3ѽxs91E4yTk.weX X"<ְnq9X-3J_ILl]i sҍȚiPn ϧhEġ>xF/iUŞiu_!&%a%`!Ōm<߻Ϋ~$g%Iv{o_@!}aVX ޯ'wKa^mgs/_7CƩ-燫8IP+dh\Q=)p@cFR+ |ȼ^lO%3C(yEz!oPvޓBʾ}U7P^h}\,x>!W_[s&$RH.՗y@ӪT5UV,pj~=OA%)IyGt JmCSѶK)~*"m_S p#iZg&k9lRd8ħ>:׶mṕEvm Hӳ 23Y˕* VOLk9:\FB(t +vjI5 czwcHy:$>\./[)A*,j""e }b(SeEaT-f[!{'OMRkm&Le@._I w1TJFwYE+ٳ0JS90q.z16LNSa]curNMJthoGt?{]Pz{?_T0ݙ`^̛oSOSYN(o&&x"ЪOyidJĵCaL^[TX&{Ggcf3H qb hrs Mc.GVOCq]jt$h$K O~ry~΋F#|LyHx d_+g@.<eaj`|Q m&#o@͇/ɴ'(?`"'・~TB bۣU>H`RlOEEDf?LSѯu!+aeLJ(9{"7Dچ¹'cV*'A4+~;|ιITptw(f4\i/˄K8G{ 7_BxJ*o$xOcf` 8s-zy\\jʸ52Vy߂8³u,tW咥纴hkpvH~j&o ! [ k+"zQ`Ѻs/my:!M('ROԻͅU!6i9uF>[CD \8D,NZē*Y'9mc-1b |!5_WHN&C80X !A>F1y+YiD$Y(NkzW,7uhr>b>⩐2Xi}ސI|! ԫ|3tD>Rl2XUjd?=Man6/,.$Mz>5鮰zvg_?/ aoNjzo3x/SrRV,@|Xy !FHZaުJOկɛv],ݩ(~NHۍY/;#h:_q jqP2i]_ik(Hg_nffKE*Cr-}Ã~=.ۀPI*+ :g[':EQT@p%,uDWgN F}>E4ȏ-Y1-3q&s=pBNVZrx!^c+;~1pX"e$tT$\Pi~ 9ORBCs_GGBn rAgp H#7̓Dp9_=LőpRh|Wqn{)Y7d\G%Bq TB?EE 'NLmjHn<5ғVIʟa<(т˄Z-uztaJ^x|ֳqPsG:sCczh+}<Ωi0j(R_W2Ieڊ$6U ڷ1ڹv+*%ϚkV!evzk5_05h"W d-lj&Heo6zHA0vgYy{D_n2u M`džMǡyMVwogӨyEF$|4p<iΰsR&䂵C >\vvU7KI Է 51 `~W}Pܰc=j͇ [},VqlO8 :il&|>7lk'W/+Ѯc)8SS.xhRsa~9ź=kXe;T͵.Urq65c`TltɬI1"^,(1&C]7&9Gi9@A?~f&B8ѣ 4 |ݤ/gS#&Mej.{eL#ajB=OnUuI=Tlm,8Mci#2"0wunޯ*@& H S+>4[2(W"t]zaFB1Jΐ蠑W,A*T!'cPcْ'\iH(HWdP.R8-9S&CrsөLǺaĠN=Xgk f 9 k^+xP*aRYuΫt.3Du[>n] xc${{|/p0_IK]\^Nb 0Ŋ`c d)0֎?\]"U(xyRUs}+:N>+eJf`|lu0|1ކIgurnw|GBS5wf=69.*+/+49w(?G' aĪoxh4nU TY`wt>k %I,9$Og] g͠!4ipط'%NYWҺ叾V 2 ETH@0NyMZ4atSdIǁ`?N}#1^W w>VJ3<5$e pI n{CeE~vVPnok@WVS?_: ~Rb-xii]{82FN/`t9F1` $pjQ *2­~`k;J8Ô֜~b ؁t+&T ۥ nK7M@삩Ews/cQ:5{oŘxgX ulh@s:OV8 #b+L!?̦{*n;0_Eť/H佞'B9 o~ڋ+sYle-GgqK tLP!"> yot/Ӟ|e=[ah/,brFx@ B۳oEL sh7Iø0 D}]N]rW+3ʏ ;q\z+,3T,3odһKǥf{tj_X7m<+#(3x\8{':#c>N&z*3XdTB 0?L"}ӟvwZ6B 3oUj ;%B׊5S5D>PF%|K%Xa8_,}S1 lB{N|>Z)o=5brg S*H3pv`tq+O!psʣ>ʒ߯(nm-8z$:cD9~RIX!ȳO2NvV pdG71, xnF%=F0*,r&-~/?5(2%c[ 翓Ȼ&f!"TL澈* @PdWE>3ND.jϾ*NDvĚRzc= k/^L r>.=q,,5h SEa`o.ө:,tSqu\yyXUs:&GoP76 !g~?vI';APNmƭ]d ;s6PRzۂ_&s$WT⻂m`#lyt:df[fʈ~~7|3= H~*M)tr=!M$ͮva[9{N!!k#јä;?'b*!zxPHvHȲLi:KK eL!X-&EQՕ)ZILaCY\hF&bOC:=w҅I.ݎX@ԫ$ /y{L[5*S\\>HH*bI zTH6H, O"H;߄@G9c&J!a$EI_zjybynG*@-ٟmep$/* /5+a|Bir| O~.b3Mt2аpWKrg(%RX6AKriYIdhePkXZ.$p\QY?:ජ*6?"- ! Y<Dag,M.T}[Aɮ85*!*t D:^q9|LX|NհxX-p@kr, !9w\Vd'mnޞ[g">WrA5~ lFDAa |0|p8r!;,Gr4v,S}_, ?qM Я.>$G}22Tr~֠u@q J -a$م8'˩S y_g ٰQFo al43O_daUI:I U"5B UFo 6==D.# 6k5%z,Yw|ߨՒ/^vX/ɬ'# 'x\ܠSjl}Ӌ}*p9Z!6F"N I,VLlYT 4v=Ť65(` ļQ_tm(,@ DaՓ5ՃQrr'NBt `TB:j/;$u7,$zgO5nK6fX9? `.eR.@ƪwhs>.'(!UBQ'bؑn9!{kp1[tc}jY~lHŲ?>S9br]jcӌiH욊BHN5=ֿEF5sR7 PYI&=ս@Q'dӥ[OTX ]uxjуb)V"YTT {xYK%T^6Pki:gMQ:SO'Ȅкbjc].7PPa`ҾlA-cto=mǟʩk31#,E %ESӧ:K"_!qFH}-Wڎi&fxάZCS}sP7fJui{Ro `1r;D6?&hgy϶4@%/kU}>\%f#Y{džHf)ʀdXu?q#Zic>|J8eP"8!jVt)&fv*):_ S{^U1ƒG"eo oW,I'(o4>IϺݓ%f *"L'޻!b0;B`XFf\PҰP4fi&YXn~8k';rb<@4ԒGa|]7`~4m.Xݿ3 'SjlbϝL*3Vp8C*đuUV3_!^4w(9~`%A8E;ːUV!Z sm􈰬`]-Y3Qƅ㳇#{ `:C)3q{"<"? 1exn 1,^yIw"adUͲ|_,'~5Nhi"lNޒF-Ev18]bUnLc2Ё 51te)2c`B=$p re`-w%~K)Ie}'A#u {Z#o.y^Y 9f-8iDF"s]&Iגr0>w?@H*幹N8%U&ߴ''i$defm]S8g y5m:ffqI7+ar` BsY%csFrt}RDP'=g<3uR-yk4 'e'Vxn[X%QJ\}4 HRVm\8{oHB92ɛq0/Xi_I.\Ԥ^!A_ eB+SEuBn 8ЪTh߻Y~[ !PPOϦlǩ"B{7iz9;%)9 % V(U1/L>p~#]wu*Dؚh }I:%Nˡۃ0)A*q%{>I|dpz"h6nw䬃Ӎc/v` aR62=;|I8&:'$4Vc@SdCxK̤FYf T&Ӥb Vl׸9qZ@&PYFRNoe6W&ڷ:[)!XŔSw}Cp=eKmiguס],v¥ƓÂ[*ԮM\8t Gdc-\_XxݡF;ѰmvUTѲ>8z&߷][LoH5)Ҫh*<%JvϘRǾ%ggh,U:,ʄ\} qcs+uNOM4.*cg&/ u+% xƝGԏ:2?dЫjfKR`0\voZp]u}-ʳUla:f1wLm!i~_悀y]3u_tf;6Bi;O⺃\+:;Z)E9+1,5&?N(z~]qV̾OvO'.vc&|YRuEUmS9Ox7ZEEi@40kNk@}57Rbx¥GIד#G[݈&.xѤ!U#.3H#ѷa8#ю#IVi1ih{O"'cO +s=@sٹAY unT*@*-E̺0I~ yEQZM5 ^cH_i32{IU}Hl|'cT_CAy!| #>mBT񎢮! 'M8<#va?1Q4 l0 N>aPGdiį9Ce_C ugEW$#d \Rr,y3ͅ2d,f MlM>}x ':zm#Y $e:QT?fptd.:a)95TAk{ç@FUÇjba11 #M#r43-!rc[&!gL(#8z=]6fbZ2B)*2IKtO?ٓgܷkK4^ƨ9@jY^HnjV&hac)D!i4gϒ/:RQ˜)Yiɳ aW.̀W> Pm(i/?6@)^џc{15՝{CSo7Qcؘ ( 춻P=#D[;pB1o,:o]9ͼY(XiꘁײG|`VTvq hnKPQ_IτƙMoocF !9lf֘|񯑎Qgc鶷[ x* ,6|դ30YChG )-t n#  zm5y9DP&Za7QA3ѭBMVjwKxa;[E=6T7~WY*||-A@$%&TaNR *m >gEcX@OnDq\`E09@Nfk?z0J?z Vp/D:0Bza}d,bA_#񃴴!KJTd? рSR:V=I䡏}FAwu;7QY_@dN^/iAG9\NCCן|ޖ4r;bg΋i64Ȳ[m 4ǫU@f W݋/ԾNdffnvVw17>>SkAQwWz;z%0":窱O@^^%s(!S[(h:" I?B3٧gS&W~̃̀?f /#[:+8G#?Cxs g&߱;uvlPӃqN¬:<G w([X&JZ"<_ [-h1[#Rb)&J9F됨Ό 哢H QE c%zJ_oqyrYb-  mx훚W0 "X?dן jީ~$BnOtO"ṱ=gER+b/3 9|X /&>J+ֶYROB]Ejqjf' *AoBi]lY+þ̝'o䚲 }K$elބpcQ[^xt*'@]~l;IryDYc$t aauh04sUn IHR J#ywq"#*̐j%+\KvQkH{=SL7c}^h֢dn %Jf(u(VttS\|psvơnBqҶ[>eIBK]x>e5JͫtߐQ$52_{(HAvϕ7 ZO/㶘՚gTi鉥zY‡ZڭVF~l'tw7%z/p]U/Q+ s0.[hu͍uz1,v*SH!X\MSw"ܜǜJIbvFl؈;\EV1@@VaH-`Eejj%to!~m=%Tʨ,9cB-v6N%(hfeFGW5c"ǝAkH"~8ݑnqu'FRG+K^ -z碂_S> "YU mW(JiwJ-HfKN'|0JDNL(-jr|kR+m712-qդ 3 dP TI 1!}=Ms.C唭][ M=aKv1fUMuy*|(ep?qd[* )D]ULaƫ c=u @yfA37@&/q{F#?~t$tXi't778ݿ >V"7 T6THt>UȵZ?mg]I,ieG{?4^!aS<:pst 淥 v%?,tأ"KM/ {#FRېRp ל[hc)k[anP+DA2-٣&Z9v04h`~nF7GɯQI5tfȸG%N=#m&XFnd7╫0ʟNZ^Q*V,u3#:t?b"eO~bl>?Mi,'l(MRuVw8vPըAVqcF92m #q@A>#T)R4 lw?0ryPQtq꓎[GU8rIB.stoGS`%#W ggiPUFgyePsw+AHb!$کѨOɯ#3P *_h4}N7 9c"4w6M\Ӭpw7=R<I7$+l*e93PNH0gGXpC1xJZtZ=N)A:wsBYܔlXpZUnuD5-_퀯J\Ǜ-H0+n}IMr䫃Ǔ@E٠}:^6m+ͮou+guh[%З뇑eϪ~9 zzͫʫԟJp3Pn%3t+ a]%npLŪޙO*+6x צ^<ٰUßYX/(Fc [ȟvܵ53|sa<@w@4gчX4kp4, " 2N0ǚQd+̴^B?ѱiϯVXd_ LK? r-a \3ߞ?B!xŐamN+IrJ(>ٴ!wMg?mۓkLX[> Orl(n:+ٸ}G'_^_WDܥ"!E𪜅'V8펧(n?U{è!|1 T<)!}Q F8$EKf "|ֻ|/oHz<=ŋŠ  ,YYo6  ,Uܯ7zejAVS@S߿z|!Y-7aANh'g(fyꕆV6lʪ/V釦엝hI-fP\Tl?I)sNgN ^y>3 p V>X'.fGE0Nzk>*@ͅrX .{KvɊGEC3򁚨^S=Ս Yyi-bE|xJQ8v.q;Ts<:\ -=რYEh/ ""е"SSE!7\,wX/o:8m(veA)נE«I* >\WI#$grۧC2. ,Kٿ][|K+Ux!AʚUO}jzzx@S G,jZ<,ٳC[ٚ-b0}-b,61CqKć8aj|6 Zyb A3RA)7CEC@x|3nNZ$x)=9x YUQBB4큵2hc={mScA#{BfCtIJ}|.k0bXAm0J>5JF/j½Wv5h&$6VA@#-yMN# UL @gOzJaI=^6kn@lЮAg{$}R0 BPe|>2&+d5S_<:k@p:X4eA[Z)K\ ֒II7Zr5A;kPϛ޵ Jr0_Aj>ީSTI Φ'![`’J$LHLFu҂>#._ L]qvi32W~:ϑ-aT&Vl.ͷ ވ+:׭^ކϖЮL;eyv}=j"1)rqj' jX23!hb_b">^ f.:Lknph8@/pT{,etPX)Z3`Y@7@=͢,N`$4h|:W3a&zvd Fq]F֦"W=#@rUdu`{bF7@VO.pi–ג$Lچ,O }(˛(] }nЎ|i=+CX h6 gKJ!Y~a<.JXײ33|#0s\HHvxq4BsY+ E:zYlʹPjKJZԬ*i+9r 6u`s z&5ͨ ́綩o}0Ρ K7 ~/7uN *ԞFxo>*|& udk?CyR`xD~R}ҌjX.)(0/ܯiQ>R:^|ޕ$j ؞jwThy Mkj<*t:J|ՙs'Be~[!Z<𙻔WngN:G0KŭpDA`˵ʓ";;o=ui"db :&:#pkO܌GEKrjyN5 R $8ʀF(T|ſZ>XgcKEvmU}Wvn#Xuk;H x*]hʀCҋ]OV+5ALjnVw &rSy}XN9h}j7X=[~[X+ xI3C+ v0ư\k{5Ȣ,&qHh>(l#'J "ZL]Ū? IJr߮k:u1}\2'©3nR~sTEZpvgӻO)Ibt!J}&w>@3hQT&Xjb&I&bBCʘܷ),TGtl-h9%cz<۔XDń_0259n64;.t+ Ͷ/?[gtdfFwPǟJqM]gE3-:om ,΀Xe?sKR`U(J' ڛə:( j]&Fd#!uGVl3#FDa'\Ha#x*1 %7zWZn&Ilȍk!cYpfw|+79ͻq]CkQrUs25)b v9Ǧ~9@I쵡-BuI;`U.R?U#ZńR ]+ }mN BCs S,;A[p?ٜd48ΉƔ,4޼ߴုWm,i8%zLàzOE#* VG'†BOR~NdD2Jw\.c Bko&=>D:ęx2l_R\+@AMtf 2B]pk=U+׈eW['Г" HϿ&Ɩ@Z!! o{Zz%$ŷ@@qs-6cLq9VO۠8h.\oU[p'bƑ{V0-}M ĒTvo|`5ٌ3I#3(94,GΕ`my CdӜMc j<>FaMa1NKE6#=mpMk7y%dhka[ F&PD*L̅`x|H2%iӤ4/C:^"J u#nT88j͈yr_] o:^9+c i>4!9mz1]db^qղ9̧ܬϕaYrūjf$@ *3U f`7M dZ/w Á\y SS˭-qi &ԣ%f l-zPb3A#Ll+ xDTIxX>R<5}f[Qu );e(.P@!gdkOiF:wMXІRA'sUI&JVQpqIƂ$wFg5(L+[#?sQinYY]DAnavWTeVAh"J+>K]LkŸb |iNc_ϻBZUv^%Da CQڬjCRXDÒ94}8Վ-1R:jAD>stkR(%gz O+2|@YHh.JOdZ|U>{)ыc2YU<ϯ N Z؉; g /TpX^'|ۭtݲtHNoLDÆhF 5a.PVTM/0q!D2Km@oc[byB7>:>½5?$(QK{vNUNr6 .oW'm)43U#yar $LMVeKoq=eI1֬ס*=o440ØY׃l^uO&V_ғy,`$ 'UUO($ =TG*9*=-8Ra-Gyj2kšY!գֽAYG&\䒔RpKo8aKiYĿ[@pBB&KvqpŁ5+â~;y'y9`6 8: iwLnPCj鹎c߰28ԗ@Ƽk/ӎg5?h" D"hAa*7% 8vjzY΄:S5*H":^Nf_)6h"=8 ]`8k6BA1%!{ٸ1ᮘv j>*l/t{&N*+a% _2mX71_)hxM$;BFҨx)ލsU=+. K{b̡Μt-V0Mw8 ZYo)U"l3>;UVԬhdY]'3+ɿĞl#:k"[ܼ gʔn"4teUʐRuEݹ_`A4fR' 'sN>Ux% BxNgvK?Lݰ^KNHN9KsPWŸ̇m(b%O} Q]50Pnoh"e@dC-өz|Iaks=Tu!wEߏZpvmTܮY@gع;9S;Һ7ѭ Vڏg (5!V&X/.4$I P]8bE0-/g gNB5ȅuȧcg@b 쥕&Hu%"rDх4%$@4'nWjA9؅ 7.U387T<"1]y6;7۱׾FuBf/PƘGMӚW}ZmUCx͙ t}\ɔC|o+f^*ť.ѿj%dzy5a2XYC:?Ӫ ( Yo7oRBgEW^MKڭ}0G eG8H,ox0Fe K{p›{1s7|1U;v g[Gm?yffѽ=癆 ڐHKz&;BUZv!2` YFKo;Xw 2d!H8jX;INU-AY"@ߣiqT6re^l^fV$L吾\Dw\Qٞ姍` $.cfgdY{_K7"$>&@Cr˫D$rVU_BBAx#,e5G7u}p(,_Š*szPu)by襁ӔP]c\ H՘COC-voK ja1#[kWg|`-L1ӂ/iyw{,VY=><rΕ~@K~N {Ejpybd*9VV꓈Ձ3..27رa|J\<*m3łuX"BA\@&PPlʪSXΊ7ĵym9nI$#(8K 1f) u#'v9'M,)Q/8xlW̅H٬~ThQڟƏFvƐة/)I@S|]c>[э/-iAemǢElJ{YP77Y'EH*M}ڕncXҦ94:>+Y[;im_4k`*cN4ȞП41ˆ͌Ce㟒S| d_MzQ\gӳLF\e'83[n>yQcÂ;|R~^]ؽR%/,t9MpbD}H|)9_)# _!~y0?cgIs޻QX1|z* E^6ٲU%tB1Mb_: >zkw >ZtX#a]5֯K] 8a nԋ s[_ѴޑZ4*-&UuI 8 r=A b՞7HѼ"y BsWOi/y-gf:8W,Z])fehBS6bO &\/]Zb9(n9mv~Xm rV~j:Fʋ) 7e};L|g )2Xh`yGjEnD{`mr 7A9xa5yO W@̓k$-S ) !bI~DoHoZu =ANk X9Fʱt9Ք86uԴhUa6߱C012ض-pu)2C331NNyXXDz{2J\@ٺ!vƅR/\D#GOPf[<1R,Y3øgC?ŷQgNYd%GK&[\+ʉӊm;[d4n:T\~b^PӁț+t PB7#4^@pT ׄBtƉmfmlCJ}!Z#Ξjï%eX9?ivSO*"4uc߮j ܯ,]qa"M ! L>~ (n4SqN(K Ij f Ɉ֋)I*N "Vs$ڃ [TzS w#D%Mt.5+IF%W;ۅM!y`+" ) ꡌ+{D7rj`f=y?#m[^%u%vTCK5^^ nrq+d3wMh߄]+L76R\a]#2 ~<ͦgݵ.јUz>B!t"ww`OOC'ʘ]vg;价? @ep,zIX*!Nˌ/gdB3= ʗ)ZVjYiڐD6 KOES1d}1wR _X0Q%48҈C =?ɖyB0t>Prj3vYB 1bMQE=ӚC>@ • Jr2dm,x }fS7uh%0%),g~+g1T# a- śTѽA0m(RcQ(%lnC%_!BN/jY,ڔY=/[̆t7DKC3::ʓGlBx>SZkӥ.Z۳ӍB5Z\)R:bY, q.{a=`cA؜<\,l#ZzVREɎ$gg+,Z!}*{mHQ>Шe'柦&hz;}h2cWI)z6d&sl@$\V(bwyG|z/a2wEӈe1?"=P"52˭`%iFgjY$*瘍ۼ9Bދ9U[d0m_&©$T`X6s३\=jkKS:h 6,5>vֶű'?.+9"HdsvD rIÆq͊S$8 7LѶˈao]X.Y3 +=wbQޞ`eWRƹ:(Eg)BvVǝq$t(Ku]VU89?5;aGʈ׋sт@3&Dɭl[mo)ejcpD'=mQ32t9.N&dL`ߓ$5(휋9V 㞩e}j ]% z #X@ZXYsg|AXpMp5[& Ps.̘ti R(W yQGo63;˫`Scˠ6^$Py\J~-mѡY#G|v`>LCEadpn?@hD@,ծ a:Dz3[G?iQŮ~БnВ3iH P$p l%͍4`JIيapCP)-S+)/U2ar(.s ɏc>J:1ٹ>YE&+˞X0(dj`Gu&sTvbg5ϊ~@A䓆 8cIh vH}=߼G4De;~j|P/6֑-;*9ekKXXfodwr#! m#+B{m5T w-{B7a% ?&ry "o\kQ?Kyb:ī:Tx]o+XK=`nAr ?{'r݊L;)?f!=ԇ=%~+c4I?7$,p 3ͬ\|sїUxvgfZߟl'""o+CrxZT_F<]5m&Yz")}bC2CˡBV tI2QyD)pZʡnmWF[]ȫ|Nўn|])zs[J'?VXZ_/ILN!QAa w[ I}W$ph& \pB-oM>嚆hϊE|F%VJJMȷi=W&pOy;}\ϣ4gy̖-oIf3pۯXu%J$}IN&\Ea!Q"xڒot-*>V;җBrzhۙ2{Q*W6jDĊq!}Z+Ge?}{Cz9wj 0{ȑh= –^DH<;1&yg't,Ue_YXz1KVa=AO3T4+10*(_Lʱu?/9CTB:Tr V}Y 0OPA&- FeF&ztp@u5)do5-osg8T(=uI{\^[<2iՄDgI[LBLzmxnIH/w},4Jr14KJgY,ʚ]DLQ. ?*XȾ-I+95QX$H- ;@c]M]f=GMNav/뿇ض/lMEC-6sHF$ɃzY>V]LB`jnMzT76-R9#I*[_Ǖ:26"Mineֿ"=0cs3ҥQ~j6>x?-.KS ;I_Usr1/ϵhQI/ SG+wō&D-f!XTeI@^}^X;4^q$o5MY]gzq+ਰ\heF((]o9reNCެg'di4,;V΃.ۢHDZ# Iu`@ {,d82bNF_0 JF_ɼEY/S?՞d4QHvz5T%݆3_ZSW'>9"Ehwax[ex҃LlUXH-h)"kLD2hևZljX1/I}Q7*!4:J_ǿa׼[ePVk MHiZ}'\&XW@i4ђYoҼSWELݣc|AwD J˰G /[/^ pj3W=|JΎbx|{ *1a)Cׯfc΅%J}BЁL=Sn8{Pݙ[imONO>-o VC!,0Ŋ.bG[6ݽ{uWZ=5ڎH=KVo҉JZF-c~uعDUXd{'^%Wx2?xUۀp5w_3zƒxVM+ xV .`/ЩjMM2u2 9ҕf_8ϳ$&d8XD K+w@MqzuDy\Nx .!$wGbg6^J\_i`mj'(Hzsd kzjM8cn(ׂ;rWR4ܩ Z;A_!8tH˹WHq#EAz1F?TLSs &gViFB̉Mx>aF)uDGFO;Hy=| H|5Jx3v_5$j+as3h5A8KX݈kPLzw4C}3m8H!Dk7 E؁e!H/P _)ت #,^!J}R8}-Ź~De c'RNu5FxQ7VKR_W8p6خB,o/^rJ)rI"t̴$N`oB3=-ܩ:Cſa{߰x.؆TV3!wiO]Ź'&yu`"ϯY7cjiFe C27)ם`tNo FqȞЏnrܻrq'{I]$10iDBЄ|[{(~iwgFOkdg'Bh.QC(WM)sǎTao:* A]Q/Ҙ0b]O@sb}uF vCD4}*@ TثoHs4rgƘ9?=CEd& h OG=Dw-4l /.;X):Kȍ"2i8OLUx4t&_Mhԉ܀Am4k\ `Ț7V*?Y m&KΆv'/eefo}v%HnB4c#%^/o!4ed_8F)v%j*3 ޾gu$N@J`6?I}؛F6cާڛB?\{z]Z\wo -&Kl`-6+WU`|o0* <~rPH %x̎4Шe.騶:;X0sR1bj4ۥM[mCGklIP4,Ѣ^*ah ʍљs_⦪"ubHytFqWO(Wvqu鷄18 JFh&_eP  "mZ+M+hק~Ct> /ƕ*jJ=N%6c+Dqx||)IGP>G}J@,зn_d['bzT@)}}Tؒδc2+C1VWIJϯ85bLJ _%ŖpjfYkF94MdБ{7'_|I}> "/0~t o&{#`:"=5VT%Ċ/O > Dmv!R^ ֌A\ۯzIȑ5D Q p.ȦP^Sa1aj{T E$/>،X߱NnAyuY&-Kix29agUٍ§:&/}*|abF5~12~e=$5yj89 uu-P1'r+xoQ5e:.ni0í#+&Y5tMkO5٨Li'sV*AFLpnWe| r.' ]g7C,1}?G*,bצ0>Y>5Zq6HjQgӬgTmp Zy?>}b~xl:]UUɧBVN i#vв9BlωD9E(d};7q]N֮h`iw[bT妤i\[U F(rpx2/Y%Ugg^q_f m֭ݞ 4Y^qG>Bd8JIo/F_No!jqZZ`.K[G#TalN񡆸u2U!0+V+*?f&H]c쿑6?3d{qjRRWQ}z!(#S٬H<cUS[u^pj5eZi;9fq=!?JKQRew ތ-~jJ.uQ[76Ɲ)uX@`EQqi: ׿ttZtű4Ac_J)TvjY?.Cn׿eӏ%B4|w{9m(Ns^0Ia3o~(՗LaƤek lm6<; zqmy !^kzl*U^/N BßRfθ|Ƌ:odU2N"8a;vb+&?M<@^P(p ?Q{IM (詴͑]Jˇ(;zSDۋ,Ltx:1U/CzQTg.UQyp7v\xJBQJ vNZTx|O^ ])_!ٝZx-_iլ NC{A,= ʵAZ=SkӪU#.D͐Y88(o`' rw95^#^en%?k߷b?/@s!K7eN$r3Kk !t 3gi{P~ضS犏 R}WC[n= 2Om$ϒjI>ԑe1:Yc>a ڪʳ`}h)9w~N; \lNKFO\Kt {V-, ,Ltض{!xRޤ_$- p$<.B;!eXdd$lmamœ_s]Dh #kټc`pפݻ`PƩν-7{i6̺/4N+kڛBǪ K2Ffz23aj4Z!ǒYwYP],殆/-?"^i]ښp4V;`^|&Z(_Ch^3Po[Ζ8zaՍ@ƹ?OvM&R]ܥaIB2Fj|TĜ~EI4JߓI4qq^63+! g@=bmdJkL$=k%m T3wx{I:˟n8[U(^y w&T|xj9ɛiBj~cE*ƹ H._E;.)\C#:K(i"\Cs!)A9qbZx[Af܋wUV(qG, ;ycV:S! F'S49ZAOu5Z!=) bS/ܨ~!z:g-|77JuCc*5ٟ@J|^?(T Ď.1`^C4l fYX!6jo/%̛fFj@8fk:Yڕ@^$')8٩ -MP1¯}7,<1M7B >sޢ:–'@G Kh.aEOЭni(znE-Fq"r!6A#nu!|ߟ=txr 1Kɓ,[<0TPjfxywx*UA豥9OJscy[BfdPCd|.\v ƅQ@J<."UyDz<BhO yĒ2q(OgUs@<.Xzn` =Wp%1ie8 \4xzrgxUĭcj;08U5xF-AWӜz]U&?=R;<{VYtļa\ey@yuTĦu9R' S$>+ճm֡՜>|Ju{| Es8>ɶivq b 7jdYGg~V4`"_3X^{GU%4/@jLs[;!vEJ%iaN,)[qcWGyCѹF"\nϜbz]lYK[u`,`@/!) γ a4ƅ{J0[6#OYQ%:q,;ʰgI2 F;x4oDяFK1Ԋƻ&z 7/ Ow #Uvd?C"b?tPP윲e)MŠGꆳ䯬/&MEd7At>Vş"e>&iǦ(Oe5{oU>(2h-$hK]t߂su,lJnH.#P\=&+DMq>HX3aaSyvP@7w=Q:>e82C?qXkh 'R u~>  zd3"X8Ώu> jQv^ZhoơuZXa!_M7cЀYKB k*5 l Q~vsD@xV`48r:aSo@'QCDe =6prńB&SWL/1% D5~PZo }0[s+5۠&~TF3. '6˺{S1M>G1qg%hznjc8S.rD7Hh|[A{癀sTuf</`& so/"?h$J:DiĊT{._5nNz?nt\DlHۣP+i92;`0懠/cٗFuJŴ$Sw@w1]W7iH6bj]f~1~Ý:Ê !>o@wj<;ď글r٨?1-*Rj$@;5"PGqV旫"f.h۞ḧ7bZI0S`JhL/YZ<B4PX.|řJ8( iN۱j{{ F" 06T7A.w竐 VZ!&xczÎNs7tZDhkoS΍MBΤ{P^IY *e+'mQs$Bé,M 6#V_n`)b}QKBjIaJ< vf$:T[vYiF":o<3T(JV[iSP끏vf ~(Q %f,8' 6ε|"3J1ilP*]pJwNƪ7R5s)/0&{qg>0fX v1_$Ԝ- +oWcMg@kۿQ%.+b6.m!%A6ȴNr{*c֙t QIN ^`X]I$7D~M';<L.SS3mn زboSGՓy07o pg.AnK#B  S!MV..yD3!_%|:^LG>{9@Mj&/rgqy>* 4$-:Bqm憩]s ]w-e򧩇v279C _CоJgМ65ABFqs:2zRPT/0qqu3jh^AuDž3H>'=m'AݠC" 3<@=rs^ ^ͅ6{F뒬r<4繴Nl5+aKA>la͞bcdR ݸߤ,#P?`{ ෦LN+U\g?#}D 4s!<ij%1$ݍi"Y̫.+:%lO9f, lkDjX<7Ez:N ͟pK9t7k#u)DthIl{SEI- f&kp )k3mu܌?O/J XxΉJ|9ǃ(noKӿ%WKH&?%GI,Xj/fK8|!sEh?4Rx<`K&C,O4)*jw..mfi.= }I^oq1OHc IDvL?`Ye 㝶mT30$zŸd(jbU 3nDX >L *hnx.Hz_s)psNlE\2R)fI O|[)݀=vS6M}Z 8McG#?k7?0. i=h:]Tli Vѣ},7 BTbI`ٌ鄚!Zvin{alz)䟹ۿQlH:ƇwwN: WS?ߣ^.;/ ņ_RMkff5wdbů).#V󋖥4ۜZ!Ӧ/]EGj19KM zGyeFid";a]қlƱR/]zU塘8XԼ&hfQ+ֹ{Ml$Acڣ3B&ħ{L5"+#@GZ ?))!=qfm, 5m|GirDLVSƋ.POs9x\| y0"%c;rX/R[Lce68)}'h A!;ň.  ,+upn|O 9zVE}}&x4 r) B֬pe ݛ䦫Bq#lT`<$j VB>)ȟIұWs=$V %1̖u,{в>(;:ε|\Z(#z(V[y`3@wi؅iw8՘ º1?Rx:tY:mv vzַT"OMJ9X\h ]igmm$ND1GM)jK+9S!n$MhM3p xn;%.2\)ț#@RsP\ƽQo6wMw"a=>S9f@3\lIuĪwAOQ@"yo}zfRsY'b1x#r0 g/4d//. ǥQ7!c GG4E$!S9ݨ$!\N he3U)A9X8c YշK63^*"6eR|Os~8"Xp:ꟺ)*1Wza0OJKX?A=\ ]virg'>q2{:B[VE98IHҏ9qYFH#ԇ%V@olzFM{?4GvLj/[BmXP} -JA` P/ |g3~`q TLӋMmSpH+)X Rfr7s\xNC(cW9Gvn3j>+aP= 2/!Ÿ$*gu/$zn{\0s_:seO 6*VTmZ҂g96^*AUyMEiNJiWH||aաp{0>KTϨˌPH7 3|ndF~o)͵>fYPo>t; :ǩ#_ߊ7_l :ŀ`kp.J ۴$坬PjT$d6?i܄DƷ*M r,fFp_tRΤ1xYҤ0t]׏Px@>gF. .$բjruNw{I$˔ 4<IHݦځ?(Nb|mk6$)8k94+Y.¨ LX~ O@钧.t: 2#^e;'jm<;98,!݀orh*>x޷u2qG8sUyqBCp^qnyh3^Lm`#n֓(REMz6ޖkB'2Ԇ.ܮc3DA{[݄(?EAO=dA - kNHܺdyKsixfYìRwqثQdm Tˉ g^B1WY;%qT^]ͥ,7r`&hmJVB,p$%73&U+gGv7lb'o!).<Eق} ,@-=@eSnrOdHA EV#BM aQ;[䀆deq@nI*1Qwm0bczé ()r2 J3E|ˏ>Ĉ]KܴTz 8e=PIdV.bȕ ZF+7)o8uVVԺE'VTGJ%i[ool.%^R! lJrT"3â`#겨E6RU_]& W<&U/ ğ<>%fk[͊Z.3:HZ@6ylu7PUrbPP$}Bm(ȜoWϔbj.ODE] iQ _8PM_,,Ûa`o#QxI_&<5onlEǰh8~GnʅXHG35I rUgLySxp'#iaa)FXk0f<>ߙrƸ`ʷ>o7mSa@;,agid?J V J܊]D^#o:8H^wN\29 :]L0z.>srBH*6Oksg*S*L5fӭBZqJ߰8^AoB2ejjpW m~Z01]|:=|{^B `0aH=ɛ Ȩh`+b.5YEjNgi&ވ Gd+W.V/G%p>n7: є */2=-Dj7:QGƒ/d+=l]qٞQi41H@hlbg f[~S'wy-c}]E [dCGFwL3>@ “nEwD4D^Li ɫ64Х3ysT}YʗG޸a幊Hy4AN97r8WsbBo{'mp"nak2؍~v&!)0[db}XqEQ ngوx;j/Eu@ofV,U0f}B\YӊS]ݕODE7;ܹ,HC<Dg4FԶDk2/f/tlϳ\ÝWx쮭L}֘ØQ? {Ǚ* P!EJ@9M7L:qEhm-b*ˆ;8jɀ#T1K$[Zܸ6,Mim0 *'xQr(SGwLghp%lc-B{Ӵ%y0u@ݲLBRAmyJ}G45{q(p_S۳YN]} z+גR̾l춾%[z{[kqɻP!*G!Dw믣+| )v %E1YHLSZץ$+L <&R=K0+362mߖ43'-_WtLF[]*xͺiΪ nڹ: m EXݗ!\F1L"W|WayPhШ^?oX}Z< Uf+v}>)ˉL74[~Gk}ph\M"yzEjA@ޗl(F{K/vpy`^L:4.j"<uC boZ%u6sO0r+wGbxl"FNzœmYF,'WEId.f#^ghp?a*uQ|@O7_|ZDt="s"! ٨0>wtۺ&5 33Qs*QMg$NrTn C"e*kRH,Chh?DKKؿ{lpCM=/ )?Xb,B/;Gf ̇߯ ~"\rxUN:sv<'^st, %|uҍYB Sqe%!8t17k*! l::u9 $/P@MxxYt$ ׌c,T_텵fj/)rD: !AvѱI=3cR3X`N1M4MO*6Wu\?VF/Bɰ衝wWFil]ņGAquhJX;Rk^Ifv xq~P{iz'&N:6D!h]u7L(b@[X>­̾m#DX8Ɍug}T?GµAHb5e;߇ˉ|fOvL!SD@?ob`96$WdPD hEB˧c(41xsP|zQ%sScw#EW`Q#TC |[d!@,S+(#*}pYJZV^@,rۏ (j[E!,_IMaK  m0xZcTE" [s/5Zc ՉU'1ˍV ,+X8K֜j &md("gH6a: MIpPe=`mRR_4:yJVE?)rwu@r֎E]d }zl\^ kt2uzFNoFG+Eb)%7uAoQNvlײ|MGt;UFla3Է>;j{le3}TjXN:=5ϨIB)p;76V~^ƹEF/uyۤ?G)zrz:֍u_2fo{|p`j  ; äpJ:Tg'V Ӑ,sw/ Pf * 鄛1J&#]&6= D.b*t?ȃ<2_~7[yJ^n}Θ,/q;8s" bXvGA\7g-{7mn|73^F!˸iS12#w7[0_V ֡"J7G@S'@"TxQg U=U]a\li.1^l41Z1ԳtWܹnf7Hx^%/^=*IK~-+ tY]4FeLxhtS"@oy"Đr$ '5"]w鹨s_oc1oR[*5y1, ƽ_}0LӵGc9kw`iT`e HU=lz\ѯslLױޖq8S %i;Hu{)DxvJ}A7o_A @O@Cw~5P=śߙ7 4殐V2lg\[-u() eV ,Q&F ]jW{U܇0ڲPeĺ5:߁C :'j2}'jݩ %%끝s*s,yL4aN]!‹{Lkg:,Wc!ԥ9fMP-xM6lF;uI]J9O6 G14i?pbR_fw)ʂMn\#C`BAH(Yk7jdk0!bJs}C4ݻ>ak o KvIuUc&/ݛIqRv4yԩ57Ҝur`(o5ÀIEO+/X2 Hv+?9f/^[㬴=߃8[8Ǽ AiA۹9#;v,RֱgP@&I$ۿ;P@tGa\OF$eoETG];R*7<vMI\8O} F@DMkv<؁f ֵy?AP/&62CxV7" Y =[#7Cyn P~QDċIr9)EVmjtHḰؓ>",SX{G~nRp-MAyqݍ? Ou_MQt7uYXvjPnsCTsޭȕ0sVв[I? ͜.7B 侖~@|f973FzTU Ԫ5 H/:O3W8bI3VfX DJ:EJy4,@_OEǒ@ O5ֽsz\D$4Z?UF^Q>$jf\m*_9.s;r%z+d!\ b a2][_ԔZPuP&K;K߫]YB 琰Aҽ&I*%'2&[c,Uu=X~jCGs9J,JL+A. 6VNxc)RKyеwIA\Y+(H!3}7+CrԻBdqjoPGEC!D3f;տL|,ԚSE# fnEGSU]oP\ a a8%bTSJ ʲA )N&*Nf'c烲=\ƈA UNXTk^9_p-$Iۭ8o N\<{e!wV ܢcjpѓRS-a ?`m84W wԖ> 9<@Nsxe^0pO, V /΂.,j6RıKm "dћ:Xn)62uY4njfIutt45^XjU{ŏmOy,;aFPoVY} Xq j :-o;)+Q@GC'J!'?hylŮ9ʐ06D o:h"D,mۤHBT;.I{qIr#3*YS̳) VJzWb[ssU{0/y"TJlJ-Zsc[g.ƪԘEֽo_m:_3 uIp׭!YcoWԏ)quDk؛5U}9>,O₺+}S4N޼]e<-Za?c!> y'=+Gx-"r<*}|}PJ`.;wYJV`b踗f:Y]2Hׄhc8DQlT5 \eíe^J?jEwKQ\3T0iYm<.HJQ13blGv*?Bq7c=)kQ,R g@oU% @[NrT1S.1 5ڥ徥#S;p߆oG>qU@>iՋM˽w2%,ݽcgXb}XQ5( ֨Ahυ}5ցW[M>>l΃Kp ѳ2*+ТN4H%Af:ԅٖpK/KRٱe?$5m;MhvIOJV]0L%k|>lB} Tߵ c2P=J>.PfhmlDK9Ěx>NލGAC P9w]])]ǷV5""c/Cd'*9h@HJPKu幦-*;8[f.rs-gJa KF H֐},,=&i1QnGG54pZc9+ԨELUn.sS)ݻI5eрF`n}1YyzqUq^OAWK']P  N`#X~iɕ߈^B(eTJP|UiU, =7qVZ Z1Ξo}5Al("ʑH ԄCow@Ur™g[B.m#A߻l:9PޱS7ghIA#s!5:r'sQ> =Ō8ƧfՑ,]PNncBhLj} FIxO G`$.TǫqDX_ԡ1VmT|{U6ΪHKᇽ/ꢬWC&EV?pךO(mzg`@̓1ܾeue.yWn;zu?ɛ)hsU_W{5:Z>;K &jTK _;"hW EK( $DֵMZܜ߯֏1c^aK9 LX#;IԵr+.9 e G[c0E<`=\B\a6sUb4=Eb &磳_o3o% 5iH*2n=TIOU5Sh>jAs* n4 o*w5آ+`KB: [l8Eד4JkO hiؘKF3q :H>g{But6;"{:)**xxBwj݂!oqvqm,+)Hq0:yu *O H mYd3F#bC_ Y!qbwK]q=@&Bs紀k08w6ғ5r[|c6 ЪR}p<Ar;"w<4OSw-c0hnYZWr1.5NV'f:/BP"}nP4%ιpqZQmh/{96Q7ݘQʯA-Q9q|a(dh@=1?@PIhftEǍm:%C{cGVnю6eHu^D04K M6TX'y`gw6!tz4eofĝ z/|0ߤ/ ]Ii(Y5[ euLǚp!&fn oVd?KyCc N{ْX_ τ8q ܝ="& u1! AlP)u2'SU0R+ <vTSI>rw0B_BaPX2,kDЕYЅ,wfݨNAo3Q|Tq˘wYGt^4DũOU&ZrD~w2^'1n88KLtqDIGE{SK[*cn3S]'AOwTl,aBι<,Tb7TqEPy꼦@}S /z|mQIK$LOP w (y j37)K 4SѪe(ʡTU=%15?xcq+sx+C+OEQ15E0~d^4*3B.)fBt3V/Gnd\Ul̅ &qay5Jm +- 7nLJ{y8վ{7Q!plne?#v3_P@ZicuxwR/pC;7* 2(17A{XÓn) S2ITPj1Kf|h1OPϻ!* r"6gQȧ0k繲p i qiN;0LC>>F/.߹+F r~5šI& +n0v֌4INbD}!YK`p|NͅKs`κ=˥ #nM19e[1k^j 1ԝWTb\ NP{ =2&z]O[XzD5 kKgX2U0o]`?Y:Jt3ۉYبť+K4 ;6!ʔ9ʢs`RV0~>&Mra盪srϼ-v Ǝd,_; >?fx[%_ʥg45BvHAr :FJ$=x jlDb-Ӱjrt39 6O\1P 3) kC1} yp9  qMP U=?X_1_`zMIGX5m@ cxUh\^ٓMпzoJ:_dW>s/Ij5P 8|{'+&AB`!e@4 mw V$?G3v |:OkQCoT5l` 893JrJl2֊<~n>7!z+OQP^F)?<$(bQVE Ta  `[1ol]`4@榽I|2ӆ汼㐼n|y=t8d#_ znWR&zؾg~zhRzs;Y vBT#TH/;SZG&~}lF=.lu1I뼰i KGgc$׷$`jB4Aq'hoܽ&c?\_Ռo˱y.-*/dF M4k4["ujX'^4 =>2 Ʋ\B <0^i[=RT+O4΂k2_eȊe=7<jw=92)8XOQŞԄI0逈j-{:9i9w '~+_e{r|$"Y$Q՘{]!:Zv á't-eNqoU Lu8Xx擥k1Zl_ ?'uݷ;!:N *M:Cھ2DU6XY=>q}eL!M,+ЙvJJ޳c=cH+~˸&Hm uɀ`?!gf{۪W\&몐(mJeR:_'=\˜"h%P^')ve8Kjt!jRCko"_!ҋ{l8*8)e G6;2V-\j{;r#34C >+#C_]3B$,AP긣J!KRAD2Q13UW1ѣgL CZl $S}zSqAKG"Ų dvdWk1D< SK/SEEᕶc?|Cv-Mu p?̂~=.-=X"Ӂ=Pa99-dn(+^1}%A7R4v?8{g JN)C#ym֭|14er!i٪)0mO}]&;y Luxg+e r&Hn/!.څJhp2A`\v3̖7riNcFaso}|}I&2ߍu o|RK,SĐs189q1Hja>8=$ɟ+tKGa-d̪^/EVQpfvzܓEon^/~ȸd_@ ̑ʦJ}_vzq$RxNޑ~Ȟ_Z`yfZd,ݥ^tZl)>M^ 4A04SS#fp`m΁\ $GFOh槻̝J_qJ%^YqkY5 J[bva&S‚Y@J%o%j,&"q0|18`d;\vLA G Z >DR.=G¿S+Je-0ޯ?Sbjڒӿ4(̙ckn> .Bq`EbTKrEДc,io("bɄI-fgSgauZETe4̳7IHKkFn-B9]Uyw5GYON@vε3(ǖގɕӎsP*T i^a89z ;4nZvij7_@~wd9 O4ʍpl>Z ߚn̍[. 5 pAȸOggE(BDQic ЯhYZfr36͎?MXn >f^-āZ'FUw46 g4jp@|FPs;F*3#tQaYe-lSez{YlfA'>‘@Bp Im㶼6 Mi7y :Sܮ! O4v2y` *{^k>|\(AxHZ]uڑh~ǕmE4З֤ Y@)]/됆?vWmJఝ~ֆ|呉ndGzs -j^zw%q}h<w9 5)].or$3Vd @ÍMGsx& ljcȜROVL{/Չ#6\it޲S>0\T\3'!'B#'2*c1r C/yYH>/Qoc9R[}5q8ܕMߌӦ@*J>v-Q R 30Z|kڗ!cDPAQ8#Z&*exǟ%_!\zܚҘU$ ]vǨϯlBOs2 Z_{@F;5Z~y9 W1Ů4 aԸҕ|pID5u$+$6 *Ws^uuφf6t(Y;#SȽχj(=eT[,5+EĴS/l~c& .xL*%O 8ى,X VI@ò;{X0W6 3_6u᫿?p9r9g_R} Q ya<.f)Qgi{ ߬eFW"t>m֧EZ"ǣ u„4 `!E7uQHZ uRtLybk$-9? /$i*j= t- X dt[ԔRڻ{~ }%$j>|_6Kn,<ϛr:41 7\~D!^Oj8q̹~P=3P'LD%Hq,qErw>{zMJm_Lp{V`$ }6}b%9|w+>>[9$Yr\,S}f18;c˶cI6/u|x9C `ayi?2' ww+,YQ$u[,8Kݠ[d-'@Y m~>8p*p'$oD˙1j= 'OM[ {{'m7k2nj![L;k2 h̩p_% Nc~T\\K,>H|& K!UkmWo" o [eFiZ/qqp+9{0UYGudւ,唫/V''p<8FJFPV)Bf5M?Dܛ:+=R3< B3L͈3x~VB9K&@pn`w6Y`t+jDX2`vu } {2kԙ7,N{dDx/HjƈQ(*<уdN S uH>im~Gϥa(<2"d$6D1!׫\x4ҎNАS1G% ͂c{p6u(prTcǢ pc_nwaFOwxR@O)% =Gzm`dQף'y7?(xnM!1B®l,v#c+D!x3*6eU`9WxlV6qAw# B@bڦUr!.7.1:# 7q= Ӓ"#7/){Ox߽=Su}XHI,lCsj'NHPNyC]P##cwwM_++h69(3W nDTmϖֈPdB l_RAf02 uU$eҐs 84IQzcL=)V.}"Uҫ;zby _AVɣ)B$w5b3+jz(!L7u^7Kp<` 6H WՃ=-)A)I9P;Z2k maŁ8@'ԪV` 3eZ(:7L.P/iH'M):[ Jް_Qj]Ȗcpa[ւk^KnhxF}%=}^7c"gk~>(ā$YrV 5X)Go Dz>IYyrgO]3d@vIqdpK&$]WVұ8FzEj=ouuD+1++o2T}Ped~}{Z%+eI:BE]YΰBoHE. M5+7ml\cC# (2(+Tz͌ v{oqU' A ~k (ӘGDZ<$kLOzgT_ħ!ZYϽ:FjY1oT hPkP?.n{0:m ? DgpPΥjEn3vYKX灅ܼ="Q}E`S /L-Q?h]˳na$^GE뾄\J1v".<ڢ,$_4~ ɞDUm{Bh/C lFߘ) c>ט;?=B;v$-inj#&r2QrBY_MV| K$ X)A!ZIHһ>gm^єrrޙ&)J0 ,hM*`<"omaG\5nT׀T;+LXn7Qj@&%?ϛVrk?Ap7d.ϴ復J :JT;S H_?\!?.BkW/&|3:~E1Qu=Xtcݱس&wEp+FV9mٙwX܋Gu^v?X' 1TϐmWpx6;ɶl:b3YVZҋFbJR DC-cPGw29@lj{-'G6VS.﵏cgERhqb@'֋),ZR:O@f'/殠q  jCN=10ztXV89(=u4I!~F ǽE)~b{Bu?<j4<M!؉vH"4I:Cn֜"ap%]g174U88kjk)84bL! w΄,}= 37} !sů9|кwg:dC,xh!JpX/"uv!|rPSd|7` &v<;V*6YmJadҞ.2cS7X7##/')46k)~!@N1?: m[Y.|@<2P(2I1*?) 6RTL)tAcJ'wid^ ?^'h;;{[!&i3vRC]0_`vXY ~qbo|bEé띉ZȌ;J&nT0 DMyOk;C2:3 ]3-cI rSa8_6e޽Y#֘@?n2t)Sq[uN!hRl^(0̇a)vl1VbcLUG {Gi KY&r:٧!c厪%oӳb1VߗvJNKfmKf(ΰvYg7 <7ESjX ^w_eXz$r}MGs qkgeާTHq#IQ,Q6՚<-\\|ƹp[@cLITM`nk=83DѲ# H^CPK@4/s.K .`a8&ᅪa+@&-@iah$K>dbg$R!M ̓ΌW8MTq ;Wph{nq?*@-ouxtEa\THo׸Y,dS! )P4R ̤'8\6_tLmER1X< 8_[x-jS'/ ^XܓƮgB ZPɦ@|qOp%oajܙy@!p N`zGJ%K<=m*tpOL~0vS.˼)ZUԟ9'Zi\߮{D׸j" MR:ytoGWiBFJ .@EՎ3Lx6eJxzA$r̴"sƆ}J$!+kr+ y7=LQ 'v{b<0HWPSw9 ŚRFkL\~xߘ"">Z?ܘV1v㣾JPL u2j|,+)5! NxwtdoC bxarw olS+FL]*jj2=#:$j(ӦAJ5Snaꁆ%K}]B)jLZPhKv., G@Q3ͬsyx*9Z5{Nr{]*1af$ .޻L9o̎RzCbvb?!|> 9c}~Q%QqP!gS8i8qbwX~Ε^n/HX–^:Gw$M1X$YY%<E &\]+M.9yr6>vNlF{aC ~Rbӯ6)2@dHj+2*=OL9|͖6P)YX߄LFnki~bnR=q\ hERw*zxppݘl"hL[DK߮<~oYEp%xjC& B˂Mw uqI>957|fH[14 ;ijo![,1?~ԉi d#{6>0Q<;G[|~0(ZQc'O~d)x{^7u)~\Qob &nyVMb.eK̃g l:Cst$%)HNP[3?kS)2Gh!e>QϏz<拨Cce?bڌ7v~[<ùwH dM>R_u ep,o|/uDu[E 0?*Z@y5aDKr& 24fۃ?W⫸J5<6.c*YA=Y SZ8ՇLT=g=r6@&}͵$qo(A%4Ve?` \R/;V풀 ,M h|dźq3&(E V>C'#y:. (=u]́rA7b@Rv4X4DO{]mOeaAtnޙ6RU!呫A6%)r"~檮^Եt{XtqڔP pYO7ཹtjֹ ;6VXpʍ/.hxgFiY^;ך~E ΰR+1#RmE%XWHv[oB3i@Q 4t ю7zy()+CN1L| Š;7`d'LDEI Os{47gwÇjY&}'681 ˧8xzAk)ó{-QR9X0 UN~qQ*o ǰ52{A(S6:ƨfE؎ԙp "+inM@hƛ5eμ_>l#/.~dJ'%0b^=c` \nrQdBX 0ǘbn AH6A76c?F iYX#\N,g2ID8gfJ&LM@߅Mt>7kvg ޭ)怦|}0I> ߴ;s<7jS6j60VW%T_G~\hzaK2)G >˪Ӂ+^xyg ",vb2.~-`  qkƕNK#vkHq5 ~qM7L?-|ɐЧZFQ@skVB z^}T7+T'"g{ʆNO+SMI);Q7?%&ve #'i~ꦋńM@ꥃf$SN#'52ay ;HbBGipZ֐-g#STq ]m&qэ%\@̆XAGW/`_nibE^r,'T~M/L ۿ)#Nϙ"}7 <QZ`{4[QcħBT^2͜O+P}˚Zȕ! #"ܪ f +8²Q(/T&)σKpB KL(ܔJ ^hAHTT~S_x)d԰]^<wv,"wgEz-n*T!9 Ƚ15KRr#7Bq[*%YlKŜpf=SpId9޼sGxd8t!hߣ@r$9$PE@,y-[U6.F8 dπr;mw|ȌoaҲིƠQ~(9SڭѦU}>Mr/)p0('D,0F"R#6WK@Rg+5/T׿57ܚdUMb|7C!vLA )Ud)T-OP`H#Ox=IϔG2N:u| "[G)>Z=gF̩r0{ /}m)ӤE/խF9xa{R: NjXY8~ҵ=Լ.Bo|p\. - gewcDBTZieͤ&t$eAEc\5/lu- k`{Q-\͙{. jݔ[> LTp2} 죇1GL>2u~_Xa~(LtF~a,R *;넷}ln*fpŘK'һRKkB9jjss96p6b5~>RL@ޞljoӭ(j'oNS>IXI gL@mP{y`LkؒKR_sG0SŊb H(M-@vZz>^pbQyY6%ԏ|ʙb=X}\l8߄n<ڼ¼͕W X=@ .5jL+ݹ$U\jQA#Qd 0b$_gC3Qi"Mo(uc9Zȸ4@_:Z.9 09۔Q'b̾GJJf*j<InIwxWyDGĉ ˩vOe>QA4O1Wu'Q"1(p-&oXoJ:yl +7Tߔ]hGmJV9l\J4 8~T>nUX,{Nzx|}ŀcm{|[,s3% jz@a4T Xj f)!5Scbva5F~7yz$yI[, *v4K&yVz][T{zC:nW؃:&q0~@01o>.;//!P\\˖ sLFF%Rq=[U(0% #Q%=cVq{{@4iRyͥ)*]) vO\,sd%ѓYDkѼkitOc^o+V續-F!ej& 6rn^X+jΒ].쇖IOt3z,dH0>"Lg|4$?!CF>z+A^n%[:CvD4qI}}Tֽ9/-WJ8|DBu7z(5)'T);tz/0}&r&xl^ʄ7t84*MZ0a%k;s r?dH6>Jj4ZgZo۴,.e~!Saڷ^A,ΚZd;l3l^'X徛۟|ED@c:i=e̯R/)?,.D7ǭ';| DQŎVhZbcE'<#@39R1ˀ1M^ӄO:h1g^Cwן79;oM6$DҲa#_S\,*ݼk ˵9B^mn܃)E>-l=yMzX^=X ;x*jlRdpv{Ly㶛)O2+>B0-XtRuo-3Ov%_+.t{67s%9yq (qqJOVλ6ݸӳd'͠wf)f9_I8?g5٨WkwVVh}Ioߗbzjw Kad =M^)6uo[;EgͶ3<]#@Cu4dilRÆ,{T $fʌ&IG)o Cy@⌊Ky&N#{p/2/V\ۢ0 |I(]S0d zX렄VG=?Yc2&zIJug&Dz:kA 9pʶcJrHlJ:X47>\9Iz:W`b!C[mBVUF?/?k5iaDoWEK $ܗY')mj昗 h) )_":8C'|Qȃ̅jV ϐA73Besi Q8hOJSˋ)P}}cIgv˘HT=AjbEHau[n L F' :DB? BCx@\;v?Z? {|9)>ڠSI!˰Nl,BWƖ9aG ?& `IaF̝_,{ٱDZk"[=Lz9IMKIOwF}ؾ"SU9ȤɃ0ܒȖi^6՞X6scs:?VGD"?Oy g2!-"Q}ry^!"Ko,M>< ??<>XIe^c }T0'S~n^;~eM~{x )|!6<&?i@,s( ?sJ^%Cw@NW!h=.7Zl⛥ zM<׀8f#-tkzxRb>Ka-jHcIAKqED7/\H61gEuLz(M/Ҩk]FgQݡ1V6?'"_՚› Wzp6D$sUɌvIl?ڐ 7)ۤ_sO1T<"79I Ǿw&xL@Qm!w)F_z¡)gU\8sN3W!5{\&Sn0u Nˎ;+]D#K ExakU*9i#ܥP7*Romծeב Bq ,bUyjC{sdga(u8S ce4PmLT&I]B/"riS`\:ߒ[-+fN.ajZ(y9Ğb׎ Ǻ,\Ј;Q *e2)[)=cv$Jߘ^Ծ%/"RyK1:@8UHсλNЍ"|ˆ15b$%$|3l Tab_XekحbFL~NQ)o˭A Sp=Lcfr:{H4+G[s,Cs"~풲@v.ZpVt$+,`mՎ*hfFzaV‰W>nT4x9@D;^hR YOcc7][H k$\rQH÷7De;ژ@xGgS&q5 @lOڕ1GieZDTק[9s"! #;$x\ǎo*RP>E9KN s<ؐT_ +ri6lU>eC>2TM>SLo=$K0'%iߚ[ƽ>t fx G;0qXyeuXUUA ;BQfqwc|+A0l~  ]:d,?'uنuKnk: qlo'H,WpfrjQ;낀ੱlQ|{'t}zs-j/u&ա7_2F%|:wѴQ!,xe$2 l@NF2MAksފCK˼8/^`@u]?aɳTU`#FdnNxvoHR3lJL:Fd6E'p9kԚe^aY4/Xl7\T@i<ѥA`\bj$Q,Gnl`cࡽėfK] I >Pv #.{-s)2/9vc+b uPc -UƎ`/|+6A4ߒ>`ܒkBr8ig&,,uc*H˂#W+z:-旗Mxŋ^/:ǁ@  .`w;ERaR?ÆSn+6^m:o>P> j x-`§6Yc({ȎaL񓛨KpPWqЎrN#sZыӠ|>9wF ةjyG;R ͌SQ*O\+G!ĸRN9`SQMa0G'Zc/OgXS]~Ld຺:\)|='1Hew_, Jb3ϲ!:*oMOmo!bYaSw>IJSP|VWlM ouїcd+_T+`x^ZTn m* q1q|O2տ4^]Hfc\5Zf57O5=aFV͎z{xq}ti^ :еݧJVr#kS?KM(nהLLڎ uMt/,8168 iBr{T3dP-r8U%[ECM9hqvT7'(;䈌}nR8>ДNGK"?ۉI\ʹv,7c)?3*8WraH3]ٶ{(k'֑2Ukw?5hM"⢇.]%0̐n`+PViy"3E?I^J]M}YG[SzA (tQ'eYDߖK<{>F<>P0cg|ok(SxБ#Rs*й葍WZUa^A^ia!$Wf4k7-EКO HGY FڞձÏuM jCkrx"Ậ5 瑒T3hQmeRc݇ވ U3Lρi655ŷE2K}oXv?Kq}X4nJ3\Bf9mzAqI Z"==9EqB!CV <g #<ǒETu4*>9?:㜌, =OS{fb\#ͯe1>Mweh;< V6 o~B  ۛvO Lx8̺A:zQ{/ /\v0p_N{_말y*yD7{ݒ3I$@i㱇i<6RWJV1SYS0c5 Gf.%~=D~_fkK^:Vꛁ¶[ikFuVQ~2.aiMi=њ־SKm,R&*>r2SLK[xa.f%Ag,*\jVD}L3t>5/6LXh3Ie!%]޹ lLRsdL](` 9nj/ |[Ex^zĄ:=$yxXVźȳ286#<mzΚ)y 1Ո9]\XP?tn47@K~'V fS/#1\ľ;Քoxُ]E*5t^!%AkFIث؀vtDZ$l{d&dOla@fљ@}ePj^"1'1|19w= UI;}LP}yH#6d2L0*bm18ހO>>8)艄y_K)Ž  Ձ~RK$@BH!AYB@겥Ar8tpA ‹ōu>e pˢ(lάc#\vӓN ΅{OTo@ϟт󕺭& 4T0 7׆D#"Y$˒mZ)R#+XfI;f_'j $ -=oE0}Wqscc֒ZoouB"kXw,rBϠ-O./Z {|,GS=!٭l\yYLe* B _32CS#cazDe^RJr%t$2D92aMڤ~0c;- ^9%st z ** a`;(4RMp:Keh4e zTs44qB/eҿDPJh={:# xq'3 kSLΓ*1mZ8!3 ώR_eoY'Fr&E4zM^{ѿ&dFo) AuUnN3$tvMi١ Hl'.\>[w{SĥL]k+MH(h" e;Ϲe* HirhK>6r{B̉1S)]kBZLB&kڧRJZK]ֳ>- ~]^JkDfPYm;v |cWtA/ [yG'KLip2V&%7B r]FGY$H J+\}rzňwJZ75i:` "ѐ}?s<-C߳b]v}w~gA_u89pA,nX3D_kU;}!'2StEC`1H1xvNU@o/θ=,@" v ;C QєPfHTR! w%ҰPnWVENXdm  *<h:4Z|rEhgԫgbx:onsj F׀X<_nTި:we-Ů1*%vx2uAe&sùi~,^B9޾mQYGe$n;.%tŕ {io.ѩ}¼,vf%D_,@C&uO債ʨTe+:'Olȼ jHC8{$UFH-S[i&Ԙ W8Ķ;FZm޷텔uiXx-u`!rxÅ ߳ P4Ivo :~Z'ReDHWw|bz`1 NIQsxeQj; C'2`!|D^#,~4]ZFC-AyI[p :830E1V᠓miEKXĆieA(6"SYZ `re:kxHܘeIp^P_o$(?OzPmLV)kHM9'B*_ň=j v%?8OlQ;׬XgЊ8#nA]4:2ʹh`5`Jr\w쁵|Zq6cw vLP dM]*.MK{0uxhZ0"4܀jGd0 1m7rHY &w.g^hsďe]j)X^fkq[, WdYu 8~TgJ%pV_hi0g)Ch: )g+k4'x[;t.Kp".*oN–`X!QjYG 籔/!KŤN ׋Ҷ~m 1KQY^Fa*JpI\/9K72n'*Ԣ ӹ.7do_B͢ѝ>Rq&֊ {-DX?4ŜLp5,W%K5lR@ [i1J?lG+|b&HZd_ IgÑAH ~댱>\MmמmRSgHT{S}xE,%Z"aTpfwXpH%B 2;LA;d0#lSF-bs;GzǨ|m0J 9QrC׃OWEZ+# I 縚Mc[>F /5 7wqZ,1:!e:FS8F.eLGTE2*_cJ#)6b@ju@֞KN\+H)Gk$'ekcm~T"ӯ-?=0owRgK0ga~,DmP.pZǑε|^Wgyh=Kt$'\/4--TO}= 3d7Ѐ_^#:4BM ?C#+v@ꩣ;(X>:Omظ1Rvp5ηzbղvQjs=\8iDt/Ye xs+[YE]^?\[`Y-Ľ:+@r靥53Q7=)ou \~EuZ̻;1[J%~*7lc-,1W!NHuѭ;^>'fd]]>?ڈqX,tXԔߑ!E*blLאlP| GԲ4?  >XC$jܢޖ]~=52G,2'[ 5,7rWx|!x t<40(`) r̔^ X IV I,&ɱ67z|!yEj<ƣWʷ,نD <4-£/a7v-- xZKy2[猔k )P?ps6it`KY/,τHE-_*|jSCY.Г^ڀC wx߶5ApO{_=YUFb x_Ri8 9GKz:}<[jK<ʩΤċ = i BB#IN򔷈sZǘ }Q=I^žʒ%")Weς1`Hrn0ሗ˫Ssi#vWƿ6Z _gܖS9OEIZed?ms0; ׺~G#t>&/4u+e5X2LѨJVe#ݓarpX~o%n-grY G>s ,>\)) <ʑ6Et[W#颾ѿcTw 2S6]JɫRNX:o%Z,ruuLa 8C-J|(w?4.1Ʃz3(@bZD ,!=׹raw@q$[OJ3ۻPܒc>H*OpkN lg'# ±]GX ߞL=BA}׾}&_a]»xao̸vZjhsRnVXѴ`^OY@7p'tSsWэ}Y!06?{ er$lr`,ܑvxم@?!q|vҔd֛|m*9nӧ@,y,c }Si {ШT{X~9uw6m 3V/]*}ʈhͯƊ{_&4a"@acN̠Do-ԡװI]6_\{mxT% } u̶BLԾX g204x_F,DP4Y`O$s& P *+0oX8:GCxڻDeo!W Oh0% j.f#1tP1$BKx]^؜ 9PVл1MJ,ey/M;Xw.o1YDeGpWOA0 &)\8֠`h_wq Y(9i8M̮/K- R9ż&NkZ'Eû YR|yINu{CS6X(X]]:,3uW *c~ֽvQ"E o es5xW!]iQts$so~szbMDr1}g|ax)̍LmcX_uW$`:QŢߓ׊[AV`Tr'*M3o=Ӣ(A,?b2#zM<`Q,QsI|K݈ԉ$ x:"$E` uoxaf]ҽOOŗR@\!NsYзH)f7z\WǷd;faQ'km̖3韘$?SLST捲h9J\ EFZXZ9q3 0͡]p=f78z;CHx0 XR3di,H@m˥,;SvB &'#y ZٲIJn`ݗxL|{̈́ШX5f(lފ?nOVUX.x e>zu }h .:!726|VnLJĸOMWƱ k"o%}Əv4/IN&'YȮDVҳ߹u L7,EC ;i^ tN.|0-]آ 囲ioO%u{'kM+^Jª/mBwb/ʹcpY+2 'W7=Pk"y9:6 _óNFM4h.#x\ī%>pֱ J~^O(ɘP!?6N+f3Y7%6- xMbV#=i .\佥|"&Y_.^:Ybog_WXk h7/@~(Bƨ҅gܠ6Hצ#\prԜ7W'2nRW$GMn>2Y3GN0F$#dQ Ol~R\L/)F_ɾL w )u{VWȜ@7):3*a)pbٸd>>XÛ=oX4OEwlnoWBѳ=3]ň `[,m ӁB7eNH0;ἂXH)2[#NQO0Ge]Vn'5pdf okl85||'SF;wr?I65CZ^*7qx*iRmvp .a994݂ӝ3Ȏy?#ib\wA5 uPNK;_x"0f}n)A`&X~^QQރ_;. [!q,u}+Kހuqx<~NOl 4ɖ[1;1_R]oz1deE>Jw2)*. ۋ?߻}֌`ILN!o^h KB2b֠L WFru˓,'9bo J,ϑz^(+UYnoM8I-Y0',|pZ<ɖo)!y{j5r+Mf8Wmo'NgjyAsaJ5( ,mz]>+`Li,}j܁mA6'HrL>1DZcJXaL,6qOc)[(8E5q4醴{ .=ޖL-((פ>a /ݶ藵ThUis(6~6?ZPIɿ0Ś=c阴!AryDe;L_*㬍up,+SE*1ced$6^]{yw}^z(,j]£É暞-1V:f?ok?I} K"SdIEb@_}ob9F&7©-fO?YpU>*B(䡷GsZnZ4~}|7JD$Lq#xwݤ( fȖP|u W} yaD7_Y1{Yh©OF&D(cBh?`t߁pL˓+iډ]xd&m1>B~5kTzap L*U-smuVf@(;Sgh1$bk{VS Ȃe.MT1<%)`sS"%ۑ>l'SYhu`Wߚ DDwq8*ŹQ]8\ ([X+[4L2(kv(?vBx jJ< 53g!H4;>&c0u3B윏ܝhMy&~'i!^'1wN]À3ҌOې3ť'RUŵR):$@wꚾ,&EqG.zc9#ǝw27Y#='<\3?hqKq/PQ[0#*fRґvkO&N;a\U:Ī#`NT*(v156wuWׂ[9S}BSwpΦ`*.ÙEFo lΘE$[PЩ8&o|F6 É%IQ[ q1k -lUmsQUϱg0M0]+YNЙOTSVHvwzeK<1<5$SvG$),䝞$uv BդOR3ˈ-CA^M1R?TzZBjdQ*{%IEiH]p&V%oXV|V. ~i"F+D5E-pm*z.^Ia1e)RFhA dRp!Q]-v}fPy7=Pk{ Y@!f8fJ76IԴql7hvP%몋 P08`Gn= x"DSӬ [ue8Pœ9Ç>c1ǜJ孕||*^&ưph΋us=4 QF)v};WYI^-* ~Q~2RXD𐺍uI(=3& 9$C[0]f.BtU5hQ L IA ŀ1%z .#uq|WLј;OM5?*ܘBz߷:mEšeCڅ Y2$p; Jڸ*h0%l>_Lԙ8{$U@d(¨<ɐ`ōII&ei+@r<(SW2Xkhft4G6" G1}7`fxc~EYٳ1C{} zi,,RgUCZi(2%4r_G>ٖ A5T[V,Lf % be" xA#mf-errL'ײs]Y&i|H"B]`2E;pGy ngK`JS% Qw)G&״m4ە`Y~>]o#ͯ w-]Wz_W %ڎ4]ԧsrɯ(<9N?*^~j._kd^[[m&lߩ"k\:Iw"$q59l QP/ =–D#z]Okkm9\1H p9y"^>{gm׍>:im3zpgxKϸPf;}2̭k_9OrС-R0&4d@>e>oP'X,Q jOW^==O3:+:PeZ+h*<ߨe"n!qk5)o!_oGļB~7?2BG}9$Kۣ'l`JЮ'h`9oH=1tA~!zg̵tW`i7Kgcַ#zG%6x?aBE-_EIPa2TS9Yl󺒻// ڢv$گ\6TI3o#竊 DE|?Xo߯_mN ;j:HU`+*0*16 vמrsT_d~9[2~uo솶n;&|lመqᚊ`lHYϷqxZZjjG`wPgjuVXPԀ4v/֕Axw/|gqGoBSۉfze[4{np /rh<7TWS XfҔ}Zfj:>Y⭷SV"IHẑRaCB~3D˷K:HH_omOv.+5j6'LD& '3'4w.Ėcc\p@j_%Z%%&=ݞ~Q4s eWyxYk3X{ {4yɪhy>X9 1Pc#/Fj;;I zS+Y*BltNpger~Qk5Ԏ% M2r@|3D;1Y4}ᥘَQZMFːOsM1Yg l'h`2hglmjFC2 FZgeͨg+[7Q<~ĢK A!6Ed*-gW!8B$>=Su JđTmR7"N{X ų<ɽ9 M=z2"(z| z}g0y.&V}hG 0#o=.e9"mWc#=7H@fKɄjpY? wߞ1*z_{~ ` +2#xσuSOx>EE^{+^,I둔Y2BDa?a9V#'r.?iH`TI-j bK.̚H7FT7UJQR{xA!{¿-c-v,5B5L5H '$c\ySK]Io>Y֚btyKk{| [%<)6Dydx.2:`t zbG/z GٴpUKUuT<]4G 8U>mytmΑV;jvTI?_GD3u!nǦf_6%)`>0 ;E1ͅB,| j⇳+63 r,Q=W81{7 bw#wȞxX뉼 OgqVFJw/KE>|?DFeQb ܐ!wLEyzOv/Ұ']ϼ#\.ʧPA{:=N-G44;ĬDd)GhsƲ[4i>ۿ&i2-h"jmmj~>M)iY[}$um%^D'{7:v=l1rq'Lb|X)޾'k9%{p&_oCgЀehV @,9oaK0TC&<m252|4)Dqy]t6-)N*.\uEP;H?(膟&%43YL?aYA-Ɗs6LWcʬ|3~[U= NrW@τ|n8;?ۆR}>[ԉƑ5)7?9F{]m &Cӽu(vЗ"A89n<ҁP\ͱ ,%`;wT |GHd\R%G? *@Ea|yBQCrP,G0+q*XnlVGG+0U}޴E~ X+^>~M 策AsL"{[MJ+LiRW_A*1. Iԇf# DP)X/gyvcf;w%|}̔MLTBo\5 .`v Kp2iEvs{Q:1pk4s/i-FOI 8L0n<F!C|Ln S;t!諒R(_I1EǣX]|0C.L4ci(5IN^/B؄WsbFIs@Fb{Q~㩫̪,Uf.yP)rŗ jEA4.oNXU):3.5 ʉ6(PI?Ѩ@D쭢[>lj_äwR㱴06)Ȫ SEz Stg^˄omء(\Kד0x~v;.Z !*_$'ڨ51ڲYO5Wss\t%fg اC:HIH=LnK&gK'u 6{C-w!_G9Gx V] hZGi<%Y[Ҟ:qO |SKl!ρ{M__I!=bE*t@㠘XM tThY{aeV}F WGF bn .fyƸ$'7c0puVn%WV$Ha_WL=q[sd[CM~& ?ͽsI= F͋ W Lv*+P*)}|ݚ#]il(7 Jժ{Zj'F$t E\只17yJQxңļVt~VH5 i5 h)N :"c$_88+2O /FSMfIfv 9!|Ȭ0;Ko֗ϛ2FGԴ~iAoQ]OQ(M_/GX$cl$X 6bd,FD: ݈5=Q6_Ua9nB5#pNfB-jH9S߽5Dl"lEHMGh,\37h8>RI9^><8W?[)~2?a  j`reYYoGu_`^(1N!×WϞ1td 33Z=K$vHqLZ$z9GeBnݛtOMCa,ѾWRĆ@|@pE{7hǸ{˵uVE5GoShIn~IJhNEǮ7vd , fF+%Fjxđ)֣31׎+5J'?E(p!|ε#дn|nUnre)bJs^-m+ĚҝAmI<2( [?UBr)f4mѤYFv088[8;hL9:NblĞ΢F z&<֢UVՕdsO.a8Sxf(0}֖ήc:F/kX>I6 à!q1o=ZbM|L岉Ow5JP,g1({-2}PIuufO؍iqqDLe}_)&6^ p Jyfh'u惦]mLw`"ڃaP\j{;%Q+>p}_|ik$uO+df1#%ʩ8Ŀ!qpx[K(KByLO5;7c>Í(gL>*:Є;\rse _pٌ桟LX^Tylw w.^%dlip~nm ɵVg+8׺=Y_f~I&cCF33t J}moR yk63kG W`zh60B:x|TFḠNҰ=۟l $|q!hwq3OI wy"~+B$Yݗ˚.YR·j%uVuoeBw{.( }W~R3 `k8=eMQ<濻DwB gH׆DCD "'',ُޑMgUF0*닙],~OWY*GY5D&c%>">''Wu Su ((8-c'k:)J}Lb_VU 7\*o}fwѻD eϜ g˴Mk"=Z0zxk}w H-( 5N*TSiΗ8YW "P{͘9&3 J> jN#oq62聻BIt;лgW=@E*9,#˻#AD Xg41TȷS.Y 鯰;4ѯNѲ⠟3*Dxr$Ma|1r}OQJc濨dé$L*5fEL,&? !zʲ\CMOwEǶဥQTj}+gd^w 1ұM}y{{^k5[蛲50V#^TyJVV?n-x- R`DSUE8L;;Q3#j1-QvdC뵢M f UQ hql\%ުdԓQ'0PBd?S Un҇jxW+S~ 'Eh_}QSc'T5Qc/HhHZ?,,vVaç\ D}RQwlASH[ZYAsQPDI( 6LOT\ٗ\yPu,FF` SEbLm@l-DA`Y@>вf/jmM?:Sܢ$eqOm"SU`qj`qk6gdYm([9|$M ŌXTȑr`7b)&a,"vkTu}%t92z WуÜ%@+^WNaVvjp@E4{k^ `„^8,l},,F(I rBiTB=s% ØW%wG:F*NaSǁ̛t nb5"%=?~4PTV6u 5Rbpf_F {iі\80Ċwhfxu[B@Yr?>'2Y/d|zWN*hXZ fixsOv8Z4V h!rg%ǭ/ IDM jwI뭅ty]<mjH>oط娊 0*zӑ6hb+๽iv7؉K 1,qτ&Dr=(Bt+{G"GSoޛTL<+>@i/\1o~jӆ`ltj苶t8+AeI#Nuk4gK!a/3+)H DjSJ!/n`ȄTc0E’[9 ;$ӾjƦFd.n#`x7 upiB,&(%^fUcOt^'vd pȃӈ(|C ->cy+<rHdł,ٺ nx wmFM\- T1>Z\&F"- 2*eﶌ,[UNK9DA!h *|5#ൠ~ϥ 'x:%8 J~WOfEB^PlᅭN9V*WځG?Rt̕Mq63DBWz◌֦1A$dz_mw* 6ԭrF{U=Tlkj-9Nb1 Єs=mQ ws3lʵ#tB~gVڀq[ )6_E0, Qi"!mpp.6nCW)+.SLndZX"[V +0̥Y(-D%S-(} 8Â.: 1iȯ8T~cN/kdvrˬ(yOR)#RQ9;,&O}5GbŠ b+ދB7߿8Z+g0zƨg-ͼ?>A$Aa1d"%z u}8 B9e͊cC\lfd_4^65K<_u=(;f$B{(ƀ{² D/7%THsʳh+U~Ibpܦj*Eʗ]l,'ʵ[<<?ؼ |`Zm8ߩSd&Kt~tH$匰T^zڶ mEЉ$dhQ7pqb>E5Q8 X kI2(ZAUL ;D# Sf}냪Vp9Ʃ Fٕ^ `J )̿U AþѸ@ax=sr~,Zj*Rv/m Э U笄U .[50 jHlj c]f]TzPKu0廣AװPRjkYhRG ,qCmUZ6ÑdڢaxBǔ=M0-wJi+pyk VU"3,_Fe~Ɗ-&RҼtB E𦒹QƠgX릥VF9k_{ZY#fe^OGٟ / XJfj;69jˌDR@>(Fz(^b\Ԇ:b&[h,^~%ݑfI!7gvҶÇbEom%{igCI`8Q #N6+  3 LTar!) "Bq´a ˶{uU7?GƳ#wg~(;nhkvgfXbO3&@` #mcA LfUqͥu_[tIkN7lk >^VƪtXꁡAO({Ydtr~pgxP(m}:aNXu+L16ݬ= 5^YB1ͿIrՈ/"TpT ")]*iuq%/UZiEovͩb)M%^RJ-k8==gΎU{&;שtj!vpSa~o U+Ч%,l u)vW8'׺ ,Sht'!u*h)g~c\V9Me1L4Bܶce+~tm+'/t}-Ɂ鴞Q8'OtO2,:$&Vm6 Q + ^5_ޚՍp.439Z"b(n<@R:fn3ydQV4(XkA\R6*oMtsQ}`z"Xn5\uYlc튺Uf,vMhmaWOh|\+j1+%ӏvhnqZ&j֫؛vW zOaHԵǹ_q1e|N\ͩe3dy2Y(Ɏ̟ ųW9Jmjn.m0j$>J{gvqַdU{  TnZN(h ̺!O~D/ܤ>KRPUMPx~9/9륬T w#́6"a"O`H'kid92@Ѱ| umD,rLrش]˿"ciE,\p4+[xM>lj2:l1;8AuAr硑_g,;e9 7N"t9|lu*."#lPn~OJ Ǖ}Q;. U=.|";MwwrgX;zC4|T~5ѥ!c,Uk%ܨv7 b3B;וEE֤TL ><}DpC 1< .Uޑ@PյL , >ݱӱ\M 0*rZB[5UXa@TKlGs"~Vvg~IdkU\$\uH5 MZgvƷQ:oΣ91 ϐ\ Hoy ZQh\( <V-{)׼`ua%t*|1R#":{!于_2 Gw-Ʌ'5y;x4^ؠ: .VVB HBQ]`?%^>DZ@}i?c$}j/;*mfsR>*ܦ,.oB {PLDxoF+aqf%7ڶh=xo}/E/ˡ*Lg*wr%26=x=E{I rrsMbl_t)H$}&,!&a3/zA?(^ȅQGahFdSbI TAރ>\Z ^,܉wm[&{rfօ$Jߋ:lZw)ΓB8WRC%b߆v5ށt6ߌk0bT_Hv# i8 庒?Zaաy9"M#ڋ|t4 "N',8 9'6֓G-{3z[ 挃 =X̋qc>C91P'$ ӂŨVPA҈XRzBo1Z${Zx :U$ ,ʸ6dzU8rDVɷt.xPd.QY^o!U̍&)tBeޛ%?6 3V'bVU\Pj%GW, Fى'-(Rzy4˨)tJ@B$MuHb*1y 9̪(1|(saRc7C%=^8)a% [FN^>t_& ]u7q$d9XMa\B {mNߺliS6l=@|iuN2Xsc1DܽI>nsǞ+)y{O3++*勉s=0+Ԑ*Ł< ?O5:_xIاݬZc%QatV \Z!Buhz=gL]K'G/%"̻VDZM%~E C|;; *a7 0]%gt`-o$Nē+y>lMOXhgJ۳Wv*i'+_>0G|e'Ϫp$%L ]dm1(Bs/?Ѭz``z^ E4N[ >;0P6 eyއZbC$PT偱?_ڵJ=@# 낂sB!۸jyEq*YQz'R9i& g:S,聓\v ?xHOi_#_fȳ2r:6}`! sjxaS"BIvG'k .GLܸ(`ڄۓ] pЧ|wіu^^B ?8gA WӜ321e7c'169N"'uR vJk*tJwM!+dwg[OLވ:V`3:B o\FTQz>ctB-Td=L^|8\9btU}D[/LLisC1lhh '1fH3mEW/nݽ tM{iSozW_o[u-&^{^WAM/@/\Y?w[%3# /߄W@]-6jŷ9wdMQb>IY]vti0بv.zWCF3.dhuM89r ;{gX1Sb{k r6A]l`UR% or2lY1O{XK|.>DY|h3Fe%K2;n`J gXUۀDvN3=r ,q,]dY+_\qUv@Ljr * Y S:/MϢ?b^cHρ.H?<׽\ * 4OLdnW\@@,[ C_1ߜͫ\E'"_Ԡ81HdyLKQ ʯU0Ġ='P%/7ofw2\l&t36yewVڟBH)K߭#>6)< 8)! =>9,; pJu$<{^6[P -<,>9B.dQ{!@ ,XYw9ئ>&|B-Fb?^ձ6cd>̰C0y7b#@kMÖ Pgأ$җ#%&M55Ӷfi"fzKkR=0WދE  6bCmФ<,J296&$4s H9oeL%Zf0d%KƏ}ޮ38^t?OTCg"lst۶T3vkuj DO Dys@[sjH'mif|V/ JP^I5$;nNOu 푭I 󴑏|!=VmW'BC 7KG6-S0P]P=pzP*{h9{XT![/R_=`T" kؗ#(CC|+ =ֳ<1 |~?TW^?-X<-f^s1j1Ba2k(VFZOvTڪRr=/(l%SM9>)n'cspq# Q2dӖ喣hv(04OZ[ Yps)NЂ]b:k0, }vKWUNUCndYH !(PK**.rn)du"#(KP$7dwl5L2(Z%r6tkd GfW0Dc?\"+]WfiY fxCS+5k-^ eg_ F!q KVICU9+;8${&ݓLBY}wt !鵰Kvl\P})*CTzK͖=({t5\xz[fYrYs7M&- 5]KEVq Z WUGÀޥT;l=YUCkzs)dE'ێ>{ faW YXnuwR6朧5}Ô8OI?`jr|$/vz#e,|#k "$'} ps Lk0>be({0czOб>ȧByۙRϵl꣩psvڞd148SuTjEdoH! 5ŗiueb8FnSҀC(m(sɧu?@1lf(/YɆ3mdt$]T#`)6 # .WT{hV'NnC7.S^xRJBty!t٢AlLԌ qz>"Pb~L 3OOh {'Ar>1E:0ݿN&$#dBMh&&/>~5NJGEJ#,CD sV^Ք2ځhC ;HAV҅Orpy⨄1td.m( =)*;Up88qFh/-6o ~}b!<)ѻB ٹ!|-sо?(ձKT[1vl2.o\~,v+E7O Mvk xZmŠS+C<q3@N+5.%R{@<{ΛP9YP '[䟄F0H^7"*f[A|I)agOcf!!Ʒ  !LN./`< xǡŌ1_F媥Sw^Q,#U.,O<ښcCmiuHe8g4)҄^uT* 9C͂'㞭ʛ\DLW93k.PQ҅1`!4n~ٯPJt?LѠZS lln^JeavZ(ˉܴ4.t~.mW}ZfxX#!?o)fy\g6AǀT9W*K(l%6|53ok/w"{Ռ歖AIQ'Y+/34Pti>s :6k>t (ݞF16=@|(F,,zG΃P[@KFLjteJeg{5!reO1.="%\Yw?Ȫ{ !;yJ"&}B+Tw V2CݢnTV37=im]|$Σ+ Me a&A)N;8uzb^UQXQxzw1+4{- }s㕠uҔgA v\@Ü,PLs"7`KC~VRC6d{õSUe>a!5e>4•Kᷚ7(P&>EI_$E'oÈov7?W#R\kC+&M1Ȼjy6r*d`TMHJiZڨjk*VC&Ή5| "SehN 70eX.@U X>vB\ &T;x2z ?EkEB?U@Vv8Հ ٞW,>)UR&J?~\Gqމoh Ж%+|orHkTo컎8ԙu,kpxZǘT>O4 QYdY3D3 'N UP"f էGk.[&WRl=XgAOcCd(yEn"ʓb(Ŏ TN;  \(M0U]< 0nai 1nE >6UhҕJm''8]|رhF;Y㩌䧀zLls$%sǡY—i pvJX)`Ia3hcNUSYIj|Eׄ+"(̓Ü*tR׼sCJT(r֠'796<ĕ(%,ybڀ2Zo]bu.ES!a!M^4j-@1'nlޛE($ ~-Rqr=!iĕ/=ǒ'0(i#ydߢ |Uy)} 7Ko'_Aeh>3#M vODQJ4zh;qMi<.+TFU; tx\hījHlI˩R1Z\]hO8G}aU)}E,n+w,$Lo:[6'x{ 5db ߱9Jo= H;ܤ/ $0ѥ& p7tsCdPNat`}k8o?7jVjM.cGa3Mݮ WE/x]tE2uptAщOYBVK}R'Z1")0>L7xꨆicSL**b|cT !l I>qBLK@އYFmeg%hC,[']M~"q+lUP{hч7 xbb"0.o됴7*)4%Fvb(; ,_1DK,p1 Z[L#QL0}-  OzCJ/̳N8wz|~F,ҙ sxJk\"4EJw)JxSrm7Eq~t1#x.u<<N OG=UH+LEooA==:__l_T8b}e*,q`6A*DU#-Ei53.Ym$/ptZ]b_{RYD\9DAMYG7 Ș!0 #D4TͱfpN8qtj 7dRBB hp⨗pt,w G_ mz?.1'q7f XcVI]Rv}a,m@trh*?*eC!.v Ųk>BՇq5>.+0IG5sca IX+ܰQ)_o u>bYlȝ JFHT54aC}L$0{ ䷀2VUB[Q ʣ=jHqUݑĀ1 5 ͠<WC\Ibx]ufJ[EBźepp_54w޴pYu#@svRDR'.vrX AKj((+&y= NکZN#p Ԗ._(:D]+&, tw4t܁a p&^Z2>F" \-๒4Ng9BL-#^G@\j1X- WR  j=A+}qqC|V QJ02j0B$b' bくIw/u$]'7s3WQ*M(@r. +p7DㄨSm'H2 8Xv,s!~r}J48;t1pcHN?4"4=O KV4dd~Wܷ܊A]eQb^^ eF?+o?(1ǩv-7ƥu26JͅjM?GL|of?kp\ܸb`f2ѥ ZkM51nz룶 G(MRP 41@GO[S~~(c۸qe?}6}Q'^|{hT{y|outv{`֍ܣ>`l36o]&)sI9z#Xs~ _7&x&%EMޠsەR} 2!\$̥̚O_M99vi:IUzĈ[[-Xf=w̶-FqEHψfY{`6~Ъ ??3y.G@E |@`e|V-$䱬mdnKYA ۞1lD)KOMT :5|B&zrĐAӘ;?7.M%q|{#=oxUXd^$DQaVTkHӵ'pWciَ8g ND K3I*cuu3m}AFzg뗇69pt!lvr6I<Ϛ%۪b@ xH#Ɲx+vP~@r Fl4cB*Xk uUNŘ?t]䤇B_YM}Y8/WIEL{ܨh 6qN(8P5d"F&KN3Kӡ䈡M R\+z2JWYm&uG?kk0Ռ469Gl62fv0WF@z/[z^v覞,F JcS|sݼ#cG_~`GluVTV1Vp^dN1iuMxt1$NP/ r\YO5IT?,xfff *i.P+;q]"Bq ul(ۇ((m'̍oUuIcrn⟓.rEMfs5F%'q;ѢwY4B]/zP뒭&=̫9$6 nqsڅ:+('xc\#_O ;un<3W4[-K st`/Hђpg52A&,Ώ,4i P^֫t3T04.j\7JpNIHY46qfpq uݶPElyrjoO J@PqJ wA~O[[?T]}lPk*=* _t/Di~3{>z ՝E%&04 [+^e|$(LT@L1J(pbYG_ƹh]2 `>JR=dRVx+ 2Q 0ȂApsOhT)\^c&$0|s=[Zuunb6L'M]y懔LVhހr4bL׬_3yfgMzdRj_'.dKR0UikMYZ[{ +b[ۜ_Us, D:Vs=s0C0G 5͈{d߷[~jBm ?%`(7Ue \3Z/Vmb8~X PyCQ8??Zfi֋8NLo~ahEՈQ$dnO=7B j>u(UJHgphY dXLPڧ[ʫ>#lw4E5j4zfRֺ7<1o~rFtb:<)᩹ DˈjfLvE&XaDA!Li!E{)Y 5K :#.ϟ0,zBoMPQ4d{%DP|Fd,\,#^-t%9tBt{ {፩eyB{4lh݋88>ρP#|Byאt^?+5p~i"`@?8i νM#h )vAK֏Buv%t= L#rOjkWsq7de>* J~ a)p)ecOcqSbiqi _|JvY*4:DsϤIt Vk_f? >_Z6կ:qz⥨d>1dH2p"h{0аOla|N6#2(/Pz_@+sîz$R)$75. xEp`bA5x٩eu`c 'U@(N2bsҊRÊ{n:½#`6j\Ȍ|l.lgsEXdҎduI~QܽɲBڰS8iWr! llީ2x@y[Drl%E :l/ⱒ+cD ;pJazz \[@ ,3B~JMy"YHvIo_nD"WB!F-a Rz6U]IAI dc<¹oɳud>gʽOsѸdei9WJO$EVzYTM2dXJ٢޿]W_N'uYD?KhXeY3 P.VFz*늌C|3>k.SG]yH p"fc/p'y_qG^<}TaXffvLhw).ɷU֮2L unOW yr}\~Jv esJ嘻c C@u.XEʺQ'uuǧδb)_c( 2ϔS֛62XWǐЀީ+U֋LZa 0%D;\p)kc0ͳ9ˤI3| 穆n!ۯ*V2LQY-\/e9<=i Phefy OyCAqEP%ķ eqr-^o/wȄJ7/Ygi[rQyմ|Cu`VYkv&qk2x=XpyyK?4R~d5ֆtE5~w%য়/"OI,N&A:COKpGQPy0Mt t?g^j3yL -4KO,chbg=p.?`WӇRHvX>!֪V.(Lp+IUرMx"f ѓ돘Z$mU S/e&usǐ "VL H 3D|?^MrB,/姱d7LձW=5}j.%g;,aT.1[IulT vNv}h'g* r<ʍlt&r7%L-䎈 4]8l(G L')l_{r,1WRWp643K>.):A8l @+ |bGo.fWUO,0=ޯ=tںH|檈bMuʩ=(ˢ/Gn}|IoD }%Si& O2_FY24UKrA%(QDH3iFT`.B{`b@̕4D)nBY8oZBvl諁x\a7JLz Ÿ50Ѫne(hSv-T`f0K28d~|su[Ӯ3`Z?l{H2TC|~)WClz<JݹWښtVl]6XnܪV%},T?toci{k08t|+(P:3RE:,j$y<>x7#N ]+X'Iqƒzc2X4@`VWf6Tկ1r9I0!G\x6ܝSI+Y҈;5WU Lށw O6LY l"C7q@yض*_hK* 6ĊXB8 ֒Ϳ/m&mvĶޞeO̿>g{nJ^do|tyfEO-۟ WʸE @G(y 䁣x'fSF|/|FR^fqs/Finv鏼@$=L~1;ҏ>f_K4m")2Qk˼c¡"ĚJd7.OzK߈$)_)9e/2\gͅk V:S%Yr18 ~ie_ȉMKnϑܦԯ~+\\+җs=+Nt1B[טsqb5!{ng)%imC#f֥S*Pff(/]ܿ'Do5 KYqeÀ:o?^(26O){WVad{%IHXE5JT ;yQ_LRXc\:麿ӍEe9mجɏ :x9U ѩ~n\Eu"z:\tES嗠.OWqƟdi3Τ&SHfVa<Ѝ~s!J<.f3ذe'ҙl)^u;uNayr,;)qm2?oelOSYvy6!̹9DT~xIS @'s  !" 'KWqVw^-мϰ^*&EUt'P'=Ocjm-TL.夓:T.Gf[0 #P{uN[%&CJhxs3F%p+)s{)Gmo_v},UQ6 X{bB[o3g  ZcB7A'gʛYr' \ie͋(mD؁ ?}zOkFެ" =V (]S ɉG=08. '9?;Է#zZ2MiQ5}uX]@p5Tt#ϐAS뷏0f\|FB/_w6ĉ,Jq[k?w&Trj e%)@:pHv&U)Zfp}sTl*EU2fNjf ]ߣec$%6Q2Jk{kYZpCPi!oyV0AgpaӼ0fJ lsmP7 ylRZ:/GQjg L<6`qƿeA$yS'F-e@9.mRLWv`3qZQt u dz2l ' 4DBl~;@ lP8UtgRGLWni`xSkJ/ 6ϤvRKՏ1`Uˁfh=Im7۩Gpe jxrT+b+pE]ALZ${gU7_5Xo1ۤ$B| |Qc%B( G+V%AN$yR¶7A"r²h:B"_Ҫsz\wRpq(BrqݳC,xg}(t*"Nz Mv,\.cuvEݽXc_m ma+gF$z+pfsz@\LW4?9$BlUF[$t;0\\Q$ڗofc3D)#an.Z<2`rsT>LVi|eB )SE $<`ҝ[Y5`-zT1$h`'**AvSI&5l7h@j&0}ȣ?SV XKV׼eW_;4iK Po}[o KN ~I\c8xבMu#(b~2a{ ւS ̡ lER˷Hz:du,H֔u4$_hlX=ߕeLz%PD&sնh{!jfmP2ӕPC[dqga 3Ya%6:K^{m~`AY37J"(6vQc ZRm:V*h`(9H `Ue;=(ZD'>]aQH-RXg8Y3@s@H["H6|d +̺͛ϡC5E=sq TV'l?`wtd(M hЫ'u&K =٩ҪcyOU͊'[/%n*f'ůjT[M4x0z)e2 2_8SMdHQ-rJآ2,A 0G(G "9O;=ឯ8,tQؑ N7NbO MJ&s<4F/i}t٥oٕ@6Є0F,?{`d&$9qʛB׆1W@Ij r2tHí5!^.ZJt}իl_[ /dYZ;@")1. 1˅[6w=yr+Ӆ6&-Q"{hGjhnDecqEV_*y=BFh#p20`@3[9;p6,}DMJt4'luHWVb}J]˹{{Dڋni"h ؾ9q 3دf6y2A&9u鈩֚ xrCb/Vm<nҠ8{V(]+w@b?dR`{sWnI}rX/Ṱ& 0Nu.@rrɚ,*!T@7n4nrPѝ~aHA:{kn|hVd1t &.nt`HpJ,-xqȘ@3g(d'", 5O ^SWDI xbo-<8g\]G9(zҐA+s 1Fkl8ҧ݅eN {g"=}-,_%;k dIv PO"gM(^#^UeE{跘CLzZY-}#4CK_;iV ys?~W h_gw4"N: _ .r;r[7ɴ Q-ve .sO\D[6Zd7QO!?^ e;(Vτ qmʹ C?^2D.y(=,~ƳWKZp^[._Ϡ݊|8:f-ݬi<J(Aln6<4N\)KB$ .k)ГNA 0PIT YvޜGdF4!YzA @*]@wEgԯ5zmv2  ;V&\;ysɥ{[}1ߩ?45P\q̋:aj`& f/ Rԫ[Eu% feo܌*xU8Rӻapq:&%E.4(C&V(r[řpcF 3Zg͟HW @٢O̦Ñ!!{EiB^&{B|8Q 膖RԈ+L7%rgw^&&jFװ.ʮI4V! b)?RULG8ZS=`irFmI`"Y&VD] m L1b\O$G6ɋ1yETqI2̖ܸ- T8 VGSD/A;וX%eʢ Wh5~?;~"M\)U9pM4ܰk5zlpq5s&iΘ! ,x1 ; &̷$M9C6sR[YKzkc K/B)u 38<-1]|4׃%"s L3bW够7nM >{+8%1:g))Y5aHxAfYvO/j!镎z2Eey 抆o@mvS@ ~saRD;=vk(d< U-,oMK73F9хW0_E-K ȉH1ţ9+Ep 'ƋAnZ1彲.l%ѭA(0Pr7Xߪ {Q0wEY|.Yأ(rma \z~Ǝ<}% ;^A$Ar(i3:;o 8W T:߬wwx;+b\|FP<nCFR_g muc"aQ <1Zfh vKͮ.Qn»)+ p25Whp;lhPl)|YAN4,Zuũ([ZEg#ޡ5` ?d-Ah^7jqMa$ CJ)CNB?Q $kH޹qŤq٣Yllҷҭ! -VP}!v1ߋuDI:6LW7X+,x^FuUmp~ҫ#G漜T{`"X8{g"7eL|S>qwgM̧~oF˄=O4و䚕۔1)K)pjOBrMJ+\'k: iɶUDIyLKkn5z yxrɶ#)VC2~\>tw+MQS Gmn{7h-8v'RDhZm2B"y-}3"kMgYgt0W\ֳ¾rVӀq-?蝹`i{)T \@%P "-򗧚(|ʢ ,T +uȡ%Q4&$ V8`w{霒KKtG;tv9syz9,?8C6(s(2_7Rs>o[>|}6:NZ{^y)[yY )>M ߖPO7V~v+ɺٟD&8SqA t" &ũT*Ua=LK(mEQhlU-*^X||KˆKnHar'bnKn% z'(qB[5C[]\p>HѨBȤ UsFi&G 64l)oFX1۶ }UAΟ#I K%A'L{m>D?kAu\Ԉ h[o79[ *特9-%LD8+{Ľ.($nR$i\p/|]yuTèL5dg?VH2Z"CWd>%S;gPA[}fG2jgn2r%3S:BG eS:D{]+K(6bˁÝϸȢ88U5{*JehZ5o](D`eDTm!;m\p|vgTcE> xM0GLUg7\`et3 c><+efd&beikf> R 81~F1 o-bч0p뼯Of]$7aK2Eò#lY 7{ɑ14馋1gf ΥV߼Ҩk[^G-DBBr~h6Z]9*a-wb}Gx6#>Ԉg^w[O;gfkq+×N.RG;s#.$FbQuk4By\s`=sJ`5(LF >$nuرDUm] "14dE2 ^إ݆*R+5''@sHZ'&-CH=v>] _Iʷuz/),H%-eq ϽF"#~*`׳lV0tfNJd&hsu]"{2),~hDe<;vN5l>KrNolg$u}yY*ѡH(5۝iw17Z+jUZDn$|a_RGׅ93șѼ=Psq(ݖ0$7Uz*RLާPfZ=dż2Ouk+=SȍH^e? !eŷj<n/j ^v~u47Aj٪w{)^@y Vs6vC~~3ج~P.e*۷5B%R OMei'q\s)&B78 d+6&%zˣ/ "Z4,{-:2Lub;+hRSlۗA18dC )0 71 <:(rbo?JLSU a^gH#'_aПs=ܹ0+ ;z*|02bߜh[d Fp&C},S=:ܝk(IᅵX_OJnֹubzb mx)`("*M #nĺhcaҴ7!i$uCqɟ- ?a[^wT) #Q P!vb)ZsiB`J5;`Pkq"qm]B:3o~[ 3LZ~AzZ6tb%@sq 4\^]SYoUdEDz'?'ĜL|;o(b5[D5 Ҫ__2m2 |o7?ё֘6ZR'ؑ ǾãIl~gT,>B47hIEkg9M=I4~ C$콜˧]_Ư^ԉ>h󔨙q&{-w& uns>% yv$dE*T9jms~BIIP=oJ^4.)ؤ1*y%Gܲ8su÷fCAyg4k}.M F1)NFl~Ch~,tjBnN3z\pjuz a<+=䯼6F*f!TEQ5Rg^}oGJAr@GՋskB#Nyķn;Rlp2;]/tӿ9ߠZ"o=2Aާ`DzE9R=e),U-5Ld0:WULCn!팙d\~R'PV%'ڭg}5\z9^J{^H)'po*;wFq=\ 4ij"7+QlU&yR˙7RJ V)ߌ0X[z@DۖPD?*퇷#jArq:݊ZWV։q Q)¦a&.|*ޮ*.Pb si]zApcv'?)b_TzR UP(elΑ8W}Y[&3 Pl튍 H7AT Mx1DvnIHNZL~w4Ꝩ%#ŌhrDBcykƂ 6+M|Ha*yl0ƕ]GBcۚ~LY;2S%z!r⪤?'tW<:2#8S {fp/7ΏJz:̒嘁ni)8 I] q Ydv<&O;"hi;>|SjM'x@u$rh5oa#6*o{b_lOz'Ƅ|s>ظhgc_:z=$KR*>l5. [M:\!mpVLIɍ踼şyOvs4"*~$ݰ:O,a*haWJ1%ذMmUW@b ~(’@(b*Md .,mKLf̵8Oc0 ƨj~97˜v"~RExz :7GK]j\~Y\Q/%[୏ YfaVYkq!Qa- IgApV ̸\玲"㕈]S`|bbb":4FpX2(lQ-|C͵Rpy]PveK%9w#?&v )`hi.͗jv }:(,%rLoM;–gE5Jkw+&;@649r_pg+^ѠuPZjdiTb΀ۍZ#IbsדL95OJ7T"kb"!fA6;5iw#5Wa@B|844_Jv<!=F|vۇsjMws9 y"5G?qu+vNϢH,?.\CgΎCo5%W8X@A-v p9uT`mv370k<ǃ :']36Ĩ>~Ggt'@ #ݽzza~?,O~nhdzp>U̗gFl#{Y89:`XOڰ0 !k{N?2qpÆ`+G~բ%~ϡ=ӘyҤO򦖜eՍe]2 5˧ObNk- r?Z}xjU8F}R#Q+ Pzwl+턵 ch bO<֝+c$P}p/|_$oMrZG@nHv2\Zٙy! opQxY|6%Isxxo:Fi)Mw0-rG-FDhMUIٛΚf$?N$ۍC9n&*mc<8 _dܢM99^In;.99ώxc*7G5nVc5w]ESp;S2B!'cF$17LÐpoV`3#oQZ{/iRk0$.< >:؎Q8dp#e2F<|%\+)1·csjS&Or7'KH& w1n}[͓M-&7>ϟXC3݉yc'qu T!6b\$N7]'Io!M˽ǬNTAS.+I)C:Tΰoh2EMW3^Ugd >of@B,5Nw' =Gb쾖OHt BZP8ݮQ 3ᘕI17gO*ݧe,t~Υ(/n1u HyvL2䆅ٍ~: '=b(G+U8yG3> %#i 6ZC^1l 9nNyU A2y[}HmXSqU?>Ut\{4%\m!M!"1Ǟ:c|ݮf5&\i&&{g1}6Pd":ϓuۦ(:v}ס8,kCLQPhjof4S$ ëM'kB4P'BNC)l7ANU 6{FB/mU xؙ8!a\m["e1mF=@NcguX{(C՜ f|*d254{|G.jCŸ-^ODvrx^udgXѹRC. G )0mdoo2h 4j࡜2FOVI4Lj6E䮆KdZ{۹bhf-&`{yN:}G5V96DJd~"Ĩjtҁ}&ȳ}Wx8"s1y;^)i )KZ Uě]oJBalhhɁ@q3Φ)=.K eBdGҳѤ4,w*EM< mrS1)& n!ƻ(SAQWT8iIN^@ft4#b&>-LdL ]C<@j HrcQ#6ef4שgsRq.m&[lYa,mפ;ZAi^skTX3u/7IZfXh}i&.y]@ceIaE>a}*oFlMOFZ?ஆ+uBo`iZ2VLnCBF+fe B/d灈To}2oMM6B%!&* "k4]cHL2kͬi=](I{қ졙-ME,M `ņ(0R[klA4UqJD(QCPwu0SIFcX$ łjO|ܧs> \= 2YWU* |t|?fGQ/(@lRn¥{PaXMf(0~!ɚ;vMcot0ܥ#0S!ZworFUFcI7sjs֍-)ƟՎ-Ó紨hh"ݕwT:ggRa*^1u`QBcd;rCս9ci eIN<ѷmdd lڊ<v٦juM3#]Ό ,0oDžJ<.zvY߁b^2>/42m!lւdKiK+JBwn wG22=`5Y{b;9l1eF;iפמlJ W%nbtaޛrN@CjS0J0\Cc_޳DK@ Kth <р.0y, lB i8_?WTiCRQaEJ f0gTh0}cIWH"NPtUqnHֵQ|>V^hB]ת'ikI;9I{Y9$1tKtӷx3&^bf?,"jx+TRӳr}2/6P7,`'D '+D%a#K|PAGt5u՗:8̉`[N}:s/͙\LTk%{0nÉHA&UZ;r7Rc)"9&lRsJ>]I *DO۸$iݕh0X #;\06 T ̌tr؆)6Jܖ)g-˚pm3bNiC/㤐p˘@ 5T5N<}6Reb'",q'\U"lݽ0\SJ!ѿMRC*&A?wsgo"F_G{)3MArP7IEY <Ȩqd:ºs8{R?lP1:[O/e7?5e Pw$Ҕ9 nOkFmst7q`~˕Ym;I!GH4Ka0rdT!z}L:*pk )8LFtn{5"^+qsG$<:ppڄPQ#df#V_r2>frmnZ%+\NP2<:Z)7 〚BgL3]G~G1^|;ˉ+@n.+z+kN*ԺIٶ{o-RxWkO;ˀ Z- ~4sΝD~mP=|Gc$w*2 ČRbC du;F{"!=fJb_]/^s3QoTN˺FVuj񆀑4>ONDu=*I[KY,cْj)'T(}89.nbEעr‡Fe bSO/CC. sW^$v_İb{^67:;2:C*Нcw*F@n3A-)8a:p %~mrur .[j,8ߪTxHP<8~b'dd+;Ќabw(b[i=fVDOSŒ2=h$!ah3"XWbV/EvY2˓YEKEc!\[a\DB[W=RRb =v-Hꗶ':j|2u{uo<)ĊWh@}X,8# &;n3}>.ta.WMNY8&|&x^/D'a@ѳ78 uZmxT_/.Sˋf0nf "jy8Uhg'gx^-d44VSz,m?6xS# SztkkVa lB}[v]5 {jVÂCpr&LW5i)Q{X580}Ros8uQ3/!BԤbJ s~]N(kcIoΏh-i4| Ãhv'v 4p.XOY {A: n'͇wH +H - `l Xӣ^Hdb0!ٚvĂ@KlG{seˆYmo$CL Y#S=[d4?M)$ZHJ[*:aGerdЖn2%>XfqO2p!."A6q-FJWõ>-u'ٍnx}[Zι1 9'IBG0"-" x ۜk@B^t`y<[gdk!J{RPʢ:d:c:iiیik" 3Tpd <A YmRL"svD h6Vٰj1wNͻl`[K5Tkn?^o~\"b%9k [l3unF>.:؀6u);K-e5`𹔑Ak&9j553t`oTnwQZK6y^D\kY] hNaX1zzgR&xao^v^wyXV%nOT2m== sm#υenh8S9ou ,xŃ0,^Nvy\05Sp/6&N oiakiO*N8@ikO,zqGa'+KC[Vd@nN Q%(|50tyӔSئPd_ ,FY&_ys|Hua[o_dntjұ4ޱLV;s!A+B3Pq dGRv `l֠J#ɹA: 3\GV'0 K w |7hMU" a;c*NVfrijzޘ}"_^'q  b ':~-eRbb74,\A~̭jU@ꗛk[FF%HL3=mx~<6S}D *( dm/5$ӝڎ+lNDQz+ a|ZĒl Ѕ!ЖFV|ZAg\R$Ot(?HPӇæy#P#Ht!2 (<B\a`{Y";Y.b:`)QYtҵj^NJN'cjj,zW;P@)֝)>ko{6?Cش EcSS:i×l9zAj{F)vؓ3 B&)*븟":u @M.dLLqfCck}>QKk>Z _[z/O%YL~UDp0{GNV>(9@[ %Jߴm]qkˋ4a=F^cZFsjޮ ?G ]vώj4; 6UzYU;IV& $ zGC®'3AcJn?C>(Ŏ|XxQxsL>ͥUQs26j/Ʊwd縤&lUYFn{6hh%4f>W mޕ8enșD?Mнc v[#س7@qΠC3WCk`b'C$NEnIk|z4B]M l輚oByZAy̧U˴fn=\)-,ȵ .e(̤s1qIt Fʫe~oͣټ3'TK.@(Qw<Pp% -!1_:k jELhEW)q$ʵyhHk!)Icm _54>k< 3BE෨$ۺDUYw_r_ ޘW7 鰖j|WWf>H+m:}ZAq`gձ50 .-|0֐*y=.LS?m'y7HgGIwM՜_}n@P|\ʻaߪ5]D ;ZQOSجS ٪3 e4os˝g؈@EiLg8/7ȼ]oEBįHo wÞwlfo\tH=^Ƚ~ȼ-Cǹ`0+B1a'^ ^)7Ioa`ǒ'fWqHA+'0Bl<ڍ 0\CM05`f;ଌ΂|1URȤ1\A-:}2X0KvK2kO6x~_Fn8Hr!b;ĭ.|r?ICܶciHR O|{8ugg0si:[k9lʶ=*&b' 27ɈE[&|Ol05xjpLmOOa#~c"i'3Vr6(vI2H;5'|XJ=n+×OȮ+ܔ֒Wy  U/qktf-tcղ# ofoߒ;VXvm\9)lp3rlbF8ᤔL2`GZ+ ;#2Cu.Ay% 2^}}`?yӴZ u q TWbqgi+1Ql +vٲ8T>$1MJ)cMraC]zP#4l]NGr@qB`*GTK3K97e-TD" 9qK+a' $UHY%l;ؿ( ԥ5;?)f!@V*Eos/2yP;ΎCgKMEպ4LT%pp9Rl8Fsw'W ),\UoJ V ʼ^1LGS Ŭ$it LA+TG}2n2R8We5VHʡ 7[ }\4QO/3Qx(`u> J57ۨ#)v@4D-TYWL†yP٬>#Ejlh©{2 + PLlH?K~m@<x0='Ese"{(B =Ep D)Bo~)5u*$?YY8$4D-:ѽ%|([]B$rU\BWS*ϬX1ɨCɂk u~gjM!e/EuDb$:?W|)^b1]Kog5]`;GJ/#@$mh\Ҝq]ASК38uSHLh.;Lfg\;^񜴐"Or)]$wBbx`%y":LLسHvz7\xMM1Zr=ꉳ2M15Ƚ8Yd6h!n74tG†b0p[98W󈄳#ٯ!QJT+r6:dFcoʷ :aK Oo]FIWT{.ϡ,fuWh0U'Z(8O1\DSY`~%,d@ؐ D;AIe8D>H7Hƭĝ/@CÀ0!h :}p0 **Pb0叀W ϳO}bLb| Bk8lB=h,(MiJo<)Ӣ8,53ͻ- R"ܸ&-6+h.zΐg:%TĜn_:Zrk ꛠ3-zikab\tWK~/emV^l}YvQ 青nݎ{9Țhm+yĠW0@HQ,9ڬ8O1wkE7n LP`MϚ3Hg3η'y}˥<":ȵ=YZٕC+Ĉyvo O*Zp`72۶2As Q{xD 7wg~ `1 pY:.YѓSAF&oiIfB993q/{y){I'_L{I6W0s7YE$l;S zV*-FD?&vj?̟-h`\SQ k;aȝSa-g0|x$|͜T$(Q}(gRXB<5WOsd}O*Ӛ+1&3{ !пgwu@~xR'<ƫ[<ۉN iʍǣ?dQDDU !˰+-rިb[VAU#'ϕHKv͘[)KU͸D`d+kA"#u؝[xnߩhg.Ā>G6χ%k~e>jy[c)5I=/PxH;Qy}DS%n)71NnG(C,@$-k-s I%=AqߺB@@hؐK$.䟸 ?y"`05V4:bU&B g)@B+bϝ0鈌F 5ptA{뭾S);)i[\xra,Y<+xW_c{J:kɮ+VmypǛt qi>0Щkͫ@)ma?,_1T XOG\MAsOus|8 * H&uXnNƥRL/Jz*g:JI1lk"g5Zf'@ΪjA#QGʕm|kh);}-kS*:ʴkrgU"6L%N4Y=:h暛Q&B "XU)-u? ?~ ~%P cpEAb4+RҶ Gp|Pu;V-AףR~ju,Nc&I(\V)(YC[WIdm/QMwRy6e&ؕd(+I&ƿS_Dn0YDg F`&/Z,oN= /EB0p ~}C4 5t|_ӿ!ڠϨ<G MZ8Grtj֭%Bʈzi6Nʈ\ht:?΁չ ?۔]fWp?:˺K{ȔO][d,nK|Lw)PXYo &&Q3DN"2j 1 K#8鰡s}AWc̭CɁr,ndOK^hiM#FhaB'Ȅx:?#3L;<uf)S T%fV hn3D8K6ҩ$Fڴ޼3/hh 4t?!tC)a.ydMK3UAf(jF?O,bv%1C"xlc0|ކb_O呑Ns7愴:s4ĺVu'";e@ni=" qyYѡѬ8/=ISYӣtYG=fjsP%<R'}<,B Y=OP5CQ+'5Q5xm~Uצ2)3In0M{J)#nSݿ8H*ʍKEN.X!wx+X ,kNpតl\|žēW]ptCWA -\웼1ݓ]R.ik]=/+Z]t&^GB7#SVatbY* J-Yl71(z셭|mY1<ƬZǨ^7<#U='6nаƗo{qQlL~_Gmv9wɕk~V8&UYm%p &prx+h %(ڟ(REmDp\٪{Z#$0#)cڿvʆGTߜHGkEciCe~}0vSRHP(8>99 е]bJ Qpf Q]z+\Ɲ6DҧPc)WI7@yE y|xN3;)6 _R X,fҴVGD))SfVhNj]?F4 Ƅר'fSG V{w8o7e{զ<p崦46„ѭʠ0OƵ3z H2IWb-`6"jhX$:pcF3OW]kR3BU+\k>7"'7n}dtvR墹GZp0r_.2{uS/WwÜ%kp\[*O^Rm"竾 'efs'4ˆר zW)ȧ޼r6 uL)DMfg4Ro*lrw1]t/Cz5~hN{>ߏX羲pebW3aԇgG AX2ױo>^g?찼ek.ao41֡%n&O WtZ8\@P+֦eϠbMMe*[n0s}J+`UL},JLeGq)DZڿ |uo7M|2+t`RGj<-,ޥ_PuV]nd#XHtP;UH`ŸyLT,0 U&%Uٸru$-[BCmt+9ibg8lnӓx (B4p ~>˓LM,_=lG=Yp 6biA`:(7Au#kYo g:v`h]N8lڇd)G/ ׺~>-(佄 ؅0)–׉ڮ\7/K4Pz!}T&;Ipoj"tS/HɌGH]qj!3A,LtQO$ENʣ)-"6z+ؤqaϴ!eilLWsD øvdL^$Izs|`ÅǞz*7O\ [}uG>ʹWD}|)Ea;֬x^}K<ǀ]9#?,\ zOpuY3ePQ\͚'40llTp=#?pS,D]?iѪ$pdrw"uﳳ2. 򠿩~J}/`}Vl) `-xs&] n{fdiqv ` !Ӗ sxY@'l[\D@it>1Q8KXbfxvA6!7 ֿ>h<ɔC#[_Dl=޴_k8q)? uD3PtjAJLc: ;nWk= K)PR/qɠs"ӭcـ ГeN'Ёn~O|P7j<|ͦCLY+]Jr ̛]S^fmrLN|'Lo#T9?L5g45G[LA+ZvEEJSzrkiXDND4ܺαM/LJR YvLcd'6?'Nǻ2d͎4 $Ӧlv~Ba-@-gWJ*L;$^ B K>oE!fA57oI6Wnj^G+% $-\,lL"&:d.}mzf.EC+1XK3pS{W RY{ ( 0D~j\v^P$:OԍTMs&׾CH֓X &XHr1JS~z`4DGrW=˨}~oH;^GfHJ^@zͺtȝ=(h{4=GPȋ3M:Ԅ/ۧ/FZ)&V?V:ǭI~ %`'=N>*tI2C>+|K5XF7*F@H$bg~L$'y|q@_`_cquVB~˝̝ T*Nx=ɰ@OTg'= fV,+\VqG8l'q-ij7 ]r<53DDrDL<`82!a#ºj-x1~yCzvizĪrt`֛$}-QkܳKG\2/R 뉉=79_nv .Xl~{=IV?SDWW@z-sP?-Rfi[+b&#AP\ 1J g/22uYYg4u4RB^mL>!/:*Vef̜r@S׻JvV+XQqn(,ܴD/Hqinxe|&-3cVK'74CsOxޜcvc "U2WldƄ/WVy[ODlJtDŷ|>%<\p *{&]APi>c|44 3҈M@S HJY|1y7u~}yf!7M6x؅uHKfׄLeSH_fQhjNKElBCXCf;'+TDXF6e7y~k`n&8/,p $hum(۞sxL碞yvf"?ڱ%Hҁ*$K\J&rG챾'=vO*1+إf#5"r(`P =xZ68`vo5QI6JN1;4(>YDlⱍ$Y{v6sCXhϧ)^zIs;D6ru ǕUmxÈA0'A': |!9y?/k#rdeWVKwQ7#rL4<Á sGP2ESKzdŤgt>d1_<~H5P"M-ˋ`RfY$iOn6ίbKMP(YN+hxk ;,`鮕Gh^ecL"9%h?|- Ȗڧ*dRB<%B!AػT$EGreVfYgIj([!Kیv2|D"UǽK0))]P,f $b3V< r#.yzeHz9UV-=0uT۴(|lڤUBVQ/ᜭU| BmWN_.:|i)zS+qqZ=a& Ad r:K)~/Y 96X|uh\&=8W33z}SY FLO_iiIe1;l DJ:SCqT }'ng hʦÏ2odp[)qC(ft^JCZf!}3z+7TC4LjKu)sp<,؏Ȉ3ڔ4XSXQI_&} :H;[qI,2I*/Lloiz%qSfXs2R:IHJtָP{FTb~$iTi~⺂,lUI7'5syf",߻ 3-CQ X22i ^2:UvGߧ셸\uVՉھg´W4|eY8dyN `w/ԉV2vX`ITW*ߘKi"K@%6h/9_'J-\)*U7'h {_ \7̇XWsԆ'p1檯#hI>P0qH%YL9t&`>ELdAaQ[@ai}:3؉F"+ 5R3 yJ_kLj@ IGYJ*'Ǎy>f-?*dZY%Eۙƫt mI1uЊ!Hw*|qO`)t$O;Iɕ@c .-RJKߤtq[k'BKuq酥j6zj!zzpl]n(4vt6lzݫId o-*Jg-0Y/# 8Ͼa0df5yrp/+jzD4+ sjub;0-m{nGF/ꎃpR*+ӆQ<6x4hݸ䩵轢G'ߧ8$}.i\Q Er8{:hwAk1\tuuW@jgIUUVgYOsO9d WM̐|iI{D;h cTÄE<ˣ\8xS|* Nj%_ƄSbg;tamǙq%_?QG{Vw]O" ֵ@߽~[f&]#.׮M~PU?| "(]J JDM8Jq]YY.ZͰqj~]yڵTĭ2Owhc2RI!910>{N}/݁CF:-H'Qw) QL{⨞pXt 2zUt 3 ƞ•"KA-~Og#2,>#"=|m­p=Dh)B[30/^mq{3^؀T* %kS |n"}^}9djC~ ) S@s' }853.K_^vR*jXrE9%垺JDM`T~sS}Ӷuh4mٞy""C.8/0FT"iX4=m/k Жҽ=)O}dКY2 FeFN@H4- n;Ա 6Fh=wP,V\FS'D暀U!uV:t֨Д\nn/vJ֜bTaV!dFqڛ"WZl: bnM@,_ 9rouT{9huyw !Ĺėg-IWm5s~aڣx?[ث씩/6~|:SMFo>j54KPviNcbi4Mx_!z%@A[,ScvN>lM$z-.^]1E_Mv*1Xׁ=Tl XDPX y}V,[^tD٩.FXɕXr?J1ZFx+ֆaKgUVͳ>}*lNaҔa8?U+z_0>79sZ*| Tb~۬K8j!I?@\'k$VՁX_ϋwtdb3mX1;Bѽ/Q4Z 1쁘Ef~} HG'^itɆՈ_xEEޞ;s藌f4KU|Qp$놃Dċ%ΊvTYi2$YSd&q/#jPiA"mD@/JwfWle$M?bpbl!-YАZ,}щ]!>jE4-T}%\:wu~+EdaTk o25WHɱǣ$5f<ߛ% 0f $(V^w::00jNffw\JH$`xv h^HJhp[LG"]T .rl wo2P}SE+ u#CW/Ǫ>\OUǺnYOnO|AouRޣ%z'X1ȲϬ4 yy,k} ՁzGSIy&Zx˻!"\b 6 3jٻ{V!^Jo$Ers֤ OqNyt*;m-kf>$g.65FL7cNV#AW1.8BTFb~E*˖xΰ凔P1[e\ۑXZjAz<@=kl6Xx6%ӿx{<3V|a>=%]Nzx9AXP¾cdd~ lw@Vwt@Bg aN_ӥXWO?iWWh .xKg7vWw?;|V:TC!?$,ǂYL(dSui@5: <M| $sӍ|ڂ5p:Fw?FI?l`,2ڎfE ٣0^94:9| \7MKeq9u֨F('BClA޸H"[:LC^<˄Rc9|N[@L:Q?eGd ?bǰyCV,|=o~@/dvܿ2NeRB62Ln 03׽f26U[+*`L =J@0~4wW@H)dnZRON&ͥ1#|]3+SGde5 )._!5~odbŢ٨w: ɱVHN]45Hen6Vϰ)?s`HZ[g N`5C=h+o2BK#1 IU;RTj㘚:hv|V]L8(a֪Ώ5W+"0zF{8ШJVMgudH0zI2G:D>R󉱢N$"cjUzI\A97_  >&Dh[b,fj%OI jgRѽ5]x^[ >!4ک@ pLi_=JAzJ_ 7o6>|F_v9E4=:'GrCp2?aFi; =os}#DS)cz`<=e5V|uс;W Ubц@\xC3V&zEၠN!([F>0ZYr=P,r4ql|tI{7x}Y^p-CϏCp ~*e ʌ-kLyFq_Lw̒ w Z mɢ'lrR&P #S-?„x8lDs"Ӫ4,U/䦒IkJXi)M## gPp -JKg<]HyHky[#k?ڃ8t- ﹔&/a˩W{.X*]e-^L*JCqǥodbi1x͉Xj6|lShosUw:)=v}gkk2\J1iyuHe˲lQ =e۝w;\4N C)O%L0$8ҧU1?,jpHuC\|McB25YrٽL2!;w)^ʞ*(NOiwb>m؞vBa^+s > f遄"^[H }{e&YмV 1İLA:` /َd] #3g-PDžΤB 4׮/_p3S* iN577˽]]hp1씍'~R$}A2XU74'YeVvbY`G| \Qǭ3 tfk;SIjY&v>HĊ ɱƪ7nr1څOtŇwrMBtT-Ͼz'%? R 4eL`X9g爯!|~ 2"/vd2b;)E5ל*Lݗ8,\035DŎ4=T\yʲXt;}uȡG E8pR(|^qb9^xByuDx7c8qټH =F||JzP:~A{F^4͌5|*vISօ#-+M=M1'?'Mx996m7% wU&@TPun,ՒIB؉L@l~nsƼI8}|vo3hu1'W@C)!]! '8ibQ6 PO2JIK ??/ ejYҩob!_n]''ǻ 0DڳÉ&"G}Fr-hӐ ɻ4&S?!E팗Q'gW .E@㳳:A ffQP*ɞQ<+E./60@QH& "H9GE+ZJL,.>O{Ӑ!`Rvz`XUE$;My7e_ ƺn"c: ͛*87vEzȝ_6cΟoDL#yc`vW!u͎x(l[ܙ@jcV7&KGNβeLMzd{'zz'관a0M0t?4JXF5}RV.q `eX9ps[ʩ1B(P[rM O" @Ît(wo%]ŬYA֓ؼ@/_Ai(DnCCoD p_DXs-ʬ H:/YbĒD~+ɮ 2)(6ӳcn12o!_x~ь ّq&.u^4,$TrhҸnaW΄j u# q+OHI2 i<.A~B 5q[axgʎ3-z* SЀ"Xޝav$=ݩm 驵C6Z4|,1UVx5b&ԒR+q !}yeo&^Vj̚' v%(Y^`!fHl)%N>(|{=AK{xc*'7 JΖkn$m+\נ q½D/a =Snv /M<4A`eZU[z9bæNsУ Sě&~Ll#@+zغ0vXSLVX7*@8R)!)RbxYJ}]I_ |x4Ȁ[>lZ|~ρoc+]#;5}(SC!w(]"5ix2I*p݀d7qѸc Vc'9wb9d\B{K-\7^Rb&˖mp_P2/Yk>]^2B(;}#a a^WUحjnjs}(F\8)z?CcK n)0w%JNv;dkSgD:&Y;|BOxi=z5A7:pz. .ױse'eJڛ+*C2,)%m'+i8NJ+f'Ϥ љp|Q@YZGUniFrac/man/0000755000176200001440000000000014141326712012464 5ustar liggesusersGUniFrac/man/GUniFrac.Rd0000644000176200001440000000674014105341742014420 0ustar liggesusers\name{GUniFrac} \alias{GUniFrac} %- Also NEED an '\alias' for EACH other topic documented here. \title{ Generalized UniFrac distances for comparing microbial communities. } \description{ A generalized version of commonly used UniFrac distances. It is defined as: \deqn{d^{(\alpha)} = \frac{\sum_{i=1}^m b_i (p^A_{i} + p^B_{i})^\alpha \left\vert \frac{ p^A_{i} - p^B_{i} }{p^A_{i} + p^B_{i}} \right\vert } { \sum_{i=1}^m b_i (p^A_{i} + p^B_{i})^\alpha},}{d^{(\alpha)} = [\sum_{i=1}^m b_i (p^A_{i} + p^B_{i})^\alpha |p^A_{i} - p^B_{i}|/(p^A_{i} + p^B_{i})]/ [ \sum_{i=1}^m b_i (p^A_{i} + p^B_{i})^\alpha],} where \eqn{m}{m} is the number of branches, \eqn{b_i}{b_i} is the length of \eqn{i}{i}th branch, \eqn{p^A_{i}, p^B_{i}}{p^A_{i}, p^B_{i}} are the branch proportion for community A and B. Generalized UniFrac distance contains an extra parameter \eqn{\alpha}{\alpha} controlling the weight on abundant lineages so the distance is not dominated by highly abundant lineages. \eqn{\alpha=0.5}{\alpha=0.5} is overall very robust. The unweighted and weighted UniFrac, and variance-adjusted weighted UniFrac distances are also implemented. } \usage{ GUniFrac(otu.tab, tree, alpha = c(0, 0.5, 1)) } %- maybe also 'usage' for other objects documented here. \arguments{ \item{otu.tab}{ %% ~~Describe \code{otu.tab} here~~ an OTU count table, row - n sample, column - q OTU } \item{tree}{ %% ~~Describe \code{tree} here~~ a rooted phylogenetic tree of R class \dQuote{phylo} } \item{alpha}{ %% ~~Describe \code{alpha} here~~ the parameter controlling weight on abundant lineages } } \value{ %% ~Describe the value returned %% If it is a LIST, use %% \item{comp1 }{Description of 'comp1'} %% \item{comp2 }{Description of 'comp2'} %% ... Return a list containing \item{unifracs}{a three dimensional array containing all the UniFrac distance matrices} } \references{ %% ~put references to the literature/web site here ~ Chen, J., Bittinger, K., Charlson, E.S., Hoffmann, C., Lewis, J., Wu, G.D., Collman, R.G., Bushman, F.D. and Li, H. (2012). Associating microbiome composition with environmental covariates using generalized UniFrac distances. 28(16): 2106–2113. } \author{ %% ~~who you are~~ Jun Chen } \note{ %% ~~further notes~~ The function only accepts rooted tree. To root a tree, you may consider using \code{midpoint} from the package \code{phangorn}. } %% ~Make other sections like Warning with \section{Warning }{....} ~ \seealso{ %% ~~objects to See Also as \code{\link{help}}, ~~~ \code{\link{Rarefy}}, \code{\link{PermanovaG}} } \examples{ data(throat.otu.tab) data(throat.tree) data(throat.meta) groups <- throat.meta$SmokingStatus # Rarefaction otu.tab.rff <- Rarefy(throat.otu.tab)$otu.tab.rff # Calculate the UniFracs unifracs <- GUniFrac(otu.tab.rff, throat.tree, alpha=c(0, 0.5, 1))$unifracs dw <- unifracs[, , "d_1"] # Weighted UniFrac du <- unifracs[, , "d_UW"] # Unweighted UniFrac dv <- unifracs[, , "d_VAW"] # Variance adjusted weighted UniFrac d0 <- unifracs[, , "d_0"] # GUniFrac with alpha 0 d5 <- unifracs[, , "d_0.5"] # GUniFrac with alpha 0.5 # Permanova - Distance based multivariate analysis of variance adonis3(as.dist(d5) ~ groups) } % Add one or more standard keywords, see file 'KEYWORDS' in the % R documentation directory. \keyword{ distance } \keyword{ UniFrac } \keyword{ ecology }% __ONLY ONE__ keyword per line GUniFrac/man/throat.otu.tab.Rd0000644000176200001440000000221414106041265015624 0ustar liggesusers\name{throat.otu.tab} \alias{throat.otu.tab} \docType{data} \title{ %% ~~ data name/kind ... ~~ Throat Microbiome OTU Count Table } \description{ %% ~~ A concise (1-5 lines) description of the dataset. ~~ It is part of a microbiome data set (16S V12-targeted 454 pyrosequencing) for studying the effect of smoking on the upper respiratory tract microbiome. The original data set contains samples from both throat and nose microbiomes, and from both body sides. This data set comes from the throat microbiome of left body side. It contains 60 subjects consisting of 32 nonsmokers and 28 smokers. } \usage{data(throat.otu.tab)} \details{ %% ~~ If necessary, more details than the __description__ above ~~ The OTU table is produced by the QIIME software. Singleton OTUs have been discarded. } \source{ %% ~~ reference to a publication or URL from which the data were obtained ~~ Charlson ES, Chen J, Custers-Allen R, Bittinger K, Li H, et al. (2010) Disordered Microbial Communities in the Upper Respiratory Tract of Cigarette Smokers. PLoS ONE 5(12): e15216. } \examples{ data(throat.otu.tab) } \keyword{datasets} GUniFrac/man/Rarefy.Rd0000644000176200001440000000277414105534531014215 0ustar liggesusers\name{Rarefy} \alias{Rarefy} %- Also NEED an '\alias' for EACH other topic documented here. \title{ Rarefy a Count Table to Equal Sequencing Depth } \description{ GUniFrac is also sensitive to different sequencing depth. To compare microbiomes on an equal basis, rarefaction might be used. } \usage{ Rarefy(otu.tab, depth = min(rowSums(otu.tab))) } %- maybe also 'usage' for other objects documented here. \arguments{ \item{otu.tab}{ OTU count table, row - n sample, column - q OTU } \item{depth}{ required sequencing depth; If not specified, the lowest sequencing depth is used. } } \value{ Return a list containing: \item{otu.tab.rff}{rarefied OTU table} \item{discard}{IDs of samples that does not reach the specified sequencing depth} %% ... } \references{ %% ~put references to the literature/web site here ~ Chen, J., Bittinger, K., Charlson, E.S., Hoffmann, C., Lewis, J., Wu, G.D., Collman, R.G., Bushman, F.D. and Li, H. (2012). Associating microbiome composition with environmental covariates using generalized UniFrac distances. 28(16): 2106–2113. } \author{ %% ~~who you are~~ Jun Chen } %% ~Make other sections like Warning with \section{Warning }{....} ~ \examples{ data(throat.otu.tab) # Rarefaction otu.tab.rff <- Rarefy(throat.otu.tab, 1024)$otu.tab.rff } % Add one or more standard keywords, see file 'KEYWORDS' in the % R documentation directory. \keyword{ Normalization} \keyword{ Microbiome}% __ONLY ONE__ keyword per line GUniFrac/man/PermanovaG2.Rd0000644000176200001440000000622114105341573015077 0ustar liggesusers\name{PermanovaG2} \alias{PermanovaG2} %- Also NEED an '\alias' for EACH other topic documented here. \title{ %% ~~function to do ... ~~ Permutational Multivariate Analysis of Variance Using Multiple Distance Matrices(Freedman-Lane Permutation) } \description{ %% ~~ A concise (1-5 lines) description of what the function does. ~~ In practice, we do not know a priori which type of change happens in the microbiome. Each distance measure is most powerful in detecting only a certain scenario. When multiple distance matrices are available, separate tests using each distance matrix will lead to loss of power due to multiple testing correction. Combing the distance matrices in a single test will improve power. PermanovaG combines multiple distance matrices by taking the minimum of the P values for individual distance matrices. Significance is assessed by permutation. } \usage{ PermanovaG2(formula, data = NULL, ...) } %- maybe also 'usage' for other objects documented here. \arguments{ \item{formula}{ %% ~~Describe \code{formula} here~~ a formula, left side of the formula (\code{Y ~ X}) is a three dimensional ARRAY containing the supplied distance matrices as produced by \code{\link{GUniFrac}} function. Or it could be a list of distance matrices. } \item{data}{ %% ~~Describe \code{dat} here~~ a data frame containing the covariates } \item{\dots}{ %% ~~Describe \code{\dots} here~~ parameters passing to \code{adonis} function } } \value{ %% ~Describe the value returned %% If it is a LIST, use %% \item{comp1 }{Description of 'comp1'} %% \item{comp2 }{Description of 'comp2'} %% ... Return a list containing: \item{p.tab}{a data frame, columns: p-values for individual distance matrices and the omnibus test, rows: covariates. (Note: they are sequential p-values, put the variable of interest in the end)} \item{aov.tab.list}{a list of \code{adonis} AOV tables for individual distance matrices} } \references{ %% ~put references to the literature/web site here ~ Chen, J., Bittinger, K., Charlson, E.S., Hoffmann, C., Lewis, J., Wu, G.D., Collman, R.G., Bushman, F.D. and Li, H. (2012). Associating microbiome composition with environmental covariates using generalized UniFrac distances. 28(16): 2106–2113. } \author{ %% ~~who you are~~ Jun Chen } %% ~Make other sections like Warning with \section{Warning }{....} ~ \seealso{ %% ~~objects to See Also as \code{\link{help}}, ~~~ \code{\link{Rarefy}}, \code{\link{GUniFrac}}, \code{\link{adonis3}} } \examples{ data(throat.otu.tab) data(throat.tree) data(throat.meta) groups <- throat.meta$SmokingStatus # Rarefaction otu.tab.rff <- Rarefy(throat.otu.tab)$otu.tab.rff # Calculate the UniFracs unifracs <- GUniFrac(otu.tab.rff, throat.tree, alpha=c(0, 0.5, 1))$unifracs # Combine unweighted and weighted UniFrac for testing PermanovaG2(unifracs[, , c("d_1", "d_UW")] ~ groups) } % Add one or more standard keywords, see file 'KEYWORDS' in the % R documentation directory. \keyword{ distance } \keyword{ multivariate } \keyword{ nonparametric } \keyword{ regression }% __ONLY ONE__ keyword per line GUniFrac/man/SimulateMSeq.Rd0000644000176200001440000002006014106041247015320 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/sim.R \name{SimulateMSeq} \alias{SimulateMSeq} \title{A Semiparametric Model-based Microbiome Sequencing Data Simulator} \description{ The function generates synthetic microbiome sequencing data for studying the performance of differential abundance analysis methods. It uses a user-supplied (large) reference OTU table as a template to generate a synthetic OTU table of specified size. A subset of OTUs are affected by a simulated covariate of interest, either binary or continuous. Confounder effects can also be simulated. The function allows simulating different signal structures, i.e., the percentage of differential OTUs, their effect sizes, their direction of change, and whether these OTUs are relatively abundant or rare. } \usage{ SimulateMSeq( ref.otu.tab, nSam = 100, nOTU = 500, diff.otu.pct = 0.1, diff.otu.direct = c("balanced", "unbalanced"), diff.otu.mode = c("abundant", "rare", "mix"), covariate.type = c("binary", "continuous"), grp.ratio = 1, covariate.eff.mean = 1, covariate.eff.sd = 0, confounder.type = c("none", "binary", "continuous", "both"), conf.cov.cor = 0.6, conf.diff.otu.pct = 0, conf.nondiff.otu.pct = 0.1, confounder.eff.mean = 0, confounder.eff.sd = 0, error.sd = 0, depth.mu = 10000, depth.theta = 5, depth.conf.factor = 0 ) } \arguments{ \item{ref.otu.tab}{a matrix, the reference OTU count table (row - OTUs, column - samples), serving as the template for synthetic sample generation.} \item{nSam}{the number of samples to be simulated.} \item{nOTU}{the number of OTUs to be simulated. } \item{diff.otu.pct}{a numeric value between 0 and 1, the percentage of differential OTUs to be simulated. If 0, global null setting is simulated. The default is 0.1.} \item{diff.otu.direct}{a character string of "balanced" or "unbalanced". "balanced" - the direction of change for these differential OTUs is random, "unbalanced" - direction of change is the same. The default is "balanced".} \item{diff.otu.mode}{a character string of "rare", "mix" or "abundant". "abundant" - differential OTU come from the top quartile of the abundance distribution, "rare" - differential OTU come from the bottom quartile of the abundance distribution, and "mix" - random set. The default is "abundant". } \item{covariate.type}{a character string of "binary" or "continuous", indicating the type of the covariate to be simulated. The default is "binary" (e.g., case v.s. control).} \item{grp.ratio}{a numeric value between 0 and 1. Group size ratio. The default is 1, i.e., equal group size. Only relevant when \code{covariate.type} is "binary". } \item{covariate.eff.mean}{a numeric value, the mean log fold change (effect size) in response to one unit change of the covariate. The default is 1.} \item{covariate.eff.sd}{a positive numeric value, the standard deviation of the log fold change. The default is 0, i.e., the log fold change is the same across differential OTUs.} \item{confounder.type}{a character string of "none", "binary", "continuous" or "both". The default is "none", no confounder will be simulated. If "both", both a binary and continuous confounder will be simulated. The default is "none".} \item{conf.cov.cor}{a numeric value between 0 and 1. The correlation between the covariate of interest and the confounder. The default is 0.6.} \item{conf.diff.otu.pct}{a numeric value between 0 and 1. The percentage of OTUs affected by the confounder and the covariate of interest. The default is 0.} \item{conf.nondiff.otu.pct}{a numeric value between 0 and 1. The percentage of OTUs affected by the confounder but not the covariate of interest. The default is 0.1.} \item{confounder.eff.mean}{a numeric value, the mean log fold change (effect size) in response to one unit change of the confounder. The default is 1.} \item{confounder.eff.sd}{a positive numeric value, the standard deviation of the log fold change for the confounder. The default is 0, i.e., the log fold change is the same across OTUs affected by the confounder.} \item{error.sd}{the sd of the log fold change unexplained by the covariate and the confounder (i.e., the error term under the log linear model). The default is 0. } \item{depth.mu}{the mean sequencing depth to be simulated. The default is 10,000.} \item{depth.theta}{the theta value of the negative binomial distribution controlling the variance (\code{mu + mu^2/theta}). The default is 5.} \item{depth.conf.factor}{a numeric value controlling the dependence of the sequencing depth on the covariate of interest (\code{depth.mu} * \code{exp(scale(X)} * \code{depth.conf.factor})). The default is 0, i.e., the depth is not associated with the covariate of interest. This parameter can be used to simulate depth confounding.} } \value{ Return a list with the elements: \item{otu.tab.sim}{simulated OTU table} \item{covariate}{simulated covariate of interest} \item{confounder}{simulated confounder(s)} \item{diff.otu.ind}{indices of the differential OTUs, i.e., affected by the covariate of interest} \item{otu.names}{the names of the simulated OTUs} \item{conf.otu.ind}{indices of OTUs affected by the confounder(s)} } \details{ This function implements a semiparametric approach for realistic microbiome sequencing data generation. The method draws random samples from a large reference dataset (non-parametric part) and uses these reference samples as templates to generate new samples (parametric part). Specifically, for each drawn reference sample, it infers the underlying composition based on a Bayesian model and then adds covariate/confounder effects to the composition vector, based on which a new sequencing sample is generated. The method circumvents the difficulty in modeling the inter-subject variation of the microbiome composition. } \references{ Yang, L. & Chen, J. 2021+. A comprehensive evaluation of differential abundance analysis methods: current status and potential solutions. Submitted. } \author{Jun Chen and Lu Yang} \examples{ # Use throat microbiome for illustration data(throat.otu.tab) comm <- t(throat.otu.tab) comm <- comm[rowMeans(comm != 0) > 0.2, ] # Simulate binary covariate, 10\% signal density, abundant differential OTUs, unbalanced change # This setting simulates strong compositional effects sim.obj <- SimulateMSeq( ref.otu.tab = comm, nSam = 50, nOTU = 50, # True signal setting diff.otu.pct = 0.1, diff.otu.direct = c("unbalanced"), diff.otu.mode = c("abundant"), covariate.type = c("binary"), grp.ratio = 1, covariate.eff.mean = 1.0, covariate.eff.sd = 0, # Confounder signal setting confounder.type = c("both"), conf.cov.cor = 0.6, conf.diff.otu.pct = 0.1, conf.nondiff.otu.pct = 0.1, confounder.eff.mean = 1.0, confounder.eff.sd = 0, # Depth setting depth.mu = 10000, depth.theta = 5, depth.conf.factor = 0 ) meta.dat <- data.frame(X = sim.obj$covariate, Z1 = sim.obj$confounder[, 1], Z2 = sim.obj$confounder[, 2]) otu.tab.sim <- sim.obj$otu.tab.sim # Run ZicoSeq for differential abundance analysis zico.obj <- ZicoSeq(meta.dat = meta.dat, feature.dat = otu.tab.sim, grp.name = 'X', adj.name = c('Z1', 'Z2'), feature.dat.type = "count", # Filter to remove rare taxa prev.filter = 0.2, mean.abund.filter = 0, max.abund.filter = 0.002, min.prop = 0, # Winsorization to replace outliers is.winsor = TRUE, outlier.pct = 0.03, winsor.end = 'top', # Posterior sampling to impute zeros is.post.sample = TRUE, post.sample.no = 25, # Multiple link functions to capture diverse taxon-covariate relation link.func = list(function (x) x^0.25, function (x) x^0.5, function (x) x^0.75), stats.combine.func = max, # Permutation-based multiple testing correction perm.no = 99, strata = NULL, # Reference-based multiple stage normalization ref.pct = 0.5, stage.no = 6, excl.pct = 0.2, # Family-wise error rate control is.fwer = FALSE, verbose = TRUE, return.feature.dat = FALSE) # Detected differential OTUs which(zico.obj$p.adj.fdr <= 0.05) # True differential OTUs sim.obj$otu.names[sim.obj$diff.otu.ind] } \keyword{composition} \keyword{microbiome} \keyword{simulation} GUniFrac/man/linda.plot.Rd0000644000176200001440000000514214142647247015033 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/linda.R \name{linda.plot} \alias{linda.plot} \title{Plot LinDA Results} \usage{ linda.plot( linda.obj, variables.plot, titles = NULL, alpha = 0.05, lfc.cut = 1, legend = FALSE, directory = NULL, width = 11, height = 8 ) } \arguments{ \item{linda.obj}{return from function \code{linda}.} \item{variables.plot}{vector; variables whose results are to be plotted. For example, suppose the return value \code{variables} is equal to \code{('x1', 'x2', 'x3b', 'x3c', 'x1:x2')}, then one could set \code{variables.plot = c('x3b', 'x1:x2')}.} \item{titles}{vector; titles of the effect size plot and volcano plot for each variable in \code{variables.plot}. Default is NULL. If NULL, the titles will be set as \code{variables.plot}.} \item{alpha}{a numerical value between 0 and 1; cutoff for \code{padj}.} \item{lfc.cut}{a positive numerical value; cutoff for \code{log2FoldChange}.} \item{legend}{TRUE or FALSE; whether to show the legends of the effect size plot and volcano plot.} \item{directory}{character; the directory to save the figures, e.g., \code{getwd()}. Default is NULL. If NULL, figures will not be saved.} \item{width}{the width of the graphics region in inches. See R function \code{pdf}.} \item{height}{the height of the graphics region in inches. See R function \code{pdf}.} } \value{ A list of \code{ggplot2} objects. \item{plot.lfc}{a list of effect size plots. Each plot corresponds to one variable in \code{variables.plot}.} \item{plot.volcano}{a list of volcano plots. Each plot corresponds to one variable in \code{variables.plot}.} } \description{ The function produces the effect size plot of the differential features and volcano plot based on the output from \code{linda}. } \examples{ data(throat.otu.tab) data(throat.tree) data(throat.meta) comm <- t(throat.otu.tab) meta.dat <- throat.meta # For count data linda.obj <- linda(comm, meta.dat, formula = '~SmokingStatus+Sex', feature.dat.type = 'count', prev.filter = 0.2, is.winsor = TRUE, outlier.pct = 0.03, p.adj.method = "BH", alpha = 0.1 ) rownames(linda.obj$output[[1]])[which(linda.obj$output[[1]]$reject)] linda.plot(linda.obj, c('SmokingStatusSmoker', 'Sexmale'), titles = c('Smoke: n v.s. y', 'Sex: female v.s. male'), alpha = 0.1, lfc.cut = 1, legend = TRUE, directory = NULL, width = 11, height = 8) } \references{ Huijuan Zhou, Kejun He, Jun Chen, and Xianyang Zhang. LinDA: Linear Models for Differential Abundance Analysis of Microbiome Compositional Data. } \author{ Huijuan Zhou, Jun Chen, Xianyang Zhang } GUniFrac/man/dmanova.Rd0000644000176200001440000000651214105340537014405 0ustar liggesusers \name{dmanova} \alias{dmanova} \title{Distance-based Multivariate Analysis of Variance (Analytical P-value Calculation)} \description{Analysis of variance using distance matrices --- for partitioning distance matrices among sources of variation and fitting linear models (e.g., factors, polynomial regression) to distance matrices; calculate the analytical p-value based on pseudo-\eqn{F} statistic without permutation.} \usage{ dmanova(formula, data = NULL, positify = FALSE, contr.unordered = "contr.sum", contr.ordered = "contr.poly", returnG = FALSE) } \arguments{ \item{formula}{model formula. The LHS must be a dissimilarity matrix (either class \code{matrix} or class \code{dist}, e.g., from \code{\link{vegdist}} or \code{\link{dist}}. The RHS defines the independent variables. These can be continuous variables or factors, they can be transformed within the formula, and they can have interactions as in a typical \code{\link{formula}}. } \item{data}{the data frame for the independent variables.} \item{positify}{a logical value indicating whether to make the Gower's matrix positive definite using the \code{\link{nearPD}} function in \code{Matrix} package. This is equivalent to modifying the distance matrix so that it has an Euclidean embedding. } \item{contr.unordered, contr.ordered}{contrasts used for the design matrix (default in R is dummy or treatment contrasts for unordered factors). } \item{returnG}{a logical value indicating whether the Gower's matrix should be returned.} } \details{ \code{dmanova} is a permutation-free method for approximating the p-value from distance-based permutational multivariate analysis of variance (PERMANOVA). PERMANOVA is slow when the sample size is large. In contrast, \code{dmanova} provides an analytical solution, which is several orders of magnitude faster for large sample sizes. The covariate of interest should be put as the last term in \code{formula} while the variables to be adjusted are put before the covariate of interest. } \value{ Function \code{dmanova} returns a list with the following components: \item{aov.tab}{typical AOV table showing sources of variation, degrees of freedom, sums of squares, mean squares, \eqn{F} statistics, partial \eqn{R^2}{R-squared} and \eqn{P} values. } \item{df}{degree of freedom for the Chisquared distribution.} \item{G}{ The Gower's matrix if \code{returnG} is true.} \item{call}{ the call made} } \references{ Chen, J. & Zhang, X. 2021. D-MANOVA: fast distance-based multivariate analysis of variance for large-scale microbiome association studies. Bioinformatics. https://doi.org/10.1093/bioinformatics/btab498 } \author{Jun Chen and Xianyang Zhang} \examples{ data(throat.otu.tab) data(throat.tree) data(throat.meta) groups <- throat.meta$SmokingStatus # Rarefaction otu.tab.rff <- Rarefy(throat.otu.tab)$otu.tab.rff # Calculate the UniFrac distance unifracs <- GUniFrac(otu.tab.rff, throat.tree, alpha=c(0, 0.5, 1))$unifracs # Test the smoking effect based on unweighted UniFrac distance, adjusting sex # 'Sex' should be put before 'SmokingStatus' dmanova(as.dist(unifracs[, , 'd_UW']) ~ Sex + SmokingStatus, data = throat.meta) } \seealso{ %% ~~objects to See Also as \code{\link{help}}, ~~~ \code{\link{adonis3}} } \keyword{distance} \keyword{multivariate} GUniFrac/man/vaginal.otu.tab.Rd0000644000176200001440000000215314106041274015746 0ustar liggesusers\name{vaginal.otu.tab} \alias{vaginal.otu.tab} \docType{data} \title{ %% ~~ data name/kind ... ~~ Vaginal Microbiome OTU Count Table } \description{ %% ~~ A concise (1-5 lines) description of the dataset. ~~ OTU count table from 16S V3-V5 targeted sequencing of the vaginal microbiome samples from the HMP project. A total of 780 OTUs from 381 samples. } \usage{data(vaginal.otu.tab)} \details{ %% ~~ If necessary, more details than the __description__ above ~~ The OTU table was taken from R bioconductor "HMP16SData" package. OTUs with prevalence less than 10\% and maximum proportion less than 0.2\% were removed. This OTU table can be used for simulating vaginal microbiome sequencing data. } \source{ %% ~~ reference to a publication or URL from which the data were obtained ~~ Schiffer L, Azhar R, Shepherd L, Ramos M, Geistlinger L, Huttenhower C, Dowd JB, Segata N, Waldron L (2019). “HMP16SData: Efficient Access to the Human Microbiome Project through Bioconductor.” American Journal of Epidemiology. doi: 10.1093/aje/kwz006. } \examples{ data(stool.otu.tab) } \keyword{datasets} GUniFrac/man/ZicoSeq.Rd0000644000176200001440000002344714141345605014344 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ZicoSeq.R \name{ZicoSeq} \alias{ZicoSeq} \title{A linear Model-based Permutation Test for Differential Abundance Analysis of Microbiome Data and Other Omics Data} \description{ZicoSeq is a permutation test (Smith permutation) for differential abundance analysis of microbiome sequencing data. The input can be a count or a proportion matrix. When a count matrix is provided, it provides an option to draw posterior samples of the underlying proportions to account for the sampling variability during the sequencing process. The test results are aggregated over these posterior samples. For both count and proportion data, a reference-based ratio approach is used to account for compositional effects. As a general methodology, ZicoSeq can also be applied to differential analysis of other omics data. In this case, they are not treated as compositional data. } \usage{ ZicoSeq( meta.dat, feature.dat, grp.name, adj.name = NULL, feature.dat.type = c('count', 'proportion', 'other'), prev.filter = 0, mean.abund.filter = 0, max.abund.filter = 0, min.prop = 0, is.winsor = TRUE, outlier.pct = 0.03, winsor.end = c('top', 'bottom', 'both'), is.post.sample = TRUE, post.sample.no = 25, link.func = list(function(x) x^0.5), stats.combine.func = max, perm.no = 99, strata = NULL, ref.pct = 0.5, stage.no = 6, excl.pct = 0.2, is.fwer = FALSE, verbose = TRUE, return.feature.dat = FALSE ) } \arguments{ \item{meta.dat}{a data frame containing the sample meta data.} \item{feature.dat}{a matrix of feature data, row - features (OTUs, genes, etc) , column - samples.} \item{grp.name}{the name for the variable of interest. It could be numeric or categorical; should be in \code{meta.dat}.} \item{adj.name}{the name(s) for the variable(s) to be adjusted. Multiple variables are allowed. They could be numeric or categorical; should be in \code{meta.dat}.} \item{feature.dat.type}{the type of the feature data. It could be "count", "proportion" or "other". For "proportion" data type, posterior sampling will not be performed, but the reference-based ratio approach will still be used to address compositional effects. For "other" data type, neither posterior sampling or reference-base ratio approach will be used.} \item{prev.filter}{the prevalence (percentage of nonzeros) cutoff, under which the features will be filtered. The default is 0. } \item{mean.abund.filter}{the mean relative abundance cutoff, under which the features will be filtered. The default is 0.} \item{max.abund.filter}{the max relative abundance cutoff, under which the features will be filtered. The default is 0.} \item{min.prop}{ proportions less than this value will be replaced with this value. Only relevant when log transformation is used. Default is 0.} \item{is.winsor}{a logical value indicating whether winsorization should be performed to replace outliers. The default is TRUE.} \item{outlier.pct}{the expected percentage of outliers. These outliers will be winsorized. The default is 0.03.} \item{winsor.end}{a character indicating whether the outliers at the "top", "bottom" or "both" will be winsorized. The default is "top". If the \code{feature.dat.type} is "other", "both" may be considered.} \item{is.post.sample}{a logical value indicating whether to perform posterior sampling of the underlying proportions. Only relevant when the feature data are counts.} \item{post.sample.no}{the number of posterior samples if posterior sampling is used. The default is 25.} \item{link.func}{a list of transformation functions for the feature data or the ratios. Based on our experience, square-root transformation is a robust choice for many datasets.} \item{perm.no}{the number of permutations. If the raw p values are of the major interest, set \code{perm.no} to at least 999.} \item{strata}{a factor such as subject IDs indicating the permutation strata. Permutation will be confined to each stratum. This can be used for paired or some longitudinal designs.} \item{stats.combine.func}{function to combine the F-statistic for the omnibus test. The default is \code{max}.} \item{ref.pct}{percentage of reference taxa. The default is 0.5.} \item{stage.no}{the number of stages if multiple-stage normalization is used. The default is 6.} \item{excl.pct}{the maximum percentage of significant features (nominal p-value < 0.05) in the reference set that should be removed. Only relevant when multiple-stage normalization is used.} \item{is.fwer}{a logical value indicating whether the family-wise error rate control (West-Young) should be performed.} \item{verbose}{a logical value indicating whether the trace information should be printed out.} \item{return.feature.dat}{a logical value indicating whether the winsorized, filtered "feature.dat" matrix should be returned.} } \value{ A list with the elements \item{call}{the call} \item{feature.dat}{the winsorized, filtered \code{feature.dat} matrix.} \item{filter.ind}{a vector of logical values indicating which features are tested.} \item{R2}{a matrix of percent explained variance (number of features by number of transformation functions).} \item{F0}{a matrix of F-statistics (number of features by number of transformation functions).} \item{RSS}{a matrix of residual sum squares (number of features by number of transformation functions).} \item{df.model, df.residual}{degrees of freedom for the model and residual space.} \item{p.raw}{the raw p-values based on permutations (not accurate if \code{perm.no} is small).} \item{p.adj.fdr}{permutation-based FDR-adjusted p-values.} \item{p.adj.fwer}{permutation-based FWER-adjusted (West-Young) p-values.} } \details{ \code{ZicoSeq} is a linear model-based permutation test developed for differential abundance analysis of zero-inflated compositional data. Although its development is motivated by zero-inflated microbiome sequence count data, it can be applied to proportion (composition) data and more generally to other types of omics data. Currently, it has the following components: 1. Winsorization to decrease the influence of outliers; 2. Posterior sampling based on a beta mixture prior to address sampling variability and zero inflation; 3. Reference-based multiple-stage normalization to address compositional effects; 4. An omnibus test to address diverse feature-covariate relationships; 5. Permutation-based false discovery rate control / family-wise error rate control for multiple testing correction, which takes into account the correlation structure in the feature data. } \references{ Yang, L. & Chen, J. 2021+. A comprehensive evaluation of differential abundance analysis methods: current status and potential solutions. To be submitted. } \author{Jun Chen} \examples{ data(throat.otu.tab) data(throat.tree) data(throat.meta) comm <- t(throat.otu.tab) meta.dat <- throat.meta set.seed(123) # For count data zico.obj <- ZicoSeq(meta.dat = meta.dat, feature.dat = comm, grp.name = 'SmokingStatus', adj.name = 'Sex', feature.dat.type = "count", # Filter to remove rare taxa prev.filter = 0.2, mean.abund.filter = 0, max.abund.filter = 0.002, min.prop = 0, # Winsorization to replace outliers is.winsor = TRUE, outlier.pct = 0.03, winsor.end = 'top', # Posterior sampling to impute zeros is.post.sample = TRUE, post.sample.no = 25, # Multiple link functions to capture diverse taxon-covariate relation link.func = list(function (x) x^0.25, function (x) x^0.5, function (x) x^0.75), stats.combine.func = max, # Permutation-based multiple testing correction perm.no = 99, strata = NULL, # Reference-based multiple stage normalization ref.pct = 0.5, stage.no = 6, excl.pct = 0.2, # Family-wise error rate control is.fwer = FALSE, verbose = TRUE, return.feature.dat = FALSE) which(zico.obj$p.adj.fdr <= 0.05) # For proportion data comm.p <- t(t(comm) / colSums(comm)) zico.obj <- ZicoSeq(meta.dat = meta.dat, feature.dat = comm.p, grp.name = 'SmokingStatus', adj.name = 'Sex', feature.dat.type = "proportion", # Filter to remove rare taxa prev.filter = 0.2, mean.abund.filter = 0, max.abund.filter = 0.002, min.prop = 0, # Winsorization to replace outliers is.winsor = TRUE, outlier.pct = 0.03, winsor.end = 'top', # Posterior sampling will be automatically disabled is.post.sample = FALSE, post.sample.no = 25, # Use the square-root transformation link.func = list(function (x) x^0.5), stats.combine.func = max, # Permutation-based multiple testing correction perm.no = 99, strata = NULL, # Reference-based multiple stage normalization ref.pct = 0.5, stage.no = 6, excl.pct = 0.2, # Family-wise error rate control is.fwer = FALSE, verbose = TRUE, return.feature.dat = FALSE) which(zico.obj$p.adj.fdr <= 0.05) # For other type of data. The user should be responsible for the filtering. comm.o <- comm[rowMeans(comm != 0) >= 0.2, ] + 1 comm.o <- log(t(t(comm.o) / colSums(comm.o))) zico.obj <- ZicoSeq(meta.dat = meta.dat, feature.dat = comm.o, grp.name = 'SmokingStatus', adj.name = 'Sex', feature.dat.type = "other", # Filter will not be applied prev.filter = 0, mean.abund.filter = 0, max.abund.filter = 0, min.prop = 0, # Winsorization to both ends of the distribution is.winsor = TRUE, outlier.pct = 0.03, winsor.end = 'both', # Posterior sampling will be automatically disabled is.post.sample = FALSE, post.sample.no = 25, # Identity function is used link.func = list(function (x) x), stats.combine.func = max, # Permutation-based multiple testing correction perm.no = 99, strata = NULL, # Reference-based multiple-stage normalization will not be performed ref.pct = 0.5, stage.no = 6, excl.pct = 0.2, # Family-wise error rate control is.fwer = TRUE, verbose = TRUE, return.feature.dat = FALSE) which(zico.obj$p.adj.fdr <= 0.05) } \keyword{composition} \keyword{microbiome} \keyword{univariate} \keyword{permutation} GUniFrac/man/PermanovaG.Rd0000644000176200001440000000617514105341611015016 0ustar liggesusers\name{PermanovaG} \alias{PermanovaG} %- Also NEED an '\alias' for EACH other topic documented here. \title{ %% ~~function to do ... ~~ Permutational Multivariate Analysis of Variance Using Multiple Distance Matrices } \description{ %% ~~ A concise (1-5 lines) description of what the function does. ~~ In practice, we do not know a priori which type of change happens in the microbiome. Each distance measure is most powerful in detecting only a certain scenario. When multiple distance matrices are available, separate tests using each distance matrix will lead to loss of power due to multiple testing correction. Combing the distance matrices in a single test will improve power. PermanovaG combines multiple distance matrices by taking the minimum of the P values for individual distance matrices. Significance is assessed by permutation. } \usage{ PermanovaG(formula, data = NULL, ...) } %- maybe also 'usage' for other objects documented here. \arguments{ \item{formula}{ %% ~~Describe \code{formula} here~~ a formula, left side of the formula (\code{Y ~ X}) is a three dimensional ARRAY containing the supplied distance matrices as produced by \code{\link{GUniFrac}} function. Or it could be a list of distance matrices. } \item{data}{ %% ~~Describe \code{dat} here~~ a data frame containing the covariates } \item{\dots}{ %% ~~Describe \code{\dots} here~~ parameter passing to \code{adonis} function } } \value{ %% ~Describe the value returned %% If it is a LIST, use %% \item{comp1 }{Description of 'comp1'} %% \item{comp2 }{Description of 'comp2'} %% ... Return a list containing: \item{p.tab}{a data frame, columns: p-values for individual distance matrices and the omnibus test, rows: covariates. (Note: they are sequential p-values, put the variable of interest in the end)} \item{aov.tab.list}{a list of \code{adonis} AOV tables for individual distance matrices} } \references{ %% ~put references to the literature/web site here ~ Chen, J., Bittinger, K., Charlson, E.S., Hoffmann, C., Lewis, J., Wu, G.D., Collman, R.G., Bushman, F.D. and Li, H.(2012). Associating microbiome composition with environmental covariates using generalized UniFrac distances. 28(16): 2106–2113. } \author{ %% ~~who you are~~ Jun Chen } %% ~Make other sections like Warning with \section{Warning }{....} ~ \seealso{ %% ~~objects to See Also as \code{\link{help}}, ~~~ \code{\link{Rarefy}}, \code{\link{GUniFrac}} } \examples{ data(throat.otu.tab) data(throat.tree) data(throat.meta) groups <- throat.meta$SmokingStatus # Rarefaction otu.tab.rff <- Rarefy(throat.otu.tab)$otu.tab.rff # Calculate the UniFracs unifracs <- GUniFrac(otu.tab.rff, throat.tree, alpha=c(0, 0.5, 1))$unifracs # Combine unweighted and weighted UniFrac for testing PermanovaG(unifracs[, , c("d_1", "d_UW")] ~ groups) # Combine d(0), d(0.5), d(1) for testing } % Add one or more standard keywords, see file 'KEYWORDS' in the % R documentation directory. \keyword{ distance } \keyword{ multivariate } \keyword{ nonparametric } \keyword{ regression }% __ONLY ONE__ keyword per line GUniFrac/man/throat.tree.Rd0000644000176200001440000000154414106041374015215 0ustar liggesusers\name{throat.tree} \alias{throat.tree} \docType{data} \title{ %% ~~ data name/kind ... ~~ UPGMA Tree of Throat Microbiome OTUs } \description{ %% ~~ A concise (1-5 lines) description of the dataset. ~~ The OTU tree is constructed using UPGMA on the K80 distance matrice of the OTUs. It is a rooted tree of class "phylo". } \usage{data(throat.tree)} \details{ %% ~~ If necessary, more details than the __description__ above ~~ The OTUs are produced by the QIIME software. Singleton OTUs have been discarded. } \source{ %% ~~ reference to a publication or URL from which the data were obtained ~~ Charlson ES, Chen J, Custers-Allen R, Bittinger K, Li H, et al. (2010) Disordered Microbial Communities in the Upper Respiratory Tract of Cigarette Smokers. PLoS ONE 5(12): e15216. } \examples{ data(throat.tree) } \keyword{datasets} GUniFrac/man/stool.otu.tab.Rd0000644000176200001440000000222414105517632015471 0ustar liggesusers\name{stool.otu.tab} \alias{stool.otu.tab} \docType{data} \title{ %% ~~ data name/kind ... ~~ Stool Microbiome OTU Count Table } \description{ %% ~~ A concise (1-5 lines) description of the dataset. ~~ OTU count table from 16S V3-V5 targeted sequencing of the stool microbiome samples from the HMP project. A total of 2,094 OTUs from 295 samples. } \usage{data(stool.otu.tab)} \format{ The format is: chr "stool.otu.tab" } \details{ %% ~~ If necessary, more details than the __description__ above ~~ The OTU table was taken from R bioconductor "HMP16SData" package. OTUs with prevalence less than 10\% and maximum proportion less than 0.2\% were removed. This OTU table can be used for simulating stool microbiome sequencing data. } \source{ %% ~~ reference to a publication or URL from which the data were obtained ~~ Schiffer L, Azhar R, Shepherd L, Ramos M, Geistlinger L, Huttenhower C, Dowd JB, Segata N, Waldron L (2019). “HMP16SData: Efficient Access to the Human Microbiome Project through Bioconductor.” American Journal of Epidemiology. doi: 10.1093/aje/kwz006. } \examples{ data(stool.otu.tab) } \keyword{datasets} GUniFrac/man/throat.meta.Rd0000644000176200001440000000165614106041403015201 0ustar liggesusers\name{throat.meta} \alias{throat.meta} \docType{data} \title{ %% ~~ data name/kind ... ~~ Throat Microbiome Meta Data } \description{ %% ~~ A concise (1-5 lines) description of the dataset. ~~ It is part of a microbiome data set for studying the effect of smoking on the upper respiratory tract microbiome. The original data set contains samples from both throat and nose microbiomes, and from both body sides. This data set comes from the throat microbiome of left body side. It contains 60 subjects consisting of 32 nonsmokers and 28 smokers. } \usage{data(throat.meta)} \source{ %% ~~ reference to a publication or URL from which the data were obtained ~~ Charlson ES, Chen J, Custers-Allen R, Bittinger K, Li H, et al. (2010) Disordered Microbial Communities in the Upper Respiratory Tract of Cigarette Smokers. PLoS ONE 5(12): e15216. } \examples{ data(throat.meta) } \keyword{datasets} GUniFrac/man/adonis3.Rd0000644000176200001440000001322114105337405014313 0ustar liggesusers \name{adonis3} \alias{adonis3} \title{Permutational Multivariate Analysis of Variance Using Distance Matrices (Freedman-Lane permutation)} \description{Analysis of variance using distance matrices --- for partitioning distance matrices among sources of variation and fitting linear models (e.g., factors, polynomial regression) to distance matrices; uses a permutation test (Freedman-Lane permutation) with pseudo-\eqn{F} ratios.} \usage{ adonis3(formula, data, permutations = 999, method = "bray", strata = NULL, contr.unordered = "contr.sum", contr.ordered = "contr.poly", parallel = getOption("mc.cores"), ...) } \arguments{ \item{formula}{model formula. The LHS must be either a community data matrix or a dissimilarity matrix, e.g., from \code{\link{vegdist}} or \code{\link{dist}}. If the LHS is a data matrix, function \code{\link{vegdist}} will be used to find the dissimilarities. The RHS defines the independent variables. These can be continuous variables or factors, they can be transformed within the formula, and they can have interactions as in a typical \code{\link{formula}}. } \item{data}{ the data frame for the independent variables.} \item{permutations}{a list of control values for the permutations as returned by the function \code{\link[permute]{how}}, or the number of permutations required, or a permutation matrix where each row gives the permuted indices.} \item{method}{ the name of any method used in \code{\link{vegdist}} to calculate pairwise distances if the left hand side of the \code{formula} was a data frame or a matrix. } \item{strata}{ groups (strata) within which to constrain permutations. } \item{contr.unordered, contr.ordered}{contrasts used for the design matrix (default in R is dummy or treatment contrasts for unordered factors). } \item{parallel}{number of parallel processes or a predefined socket cluster. With \code{parallel = 1} uses ordinary, non-parallel processing. The parallel processing is done with \pkg{parallel} package.} \item{\dots}{Other arguments passed to \code{vegdist}.} } \details{ \code{adonis3} is the re-implementation of the famous \code{adonis} function in the \code{vegan} package based on the Freedman-Lane permutation scheme. (Freedman & Lane (1983), Hu & Satten (2020)). \code{adonis} is the function for the analysis and partitioning sums of squares using dissimilarities. The original implementation in the \code{vegan} package is directly based on the algorithm of Anderson (2001) and performs a sequential test of terms. Statistical significance is calculated based on permuting the distance matrix. As shown in Chen & Zhang (2020+), such permutation will lead to power loss in testing the effect of a covariate of interest while adjusting for other covariates (confounders). The power loss is more evident when the confounders' effects are strong, the correlation between the covariate of interest and the confounders is high, and the sample size is small. When the sample size is large than 100, the difference is usually small. The new implementation is revised on the \code{adonis} function with the same interface. } \value{ Function \code{adonis3} returns an object of class \code{"adonis"} with following components: \item{aov.tab}{typical AOV table showing sources of variation, degrees of freedom, sequential sums of squares, mean squares, \eqn{F} statistics, partial \eqn{R^2}{R-squared} and \eqn{P} values, based on \eqn{N} permutations. } \item{coefficients}{ matrix of coefficients of the linear model, with rows representing sources of variation and columns representing species; each column represents a fit of a species abundance to the linear model. These are what you get when you fit one species to your predictors. These are NOT available if you supply the distance matrix in the formula, rather than the site x species matrix} \item{coef.sites}{ matrix of coefficients of the linear model, with rows representing sources of variation and columns representing sites; each column represents a fit of a sites distances (from all other sites) to the linear model. These are what you get when you fit distances of one site to your predictors. } \item{f.perms}{ an \eqn{N} by \eqn{m} matrix of the null \eqn{F} statistics for each source of variation based on \eqn{N} permutations of the data. The permutations can be inspected with \code{\link{permustats}} and its support functions.} \item{model.matrix}{the \code{\link{model.matrix}} for the right hand side of the formula.} \item{terms}{the \code{\link{terms}} component of the model.} } \references{ Anderson, M.J. 2001. A new method for non-parametric multivariate analysis of variance. \emph{Austral Ecology}, \strong{26}: 32--46. Freedman D. & Lane D. 1983. A nonstochastic interpretation of reported significance levels. \emph{Journal of Business and Economic Statistics}, \strong{1}292--298. Hu, Y. J. & Satten, G. A. 2020. Testing hypotheses about the microbiome using the linear decomposition model (LDM). Bioinformatics. } \author{Martin Henry H. Stevens (\code{adonis}) and Jun Chen (\code{adonis3}). } \examples{ data(throat.otu.tab) data(throat.tree) data(throat.meta) groups <- throat.meta$SmokingStatus # Rarefaction otu.tab.rff <- Rarefy(throat.otu.tab)$otu.tab.rff # Calculate the UniFrac distance unifracs <- GUniFrac(otu.tab.rff, throat.tree, alpha=c(0, 0.5, 1))$unifracs # Test the smoking effect based on unweighted UniFrac distance, adjusting sex adonis3(as.dist(unifracs[, , 'd_UW']) ~ Sex + SmokingStatus, data = throat.meta) } \keyword{distance} \keyword{multivariate} GUniFrac/man/GMPR.Rd0000644000176200001440000000416214105334073013522 0ustar liggesusers\name{GMPR} \alias{GMPR} %- Also NEED an '\alias' for EACH other topic documented here. \title{ Geometric Mean of Pairwise Ratios (GMPR) Normalization for Zero-inflated Count Data } \description{ A robust normalization method for zero-inflated count data such as microbiome sequencing data. } \usage{ GMPR(OTUmatrix, min_ct = 2, intersect_no = 4) } %- maybe also 'usage' for other objects documented here. \arguments{ \item{OTUmatrix}{ An OTU count table, where OTUs are arranged in rows and samples in columns. } \item{min_ct}{ The minimal number of OTU counts. Only those OTU pairs with at least \code{min_ct} counts are considered in the ratio calculation. The default is 2. } \item{intersect_no}{ The minimal number of shared OTUs between samples. Only those sample pairs sharing at least \code{intersect_no} OTUs are considered in geometric mean calculation. The default is 4. } } \details{ Normalization is a critical step in microbiome sequencing data analysis to account for variable library sizes. Microbiome data contains a vast number of zeros, which makes the traditional RNA-Seq normalization methods unstable. The proposed GMPR normalization remedies this problem by switching the two steps in DESeq2 normalization: First, to calculate rij, the median count ratio of nonzero counts between samples: rij=median(cki/ckj) (k in 1:OTU_number and cki, ckj is the non-zero count of the kth OTU) Second, to calculate the size factor si for a given sample i: si=geometric_mean(rij) } \value{ A vector of GMPR size factor for each sample. } \references{ Li Chen, James Reeve, Lujun Zhang, Shenbing Huang, and Jun Chen. 2018. GMPR: A robust normalization method for zero-inflated count data with application to microbiome sequencing data. PeerJ, 6, e4600. } \author{ Jun Chen and Lujun Zhang } \examples{ data(throat.otu.tab) size.factor <- GMPR(t(throat.otu.tab)) } % Add one or more standard keywords, see file 'KEYWORDS' in the % R documentation directory. \keyword{ normalization}% use one of RShowDoc("KEYWORDS") \keyword{ microbiome }% __ONLY ONE__ keyword per line GUniFrac/man/linda.Rd0000644000176200001440000001733214142647276014064 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/linda.R \name{linda} \alias{linda} \title{Linear (Lin) Model for Differential Abundance (DA) Analysis of High-dimensional Compositional Data} \description{ The function implements a simple, robust and highly scalable approach to tackle the compositional effects in differential abundance analysis of high-dimensional compositional data. It fits linear regression models on the centered log2-ratio transformed data, identifies a bias term due to the transformation and compositional effect, and corrects the bias using the mode of the regression coefficients. It could fit mixed-effect models for analysis of correlated data. } \usage{ linda( feature.dat, meta.dat, formula, feature.dat.type = c('count', 'proportion'), prev.filter = 0, mean.abund.filter = 0, max.abund.filter = 0, is.winsor = TRUE, outlier.pct = 0.03, adaptive = TRUE, zero.handling = c('pseudo-count', 'imputation'), pseudo.cnt = 0.5, corr.cut = 0.1, p.adj.method = "BH", alpha = 0.05, n.cores = 1, verbose = TRUE ) } \arguments{ \item{feature.dat}{a matrix of counts/proportions, row - features (OTUs, genes, etc) , column - samples.} \item{meta.dat}{a data frame containing the sample meta data. If there are NAs, the corresponding samples will be removed in the analysis.} \item{formula}{a character string for the formula. The formula should conform to that used by \code{lm} (independent data) or \code{lmer} (correlated data). For example: \code{formula = '~x1*x2+x3+(1|id)'}. At least one fixed effect is required.} \item{feature.dat.type}{the type of the feature data. It could be "count" or "proportion".} \item{prev.filter}{the prevalence (percentage of non-zeros) cutoff, under which the features will be filtered. The default is 0. } \item{mean.abund.filter}{the mean relative abundance cutoff, under which the features will be filtered. The default is 0.} \item{max.abund.filter}{the max relative abundance cutoff, under which the features will be filtered. The default is 0.} \item{is.winsor}{a logical value indicating whether winsorization should be performed to replace outliers (high values). The default is TRUE.} \item{outlier.pct}{the expected percentage of outliers. These outliers will be winsorized. The default is 0.03.} \item{adaptive}{a logical value indicating whether the approach to handle zeros (pseudo-count or imputation) will be determined based on the correlations between the log(sequencing depth) and the explanatory variables in \code{formula} when \code{feature.dat} is 'count'. If TRUE and the correlation p-value for any explanatory variable is smaller than or equal to \code{corr.cut}, the imputation approach will be used; otherwise, the pseudo-count approach will be used. } \item{zero.handling}{a character string of 'pseudo-count' or 'imputation' indicating the zero handling method used when \code{feature.dat} is 'count'. If 'pseudo-count', a\code{pseudo.cnt} will be added to each value in \code{feature.dat}. If 'imputation', then we use the imputation approach using the formula in the referenced paper. Basically, zeros are imputed with values proportional to the sequencing depth. When \code{feature.dat} is 'proportion', this parameter will be ignored and zeros will be imputed by half of the minimum for each feature.} \item{pseudo.cnt}{a positive numeric value for the pseudo-count to be added if \code{zero.handling} is 'pseudo-count'. Default is 0.5. } \item{corr.cut}{a numerical value between 0 and 1, indicating the significance level used for determining the zero-handling approach when \code{adaptive} is TRUE. Default is 0.1.} \item{p.adj.method}{a character string indicating the p-value adjustment approach for addressing multiple testing. See R function \code{p.adjust}. Default is 'BH'.} \item{alpha}{a numerical value between 0 and 1 indicating the significance level for declaring differential features. Default is 0.05.} \item{n.cores}{a positive integer. If \code{n.cores > 1} and formula is in a form of mixed-effect model, \code{n.cores} parallels will be conducted. Default is 1.} \item{verbose}{a logical value indicating whether the trace information should be printed out.} } \value{ A list with the elements \item{variables}{a vector of variable names of all fixed effects in \code{formula}. For example: \code{formula = '~x1*x2+x3+(1|id)'}. Suppose \code{x1} and \code{x2} are numerical, and \code{x3} is a categorical variable of three levels: a, b and c. Then the elements of \code{variables} would be \code{('x1', 'x2', 'x3b', 'x3c', 'x1:x2')}.} \item{bias}{a numeric vector; each element corresponds to one variable in \code{variables}; the estimated bias of the regression coefficients due to the compositional effect.} \item{output}{a list of data frames with columns 'baseMean', 'log2FoldChange', 'lfcSE', 'stat', 'pvalue', 'padj', 'reject', 'df'; \code{names(output)} is equal to \code{variables}; the rows of the data frame corresponds to features. Note: if there are features being excluded due to filtering, the number of the rows of the output data frame will be not equal to the number of the rows of \code{feature.dat}. Features are identified by the row names. If the row names of \code{feature.dat} are NULL, then \code{1 : nrow(feature.dat)} is set as the row names of \code{feature.dat}. \itemize{ \item{baseMean:}{ 2 to the power of the intercept coefficients (normalized by one million)} \item{log2FoldChange:}{ bias-corrected coefficients} \item{lfcSE:}{ standard errors of the coefficients} \item{stat:}{ \code{log2FoldChange / lfcSE}} \item{pvalue:}{ \code{2 * pt(-abs(stat), df)}} \item{padj:}{ \code{p.adjust(pvalue, method = p.adj.method)}} \item{reject:}{ \code{padj <= alpha}} \item{df:}{ degrees of freedom. The number of samples minus the number of explanatory variables (intercept included) for fixed-effect models; estimates from R package \code{lmerTest} with Satterthwaite method of approximation for mixed-effect models.} }} \item{feature.dat.use}{the actual feature table used in the differential analysis after filtering, winsorization and zero handling.} \item{meta.dat.use}{the meta data used in the abundance analysis (only variables in \code{formula} are stored; samples that have NAs are removed; numerical variables are scaled).} } \examples{ data(throat.otu.tab) data(throat.tree) data(throat.meta) comm <- t(throat.otu.tab) meta.dat <- throat.meta # For count data linda.obj <- linda(comm, meta.dat, formula = '~SmokingStatus+Sex', feature.dat.type = 'count', prev.filter = 0.2, is.winsor = TRUE, outlier.pct = 0.03, p.adj.method = "BH", alpha = 0.1 ) rownames(linda.obj$output[[1]])[which(linda.obj$output[[1]]$reject)] linda.plot(linda.obj, c('SmokingStatusSmoker', 'Sexmale'), titles = c('Smoke: n v.s. y', 'Sex: female v.s. male'), alpha = 0.1, lfc.cut = 1, legend = TRUE, directory = NULL, width = 11, height = 8) # For proportion data comm.p <- t(t(comm) / colSums(comm)) linda.obj <- linda(comm.p, meta.dat, formula = '~SmokingStatus+Sex', feature.dat.type = 'proportion', prev.filter = 0.2, is.winsor = TRUE, outlier.pct = 0.03, p.adj.method = "BH", alpha = 0.1 ) # For mixed effects model; demonstration only, the dataset does not have repeated measurements. \dontrun{ linda.obj <- linda(comm, meta.dat, formula = '~SmokingStatus+Sex+(1|PatientID)', feature.dat.type = 'count', prev.filter = 0.2, is.winsor = TRUE, outlier.pct = 0.03, p.adj.method = "BH", alpha = 0.1) } } \references{ Huijuan Zhou, Kejun He, Jun Chen, and Xianyang Zhang. LinDA: Linear Models for Differential Abundance Analysis of Microbiome Compositional Data. } \author{ Huijuan Zhou, Jun Chen, Xianyang Zhang } GUniFrac/DESCRIPTION0000644000176200001440000000275314142662222013426 0ustar liggesusersPackage: GUniFrac Type: Package Title: Generalized UniFrac Distances, Distance-Based Multivariate Methods and Feature-Based Univariate Methods for Microbiome Data Analysis Version: 1.4 Date: 2021-11-06 Author: Jun Chen, Xianyang Zhang, Huijuan Zhou Maintainer: Jun Chen Description: A suite of methods for powerful and robust microbiome data analysis including data normalization, data simulation, community-level association testing and differential abundance analysis. It implements generalized UniFrac distances, Geometric Mean of Pairwise Ratios (GMPR) normalization, semiparametric data simulator, distance-based statistical methods, and feature-based statistical methods. The distance-based statistical methods include three extensions of PERMANOVA: (1) PERMANOVA using the Freedman-Lane permutation scheme, (2) PERMANOVA omnibus test using multiple matrices, and (3) analytical approach to approximating PERMANOVA p-value. Feature-based statistical methods include linear model-based methods for differential abundance analysis of zero-inflated high-dimensional compositional data. Depends: R (>= 3.5.0) Suggests: ade4 Imports: Rcpp (>= 0.12.13), vegan, ggplot2, matrixStats, Matrix, ape, parallel, stats, utils, statmod, rmutil, dirmult, MASS, ggrepel, lmerTest, foreach, modeest LinkingTo: Rcpp NeedsCompilation: yes License: GPL-3 Encoding: UTF-8 Packaged: 2021-11-10 04:48:17 UTC; m123485 Repository: CRAN Date/Publication: 2021-11-10 06:20:02 UTC GUniFrac/src/0000755000176200001440000000000014141323304012472 5ustar liggesusersGUniFrac/src/gmpr.cpp0000644000176200001440000001501214105316046014147 0ustar liggesusers#include //[[Rcpp::plugins(cpp11)]] #include #include #include #include #include #include #include #include using namespace std; using namespace Rcpp; class GMPR { private: const IntegerMatrix comm; const int n, p; const int minct; const int inter_n; void diag(vector &square_matrix, const int &n, const double &i); public: vector factor; vector size_factor; vector NSS; GMPR(const IntegerMatrix &otumatrix, int nrow, int pcol, int min_ct, int intersect_no); GMPR(const IntegerMatrix &otumatrix, int nrow, int pcol); ~GMPR(); void Size_factor(void); void Factor(void); }; GMPR::~GMPR() {}; GMPR::GMPR(const IntegerMatrix &otumatrix, int nrow, int pcol, int min_ct, int intersect_no) : comm(otumatrix), n(nrow), p(pcol), minct(min_ct), inter_n(intersect_no), factor(n*n, 0), size_factor(n, 0), NSS(n, 0) {}; GMPR::GMPR(const IntegerMatrix &otumatrix, int nrow, int pcol) : comm(otumatrix), n(nrow), p(pcol), minct(2), inter_n(4), factor(n*n, 0), size_factor(n, 0), NSS(n, 0) {}; /* void GMPR::Size_factor(void) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (abs(factor[i*n + j]) > 1e-10) { NSS[i] += 1; size_factor[i] *= factor[i*n + j]; }; }; NSS[i] -= 1; //substrat itself if (NSS[i] >= inter_n) size_factor[i] = pow(size_factor[i], 1.0 / NSS[i]); }; }; */ void GMPR::Size_factor(void) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (abs(factor[i*n + j]) > 1e-10) { NSS[i] += 1; size_factor[i] += log(factor[i*n + j]); }; }; // NSS[i] -= 1; //substrat itself size_factor[i] = exp(size_factor[i] / NSS[i]); }; }; void GMPR::Factor(void) { vector index(p*n, false); void diag(vector &square_matrix, const int &n, const double &i); for (int i = 0; i < n; i++) { for (int j = 0; j < p; j++) { index[j + i*p] = comm(i,j) >= minct; }; }; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { int h = 0; vector ratio(p, 0); for (int k = 0; k < p; k++) { if (index[i*p + k] && index[j*p + k]) { ratio[h] = static_cast(comm(i,k)) / comm(j,k); h++; }; }; if (h >= inter_n) { sort(ratio.begin(), ratio.begin()+h); if (h % 2 == 1) { factor[i*n + j] = ratio[h / 2]; factor[j*n + i] = 1 / (ratio[h / 2]); } else { factor[i*n + j] = (ratio[h / 2 - 1] + ratio[h / 2]) / 2; factor[j*n + i] = 1 / ((ratio[h / 2 - 1] + ratio[h / 2]) / 2); } }; }; }; GMPR::diag(factor, n, 1); } void GMPR::diag(vector &square_matrix, const int &n, const double &i) { for (int j = 0; j < n; j++) square_matrix[n*j + j] = i; }; // [[Rcpp::export]] NumericVector gmpr(IntegerMatrix x, int min_ct, int intersect_no){ /*vector > table { { 0,0,0,0,2,0,11,0,0,1,0,0,11,0,0,0,126,0,4,4,12,1,0,0,0,12,1,8,66,183,8,5,3,5,27,2,0,1,0,20,0,1,2,2,2,76,16,2,2,31 },{ 0,0,0,0,0,0,1,0,1,1,0,1,1,0,0,1,12,0,2,4,13,0,0,0,3,1,1,11,17,41,1,5,0,1,2,2,0,0,0,40,0,3,3,1,4,7,3,11,0,0 }, { 0,2,0,0,0,0,9,0,2,1,0,0,1,0,1,0,88,0,2,1,5,0,0,0,0,82,1,7,6,21,2,2,3,0,3,16,0,2,0,3,0,2,3,0,1,10,15,3,0,2 },{ 1,2,1,0,2,0,10,0,2,1,0,0,7,0,0,0,8,0,1,1,4,0,0,0,0,4,0,0,2,12,2,1,1,0,0,0,0,1,0,10,0,1,0,0,0,2,7,1,0,0 }, { 2,3,8,0,0,0,6,1,0,1,0,0,16,1,0,1,6,0,0,5,12,0,0,0,1,1,0,4,0,3,3,0,2,0,1,0,0,3,0,2,0,0,3,1,1,2,9,1,0,1 },{ 3,1,2,1,0,0,3,1,0,2,1,1,18,0,0,2,85,2,4,6,12,0,0,0,4,19,0,16,20,83,6,0,2,38,28,10,0,1,3,82,5,3,21,0,17,749,137,14,0,74 }, { 0,3,34,0,0,0,1,0,1,0,0,0,12,0,0,0,30,0,0,0,6,0,0,0,1,1,1,0,8,60,6,0,3,1,1,5,0,0,0,9,5,0,1,0,5,10,14,0,0,1 },{ 0,0,2,0,0,0,0,1,0,0,1,0,2,0,0,0,82,6,22,15,54,1,0,0,4,10,0,7,1,40,19,6,18,8,66,9,0,3,0,92,0,0,6,2,2,10,10,1,1,33 }, { 0,0,0,0,0,0,1,0,0,0,0,1,8,0,0,0,61,3,8,6,7,3,1,0,0,7,0,4,0,16,6,1,5,2,6,7,0,0,120,53,0,0,9,0,3,27,6,5,1,0 },{ 0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,714,0,103,0,18,0,0,0,1,75,16,2,90,219,1,4,3,4,46,116,0,35,0,59,0,1,2,2,3,19,4,1,1,3 }, { 0,0,0,0,2,0,19,7,3,2,0,0,1,0,0,0,62,0,0,0,3,0,0,0,0,3,0,0,7,63,0,2,0,22,35,4,0,0,0,11,0,3,0,0,0,21,1,0,0,3 },{ 0,2,0,0,0,0,1,0,0,0,0,0,2,0,0,1,21,0,157,3,7,0,0,0,3,26,9,2,18,47,2,3,1,1,13,13,0,0,0,45,0,0,0,0,6,4,1,1,0,1 }, { 0,1,0,0,0,0,2,0,0,0,0,0,0,0,0,0,82,0,2,0,5,0,0,0,0,116,1,1,4,15,3,0,0,0,6,13,0,0,0,1,0,0,0,0,0,2,2,0,0,0 },{ 8,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,9,1,0,0,4,0,0,0,2,0,0,1,1,7,2,0,1,0,1,0,0,0,0,8,0,0,2,0,0,5,1,0,0,0 }, { 0,0,1,0,0,0,0,0,0,0,0,0,2,0,0,0,116,0,7,19,21,0,0,0,6,72,0,14,20,86,5,9,4,3,133,18,0,5,0,62,0,3,0,0,3,36,16,0,0,2 },{ 2,0,7,2,0,0,1,0,0,0,1,0,69,0,0,1,3,0,0,1,9,0,0,0,1,0,0,2,0,10,1,0,1,0,1,4,0,24,2,5,1,0,1,0,1,1,4,1,1,0 }, { 0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,197,5,35,40,32,12,8,0,0,11,2,12,0,78,5,13,6,2,20,10,0,1,48,63,0,0,16,1,4,76,2,2,1,1 },{ 0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,97,2,0,12,35,15,0,0,0,1,0,41,1,78,27,1,12,35,41,7,0,8,0,31,0,2,1,0,2,16,60,9,0,6 }, { 1,0,0,0,0,0,1,0,0,0,0,0,1,1,0,0,4,1,0,2,2,0,0,0,0,2,0,4,9,39,1,0,0,5,4,1,0,0,0,66,1,0,0,0,0,9,4,1,0,1 },{ 3,0,10,1,0,0,2,0,0,0,0,1,6,0,0,0,55,0,0,2,9,0,0,0,0,7,1,1,9,73,1,0,7,1,8,6,0,2,2,53,8,1,0,0,2,9,10,4,0,0 }, { 0,0,0,0,0,0,0,0,0,0,0,1,2,0,0,0,119,8,19,16,56,1,1,0,1,12,0,0,2,49,3,6,3,29,93,15,0,12,0,17,0,0,2,1,3,3,3,3,2,49 },{ 0,1,0,0,0,0,2,1,1,0,0,1,2,0,0,4,145,1,3,9,67,2,0,0,40,11,1,30,62,136,6,13,10,4,9,13,0,3,1,57,0,0,15,6,34,141,28,116,0,7 }, { 0,0,0,1,0,0,4,0,0,1,0,0,1,0,0,2,69,2,0,5,29,1,0,0,1,12,0,13,48,125,15,15,6,5,12,6,0,4,0,74,2,1,12,1,16,178,23,35,2,20 },{ 0,0,0,0,0,0,1,1,0,1,0,0,2,0,0,0,68,2,3,6,87,0,0,0,20,9,1,32,38,72,9,32,5,4,16,5,0,5,0,76,0,0,4,12,26,30,3,45,0,10 }, { 0,1,0,0,0,0,5,0,1,0,0,0,1,0,0,0,253,1,5,43,180,0,0,0,38,39,0,32,59,140,37,56,6,3,14,57,0,2,1,34,0,0,60,0,12,91,71,63,4,18 },{ 0,2,1,0,3,0,3,0,0,0,0,0,18,0,0,0,51,0,2,2,8,0,0,0,1,2,0,8,11,33,8,2,9,0,1,1,0,2,12,21,0,1,9,0,1,30,72,20,0,1 }, { 0,0,0,8,0,0,3,1,0,0,0,2,18,0,2,7,68,1,1,40,99,1,0,0,30,9,0,21,44,76,15,15,14,1,12,13,0,0,13,64,1,0,16,2,12,130,63,14,3,15 },{ 1,0,1,2,1,0,1,0,0,0,3,0,9,1,1,5,35,1,1,7,61,1,0,1,9,3,0,10,2,10,25,9,17,1,1,2,0,5,8,5,0,2,17,0,9,20,25,13,0,19 }, { 0,0,1,2,1,0,0,0,0,1,0,0,1,0,0,2,135,4,1,25,128,2,0,2,28,6,0,55,7,23,21,13,21,8,5,1,0,2,8,6,0,1,49,2,23,227,89,148,6,9 },{ 0,0,2,2,0,0,0,0,0,0,1,2,7,0,0,1,76,0,0,8,53,2,0,0,17,9,3,18,14,33,22,6,5,5,3,7,0,3,12,39,14,0,55,0,16,379,208,27,1,34 } }; */ GMPR A(x, x.nrow(), x.ncol(), min_ct, intersect_no); A.Factor(); A.Size_factor(); return Rcpp::wrap(A.size_factor); } GUniFrac/src/RcppExports.cpp0000644000176200001440000000173514105316046015502 0ustar liggesusers// Generated by using Rcpp::compileAttributes() -> do not edit by hand // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 #include using namespace Rcpp; // gmpr NumericVector gmpr(IntegerMatrix x, int min_ct, int intersect_no); RcppExport SEXP _GMPR_gmpr(SEXP xSEXP, SEXP min_ctSEXP, SEXP intersect_noSEXP) { BEGIN_RCPP Rcpp::RObject rcpp_result_gen; Rcpp::RNGScope rcpp_rngScope_gen; Rcpp::traits::input_parameter< IntegerMatrix >::type x(xSEXP); Rcpp::traits::input_parameter< int >::type min_ct(min_ctSEXP); Rcpp::traits::input_parameter< int >::type intersect_no(intersect_noSEXP); rcpp_result_gen = Rcpp::wrap(gmpr(x, min_ct, intersect_no)); return rcpp_result_gen; END_RCPP } static const R_CallMethodDef CallEntries[] = { {"_GMPR_gmpr", (DL_FUNC) &_GMPR_gmpr, 3}, {NULL, NULL, 0} }; RcppExport void R_init_GMPR(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } GUniFrac/R/0000755000176200001440000000000014141324063012107 5ustar liggesusersGUniFrac/R/linda.R0000644000176200001440000005160614141356605013340 0ustar liggesuserswinsor.fun <- function(Y, quan, feature.dat.type) { if (feature.dat.type == 'count') { N <- colSums(Y) P <- t(t(Y) / N) cut <- apply(P, 1, quantile, quan) Cut <- matrix(rep(cut, ncol(Y)), nrow(Y)) ind <- P > Cut P[ind] <- Cut[ind] Y <- round(t(t(P) * N)) } if (feature.dat.type == 'proportion') { cut <- apply(Y, 1, quantile, quan) Cut <- matrix(rep(cut, ncol(Y)), nrow(Y)) ind <- Y > Cut Y[ind] <- Cut[ind] } return(Y) } #' Linear (Lin) model for differential abundance (DA) analysis #' #' The function implements a simple, robust and highly scalable approach to tackle #' the compositional effects in differential abundance analysis. It fits linear regression models #' on the centered log2-ratio transformed data, identifies a bias term due to the transformation #' and compositional effect, and corrects the bias using the mode of the regression coefficients. #' It could fit mixed-effect models. #' #' @param otu.tab data frame or matrix representing observed OTU table. Row: taxa; column: samples. #' NAs are not expected in OTU tables so are not allowed in function \code{linda}. #' @param meta data frame of covariates. The rows of \code{meta} correspond to the columns of \code{otu.tab}. #' NAs are allowed. If there are NAs, the corresponding samples will be removed in the analysis. #' @param formula character. For example: \code{formula = '~x1*x2+x3+(1|id)'}. At least one fixed effect is required. #' @param adaptive TRUE or FALSE. Default is TRUE. If TRUE, the parameter \code{imputation} will be treated as FALSE no matter #' what it is actually set to be. Then the significant correlations between the sequencing depth and explanatory variables will be tested #' via the linear regression between the log of the sequencing depths and \code{formula}. If any p-value is smaller than or equal to #' \code{corr.cut}, the imputation approach will be used; otherwise, the pseudo-count approach will be used. #' The information of whether the imputation or pseudo-count approach is used will be printed. #' @param imputation TRUE or FALSE. Default is FALSE. If TRUE, then we use the imputation approach, i.e., zeros in \code{otu.tab} will be #' imputed using the formula in the referenced paper. #' @param pseudo.cnt a positive real value. Default is 0.5. If \code{adaptive} and \code{imputation} are both FALSE, #' then we use the pseudo-count approach, i.e., we add \code{pseudo.cnt} to each value in \code{otu.tab}. #' @param corr.cut a real value between 0 and 1; significance level of correlations between the sequencing depth and #' explanatory variables. Default is 0.1. #' @param p.adj.method character; p-value adjusting approach. See R function \code{p.adjust}. Default is 'BH'. #' @param alpha a real value between 0 and 1; significance level of differential abundance. Default is 0.05. #' @param prev.cut a real value between 0 and 1; taxa with prevalence (percentage of nonzeros) #' less than prev.cut are excluded. Default is 0 (no taxa will be excluded). #' @param lib.cut a non-negative real value; samples with less than \code{lib.cut} read counts are excluded. #' Default is 1 (no samples will be excluded). #' @param winsor.quan a real value between 0 and 1; winsorization cutoff (quantile) for \code{otu.tab}, e.g., 0.97. Default is NULL. #' If NULL, winsorization process will not be conducted. #' @param n.cores a positive integer. If \code{n.cores > 1} and formula is in a form of mixed-effect model, #' \code{n.cores} parallels will be conducted. Default is 1. #' #' @return A list with the elements #' \item{variables}{A vector of variable names of all fixed effects in \code{formula}. For example: \code{formula = '~x1*x2+x3+(1|id)'}. #' Suppose \code{x1} and \code{x2} are numerical, and \code{x3} is a categorical variable of three levels: a, b and c. #' Then the elements of \code{variables} would be \code{('x1', 'x2', 'x3b', 'x3c', 'x1:x2')}.} #' \item{bias}{numeric vector; each element corresponds to one variable in \code{variables}; #' the estimated bias of the regression coefficients due to the compositional effect.} #' \item{output}{a list of data frames with columns 'baseMean', 'log2FoldChange', 'lfcSE', 'stat', 'pvalue', 'padj', 'reject', #' 'df'; \code{names(output)} is equal to \code{variables}; the rows of the data frame corresponds to taxa. #' Note: if there are taxa being excluded due to \code{prev.cut}, the number of the rows of the output data frame #' will be not equal to the number of the rows of \code{otu.tab}. Taxa are identified by the rownames. #' If the rownames of \code{otu.tab} are NULL, then \code{1 : nrow(otu.tab)} is set as the rownames of \code{otu.tab}. #' \itemize{ #' \item{baseMean:}{ 2 to the power of the intercept coefficients (normalized by one million)} #' \item{log2FoldChange:}{ bias-corrected coefficients} #' \item{lfcSE:}{ standard errors of the coefficients} #' \item{stat:}{ \code{log2FoldChange / lfcSE}} #' \item{pvalue:}{ \code{2 * pt(-abs(stat), df)}} #' \item{padj:}{ \code{p.adjust(pvalue, method = p.adj.method)}} #' \item{reject:}{ \code{padj <= alpha}} #' \item{df:}{ degrees of freedom. The number of samples minus the number of explanatory variables (intercept included) for #' fixed-effect models; estimates from R package \code{lmerTest} with Satterthwaite method of approximation for mixed-effect models.} #' }} #' \item{otu.tab.use}{the OTU table used in the abundance analysis (the \code{otu.tab} after the preprocessing: #' samples that have NAs in the variables in \code{formula} or have less than \code{lib.cut} read counts are removed; #' taxa with prevalence less than \code{prev.cut} are removed and data is winsorized if \code{!is.null(winsor.quan)}; #' and zeros are treated, i.e., imputed or pseudo-count added).} #' \item{meta.use}{the meta data used in the abundance analysis (only variables in \code{formula} are stored; samples that have NAs #' or have less than \code{lib.cut} read counts are removed; numerical variables are scaled).} #' #' @author Huijuan Zhou \email{huijuanzhou2019@gmail.com} #' Jun Chen \email{Chen.Jun2@mayo.edu} #' Maintainer: Huijuan Zhou #' @references Huijuan Zhou, Kejun He, Jun Chen, and Xianyang Zhang. LinDA: Linear Models for Differential Abundance #' Analysis of Microbiome Compositional Data. #' @importFrom modeest mlv #' @importFrom lmerTest lmer #' @import foreach #' @import parallel #' @examples #' #' #install package "phyloseq" for importing "smokers" dataset #' ind <- smokers$meta$AIRWAYSITE == 'Throat' #' otu.tab <- as.data.frame(smokers$otu[, ind]) #' meta <- cbind.data.frame(Smoke = factor(smokers$meta$SMOKER[ind]), #' Sex = factor(smokers$meta$SEX[ind]), #' Site = factor(smokers$meta$SIDEOFBODY[ind]), #' SubjectID = factor(smokers$meta$HOST_SUBJECT_ID[ind])) #' ind1 <- which(meta$Site == 'Left') #' res.left <- linda(otu.tab[, ind1], meta[ind1, ], formula = '~Smoke+Sex', alpha = 0.1, #' prev.cut = 0.1, lib.cut = 1000, winsor.quan = 0.97) #' ind2 <- which(meta$Site == 'Right') #' res.right <- linda(otu.tab[, ind2], meta[ind2, ], formula = '~Smoke+Sex', alpha = 0.1, #' prev.cut = 0.1, lib.cut = 1000, winsor.quan = 0.97) #' rownames(res.left$output[[1]])[which(res.left$output[[1]]$reject)] #' rownames(res.right$output[[1]])[which(res.right$output[[1]]$reject)] #' #' linda.obj <- linda(otu.tab, meta, formula = '~Smoke+Sex+(1|SubjectID)', alpha = 0.1, #' prev.cut = 0.1, lib.cut = 1000, winsor.quan = 0.97) #' linda.plot(linda.obj, c('Smokey', 'Sexmale'), #' titles = c('Smoke: n v.s. y', 'Sex: female v.s. male'), alpha = 0.1, lfc.cut = 1, #' legend = TRUE, directory = NULL, width = 11, height = 8) #' #' @export linda <- function(feature.dat, meta.dat, formula, feature.dat.type = c('count', 'proportion'), prev.filter = 0, mean.abund.filter = 0, max.abund.filter = 0, is.winsor = TRUE, outlier.pct = 0.03, adaptive = TRUE, zero.handling = c('pseudo-count', 'imputation'), pseudo.cnt = 0.5, corr.cut = 0.1, p.adj.method = 'BH', alpha = 0.05, n.cores = 1, verbose = TRUE) { feature.dat.type <- match.arg(feature.dat.type) if(any(is.na(feature.dat))) { stop('The feature table contains NAs! Please remove!\n') } allvars <- all.vars(as.formula(formula)) Z <- as.data.frame(meta.dat[, allvars]) ############################################################################### # Filter sample keep.sam <- which(rowSums(is.na(Z)) == 0) Y <- feature.dat[, keep.sam] Z <- as.data.frame(Z[keep.sam, ]) names(Z) <- allvars # Filter features temp <- t(t(Y) / colSums(Y)) keep.tax <- rowMeans(temp != 0) >= prev.filter & rowMeans(temp) >= mean.abund.filter & rowMaxs(temp) >= max.abund.filter names(keep.tax) <- rownames(Y) rm(temp) if (verbose) cat(sum(!keep.tax), ' features are filtered!\n') Y <- Y[keep.tax, ] n <- ncol(Y) m <- nrow(Y) ## some samples may have zero total counts after screening taxa if(any(colSums(Y) == 0)) { ind <- which(colSums(Y) > 0) Y <- Y[, ind] Z <- as.data.frame(Z[ind, ]) names(Z) <- allvars keep.sam <- keep.sam[ind] n <- ncol(Y) } if (verbose) cat('The filtered data has ', n, ' samples and ', m, ' features will be tested!\n' ) if (sum(rowSums(Y != 0) <= 2) != 0) { warning('Some features have less than 3 nonzero values! They have virtually no statistical power. You may consider filtering them in the analysis!\n') } ############################################################################### ## scaling numerical variables ind <- sapply(1 : ncol(Z), function(i) is.numeric(Z[, i])) Z[, ind] <- scale(Z[, ind]) ## winsorization if(is.winsor) { Y <- winsor.fun(Y, 1 - outlier.pct, feature.dat.type) } ## if(grepl('\\(', formula)) { random.effect <- TRUE } else { random.effect <- FALSE } if(is.null(rownames(feature.dat))) { taxa.name <- (1 : nrow(feature.dat))[keep.tax] } else { taxa.name <- rownames(feature.dat)[keep.tax] } if(is.null(rownames(meta.dat))) { samp.name <- (1 : nrow(meta.dat))[keep.sam] } else { samp.name <- rownames(meta.dat)[keep.sam] } ## handling zeros if (feature.dat.type == 'count') { if(any(Y == 0)) { N <- colSums(Y) if(adaptive) { logN <- log(N) if(random.effect) { tmp <- lmer(as.formula(paste0('logN', formula)), Z) } else { tmp <- lm(as.formula(paste0('logN', formula)), Z) } corr.pval <- coef(summary(tmp))[-1, "Pr(>|t|)"] if(any(corr.pval <= corr.cut)) { if (verbose) cat('Imputation approach is used.\n') zero.handling <- "Imputation" } else { if (verbose) cat('Pseudo-count approach is used.\n') zero.handling <- "Pseudo-count" } } if(zero.handling == 'imputation') { N.mat <- matrix(rep(N, m), nrow = m, byrow = TRUE) N.mat[Y > 0] <- 0 tmp <- N[max.col(N.mat)] Y <- Y + N.mat / tmp } else { Y <- Y + pseudo.cnt } } } if (feature.dat.type == 'proportion') { if(any(Y == 0)) { # Half minimum approach Y <- t(apply(Y, 1, function (x) { x[x == 0] <- 0.5 * min(x[x != 0]) return(x) })) colnames(Y) <- samp.name rownames(Y) <- taxa.name } } ## CLR transformation logY <- log2(Y) W <- t(logY) - colMeans(logY) ## linear regression oldw <- getOption('warn') options(warn = -1) if(!random.effect) { if (verbose) cat("Fit linear models ...\n") suppressMessages(fit <- lm(as.formula(paste0('W', formula)), Z)) res <- do.call(rbind, coef(summary(fit))) df <- rep(n - ncol(model.matrix(fit)), m) } else { if (verbose) cat("Fit linear mixed effects models ...\n") fun <- function(i) { w <- W[, i] fit <- lmer(as.formula(paste0('w', formula)), Z) coef(summary(fit)) } if(n.cores > 1) { res <- mclapply(c(1 : m), function(i) fun(i), mc.cores = n.cores) } else { suppressMessages(res <- foreach(i = 1 : m) %do% fun(i)) } res <- do.call(rbind, res) } options(warn = oldw) res.intc <- res[which(rownames(res) == '(Intercept)'), ] rownames(res.intc) <- NULL baseMean <- 2 ^ res.intc[, 1] baseMean <- baseMean / sum(baseMean) * 1e6 output.fun <- function(x) { res.voi <- res[which(rownames(res) == x), ] rownames(res.voi) <- NULL if(random.effect) { df <- res.voi[, 3] } log2FoldChange <- res.voi[, 1] lfcSE <- res.voi[, 2] oldw <- getOption('warn') options(warn = -1) suppressMessages(bias <- mlv(sqrt(n) * log2FoldChange, method = 'meanshift', kernel = 'gaussian') / sqrt(n)) options(warn = oldw) log2FoldChange <- log2FoldChange - bias stat <- log2FoldChange / lfcSE pvalue <- 2 * pt(-abs(stat), df) padj <- p.adjust(pvalue, method = p.adj.method) reject <- padj <= alpha output <- cbind.data.frame(baseMean, log2FoldChange, lfcSE, stat, pvalue, padj, reject, df) rownames(output) <- taxa.name return(list(bias = bias, output = output)) } variables <- unique(rownames(res))[-1] variables.n <- length(variables) bias <- rep(NA, variables.n) output <- list() for(i in 1 : variables.n) { tmp <- output.fun(variables[i]) output[[i]] <- tmp[[2]] bias[i] <- tmp[[1]] } names(output) <- variables rownames(Y) <- taxa.name colnames(Y) <- samp.name rownames(Z) <- samp.name if (verbose) cat("Completed.\n") return(list(variables = variables, bias = bias, output = output, feature.dat.use = Y, meta.dat.use = Z)) } #' Plot linda results #' #' The function plots the effect size plot and volcano plot based on the output from \code{linda}. #' #' @param linda.obj return from function \code{linda}. #' @param variables.plot vector; variables whose results are to be plotted. For example, suppose the return #' value \code{variables} is equal to \code{('x1', 'x2', 'x3b', 'x3c', 'x1:x2')}, then one could set \code{variables.plot = c('x3b', 'x1:x2')}. #' @param titles vector; titles of the effect size plot and volcano plot for each variable in \code{variables.plot}. #' Default is NULL. If NULL, the titles will be set as \code{variables.plot}. #' @param alpha a real value between 0 and 1; cutoff for \code{padj}. #' @param lfc.cut a positive value; cutoff for \code{log2FoldChange}. #' @param legend TRUE or FALSE; whether to show the legends of the effect size plot and volcano plot. #' @param directory character; the directory to save the figures, e.g., \code{getwd()}. Default is NULL. If NULL, figures will not be saved. #' @param width the width of the graphics region in inches. See R function \code{pdf}. #' @param height the height of the graphics region in inches. See R function \code{pdf}. #' #' @return A list of \code{ggplot2} objects. #' \item{plot.lfc}{a list of effect size plots. Each plot corresponds to one variable in \code{variables.plot}.} #' \item{plot.volcano}{a list of volcano plots. Each plot corresponds to one variable in \code{variables.plot}.} #' #' @author Huijuan Zhou \email{huijuanzhou2019@gmail.com} #' Jun Chen \email{Chen.Jun2@mayo.edu} #' Maintainer: Huijuan Zhou #' @references Huijuan Zhou, Kejun He, Jun Chen, and Xianyang Zhang. LinDA: Linear Models for Differential Abundance #' Analysis of Microbiome Compositional Data. #' @import ggplot2 #' @import ggrepel #' @examples #' #' #install package "phyloseq" for importing "smokers" dataset #' ind <- smokers$meta$AIRWAYSITE == 'Throat' #' otu.tab <- as.data.frame(smokers$otu[, ind]) #' meta <- cbind.data.frame(Smoke = factor(smokers$meta$SMOKER[ind]), #' Sex = factor(smokers$meta$SEX[ind]), #' Site = factor(smokers$meta$SIDEOFBODY[ind]), #' SubjectID = factor(smokers$meta$HOST_SUBJECT_ID[ind])) #' ind1 <- which(meta$Site == 'Left') #' res.left <- linda(otu.tab[, ind1], meta[ind1, ], formula = '~Smoke+Sex', alpha = 0.1, #' prev.cut = 0.1, lib.cut = 1000, winsor.quan = 0.97) #' ind2 <- which(meta$Site == 'Right') #' res.right <- linda(otu.tab[, ind2], meta[ind2, ], formula = '~Smoke+Sex', alpha = 0.1, #' prev.cut = 0.1, lib.cut = 1000, winsor.quan = 0.97) #' rownames(res.left$output[[1]])[which(res.left$output[[1]]$reject)] #' rownames(res.right$output[[1]])[which(res.right$output[[1]]$reject)] #' #' linda.obj <- linda(otu.tab, meta, formula = '~Smoke+Sex+(1|SubjectID)', alpha = 0.1, #' prev.cut = 0.1, lib.cut = 1000, winsor.quan = 0.97) #' linda.plot(linda.obj, c('Smokey', 'Sexmale'), #' titles = c('Smoke: n v.s. y', 'Sex: female v.s. male'), alpha = 0.1, lfc.cut = 1, #' legend = TRUE, directory = NULL, width = 11, height = 8) #' #' @export linda.plot <- function(linda.obj, variables.plot, titles = NULL, alpha = 0.05, lfc.cut = 1, legend = FALSE, directory = NULL, width = 11, height = 8) { bias <- linda.obj$bias output <- linda.obj$output otu.tab <- linda.obj$feature.dat.use meta <- linda.obj$meta.dat.use variables <- linda.obj$variables if(is.null(titles)) titles <- variables.plot taxa <- rownames(otu.tab) m <- length(taxa) tmp <- match(variables, variables.plot) voi.ind <- order(tmp)[1 : sum(!is.na(tmp))] padj.mat <- foreach(i = voi.ind, .combine = 'cbind') %do% { output[[i]]$padj } ## effect size plot if(is.matrix(padj.mat)) { ind <- which(colSums(padj.mat <= alpha) > 0) } else if(is.vector(padj.mat)) { tmp <- which(padj.mat <= alpha) if(length(tmp) > 0){ ind <- 1 } else { ind <- integer(0) } } if(length(ind) == 0) { plot.lfc <- NULL } else { if(!is.null(directory)) pdf(paste0(directory, '/plot_lfc.pdf'), width = width, height = height) plot.lfc <- list() j <- 1 Taxa <- Log2FoldChange <- Log10Padj <- NULL for(i in ind) { output.i <- output[[voi.ind[i]]] bias.i <- bias[voi.ind[i]] lfc <- output.i$log2FoldChange lfcSE <- output.i$lfcSE padj <- output.i$padj ind.rej <- which(padj <= alpha) n.rej <- length(ind.rej) taxa.rej <- taxa[ind.rej] taxa.rej <- factor(taxa.rej, levels = taxa.rej) data.plot.lfc <- cbind.data.frame(Taxa = rep(taxa.rej, 2), Log2FoldChange = c(lfc[ind.rej], lfc[ind.rej] + bias.i), lfcSE = c(lfcSE[ind.rej], rep(NA, n.rej)), bias = rep(c('Debiased', 'Non-debiased'), each = n.rej)) plot.lfc.i <- ggplot(data.plot.lfc, aes(x = Log2FoldChange, y = Taxa)) + geom_point(aes(color = bias, shape = bias), size = 3) + geom_errorbar(aes(xmin = Log2FoldChange - 1.96 * lfcSE, xmax = Log2FoldChange + 1.96 * lfcSE), width = .2) + geom_vline(xintercept = 0, color = 'gray', linetype = 'dashed') + ggtitle(titles[i]) + theme_bw(base_size = 18) if(legend) { plot.lfc.i <- plot.lfc.i + theme(legend.title = element_blank(), legend.key.width = unit(1, 'cm'), plot.margin = unit(c(1, 1, 1, 1.5), 'cm')) } else { plot.lfc.i <- plot.lfc.i + theme(legend.position = 'none', plot.margin = unit(c(1, 1, 1, 1.5), 'cm')) } plot.lfc[[j]] <- plot.lfc.i j <- j + 1 if(!is.null(directory)) print(plot.lfc.i) } if(!is.null(directory)) dev.off() } ## volcano plot plot.volcano <- list() if(!is.null(directory)) pdf(paste0(directory, '/plot_volcano.pdf'), width = width, height = height) leg1 <- paste0('padj>', alpha, ' & ', 'lfc<=', lfc.cut) leg2 <- paste0('padj>', alpha, ' & ', 'lfc>', lfc.cut) leg3 <- paste0('padj<=', alpha, ' & ', 'lfc<=', lfc.cut) leg4 <- paste0('padj<=', alpha, ' & ', 'lfc>', lfc.cut) gg_color_hue <- function(n) { hues = seq(15, 375, length = n + 1) hcl(h = hues, l = 65, c = 100)[1 : n] } color <- gg_color_hue(3) for(i in 1 : length(voi.ind)) { output.i <- output[[voi.ind[i]]] bias.i <- bias[voi.ind[i]] lfc <- output.i$log2FoldChange padj <- output.i$padj ind1 <- padj > alpha & abs(lfc) <= lfc.cut ind2 <- padj > alpha & abs(lfc) > lfc.cut ind3 <- padj <= alpha & abs(lfc) <= lfc.cut ind4 <- padj <= alpha & abs(lfc) > lfc.cut leg <- rep(NA, m) leg[ind1] = leg1 leg[ind2] = leg2 leg[ind3] = leg3 leg[ind4] = leg4 leg <- factor(leg, levels = c(leg1, leg2, leg3, leg4)) taxa.sig <- rep('', m) taxa.sig[ind3 | ind4] <- taxa[ind3 | ind4] data.volcano <- cbind.data.frame(taxa = taxa.sig, Log2FoldChange = lfc, Log10Padj = -log10(padj), leg = leg) plot.volcano.i <- ggplot(data.volcano, aes(x = Log2FoldChange, y = Log10Padj)) + geom_point(aes(color = leg), size = 2) + geom_text_repel(aes(label = taxa), max.overlaps = Inf) + scale_colour_manual(values = c('darkgray', color[c(2, 3, 1)])) + geom_hline(aes(yintercept = -log10(alpha)), color = 'gray', linetype = 'dashed') + geom_vline(aes(xintercept = -lfc.cut), color = 'gray', linetype = 'dashed') + geom_vline(aes(xintercept = lfc.cut), color = 'gray', linetype = 'dashed') + ylab('-Log10Padj') + ggtitle(titles[i]) + theme_bw(base_size = 18) if(legend) { plot.volcano.i <- plot.volcano.i + theme(legend.title = element_blank(), legend.key.width = unit(1, 'cm'), plot.margin = unit(c(1, 1, 1, 1.5), 'cm')) } else { plot.volcano.i <- plot.volcano.i + theme(legend.position = 'none', plot.margin = unit(c(1, 1, 1, 1.5), 'cm')) } plot.volcano[[i]] <- plot.volcano.i if(!is.null(directory)) print(plot.volcano.i) } if(!is.null(directory)) dev.off() return(list(plot.lfc = plot.lfc, plot.volcano = plot.volcano)) } GUniFrac/R/GMPR.R0000644000176200001440000000136414106320204012775 0ustar liggesusersGMPR <- function(OTUmatrix, min_ct=2, intersect_no=4){ #datatype check if(!(class(OTUmatrix)[1] %in% c("data.frame","matrix"))) stop("Unknown datatype of object \"OTUmatrix\".") OTUmatrix <- t(OTUmatrix) rownames(OTUmatrix)->SampleName if(ncol(OTUmatrix)0])>=0.1*ncol(OTUmatrix)*nrow(OTUmatrix)) stop("More than 10% values are fractional, please check.") apply(OTUmatrix, MARGIN = 2, as.integer)->OTUmatrix gmpr(OTUmatrix,min_ct,intersect_no)->size.factor names(size.factor)<-SampleName size.factor[abs(size.factor-1)<1e-10]<-NA size.factor } GUniFrac/R/RcppExports.R0000644000176200001440000000037414105332504014526 0ustar liggesusers# Generated by using Rcpp::compileAttributes() -> do not edit by hand # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 gmpr <- function(x, min_ct, intersect_no) { .Call('_GMPR_gmpr', PACKAGE = 'GUniFrac', x, min_ct, intersect_no) } GUniFrac/R/SimMSeq.R0000644000176200001440000002573014105532725013565 0ustar liggesusers #' @title estimiate the DM parameters #' @param alpha shape factor #' @return a matrix represents the true proportion of the ref.otu.tab, row is otu, column is sample #' @import stats #' @rdname rdirichlet.m #' @export rdirichlet.m <- function (alpha) { Gam <- matrix(rgamma(length(alpha), shape = alpha), nrow(alpha), ncol(alpha)) t(t(Gam) / colSums(Gam)) } #' @title estimiate the true proportion of ref.otu.tab #' @param ref.otu.tab shape factor #' @return A list with the elements #' \item{mu}{absolute abundance before applying size factor} #' \item{ref.otu.tab}{absolute abundance renormalized by size factor} #' @rdname EstPara #' @import dirmult #' @import stats #' @export EstPara <- function (ref.otu.tab) { if (is.null(rownames(ref.otu.tab))) { rownames(ref.otu.tab) <- paste0('OTU', 1 : nrow(ref.otu.tab)) } # otu * sample samplenames = colnames(ref.otu.tab) taxnames = rownames(ref.otu.tab) dirmult.paras <- dirmult::dirmult(t(ref.otu.tab)) gamma = dirmult.paras$gamma names(gamma) = names(dirmult.paras$pi) # Add pseduo count(each OTU add gamma estimated from dirmult) ref.otu.tab = sapply(1:ncol(ref.otu.tab), function (i) gamma + ref.otu.tab[,i]) # C_ij otu * sample # back to dirchlet, calculate the true proportion ref.otu.tab.p <- rdirichlet.m(ref.otu.tab) # P_ij nOTU*nSam colnames(ref.otu.tab.p) = samplenames rownames(ref.otu.tab.p) = taxnames # order OTUs by mean OTU proportion, for later selection ord = order(rowMeans(ref.otu.tab.p), decreasing = TRUE) ref.otu.tab.p = ref.otu.tab.p[ord,] # apply size factor Si = exp(rnorm(ncol(ref.otu.tab.p))) ref.otu.tab0 = t(t(ref.otu.tab.p)*Si) colnames(ref.otu.tab0) = colnames(ref.otu.tab.p) return(list(mu = ref.otu.tab.p, ref.otu.tab = ref.otu.tab0)) } #' @title Simulate microbiome data for differential abundance analysis #' @param ref.otu.tab taxa in rows, and samples in columns. #' @param nSam an integer: indicating the number of samples you want to simulate. #' @param nOTU an integer: indicating the number of taxa you want to simulate. #' @param diff.otu.pct a number between 0-1: indicating the proportion of differential taxa, default is 0. #' @param diff.otu.direct a character: consists "balanced" and "unbalanced". "balanced" is default, means differential taxa increase and decrease, "unbalanced" means differetial taxa only increase or only decrease. #' @param diff.otu.mode a character: consists "rare", "mix", "abundant". "rare" means differential taxa come from the least abundant 0.25 taxa. "abundant", is default, means the most abundant 0.25 taxa. "mix" means 0.5 of the differential taxa come from "abundnat" and "rare", respectively. #' @param covariate.type a character:"binary", "continuous". "binary" is default, means covariate is binary variable, i.e., case vs control. "continuous" means the covariate is continuous variable, i.e., age. #' @param covariate.eff.mean a number: indicating the effect size, default is 0. #' @param grp.ratio a number between 0-1: indicating the ratio of case and control. default is 1, means 50 percentage samples are case and 50 percentage are control. formula is grp.ratio / (1 + grp.ratio)). #' @param covariate.eff.sd a number: indicating the variation of the taxa. default is 0, default is 0. #' @param confounder.type a character: consists "none", "binary", "continuous", "both". default is "none", means no confounding variable. binary" means confounder is 2-group variable, i.e., sex. "continuous" means a continuous variable, i.e., BMI. "both" means two confouders, including binary and continuous variable. #' @param conf.cov.cor a number between 0-1: indicating the correlation between covariate and confounders, default is 0.6. #' @param conf.diff.otu.pct a number between 0-1: indicating the proportion of taxa are influenced by confounders, default is 0.05. #' @param conf.nondiff.otu.pct a number between 0-1: indicating the proportion of taxa are not influenced by confounders, default is 0.1. #' @param confounder.eff.mean a number: effect size of the confounding effect, default is 0. #' @param confounder.eff.sd a number: variation of the taxa that have confounding effect. default is 0. #' @param depth.mu an integer: define the mean sequencing depth to be simulated, default is 10000. #' @param depth.theta theta value in defining the variance 'mu + mu^2/theta' of the negative binomial distribution, default is 5. #' @param depth.conf.factor a number: depth confounding factor, 0 means no depth confounding, default is 0 #' @return Return a list with the elements: #' \item{otu.tab.sim}{simulated otu table} #' \item{covariate}{simulated covariate} #' \item{diff.otu.ind}{index of the differential taxa} #' \item{otu.names}{the otu names of the simulated otu table} #' \item{conf.otu.ind}{taxa with confounding effect} #' @rdname SimulateSeq #' @import dirmult #' @import MASS #' @import stats #' @export ## Little different from the general simulation function in cluster, since we want to make the nOTU and nSam is the same as the nrow/ncol of the input ref.otu.tab SimulateMSeq <- function ( ref.otu.tab, nSam = 100, nOTU = 500, diff.otu.pct = 0.1, diff.otu.direct = c("balanced", "unbalanced"), diff.otu.mode = c("abundant", "rare", "mix"), covariate.type = c("binary", "continuous"), grp.ratio = 1, covariate.eff.mean = 1, covariate.eff.sd = 0, confounder.type = c("none", "binary", "continuous", "both"), conf.cov.cor = 0.6, conf.diff.otu.pct = 0, conf.nondiff.otu.pct = 0.1, confounder.eff.mean = 0, confounder.eff.sd = 0, error.sd = 0, depth.mu = 10000, depth.theta = 5, depth.conf.factor = 0 ){ diff.otu.direct <- match.arg(diff.otu.direct) diff.otu.mode <- match.arg(diff.otu.mode) covariate.type <- match.arg(covariate.type) confounder.type <- match.arg(confounder.type) ref.otu.tab0 <- ref.otu.tab model.paras <- EstPara(ref.otu.tab = ref.otu.tab) # full ref.otu.tab + estimated parameters sample.names <- colnames(model.paras$ref.otu.tab) ref.otu.tab <- model.paras$ref.otu.tab[(1 : (nOTU)),] # otu * sample dim(ref.otu.tab) idx.otu <- rownames(ref.otu.tab) idx.sample <- sample(sample.names, nSam) idx.nonsample <- colnames(ref.otu.tab)[!(colnames(ref.otu.tab) %in% idx.sample)] ref.otu.tab = ref.otu.tab[,idx.sample] # otu * sample, final selected OTU tab by User ref.otu.tab.unselect = ref.otu.tab0[c(1 : (nOTU)),][,idx.nonsample] # For overfitting test if (confounder.type == "none") { confounder.type <- "continuous" confounder.eff.mean <- 0 confounder.eff.sd <- 0 Z <- NULL } if (confounder.type == "continuous") Z <- cbind(rnorm(nSam)) if (confounder.type == "binary") Z <- cbind(c(rep(0, nSam %/% 2), rep(1, nSam - nSam %/% 2))) if (confounder.type == "both") Z <- cbind(rnorm(nSam), c(rep(0, nSam %/% 2), rep(1, nSam - nSam %/% 2))) rho <- sqrt(conf.cov.cor ^ 2 / (1 - conf.cov.cor ^ 2)) if (covariate.type == 'continuous') { X <- rho * scale(scale(Z) %*% rep(1, ncol(Z))) + rnorm(nSam) } if (covariate.type == "binary") { X <- rho * scale(scale(Z) %*% rep(1, ncol(Z))) + rnorm(nSam) X <- cbind(ifelse(X <= quantile(X, grp.ratio / (1 + grp.ratio)), 0, 1)) } rownames(X) <- colnames(ref.otu.tab) covariate.eff.mean1 = covariate.eff.mean covariate.eff.mean2 = covariate.eff.mean if (diff.otu.direct == "balanced") { if (diff.otu.mode == 'abundant'){ eta.diff <- sample(c(rnorm(floor(nOTU / 2), mean = -covariate.eff.mean2, sd = covariate.eff.sd), rnorm(nOTU - floor(nOTU / 2), mean = covariate.eff.mean2, sd = covariate.eff.sd))) %*% t(scale(X)) # multiple means * xb, eta = xb }else if(diff.otu.mode == 'rare'){ eta.diff <- sample(c(rnorm(floor(nOTU / 2), mean = -covariate.eff.mean2, sd = covariate.eff.sd), rnorm(nOTU - floor(nOTU / 2), mean = covariate.eff.mean2, sd = covariate.eff.sd))) %*% t(scale(X)) }else{ eta.diff <- c(sample(c(rnorm(floor(nOTU / 4), mean = -covariate.eff.mean1, sd = covariate.eff.sd), rnorm(floor(nOTU / 2) - floor(nOTU / 4), mean = covariate.eff.mean1, sd = covariate.eff.sd))), sample(c(rnorm(floor((nOTU -floor(nOTU / 2))/2), mean = -covariate.eff.mean2, sd = covariate.eff.sd), rnorm(nOTU -floor(nOTU / 2) - floor((nOTU -floor(nOTU / 2))/2), mean = covariate.eff.mean2, sd = covariate.eff.sd)))) %*% t(scale(X)) } } if (diff.otu.direct == "unbalanced") { if (diff.otu.mode == 'abundant'){ eta.diff <- rnorm(nOTU, mean = covariate.eff.mean2, sd = covariate.eff.sd) %*% t(scale(X)) # otu in 50% samples +, 50% sample - }else if(diff.otu.mode == 'rare'){ eta.diff <- rnorm(nOTU, mean = covariate.eff.mean2, sd = covariate.eff.sd) %*% t(scale(X)) }else{ eta.diff <- c(sample(c(rnorm(floor(nOTU / 2), mean = covariate.eff.mean1, sd = covariate.eff.sd))), sample(c(rnorm(nOTU - floor(nOTU / 2), mean = covariate.eff.mean2, sd = covariate.eff.sd)))) %*% t(scale(X)) } } eta.conf <- sample(c(rnorm(floor(nOTU / 2), mean = -confounder.eff.mean, sd = confounder.eff.sd), rnorm(nOTU - floor(nOTU / 2), mean = confounder.eff.mean, sd = confounder.eff.sd))) %*% t(scale(scale(Z) %*% rep(1, ncol(Z)))) otu.ord <- 1 : (nOTU) diff.otu.ind <- NULL diff.otu.num <- round(diff.otu.pct * nOTU) if (diff.otu.mode == 'mix') diff.otu.ind <- c(diff.otu.ind, sample(otu.ord, diff.otu.num)) if (diff.otu.mode == 'abundant') diff.otu.ind <- c(diff.otu.ind, sample(otu.ord[1 : round(length(otu.ord) / 4)], diff.otu.num)) if (diff.otu.mode == 'rare') diff.otu.ind <- c(diff.otu.ind, sample(otu.ord[round(3 * length(otu.ord) / 4) : length(otu.ord)], diff.otu.num)) # if(diff.otu.pct > 0){ # conf.otu.ind <- c(sample(diff.otu.ind, round(nOTU * conf.diff.otu.pct)), sample(setdiff(1 : (nOTU), diff.otu.ind), round(conf.nondiff.otu.pct * nOTU))) # eta.diff[setdiff(1 : (nOTU), diff.otu.ind), ] <- 0 # some OTUs will be 0 # eta.conf[setdiff(1 : (nOTU), conf.otu.ind), ] <- 0 # }else{ # eta.diff <- eta.diff # eta.conf <- eta.conf # conf.otu.ind <- NULL # } if (length(diff.otu.ind) >= round(nOTU * conf.diff.otu.pct)) { conf.otu.ind1 <- sample(diff.otu.ind, round(nOTU * conf.diff.otu.pct)) } else { conf.otu.ind1 <- diff.otu.ind } conf.otu.ind <- c(conf.otu.ind1, sample(setdiff(1 : (nOTU), diff.otu.ind), round(conf.nondiff.otu.pct * nOTU))) eta.diff[setdiff(1 : (nOTU), diff.otu.ind), ] <- 0 # some OTUs will be 0 eta.conf[setdiff(1 : (nOTU), conf.otu.ind), ] <- 0 eta.error <- matrix(rnorm(nOTU * nSam, 0, error.sd), nOTU, nSam) eta.exp <- exp(t(eta.diff + eta.conf + eta.error)) eta.exp <- eta.exp * t(ref.otu.tab) ref.otu.tab.prop <- eta.exp / rowSums(eta.exp) ref.otu.tab.prop <- t(ref.otu.tab.prop) # otu * sample nSeq <- rnegbin(nSam, mu = depth.mu * exp(scale(X) * depth.conf.factor), theta = depth.theta) otu.tab.sim <- sapply(1:ncol(ref.otu.tab.prop), function (i) rmultinom(1, nSeq[i], ref.otu.tab.prop[,i])) colnames(otu.tab.sim) <- rownames(eta.exp) rownames(otu.tab.sim) <- rownames(ref.otu.tab) diff.otu.ind = (1 : nOTU) %in% diff.otu.ind conf.otu.ind = (1 : nOTU) %in% conf.otu.ind return(list(otu.tab.sim = otu.tab.sim, covariate = X, confounder = Z, diff.otu.ind = diff.otu.ind, otu.names = idx.otu, conf.otu.ind = conf.otu.ind)) } GUniFrac/R/ZicoSeq.R0000644000176200001440000004552314105343054013621 0ustar liggesusers perm.fdr.adj <- function (F0, Fp) { ord <- order(F0, decreasing = T) F0 <- F0[ord] perm.no <- ncol(Fp) Fp <- as.vector(Fp) Fp <- Fp[!is.na(Fp)] Fp <- sort(c(Fp, F0), decreasing = F) n <- length(Fp) m <- length(F0) FPN <- (n + 1) - match(F0, Fp) - 1:m p.adj.fdr <- FPN / perm.no / (1:m) p.adj.fdr <- pmin(1, rev(cummin(rev(p.adj.fdr))))[order(ord)] return(p.adj.fdr) } perm.fwer.adj <- function (F0, Fp) { ord <- order(F0, decreasing = T) m <- length(F0) F0 <- F0[ord] Fp <- Fp[ord, , drop=FALSE] col.max <- Fp[m, ] p.adj.fwer <- sapply(m:1, function(i) { x <- F0[i] y <- Fp[i, ] col.max <<- ifelse(y > col.max, y, col.max) mean(col.max >= x) }) p.adj.fwer <- rev(p.adj.fwer) p.adj.fwer <- pmin(1, rev(cummin(rev(p.adj.fwer))))[order(ord)] return(p.adj.fwer) } na.pad <- function (vec, ind) { vec0 <- numeric(length(ind)) vec0[!ind] <- vec vec0[ind] <- NA return(vec0) } find.ref.z1 <- function(otu.tab, M, ref.pct = 0.50, feature.dat.type) { p <- nrow(otu.tab) n <- ncol(otu.tab) if (feature.dat.type == 'count') { otu.tab <- otu.tab + 1 } if (feature.dat.type == 'proportion') { otu.tab <- t(apply(otu.tab, 1, function (x) { x[x == 0] <- min(x[x != 0]) / 2 return(x) })) } otu.tab <- t(otu.tab) res <- matrix(NA, p, p) XXI <- solve(t(M) %*% M) dof <- n - ncol(M) XXIM <- XXI %*% t(M) for (i in 1 : (p - 1)) { Y <- (as.matrix(log((otu.tab[, i]) / (otu.tab[, (i + 1) : p])))) est <- XXIM %*% Y resid <- Y - M %*% est sigma <- sqrt(colSums(resid^2) / dof) res[i, (i + 1) : p] <- res[(i + 1) : p, i] <- sigma } ref.ind <- order(rowMedians(res, na.rm = TRUE))[1 : round(ref.pct * p)] return(ref.ind) } bbmix.fit.MM <- function (ct, dep, nIter = 10, winsor.qt = 1.0) { if (mean(ct == 0) >= 0.95 | sum(ct != 0) < 5) { stop('The number of nonzero is too small to fit the model! Consider removing it from testing!\n') } # Initialization prop0 <- ct / dep qt <- quantile(prop0, winsor.qt) prop0[prop0 >= qt] <- qt var1 <- var(prop0) / 2 mean1 <- mean(prop0) / 2 var2 <- var(prop0) / 2 mean2 <- 3 * mean(prop0) / 2 pi <- 0.5 for (i in 1 : nIter) { shape1.1 <- ((1 - mean1) / var1 - 1 / mean1) * mean1 ^ 2 shape1.2 <- shape1.1 * (1 / mean1 - 1) shape2.1 <- ((1 - mean2) / var2 - 1 / mean2) * mean2 ^ 2 shape2.2 <- shape2.1 * (1 / mean2 - 1) m1 <- shape1.1 / (shape1.1 + shape1.2) s1 <- shape1.1 + shape1.2 m2 <- shape2.1 / (shape2.1 + shape2.2) s2 <- shape2.1 + shape2.2 f1 <- dbetabinom(ct, dep, m1, s1) f2 <- dbetabinom(ct, dep, m2, s2) q1 <- pi * f1 / (pi * f1 + (1 - pi) * f2) q2 <- 1 - q1 pi <- mean(q1) # Rough estimation mean1 <- sum(prop0 * q1) / sum(q1) var1 <- sum((prop0 - mean1)^2 * q1) / sum(q1) mean2 <- sum(prop0 * q2) / sum(q2) var2 <- sum((prop0 - mean2)^2 * q2) / sum(q2) } return(list(shape1.1 = shape1.1, shape1.2 = shape1.2, shape2.1 = shape2.1, shape2.2 = shape2.2, pi = pi, q1 = q1)) } #' @title Permutation-based differential abundance analysis #' @param meta.dat a data frame containing the sample information #' @param feature.dat a matrix of counts, row - features (OTUs, genes, etc) , column - samples. #' @param feature.dat.type the type of the feature data. It could be "count", "proportion" or "other". For "proportion" data type, posterior sampling will not be performed, #' but the reference-based ratio approach will still be used to address compositional effects. For "other" data type, neither posterior sampling or reference-base ratio approach #' will be used. #' @param grp.name the name for variable of interest. It could be numeric or categorical; should be in "meta.dat". #' @param adj.name the name for the variable(s) to be adjusted. They could be numeric or categorical; should be in "meta.dat." #' @param prev.filter the prevalence cutoff, under which the features will be filtered. #' @param mean.abund.filter the mean relative abundance cutoff, under which the features will be filtered. #' @param max.abund.filter the max relative abundance cutoff, under which the features will be filtered. #' @param min.prop proportions less than this value will be replaced with this value. Only relevant when log transformation is used. The default is 0. #' @param is.winsor a logical value indicating whether winsorization should be performed to replace outliers. The default is TRUE. #' @param winsor.end a character indicating whether the outliers at the top, bottom or both will be winsorized. #' @param outlier.pct the percentage of expected outliers. These outliers will be winsorized. #' @param is.post.sample a logical value indicating whether to perform posterior sampling of the underlying proportions. Only relevant when the feature data are counts. #' @param post.sample.no the number of posterior samples if posterior sampling is used. #' @param link.func a list of transformation functions for the feautre data. #' @param perm.no the number of permutations; If the raw p values are of the major interest, set "perm.no" to at least 999. #' @param strata a factor indicating the permutation strata; permutation will be confined to each stratum. #' @param stats.combine.func function to combine the F-statistic for the omnibus test. #' @param ref.pct percentage of reference taxa. #' @param stage.no the number of stages if multiple-stage normalization is used. #' @param excl.pct the maximum percentage of significant features in the reference set that can be removed. Only relevant when multiple-stage normalization is used. #' @param is.fwer a logical value indicating whether the family-wise error rate control (West-Young) will be performed. #' @param verbose a logical value indicating whether the trace information should be printed out. #' @param return.feature.dat a logical value indicating whether the wisorized, filtered "feature.dat" matrix should be returned. #' @return A list with the elements #' \item{call}{the call} #' \item{feature.dat}{the wisorized, filtered "feature.dat" matrix} #' \item{filter.ind}{a vector of logical values indicating which features are filtered} #' \item{R2}{a matrix of percent explained variance (number of features by number of transformation functions)} #' \item{F0}{a matrix of observed F-statistics (number of features by number of functions)} #' \item{RSS}{a matrix of residual sum squares (number of features by number of functions)} #' \item{df.model, df.residual}{degrees of freedom for the model and residual space} #' \item{p.raw}{the raw p-values based on permutations (not accurate if "perm.no" is small)} #' \item{p.adj.fdr}{permutation-based FDR-adjusted p-values} #' \item{p.adj.fwer}{permutation-based FWER-adjusted (West-Young) p-values} #' @import stats #' @import permute #' @import nlme #' @import matrixStats #' @import vegan #' @import ape #' @import statmod #' @importFrom rmutil dbetabinom #' @rdname ZicoSeq #' @export ZicoSeq <- function ( meta.dat, feature.dat, grp.name, adj.name = NULL, feature.dat.type = c('count', 'proportion', 'other'), prev.filter = 0, mean.abund.filter = 0, max.abund.filter = 0, min.prop = 0, is.winsor = TRUE, outlier.pct = 0.03, winsor.end = c('top', 'bottom', 'both'), is.post.sample = TRUE, post.sample.no = 25, link.func = list(function (x) x^0.5), stats.combine.func = max, perm.no = 99, strata = NULL, ref.pct = 0.50, stage.no = 6, excl.pct = 0.20, is.fwer = FALSE, verbose = TRUE, return.feature.dat = FALSE) { this.call <- match.call() feature.dat.type <- match.arg(feature.dat.type) winsor.end <- match.arg(winsor.end) sds <- rowSds(feature.dat) if (sum(sds == 0) != 0) { stop(paste('Feature ', paste(which(sds == 0), collapse = ','), 'have identical values! Please remove them!\n')) } if (perm.no < 99) { warning('To obtain stable results, number of permutations should be at least 99!\n') } if (feature.dat.type == 'count') { if (sum(feature.dat < 0 | (feature.dat < 1 & feature.dat > 0)) != 0) { stop('It seems the feature data are not counts. Please check!\n') } } if (feature.dat.type == 'proportion') { if (sum(feature.dat < 0 | feature.dat > 1) != 0) { stop('It seems the feature data are not proportions. Please check!\n') } } if (feature.dat.type %in% c('proportion', 'other') & is.post.sample == TRUE) { cat('For proportion and other data types, posterior sampling will not be performed!\n') is.post.sample <- FALSE } if (feature.dat.type == 'other') { stage.no <- 1 } if (feature.dat.type == 'count' & nrow(meta.dat) <= 40) { cat('For sample size less than 40, posterior sampling will not be used!\n') is.post.sample <- FALSE } if (feature.dat.type == 'count' & is.post.sample == FALSE){ if (min(coef(summary(lm(sqrt(colSums(feature.dat)) ~ meta.dat[, grp.name])))[-1, 'Pr(>|t|)']) < 0.05) { warning('The sequencing depth is correlated with the variable of interest! Rarefaction is needed to control for false positves!\n') } } ############################################################################### # Filter to remove very rare taxa if (feature.dat.type %in% c('count', 'proportion')) { temp <- t(t(feature.dat) / colSums(feature.dat)) filter.ind <- rowMeans(temp != 0) >= prev.filter & rowMeans(temp) >= mean.abund.filter & rowMaxs(temp) >= max.abund.filter names(filter.ind) <- rownames(feature.dat) if (verbose) cat(sum(!filter.ind), ' features are filtered!\n') feature.dat <- feature.dat[filter.ind, ] } else { filter.ind <- rep(TRUE, ncol(feature.dat)) } if (feature.dat.type == 'proportion') { # Renormalization feature.dat <- t(t(feature.dat) / colSums(feature.dat)) } sample.no <- ncol(feature.dat) otu.no <- nrow(feature.dat) row.names <- rownames(feature.dat) depth <- colSums(feature.dat) if (verbose) cat('The data has ', sample.no, ' samples and ', otu.no, ' features will be tested!\n' ) if (feature.dat.type %in% c('count', 'proportion') & sum(rowSums(feature.dat != 0) <= 2) != 0) { warning('Some features have less than 3 nonzero values! They have virtually no statistical power. You may consider filtering them in the analysis!\n') } ############################################################################### # Winsorization to reduce the influence of outliers if (is.winsor == TRUE) { depth <- colSums(feature.dat) feature.dat <- apply(feature.dat, 1, function (x) { if (feature.dat.type == 'count') { x <- x / depth } if (winsor.end == 'top') { qt <- quantile(x, 1 - outlier.pct) x[x >= qt] <- qt } if (winsor.end == 'bottom') { qt <- quantile(x, outlier.pct) x[x <= qt] <- qt } if (winsor.end == 'both') { qt1 <- quantile(x, 1 - outlier.pct / 2) qt2 <- quantile(x, outlier.pct / 2) x[x >= qt1] <- qt1 x[x <= qt2] <- qt2 } if (feature.dat.type == 'count') { return(round(x * depth)) } else { return(x) } }) feature.dat <- t(feature.dat) sds <- rowSds(feature.dat) if (sum(sds == 0) != 0) { warning(paste('After winsorization, feature ', paste(which(sds == 0), collapse = ','), 'have identical values!\n')) } } if (feature.dat.type == 'proportion') { # Renormalization feature.dat <- t(t(feature.dat) / colSums(feature.dat)) } ############################################################################### # Generate samples from posterior distribution (stacking it) if (is.post.sample == TRUE) { if (verbose) cat('Fitting beta mixture ...\n') feature.dat.p <- apply(feature.dat, 1, function (x) { err1 <- try(res <- bbmix.fit.MM(x, depth), silent = TRUE) # Handle error if (class(err1) != 'try-error') { prop1.1 <- rbeta(sample.no * post.sample.no, shape1 = x + res$shape1.1, shape2 = res$shape1.2 + depth - x) prop1.2 <- rbeta(sample.no * post.sample.no, shape1 = x + res$shape2.1, shape2 = res$shape2.2 + depth - x) prop <- ifelse(runif(sample.no * post.sample.no) <= res$q1, prop1.1, prop1.2) } else { prop <- x / depth v <- var(prop) m <- mean(prop) a1 <- ((1 - m) / v - 1 / m) * m ^ 2 a2 <- a1 * (1 / m - 1) if (is.na(a1) | a1 < 0) { # uniform prior prop <- rbeta(sample.no * post.sample.no, shape1 = x + 1, shape2 = otu.no + depth - x) } else { # beta prior prop <- rbeta(sample.no * post.sample.no, shape1 = x + a1, shape2 = a2 + depth - x) } } return(prop) }) feature.dat.p <- t(feature.dat.p) feature.dat.p.list <- list() st <- 1 end <- sample.no for (i in 1 : post.sample.no) { feature.dat.p.list[[i]] <- feature.dat.p[, st : end] # Normalization # feature.dat.p.list[[i]] <- t(t(feature.dat.p[, st : end]) / colSums(feature.dat.p[, st : end])) st <- st + sample.no end <- end + sample.no } } else { feature.dat.p.list <- list() if (feature.dat.type == 'count') { feature.dat.p.list[[1]] <- t(t(feature.dat) / depth) } else{ feature.dat.p.list[[1]] <- feature.dat } post.sample.no <- 1 } # Replace zeros or extremely small values for log calculation if (feature.dat.type %in% c('count', 'proportion')) { for (i in 1 : post.sample.no) { temp <- feature.dat.p.list[[i]] temp[temp <= min.prop] <- min.prop feature.dat.p.list[[i]] <- temp } } #return(feature.dat.p.list) ############################################################################### # Covariate space (including intercept) if (!is.null(strata)) { strata <- factor(strata) } if (is.null(adj.name)) { M0 <- model.matrix(~ 1, meta.dat) } else { data0 <- meta.dat[, c(adj.name), drop = FALSE] M0 <- model.matrix( ~ ., data0) } data1 <- meta.dat[, c(grp.name), drop = FALSE] M1 <- model.matrix( ~ ., data1)[, -1, drop = FALSE] # No intercept M01 <- cbind(M0, M1) # QR decompostion qrX0 <- qr(M0, tol = 1e-07) Q0 <- qr.Q(qrX0) Q0 <- Q0[, 1:qrX0$rank, drop = FALSE] H0 <- (Q0 %*% t(Q0)) qrX1 <- qr(M1, tol = 1e-07) Q1 <- qr.Q(qrX1) Q1 <- Q1[, 1:qrX1$rank, drop = FALSE] qrX01 <- qr(M01, tol = 1e-07) Q01 <- qr.Q(qrX01) Q01 <- Q01[, 1:qrX01$rank, drop = FALSE] R0 <- as.matrix(resid(lm(Q1 ~ Q0 - 1))) pX0 <- ncol(Q0) pX1 <- ncol(Q1) pX01 <- ncol(Q01) df.model <- pX01 - pX0 df.residual <- sample.no - pX01 func.no <- length(link.func) ############################################################################### if (feature.dat.type %in% c('count', 'proportion')) { if (verbose) cat('Finding the references ...\n') ref.ind <- find.ref.z1(feature.dat, M0, ref.pct = ref.pct, feature.dat.type = feature.dat.type) size.factor <- colSums(feature.dat[ref.ind, ]) } ############################################################################### # Perform multiple stage normalization if (verbose) cat('Permutation testing ...\n') # norm.ind <- NULL for (i in 1 : stage.no) { # Reference proportion if (feature.dat.type == 'other') { divisor <- 1 } else { divisor <- size.factor / depth divisor[divisor == 0] <- 0.5 * min(divisor[divisor != 0]) } # Create the giant Y matrix Y <- matrix(NA, sample.no, func.no * otu.no * post.sample.no) # Change order - func.no * otu.no for (k in 1 : post.sample.no) { for (j in 1 : func.no) { func <- link.func[[j]] feature.dat.p <- feature.dat.p.list[[k]] Y[, (k - 1) * func.no * otu.no + func.no * (0 : (otu.no - 1)) + j] <- func(t(feature.dat.p) / divisor) # No scaling first } } Y <- t(Y) TSS <- rowSums(Y^2) MSS01 <- rowSums((Y %*% Q01)^2) MSS0 <- rowSums((Y %*% Q0)^2) MSS <- (MSS01 - MSS0) RSS <- (TSS - MSS01) getPermuteMatrix <- getFromNamespace("getPermuteMatrix", "vegan") perm.ind <- getPermuteMatrix(perm.no, sample.no, strata = strata) perm.no <- nrow(perm.ind) MRSSp <- sapply(1 : perm.no, function(ii) { if (verbose) { if (ii %% 10 == 0) cat('.') } Rp <- R0[perm.ind[ii, ], , drop = FALSE] # Project to the reisdual space Rp <- Rp - H0 %*% Rp qrRp <- qr(Rp, tol = 1e-07) Q1p <- qr.Q(qrRp) Q1p <- Q1p[, 1:qrRp$rank, drop = FALSE] MSS01p <- MSS0 + rowSums((Y %*% Q1p)^2) MSSp <- (MSS01p - MSS0) RSSp <- (TSS - MSS01p) c(MSSp, RSSp) }) unit <- func.no * otu.no * post.sample.no MSSp <- MRSSp[1 : unit, ] RSSp <- MRSSp[(unit + 1) : (2 * unit), ] # EB is based on the aggregated RSS RSS.m <- array(RSS, c(func.no, otu.no, post.sample.no)) RSS.m <- t(apply(RSS.m, c(1, 2), mean)) # otu.no by func.no F0.m <- array((MSS / df.model) / (RSS / df.residual), c(func.no, otu.no, post.sample.no)) F0.m <- t(apply(F0.m, c(1, 2), mean)) # otu.no by func.no R2.m <- array(MSS / TSS, c(func.no, otu.no, post.sample.no)) R2.m <- t(apply(R2.m, c(1, 2), mean)) # otu.no by func.no F0 <- (MSS / df.model) / (RSS / df.residual) Fp <- (MSSp / df.model) / (RSSp / df.residual) # Expectation of F0 and Fp F0 <- array(F0, c(func.no, otu.no, post.sample.no)) Fp <- array(Fp, c(func.no, otu.no, post.sample.no, perm.no)) F0 <- apply(F0, c(1, 2), mean) # func.no * otu.no Fp <- apply(Fp, c(1, 2, 4), mean) # func.no * otu.no * perm.no ############################################################################### # Omnibus test by taking maximum F0 <- apply(F0, 2, stats.combine.func) Fp <- apply(Fp, c(2, 3), stats.combine.func) # otu.no by perm.no if (verbose) cat('\n') if (mean(is.na(F0)) >= 0.1) { warning('More than 10% observed F stats have NA! Please check! \n') } if (mean(is.na(Fp)) >= 0.1) { warning('More than 10% permuted F stats have NA! Please check! \n') } na.ind <- is.na(F0) F0 <- F0[!na.ind] Fp <- Fp[!na.ind, ] which.nan.ind <- which(!na.ind) ############################################################################### p.raw <- rowMeans(cbind(Fp, F0) >= F0) if (i == stage.no) { break } else { if (mean(p.raw <= 0.05) >= excl.pct) { ind <- order(p.raw)[1 : round(length(p.raw) * excl.pct)] } else { ind <- which(p.raw <= 0.05) } size.factor <- colSums(feature.dat[setdiff(ref.ind, which.nan.ind[ind]), ]) # norm.ind <- cbind(norm.ind, !(1:nrow(feature.dat) %in% setdiff(ref.ind, which.nan.ind[ind]))) } } p.adj.fdr <- perm.fdr.adj(F0, Fp) p.raw <- na.pad(p.raw, na.ind) p.adj.fdr <- na.pad(p.adj.fdr, na.ind) names(p.raw) <- names(p.adj.fdr) <- rownames(R2.m) <- rownames(RSS.m) <- rownames(F0.m) <- row.names colnames(R2.m) <- colnames(F0.m) <- colnames(RSS.m) <- paste0('Func', 1 : func.no) if (is.fwer) { p.adj.fwer <- perm.fwer.adj(F0, Fp) p.adj.fwer <- na.pad(p.adj.fwer, na.ind) names(p.adj.fwer) <- row.names } else { p.adj.fwer <- NULL } if (!return.feature.dat) { feature.dat <- NULL } if (verbose) cat('Completed!\n') return(list(call = this.call, feature.dat = feature.dat, filter.ind = filter.ind, R2 = R2.m, F0 = F0.m, RSS = RSS.m, df.model = df.model, df.residual = df.residual, p.raw = p.raw, p.adj.fdr = p.adj.fdr, p.adj.fwer = p.adj.fwer)) } GUniFrac/R/GUniFrac.R0000644000176200001440000004027314105343042013674 0ustar liggesusers GUniFrac <- function (otu.tab, tree, alpha = c(0, 0.5, 1)) { # Calculate Generalized UniFrac distances. Unweighted and # Variance-adjusted UniFrac distances will also be returned. # # Args: # otu.tab: OTU count table, row - n sample, column - q OTU # tree: rooted phylogenetic tree of R class "phylo" # alpha: parameter controlling weight on abundant lineages # # Returns: # unifracs: three dimensional array containing the generalized # UniFrac distances, unweighted UniFrac distance and # variance adjusted UniFrac distances. # if (!is.rooted(tree)) stop("Rooted phylogenetic tree required!") # Convert into proportions otu.tab <- as.matrix(otu.tab) row.sum <- rowSums(otu.tab) otu.tab <- otu.tab / row.sum n <- nrow(otu.tab) # Construct the returning array if (is.null(rownames(otu.tab))) { rownames(otu.tab) <- paste("comm", 1:n, sep="_") } # d_UW: unweighted UniFrac, d_VAW: weighted UniFrac dimname3 <- c(paste("d", alpha, sep="_"), "d_UW", "d_VAW") unifracs <- array(NA, c(n, n, length(alpha) + 2), dimnames=list(rownames(otu.tab), rownames(otu.tab), dimname3)) for (i in 1:(length(alpha)+2)){ for (j in 1:n){ unifracs[j, j, i] <- 0 } } # Check OTU name consistency if (sum(!(colnames(otu.tab) %in% tree$tip.label)) != 0) { stop("The OTU table contains unknown OTUs! OTU names in the OTU table and the tree should match!" ) } # Get the subtree if tree contains more OTUs absent <- tree$tip.label[!(tree$tip.label %in% colnames(otu.tab))] if (length(absent) != 0) { tree <- drop.tip(tree, absent) warning("The tree has more OTU than the OTU table!") } # Reorder the otu.tab matrix if the OTU orders are different tip.label <- tree$tip.label otu.tab <- otu.tab[, tip.label] ntip <- length(tip.label) nbr <- nrow(tree$edge) edge <- tree$edge edge2 <- edge[, 2] br.len <- tree$edge.length # Accumulate OTU proportions up the tree cum <- matrix(0, nbr, n) # Branch abundance matrix for (i in 1:ntip) { tip.loc <- which(edge2 == i) cum[tip.loc, ] <- cum[tip.loc, ] + otu.tab[, i] node <- edge[tip.loc, 1] # Assume the direction of edge node.loc <- which(edge2 == node) while (length(node.loc)) { cum[node.loc, ] <- cum[node.loc, ] + otu.tab[, i] node <- edge[node.loc, 1] node.loc <- which(edge2 == node) } } # Calculate various UniFrac distances cum.ct <- round(t(t(cum) * row.sum)) # For VAW for (i in 2:n) { for (j in 1:(i-1)) { cum1 <- cum[, i] cum2 <- cum[, j] ind <- (cum1 + cum2) != 0 cum1 <- cum1[ind] cum2 <- cum2[ind] br.len2 <- br.len[ind] mi <- cum.ct[ind, i] + cum.ct[ind, j] mt <- row.sum[i] + row.sum[j] diff <- abs(cum1 - cum2) / (cum1 + cum2) # Generalized UniFrac distance for(k in 1:length(alpha)){ w <- br.len2 * (cum1 + cum2)^alpha[k] unifracs[i, j, k] <- unifracs[j, i, k] <- sum(diff * w) / sum(w) } # Variance Adjusted UniFrac Distance ind2 <- (mt != mi) w <- br.len2 * (cum1 + cum2) / sqrt(mi * (mt - mi)) unifracs[i, j, (k + 2)] <- unifracs[j, i, (k + 2)] <- sum(diff[ind2] * w[ind2]) / sum(w[ind2]) # Unweighted UniFrac Distance cum1 <- (cum1 != 0) cum2 <- (cum2 != 0) unifracs[i, j, (k + 1)] <- unifracs[j, i, (k + 1)] <- sum(abs(cum1 - cum2) / (cum1 + cum2) * br.len2) / sum(br.len2) } } return(list(unifracs=unifracs)) } adonis3 <- function (formula, data = NULL, permutations = 999, method = "bray", strata = NULL, contr.unordered = "contr.sum", contr.ordered = "contr.poly", parallel = getOption("mc.cores"), ...) { EPS <- sqrt(.Machine$double.eps) TOL <- 1e-07 Terms <- terms(formula, data = data) lhs <- formula[[2]] lhs <- eval(lhs, data, parent.frame()) formula[[2]] <- NULL rhs.frame <- model.frame(formula, data, drop.unused.levels = TRUE) op.c <- options()$contrasts options(contrasts = c(contr.unordered, contr.ordered)) rhs <- model.matrix(formula, rhs.frame) options(contrasts = op.c) grps <- attr(rhs, "assign") qrhs <- qr(rhs) rhs <- rhs[, qrhs$pivot, drop = FALSE] rhs <- rhs[, 1:qrhs$rank, drop = FALSE] grps <- grps[qrhs$pivot][1:qrhs$rank] u.grps <- unique(grps) nterms <- length(u.grps) - 1 if (nterms < 1) stop("right-hand-side of formula has no usable terms") H.s <- lapply(2:length(u.grps), function(j) { Xj <- rhs[, grps %in% u.grps[1:j]] qrX <- qr(Xj, tol = TOL) Q <- qr.Q(qrX) tcrossprod(Q[, 1:qrX$rank]) }) if (inherits(lhs, "dist")) { if (any(lhs < -TOL)) stop("dissimilarities must be non-negative") dmat <- as.matrix(lhs^2) } else if ((is.matrix(lhs) || is.data.frame(lhs)) && isSymmetric(unname(as.matrix(lhs)))) { dmat <- as.matrix(lhs^2) lhs <- as.dist(lhs) } else { dist.lhs <- as.matrix(vegdist(lhs, method = method, ...)) dmat <- dist.lhs^2 } n <- nrow(dmat) G <- -sweep(dmat, 1, rowMeans(dmat))/2 SS.Exp.comb <- sapply(H.s, function(hat) sum(G * t(hat))) SS.Exp.each <- c(SS.Exp.comb - c(0, SS.Exp.comb[-nterms])) H.snterm <- H.s[[nterms]] tIH.snterm <- t(diag(n) - H.snterm) G.s <- list() G.s[[1]] <- G if (length(H.s) > 1) for (i in 2:(length(H.s))) G.s[[i]] <- (diag(n) - H.s[[i - 1]]) %*% G %*% (diag(n) - H.s[[i - 1]]) if (length(H.s) > 1) for (i in length(H.s):2) H.s[[i]] <- H.s[[i]] - H.s[[i - 1]] SS.Res <- sum(G * tIH.snterm) df.Exp <- sapply(u.grps[-1], function(i) sum(grps == i)) df.Res <- n - qrhs$rank if (inherits(lhs, "dist")) { beta.sites <- qr.coef(qrhs, as.matrix(lhs)) beta.spp <- NULL } else { beta.sites <- qr.coef(qrhs, dist.lhs) beta.spp <- qr.coef(qrhs, as.matrix(lhs)) } colnames(beta.spp) <- colnames(lhs) colnames(beta.sites) <- rownames(lhs) F.Mod <- (SS.Exp.each/df.Exp)/(SS.Res/df.Res) f.test <- function(tH, G, df.Exp, df.Res, tIH.snterm) { (sum(G * tH)/df.Exp)/(sum(G * tIH.snterm)/df.Res) } SS.perms <- function(H, G, I) { c(SS.Exp.p = sum(G * t(H)), S.Res.p = sum(G * t(I - H))) } getPermuteMatrix <- getFromNamespace("getPermuteMatrix", "vegan") p <- getPermuteMatrix(permutations, n, strata = strata) permutations <- nrow(p) if (permutations) { tH.s <- lapply(H.s, t) if (is.null(parallel)) parallel <- 1 hasClus <- inherits(parallel, "cluster") isParal <- hasClus || parallel > 1 isMulticore <- .Platform$OS.type == "unix" && !hasClus if (isParal && !isMulticore && !hasClus) { parallel <- makeCluster(parallel) } if (isParal) { if (isMulticore) { f.perms <- sapply(1:nterms, function(i) unlist(mclapply(1:permutations, function(j) f.test(tH.s[[i]], G.s[[i]][p[j, ], p[j, ]], df.Exp[i], df.Res, tIH.snterm), mc.cores = parallel))) } else { f.perms <- sapply(1:nterms, function(i) parSapply(parallel, 1:permutations, function(j) f.test(tH.s[[i]], G.s[[i]][p[j, ], p[j, ]], df.Exp[i], df.Res, tIH.snterm))) } } else { f.perms <- sapply(1:nterms, function(i) sapply(1:permutations, function(j) f.test(tH.s[[i]], G.s[[i]][p[j, ], p[j, ]], df.Exp[i], df.Res, tIH.snterm))) } if (isParal && !isMulticore && !hasClus) stopCluster(parallel) P <- (rowSums(t(f.perms) >= F.Mod - EPS) + 1)/(permutations + 1) } else { f.perms <- P <- rep(NA, nterms) } SumsOfSqs = c(SS.Exp.each, SS.Res, sum(SS.Exp.each) + SS.Res) tab <- data.frame(Df = c(df.Exp, df.Res, n - 1), SumsOfSqs = SumsOfSqs, MeanSqs = c(SS.Exp.each/df.Exp, SS.Res/df.Res, NA), F.Model = c(F.Mod, NA, NA), R2 = SumsOfSqs/SumsOfSqs[length(SumsOfSqs)], P = c(P, NA, NA)) rownames(tab) <- c(attr(attr(rhs.frame, "terms"), "term.labels")[u.grps], "Residuals", "Total") colnames(tab)[ncol(tab)] <- "Pr(>F)" attr(tab, "heading") <- c("Terms added sequentially (first to last)\n") class(tab) <- c("anova", class(tab)) out <- list(aov.tab = tab, call = match.call(), coefficients = beta.spp, coef.sites = beta.sites, f.perms = f.perms, model.matrix = rhs, terms = Terms) class(out) <- "adonis" out } PermanovaG <- function(formula, data = NULL, ...) { # Distance based statistical test by combining multiple distance # matrices based on PERMANOVA procedure by taking the maximum of # pseudo-F statistics # # Args: # formula: left side of the formula is a three dimensional array # of the supplied distance matrices as produced by GUniFrac, # Or a list of distance matrices. # dat: data.frame containing the covariates # ...: Parameter passing to "adonis" function # # Returns: # p.tab (data.frame): rows - Covariates (covariate of interest should appear at the last) # columns - F.model, p.values for individual distance matrices and the omnibus test, # aov.tab.list: a list of the aov.tab from individual matrices save.seed <- get(".Random.seed", .GlobalEnv) lhs <- formula[[2]] lhs <- eval(lhs, data, parent.frame()) rhs <- as.character(formula)[3] array.flag <- is.array(lhs) list.flag <- is.list(lhs) if (!array.flag & !list.flag) { stop('The left side of the formula should be either a list or an array of distance matrices!\n') } if (array.flag) { if (length(dim(lhs)) != 3) { stop('The array should be three-dimensional!\n') } else { len <- dim(lhs)[3] } } if (list.flag) { len <- length(lhs) } p.perms <- list() p.obs <- list() aov.tab.list <- list() for (i_ in 1:len) { assign(".Random.seed", save.seed, .GlobalEnv) if (array.flag) { Y <- as.dist(lhs[, , i_]) } if (list.flag) { Y <- as.dist(lhs[[i_]]) } obj <- adonis(as.formula(paste("Y", "~", rhs)), data, ...) perm.mat <- obj$f.perms p.perms[[i_]] <- 1 - (apply(perm.mat, 2, rank) - 1) / nrow(perm.mat) p.obs[[i_]] <- obj$aov.tab[1:ncol(perm.mat), "Pr(>F)"] aov.tab.list[[i_]] <- obj$aov.tab } omni.pv <- NULL indiv.pv <- NULL for (j_ in 1:ncol(perm.mat)) { p.perms.j <- sapply(p.perms, function (x) x[, j_]) p.obj.j <- sapply(p.obs, function (x) x[j_]) omni.pv <- c(omni.pv, mean(c(rowMins(p.perms.j ) <= min(p.obj.j), 1))) indiv.pv <- rbind(indiv.pv, p.obj.j) } colnames(indiv.pv) <- paste0('D', 1:ncol(indiv.pv), '.p.value') rownames(indiv.pv) <- 1:nrow(indiv.pv) p.tab <- data.frame(indiv.pv, omni.p.value = omni.pv) rownames(p.tab) <- rownames(obj$aov.tab)[1:ncol(perm.mat)] list(p.tab = p.tab, aov.tab.list = aov.tab.list) } PermanovaG2 <- function(formula, data = NULL, ...) { # Distance based statistical test by combining multiple distance # matrices based on PERMANOVA procedure by taking the maximum of # pseudo-F statistics # # Args: # formula: left side of the formula is a three dimensional array # of the supplied distance matrices as produced by GUniFrac, # Or a list of distance matrices. # dat: data.frame containing the covariates # ...: Parameter passing to "adonis" function # # Returns: # p.tab (data.frame): rows - Covariates (covariate of interest should appear at the last) # columns - F.model, p.values for individual distance matrices and the omnibus test, # aov.tab.list: a list of the aov.tab from individual matrices save.seed <- get(".Random.seed", .GlobalEnv) lhs <- formula[[2]] lhs <- eval(lhs, data, parent.frame()) rhs <- as.character(formula)[3] array.flag <- is.array(lhs) list.flag <- is.list(lhs) if (!array.flag & !list.flag) { stop('The left side of the formula should be either a list or an array of distance matrices!\n') } if (array.flag) { if (length(dim(lhs)) != 3) { stop('The array should be three-dimensional!\n') } else { len <- dim(lhs)[3] } } if (list.flag) { len <- length(lhs) } p.perms <- list() p.obs <- list() aov.tab.list <- list() for (i_ in 1:len) { assign(".Random.seed", save.seed, .GlobalEnv) if (array.flag) { Y <- as.dist(lhs[, , i_]) } if (list.flag) { Y <- as.dist(lhs[[i_]]) } obj <- adonis3(as.formula(paste("Y", "~", rhs)), data, ...) perm.mat <- obj$f.perms p.perms[[i_]] <- 1 - (apply(perm.mat, 2, rank) - 1) / nrow(perm.mat) p.obs[[i_]] <- obj$aov.tab[1:ncol(perm.mat), "Pr(>F)"] aov.tab.list[[i_]] <- obj$aov.tab } omni.pv <- NULL indiv.pv <- NULL for (j_ in 1:ncol(perm.mat)) { p.perms.j <- sapply(p.perms, function (x) x[, j_]) p.obj.j <- sapply(p.obs, function (x) x[j_]) omni.pv <- c(omni.pv, mean(c(rowMins(p.perms.j ) <= min(p.obj.j), 1))) indiv.pv <- rbind(indiv.pv, p.obj.j) } colnames(indiv.pv) <- paste0('D', 1:ncol(indiv.pv), '.p.value') rownames(indiv.pv) <- 1:nrow(indiv.pv) p.tab <- data.frame(indiv.pv, omni.p.value = omni.pv) rownames(p.tab) <- rownames(obj$aov.tab)[1:ncol(perm.mat)] list(p.tab = p.tab, aov.tab.list = aov.tab.list) } Rarefy <- function (otu.tab, depth = min(rowSums(otu.tab))){ # Rarefaction function: downsample to equal depth # # Args: # otu.tab: OTU count table, row - n sample, column - q OTU # depth: required sequencing depth # # Returns: # otu.tab.rff: Rarefied OTU table # discard: labels of discarded samples # otu.tab <- as.matrix(otu.tab) ind <- (rowSums(otu.tab) < depth) sam.discard <- rownames(otu.tab)[ind] otu.tab <- otu.tab[!ind, ] rarefy <- function(x, depth){ y <- sample(rep(1:length(x), x), depth) y.tab <- table(y) z <- numeric(length(x)) z[as.numeric(names(y.tab))] <- y.tab z } otu.tab.rff <- t(apply(otu.tab, 1, rarefy, depth)) rownames(otu.tab.rff) <- rownames(otu.tab) colnames(otu.tab.rff) <- colnames(otu.tab) return(list(otu.tab.rff=otu.tab.rff, discard=sam.discard)) } calculateK <- function (G, H, df2) { n <- nrow(G) dG <- diag(G) mu1 <- sum(dG) / (n - df2) mu2 <- (sum(G^2) - sum(dG^2)) / ((n - df2)^2 + sum(H^4) - 2 * sum(diag(H^2))) k <- mu1^2 / mu2 list(K = k, mu1 = mu1, mu2 = mu2) } dmanova <- function (formula, data = NULL, positify = FALSE, contr.unordered = "contr.sum", contr.ordered = "contr.poly", returnG = FALSE) { Terms <- terms(formula, data = data) lhs <- formula[[2]] lhs <- eval(lhs, data, parent.frame()) formula[[2]] <- NULL rhs.frame <- model.frame(formula, data, drop.unused.levels = TRUE) op.c <- options()$contrasts options(contrasts = c(contr.unordered, contr.ordered)) rhs <- model.matrix(formula, rhs.frame) options(contrasts = op.c) grps <- attr(rhs, "assign") # The first group includes the intercept, nterms count the intercept u.grps <- unique(grps) nterms <- length(u.grps) Z <- rhs[, grps %in% u.grps[1:(nterms-1)], drop=F] XZ <- rhs[, grps %in% u.grps[1:(nterms)], drop=F] n <- nrow(XZ) if (class(lhs) == 'dist') { D <- as.matrix(lhs) } else { D <- lhs } D <- -D^2 / 2 G <- mean(D) + D - rowMeans(D) - matrix(rep(1, n), ncol=1) %*% colMeans(D) if (positify) { G <- as.matrix(nearPD(G)$mat) } XZi <- solve(t(XZ) %*% XZ) Zi <- solve(t(Z) %*% (Z)) HZ <- Z %*% Zi %*% t(Z) HXZ <- XZ %*% XZi %*% t(XZ) HX <- HXZ - HZ HIXZ <- diag(n) - HXZ HIX <- diag(n) - HX df1 <- ncol(XZ) - ncol(Z) df2 <- n - ncol(XZ) MSS <- sum(G * HX) RSS <- sum(G * HIXZ) TSS <- sum(diag(G)) f.stat <- (MSS / df1) / (RSS / df2) GXZ <- G %*% XZ XZXZi <- XZ %*% XZi GXZtXZXZi <- GXZ %*% t(XZXZi) G.tilde <- G + XZXZi %*% (t(GXZ) %*% XZ) %*% t(XZXZi) - GXZtXZXZi - t(GXZtXZXZi) obj <- calculateK(G.tilde, HIXZ, n - df2) K <- obj$K p.value <- pchisq(f.stat * K * df1, df = K * df1, lower.tail = F) SumsOfSqs <- c(MSS, RSS, TSS) tab <- data.frame(Df = c(df1, df2, n - 1), SumsOfSqs = SumsOfSqs, MeanSqs = c(MSS/df1, RSS/df2, NA), F.Model = c(f.stat, NA, NA), R2 = c(MSS/TSS, NA, NA), "Pr(>F)" = c(p.value, NA, NA)) rownames(tab) <- c("Model(Adjusted)", "Residuals", "Total") colnames(tab)[ncol(tab)] <- c("Pr(>F)") class(tab) <- c("anova", class(tab)) attr(tab, "heading") <- c("F stat and P value of the last term is adjusted by preceding terms!\n") if (returnG == TRUE) { out <- list(aov.tab = tab, df = K, G = G, call = match.call()) } else { out <- list(aov.tab = tab, df = K, call = match.call()) } out } GUniFrac/MD50000644000176200001440000000304614142662222012224 0ustar liggesusersb292ccada2826bf2a35e56388bc21a24 *DESCRIPTION 15f19901cf2eb348466d09a064c4b11d *NAMESPACE badb1f26ab8b2505a3bb0fe66b4a0fb9 *R/GMPR.R 16d8cd75d6f286cd84c40b4893162ffa *R/GUniFrac.R f7fee19a58554983e84a263c40944d45 *R/RcppExports.R edd85750ef9ede337614dfd89f73fbe0 *R/SimMSeq.R 89eb510a0bafd6ca234e557726b8440b *R/ZicoSeq.R c74c98533e789d1d604b92a8d6b0ffda *R/linda.R 97dbbd25877e9b5bfc96c974cd6e268e *data/stool.otu.tab.rda b00f5a7e06fe90f2448ae1c28c00b905 *data/throat.meta.rda e3d83761e0910e6a0a818853d8f76a68 *data/throat.otu.tab.rda c346a08b57cdeeeed64cc7340f2c9c03 *data/throat.tree.rda 13f22bd629dc73602f6a2daae9ccbc53 *data/vaginal.otu.tab.rda e8afc959e9f1184479124bde00767240 *man/GMPR.Rd b615f9a94fca8c8fc77cd260ab8b56bb *man/GUniFrac.Rd 245e1ccc58b416f88ae01d28d83f5753 *man/PermanovaG.Rd 74fac72cf6d103da3d71df4dd15cb9dd *man/PermanovaG2.Rd 2d5e3b5276f20b70df1e84428a5ee9b1 *man/Rarefy.Rd 9fed3744ee0d6d7ad0d03a62abb2fcf2 *man/SimulateMSeq.Rd 6ec752de31e9c92acbc3d26d06c7b9d9 *man/ZicoSeq.Rd 8d1f5064ad2f80d6564fbb4152db64ba *man/adonis3.Rd d4bf2da8108efcc779a5c02aeefcc842 *man/dmanova.Rd a3e2320fa31f06dc1ac3984d4bb64aba *man/linda.Rd 99b0a81b69ba2c9d5bb5f11fdbda1cc6 *man/linda.plot.Rd 43f93278c6b01d7cfc6330065be187bc *man/stool.otu.tab.Rd 49bf30fddf16c8dc1e688dfc2af4b638 *man/throat.meta.Rd fa24879cf8e473298fad71f8642fa7a2 *man/throat.otu.tab.Rd 1b5231044f8234429cbb55d959d672dd *man/throat.tree.Rd 0151add12d467ad2132e443889995f92 *man/vaginal.otu.tab.Rd 3268a0499f34b780da3d2913b4ac4e0a *src/RcppExports.cpp fc5ea2b9fadfd4fb8568bd11f5e338f8 *src/gmpr.cpp