ecodist/0000755000176200001440000000000013576700021011705 5ustar liggesusersecodist/NAMESPACE0000644000176200001440000000076313576512762013147 0ustar liggesusers## Functions export(bcdist, distance, fixdmat) export(mantel, mgroup, mgram, pmgram, MRM) export(cor2m, corgen, crosstab, full, lower) export(pco, nmds, nmds.min, min.nmds, vf, addord) export(plot.vf, plot.mgram, plot.nmds, residuals.mgram) export(xdistance, xmantel, xmgram) ## import for S3 import(stats, graphics) ## S3 methods S3method(min, nmds) S3method(plot, nmds) S3method(plot, vf) S3method(plot, mgram) S3method(residuals, mgram) ## Compiled code useDynLib(ecodist, .registration = TRUE) ecodist/README.md0000644000176200001440000000203713576512762013203 0ustar liggesusers**ecodist R package** Dissimilarity-based analysis functions including ordination and Mantel test functions, intended for use with spatial and community data. **CHANGES in ecodist 2.0** - fixed bug in crosstab() that affected expansion of single-row or -column tables using allrows or allcols; changed result to data frame - added icov argument to distance() for use with Mahalanobis distance - changed stress calculation in nmds() to match vegan and MASS calculations; formerly was a similar method that was monotonically related, but not identical. - added plot.nmds to display stress and r2 for NMDS ordinations across a range of dimensions - added addord method to add new data to an existing NMDS ordination. - added clusterlevel to calculate Mantel tests for specified groupings - added logistic regression to MRM - added xdistance cross-distance function, and cross-dissimilarity analysis functions xmantel, xmgram - updated examples in help files to be more helpful - added a vignette listing dissimilarity-based analyses ecodist/data/0000755000176200001440000000000013576512762012633 5ustar liggesusersecodist/data/iris.vfrot.rda0000644000176200001440000000043213576512762015427 0ustar liggesusers r0b```b`f@& `d`a\EzeiE% |@F?(b.ͳ}ö+w_O}ccm,1?VEg ֶ}n%w=ٽVe[ N*c> Ǖph.dNR`O E PI^bnj1- U'V N-HIK/ɀqC3SB<% be2F0FRPHb0A4 >]W̬ecodist/data/z.z1.rda0000644000176200001440000000122613576512762014126 0ustar liggesusers r0b```b`f@& `d`aq j 4P! uT:GǁJ~DEY(_qC9Pqy7[ 7(;s?禃Tb[qP槊?q..Xurk-TL\s`rXnAi}> B_ jW:oPZ"~A?[z z=B7@(E- (^e?E=d7N^i߮aڴM;~ǵ7y}t̼KmW0{| G΢ 3O-?|MvSVmx& tú㴒s7 uuJ}St~ICu")֮mFMI>ceŕ?Yanq0PO&\yN#>asW}CuO_-XbdOV5o'Aּb C 9P&[^zQ~iLx s ,/׃ Jՠ;t[saRKҊ ,$AڙCu0M(83?PsCqɜecodist/data/bump.rda0000644000176200001440000000043313576512762014266 0ustar liggesusersJ@mH O>Ff&}KuQ ecodist/data/bump.pmgram.rda0000644000176200001440000000113613576512762015551 0ustar liggesusers r0b```b`f@& `d`aIzE ` L|@9:_?2QAqC9>n(A*%n9*ڦA`ɭ2ys;&mr067u{[irز_Pw- &r3Wrqsp`(݂'!|t@ߠ:D$ B]@M3 z.n `K˞_\ǯaɒs5Dy|/s&]c>o Wbɷ̈m>#QWn_Jx{.'a&?96~{tMi68^s~~Rf^80T{Y ;25Jɥy2/<]=ZRcN&1^Hc%E4%@%y@64)2bZ19P&[^zQ~iWZ%@2#$Pc% * P3R3S%$1Tzecodist/data/z.no.rda0000644000176200001440000000110313576512762014202 0ustar liggesusers r0b```b`f@& `d`aqj 4P! ٿuT:GǁW&*:|=n B_ jW:oPZ"~A?[z z=B7@(חh< f8c~k;{JgrڮEWbMiȵWod~'o DU]f^F笰E$_GrԼߑr*7?tzߙeG HqBAּb C 9P&[^zQ~iLx s ,/׃ Jՠ;t[saRKҊ ,$AڙCu0M(83?Ps{Uecodist/data/graze.rda0000644000176200001440000000476313576512762014445 0ustar liggesusersZ}lT?Mc!p\߻;l&~6H" @RеԪԒ?Z5T*m%RAiUhH4MJ)BU#G$MPMBKz~>YY̛ٝînlx<=3dz0k#O,owBC/U^Mwo]?<},)~?wCwxln? >xQ׫MϾ{_Vz(ߛ;~3{T6 S`ݭ{|}#}gn?vz O>G _lK[_uw_B[No> ~zlㅏ"~';H~90~yJ:?|f|%ܕ/+^lW/&ڟTEe=r"~w>z95b`ARگhl?$|a(֣ZM`s`DZݰr[_j24♡V{#ױB*Cj.FwbIg5}cK6os']eZumτ_v>*6 vko% ]Mw;RZZE;3)]u~b]W20 ~M"dOFK[cZ&\vQF3^~Ac)Y%:u6xz?򑬓@Oq?YǙs֍'|%wuy&[ޯ;v~_/DZe󫊥/0.qf_>G1.nִ]@wXG=rw{U.`oabЇ~*/"zCu9 Os);NP~Sre}f`l(I^Binv0yz0^Gم*o9pS뉌?掞wL_ F˪~X*M|0Oҟ׃oO+zc<̋s'@&>1>t_|Ir鉗* ?W; N6]pSMz!7SW<'~ 澂s.^8ckC }lHLOM#%KW?ye\QWpUS1/3zgGzuxqf&yź$7F1rQ\2q'b\3v ǵ[ q/IKÐ| (ӍWGb6s4@^:(_V:֬[ =ahêzWAkc~OZk|N0Ϛz7y{M%_uw%76|d=yg<=o?G`c>1/s^?'y~D4KM2xN8h;&fo5tLef}r瓿_sB'<5k!yBOg}>'w7w.wO{ߧ ?{ k \6NkN}CA.}))?.,uU7\>ǸM_y@罄2'}/%q¸XSil9CO۫azn|o{X@,h+|{0~5o'kwbC}OE"; ~1u8~˼?[ɟ D?=?3OE&?Ρ]?yX20gMw]wJ|{={]]={?v9#Ñ& Hf5Vo;:!SJHS+|op3 n{Ns,lkkwl{G'ښ[FݶXmm3yG$[#d[Ψ5n-(*k[Cђ[k_!n=;s*}0a}pJ[3K2[.tK RUn %AzPЃ!Mx yB^WzxP!=(AA zEV'_ʆuX{#4ÒHJIC8` ~90ecodist/data/iris.nmds.rda0000644000176200001440000070472713576512762015252 0ustar liggesusersym}:]oyGCJ3 C1_8м%x2o|?ꞥR8H!qor~M;v!_ egAI^-FƵ>3.Z L,4g\o.9)ߔ~`pϙs>'`RK AG& (9mטּF1L7.UX0.^Wu)},h :[vNtWR} zy[oMo+<;c{Цyw }|G@'k[pضpu…<8'::ԭ&p]G?x2 0&kb U'_#3".l󻺥&1< Ĺ`¹~"=|js: {=BL& 6zѮ9PN7<0F柏_ lZn]m5yV1[^3}9Q&e >4N\?E>Ჾkx18"kp,/ځqf8HRlS4f^٩c2S͊ I@ ؗ5A2/;zΦ/[EQz,0ab8cr6W0 ݼz4'0nG.O?#fW};y#ݭ1z'0 W/i..VQæ^E/,11Nh|MQoQ|p"i+U_X1ڠ)ep#+`|c"xB[#\nDɾw+z cZaqIF0+$2O7/{cڴ `Z];BT$hovXs-܄ƦϘUWxl.HoS $PSܽJNCQ[Ara|%d/:=5b)Ұv9.-pp[ԊS~JԔuc>WI׿ dʀIpKx`zYGkSK. Ȝr8J*/>}V6tZ; oY%(TzgC"0—{n`.߬KP}fd)Tj1#*? KFp^ޝi/\%q^@ g̓D@u蘞:{_?eh?FixX-q# PTy#n$"NLֆ;n>ݗdv¶v6{1Cr FfL&?z0Ֆhq^f^D6}SDpEy?ߋc#ۮ7*!\ci- (|G|J,ApYgͻ!| œo)3"LĜP;aw T#qp:QV-fVj`7"4| RkbTʅtKLFLCD=BHr=3Lj"g¶i6o) 'Fc|N&m"x)c{]1}`4țМnX)I6RC/hO|GTmM[kpjie#rz=Jpb:E+i`pC-ah4Pv[?0Wet/ Me LT}&P~apظɩiݎ%zksAPo5~T}aoAGjʶ`oZaX{TnpJ{k jiCA_g ~S;;}$|,뿵*DNʫ%Pkӓ7VTj (_EGSh {3)( =rllK<Snk3],`ȃ9>m=p(Xz1qIbZ1W=`eZ, ,NY[d /lH`Lɝ  >`LG$~zh3P^V2zO}1&uk`Meb>XJns>N䣢 Nxy?/Up fϢ,h^y ]pt LU{eᱞ/wb,42>{\`5'8XW|IC} oFYԀid'/ec99r;M~RQ"ڊ>3:5E1:'4*"\3W]~D D|_s2A۟sW[I ќ\B_/# Wo+"?0C#(c[}pY@D֏[E]D2fjt[ C?`'"CsƢ"<+\wF>FaNFw/"ўQӋo8bc2&KwUz6":lνDj"9΄'#Bek^:{yľ04=b K[oX ߡ/ۃ)Id)̾CV`$Oj;*,}#-YAE.x0)0N9NϰVFkVAI\!$h蛰%McqZ{EPnm ܦ)ɠ{NS]z f?T3mX}os77MB`u/.`j9\k_fv~j΀: ѻ|X) y#s d wɉ?A=H|裆'Rґ"PTp#(r0sTt2{tfWcF>xf;7t^7 I;%|!=ǞXoV]80hVoySR `KW5l8FQ'uy|X*ۭ?2:Y(0X\(hVV+CS:Ms6u;!u39E_>3Gr!D0Sc7e/ 2O28޷Ls~ K-MnaKW{S Lǧhڢhmu!,%v&`tv/dY6~$>&7]Ư:HFc ֺ|G%*vG+jbxfs`xo30<;loY 5FɋkP4V DJ>ň5_JNb${ZUDr3 |'zm3њED,ϨB$yA"F+HĈw-Y֒Wh q(MbNb놬l "h1 Lj7L`H{;)kbicg(.+[8|t3Uv?Ҍ-"loy##zi:tm AEf*(U1Mx:F3HE||QK8WuDtܥb1-)(e"0_i>c?!!ỽWb)+CR[gC1Bv+ V5za'8LR_-!+)̞^6m|ߗ~߼E?⌘X9Le`={Ζjsdh e-Ys-Q(@϶ 㮫F~ 'P)hkܟy$hOy:or ojݥ'bjTK$PH}E({w6QOFw-X ԽC_tnYWnyUͿ@w0_l8}1 km^슸"h5ځPxЛ|)dt o{=8$*W=a%5y1qOni])¥E̠ fv;.p(oQ'<4=[V^(-=O-\S@ R#G2i7 ɶK'8a5#\:aKs'F mʹ.F6d&S7sE;> ۙZ'2}lj'ræ<%?>MR?h/ʾN&>"FX\Z֜sv҆Cʼ:QBͳs&I|2ksu^ZnV64IU.]&cC>D([&p\pD ձܩ#&2 hw[8$RplK{?DQQ'Aqi11QMDbcrRGlq#O-!RCͽ{1F:?Tt#|Ȏ(umxaT.og ~[DkQ hT_z]헧1rˮ/)ǵ# 1^"N<}5 j_ 1BWw)D}r+?}MB%=DLxQ >!BD\]~9O""˓t]BX>?(Q/ՆqFyKX8Fk[v"'Ğu/(aܪ}FRٝYFqc{]pU Tz0ve#T6r5WtXl&F}]{_,\l. {0A @鴯18 G O,'i?_΀O?w+S@_i]0c1 (hKVV%I nk|CCE.LnUAP.bzo{êBb@uƛY_auDqefoC&˜%c3<p0lXsj=IR N4dzpjvHlx\;ZCJiy/g-AIShX:pu#e>$Reo;\|RM qitɠvimpԔ݋W Sj"`.#EE`#n}#\0p(Su weÑD|ppEL^ X?"]\pXBF/%30&jPDlKۚ/"㛱T Gnяk1z3p8IƨvHݰU1Bۚ .I'uB`Ӎ' _Įyp^C2\ *i9ζX`[Nf8ZnYY 3ӳoZkIWد;pj<άVh 'w7ȍ.[rk9}=)[ c?Aͼw;Vo{Pa8"w""c7S~D2zf+H]nݯوdK"j7XD,/!҉2‘{o,{7qQ o$V7!iOW/{g/"kҮp Er|qÆ\-|cf( ?(GTa*!-HIDqi(&n]Fw+D:tt}j>^B%qís "" \=8&D~R?^:GCjA{cuAD/erpLʗAyUU{hϨb Xzpx5#p_{:bD4cN-+@ #N9w&Jmc`] փ9O2؂ De!X|7ZE6p|/+A*8M#Yd]#vt~c H7naTj;2J3Xy|WZFQQi[EaLAt"V?Dh5hDn r1ٯWG&>ꡚ/\Y&Ł9=]yiH%a5à)pd|0\=O.ewXuHʮgVpƥ 0"_eSt0r'/ L)PϽ S/YlA6;]l,& N [#*{9!*kׄY,FYP`B p)$NDg0BUA<|^F7[J7DŽ)j:D|}h"/pλY?NDqo$1fY17e:̟HBbμBoDx K Y0U[F+7SF``2ef0%64xQ[݈mǒ({;.Ib$F߃<i Ņf]F;>/}(Ɂ E(6v^c][ߗeËղw`[խo` wHN;#Q F'6T/&[mlb[Q79kOGfTG惎Y+pkk@ | {;5E pnFr!86g1 ^U Ij܏VvX3lN?~7(zcrK78l>"Wv+Ie&rq#`aܺyF>\t=(NԎ9mS4g Zʮ!ЄƼn<e'YN` %; q.  ,$pvO-z.ച͠4܌iJApʹhv=Q,]a_E]Tr}0wp.N{vg[;&4c:pi gq2h|jq>jt *'(nj=je7aM毛h{?V8$ )kwo8sϓE?lp>mchKr9i=d 887:5 m,&g8]9 SnԑΝf+(v? g5 ; |"Oʺ G_ecK 7rHȧ:<:f7`A=[0„ C=Jc0#Kň/;N$G'?̭bq7NQb#˱s;s8ٞ z}1KJu`"R$;aO0i?xtR$#q5ye _Vl[.Kv9^t{ on~QDWt;DIei6H:NHäwy!vFp. ED-<ok|ݗ^ՇH" =2Y7f5xE^>%}"]Z>%j  Z÷B5jF' a]G&bZ6̌<@^?p#^5'O"2{`oPFlgH7g@~oWϡ,Y8l:յw=ǺEm6 %*GF3XpJ _8rp/Uӄ mė"ڊεbPnqX?e[Nò]a{f ֛?A bv͎ݔ1֭rR]oأ^O [zu|hAU[ %TYt$qlJ |2%,u AGYؤ8j j2M؁/FJTߠrvVw4l|R=%*EYnko3{~wC00j=&hNfD &w%#qu/GJjjX AB!8p pN$CLNo,DM!Ehi;#_<3,AWiwl1F ~E[~f N *tq0.M7Ol}H'͔8/{)\>&nr?M~Pv1IdvٷQp*˓CA nX> [+)dqzΘR8Mj0 ?Mhtճ ww&pXBQ 9"{Sl^ Fg=_w2F<;F0u[5"~GQO{LD{}{}QF({?GF,%ވ\R41a;Xi"fKDV8]u"q/8~150FPyDB. HRv"o&:҇(EMT R1ft`BswS汋;"| "K\w.DNYW#b񱎆IDY#xdvA#8Dv)0Uci('Mˁ?02|!+0_dxBSջ.0`k;q0/;`yE˚zFplm=0awF&> 0F*@?I&/;@qg&ϗm"R/du"0>:-su#oVH^ˈ,lzݏCa;ej1DT6J4!EV"HF{3v6! j/RaD2LT8Oz[sfVF1!^Q_HWY;܇孈zP/=uQt^|V%026<]Oua2"f #d Uk$@(S.-P7s59vڞ%:g 3p.yԀ{V5Ap(8*׶I~78 k_ ~%1 }C|_O>%]ߢe-W L`u~ D>qϥAn<^i~\d0(8# #>)m=9ֻX݀h Mʶaَ6p\@%S z gaf {"2Z*J[X|g Xfe ,ZbZNzK[ ^o@gǐT1W= KxmC<*#dvӜ18"KWJv̴TELkSDb7nAm 'S.K61PĉSPC5u+vK:vGh}Mgou>TvՆ[uZR+`}`m!("qL6א !2G1~!?&ϝ:^qaB`?0]3>+o8я] cky5Y\"ͧԿ[FC:8|Kˆ=V>ci*+' FSG"ZQ._Y9'c"vƞ3{<~zmS#Z?lF.O#yhuZu`iΊ8I|ԧ1pv,9hk4 UL@{Ζb˥Wje:micԤ Ҳñt%Z`GحOp|6ӂI2T\u[ΰ7\ ^ b&LC2AbN ݕakr?]_-P%zY۰yOq.bc?rbϋJނ8`dk.wvYȰP=/ENZ:/b0n z߮ -Wq>pH  F4+2IDuOD5]s@8/j|±"cxyQ\ =$#Ԯ[>=+D**ܠnxh~#]'v3v +_VpLAL'`a~.?M!{p^Iy7ʫ:>BTApWfσ+WġnJ3\ ~NOh3]+F{a2[/=# 02k7W1|X#R%1rj';KˎQTf GM?*E˸h=O.k>^M,Bh9AnQNW0҂jƾs#o5y {>#Dice\K$sQD\2F;h|G5"zfg8Lx1r2bV¹c]_6dh^%p[s$~()\ֺ3!2z"Y$0*J/DѤEMD8Rrt5I Vш:2J`D$D1CSL$Ye~MWR ]lz 2=æ YEEؤK̻.[-m>ś"۾j I}J2lh5_a)i@*gAW zX( _W >ZM^ϮB~4WU.KTW0e=n-`=#nB$|!1<'1+b`7g]<֑ 3^l85ZS6$H(>+@OLKX5Z;#g~KW"UK`[#X˺JiVp5zf3*Ƚ]߂ÊE>%B2_  y X6J 4O;ÙRҀ("8M0kwScx .O ӞqBԀKp˄x洱.v}&' ,wmkַ>:a?+w_ZL&S@RڄVv *s=sRg=!5r3,Tg'`}CѠ;\uP/Ё7J|a9CbaʻFzL怱cu0:{w 0u0><2wsCŴ5 表P8Iv#X:Ux0ox(Vnܾg4`DhQݜ7`Lwʧ YbK hћQ]QHq AJwFpy߆wZE+wqolg+Vڠob-uͲ=1{q~NR,Fb⶝=n(Wmkޡ(s  ؘ}aGR1: #A퐳189bfB1&s>fHCg^ngWhF>pQd/s_ÈGdl߲}1j]jO2Fz\bT+ۻncANQ?5F|7e;cWQ^zʎYct}&>r~F$.}|1s(*j1Md3t梫$F]'ī7ép%}+ƨhU3Ǟ}z;d gO σHHy8ʘ7 Rfy1ðX/ R]Lwg^T): N'}Ot]&uJ|ﵢ= 'V#p9Q F*Wl?WIޮH\b"eBoڪpI"Rc؏Uȶ'#}hpt0pK$"Fyr+m,u6Ο>և|tǾbJƷ#1j:MFpKGduK{{ d e}Dĭݥ70 ÿ1ZQ $cYiL0Ijѧ+aK L|³}1g[^I˰""$6Lj enbm۠84If;}޲ 's=Oҁt)pJ Õ{ܫХƍhv`peL޿ia&)! v;Kp8x\Y8 ΕeO{I{G>:õ`;CxνQ{ȓqmgspu܁Gpkw"zpH:"\o_1\|$@.G| νQlpi?i 7o $lϼ7g'Έכ,\y"6v[cwvs/WhåFop_}dtm[ w2\hVo\ yZvxT ֥w}u3ਸΧ^a$fv E"="ѵQXL(Vv6D\D{'쌈5_wKN"ldovDuӔmd v >r -cTQ#i {TH 5eB~|g lrXDNZwQ󸾈""Dl|8$(/b65G`g\C`dΘb>rv6{?QZLκcўK%_,\Gcozaшqrmԭ_ynE4b31k'è0 Mby &1ǜna,'>#հ1 }23ռU_Vؖ4/r\B؏?@4>t2t2ͤ2lȱ8wS9Q!m7"ak|g+%>]P+. f?`3!V0vA#0V? o /mS^ۛҡAo[;O<ba_'o?wj/(?I[^^GX@U08A9 3%ͫnk\J3W('?',v g zjesႰ7(۳0gt[ɂEC m_=ct-0K~sY7 TTWܸıRǙC,ǴYPCi:fq1ĝϹo4 =V ާh4_И(:51YpbB^5"z Δc]7~ 2LU%Fv _sÉsxHc "?ھ߾2(hm]ݘkv)bGlxو hX÷F!⅞6G8ˇQy`h;! xhXvgX0|9U^DZv6Dd5lV342$q1v ua;M><'D10*`Evo%pTs#H![U}V~7W42*Z6}m3A%Mӷgr[pWekD [bɠol5 >\=%:.dڈ( Źl` {8О`gͯE`|34r)6q'mp)YQg4ۢ;/>wO +.aGL8^瘸ꜝ^F8[y:KNQmWb:+џxoloџeUR {f=0j||LIIv9JNT-#XkPaDP Jv}3ݘN4$W/CK'135pq/'eL( răr$C<ޭf2= gr̓R޹ԬsΚEOl kpuX r1ԨxSݠ@cҦe&oUgL[l0ndk7L FvP7z9Lm21r' ޅ׶:e\;yF|;#] siyyIv aԭTمH|}'"80R);4qy!7:h&vJhYlkhF3B$@&`oi&VIxPOnDq3F|۷UOUhNEP1B|#Supd; k<9Uk?ooLFF3hv||$Ĉ-rU7zT\wQ|-L|0_E3uI""Y~ptNkIʶeOV|ծ|C@TLo8p\>tL֔MtR).(x&?XX^$C0OdM}8/ JMlپ(?l_e1_=0•N;*oFi^9FO#+HYIFZG-1=OWF&ۛt\4F7{{.y`; >^!j#<54z: Ѯ= 0J9!]ڝ@5F\~qtOY1tucQ.?cd6#&Ma[k-nkᏣg1lL+!YEfEogp !F>m|>5i*X/,`y]裲Qʮ̼b0!JovT9{7NϽ-'QWK0rsf ;8$rH~.t,K톅jl_ =sSzC 8ckexi0Thij~`)skp^-, ?.UրSԡ q^38n{/ [a,Gx8in!jT^ oaõup>$p8ޖlu9DZ8U?l&8RhSys䲩%dQF. p w-=8k{(yVr80%[}f-2o3`m5}t|,ۻAz? &h\`$[:BĶ Q$\O#!dA1=U~gK%ZǔJ`ig@u_6DMzwz{Wz]ֈ\$L3r}pQ0/o]o|7ZV֭+qOԔB4~0WxkKFD{݃~:2H Β6JC %\ޕ B /sM;?o1k ڢ29QzH#ڶ+{jwpi3mjt2x:j l ..%uLY F# 7vM1|Fbᦆfқ: ;oEVHfpF9ufgXnEi>Ȱd)&^1sn#OeA)H va;!3Ng~iɨ羘 e>M?m"B8P.?8e Ly FY&5`,Ѯ:~tۧ'/»7Xi5*zw*< 7+{.D ޕP@?o`lLEX--Vm3<`_ ^ѧxjP0@d ~;& e? [w= ._^gZ57?LX֣{fwd*)uݽ|"ޕ=\\~g<z=KCq7pmQ/E^uڨ3DZ8꘭(u:lQmy j88T ZʇcQTe8k-?\kwo sҔgqcqs*5鉬r~g?lctE =yVuL'j/4  ރLSquhr/Ɨ fZ! pkLn>l4kAy?$J|bսaK|K>5/=Xnډ<{Agpk0Xo?s~"3–_"fᴤ*Ϥ!IQ] ^S_ԉ/~+ʤ_p؂( ?{lmX zcK`ot0Eu)gځyԝ0бL\y><ȼI=?Ž6]bLES8j\Juծ.ⱑۈq8F#W\\P@igv#0h:x+%ñk wMA=X38rjw7:e+S0D_ fNYhs|x8\_ad~ oͱy9'xe, ,3/|@S2h,q>iph;V*90Wf =(~ >18x ։{ )>O¶}RysTވ ̼Suz<Հpv^5,߂lQra?T0t`JpFH] 0okjI`l^On!9azm)K +#3aV9w3Vky #V$7;3SH{tPN>?nvJ9lk{XJOr%Ůw^\W̺Opw"x ;5\' {w4ķ}wDq]*Of%EbgASb^LnO}2JP ,NH,fg@pX_kXspp0@]"g;,gÁTݑ7)ѠXF%rc>]Wcu=0S%#2Y*l=MD8LN8J~rX1Dѥ`<(Wt]Ve+`pGf$Z04 A“_\eX{Ymw,T^s3g`~ݱ7s@ 0B7v}ZxޣO=mF&ϏnK!ji* ;Dj.depx g}MyaJ[AUjl9ߺ,ti${6ao.!`:ϱNr4`c=@;?xlʒgfF|%jZu&׹yrAE c8ƫ 2a;\2lz J@稊5 T ,v h?mvj`8?4FqXfd'2bSy00>]-,\%HrƂbAkIV X .>Qwvj[r=28] -tsZj`j<x`ӦTt<}R+96< %$Nʀ+`@2yA`}ĩt~ a D+{m:yxsGeH~^~dmeiCw#jETZ紫ڈBÁۿo{9]BW3+#=L,H{\ziRʫQY8!yr-#ż>K!t~0aÈtG"DJg# .sđ_clvwX1DG- ڌ-{!Z+e.~+.5EkbBk0"M:>yHqՈbנHG}Bao) D?%yE0&sCڧ>F(}8ie4D䬏j#ZǾ1&-; R 3m{WO!ru1"~"-b@dEUu'`r ΍&聹O6q(x#.=`L+E־Nwo{XSqJ_!̿^p= twv|E/A 0 #yO^Ge~Ɓat sf땵Am{qӻKNA0 Zz/U^4SCY<+0[W 0gˀQn;{XnyJl6_u w]z jY1ˎ$ou.4m/lu^'qjbc1LUu`̞^3ˠ]#Y}mz;kfY}t9 sU)a\dFJD+F{=Cli:!T]fsp ,t~B<0\q}s5aXۨP1 eao>D|]m/AҠ0bURyHZ?F7>`%1UmyUg".P mjyۭa UNPrg90j n,+ pgG~$cg|wʹ(|#~7o`xmw5_70dViRxbэտM\ˣN<{䙈Fd"fr^p:WL`$@_ڻ`1V\4Ͻl ־Lpc-:G`)Nʃ-Uo 'Z<3COKQᒸKy=\H_g/8_ J5ZN=.f/e_Ͻv_*@-* F/?š?祊_]' pW5 ' p)2A_.:9[iLНcЗw;Eo;h1 y/׀l90if jIV_w\S^u\%݅TҚ]OtƍrSe`z*HM"v} `>(ct(W:B;q0,^5xZ8P?%災6\{ۋ@ɢe@o-͓6C&I&? cu +SJ QCx怚MpwƮ20R{=,q-/ D4A_gtj@&Uq%Gh4Zj%S"H}p 9? sMA+;_`)4ޭ>>|lu LX%{e0~l,I}`tY?Vs"=`,SMtql<i 5< O963S7c | 5f?h<98 \y􏔘}fU`㌹A0de}.c|w;nq ݬI-K s[*Pf9UGs{54AJ.3G/Ͷ̸&k?{U&~оE`঎y:nn=C[?X([nP4I% nO"fkUWE9|AXD}s1" 0u8#|JHn-_өlX,ɝQ#T.^3ڣ֙gx`dghdBLǨ&qp' 1"Yփ cNKv6MCtb)ؾéj^xEZ+ow<G=fdm OLyY\p]KaxÛ~a6oFcxcvX[sFpymH W1ܮ NS`2#) l>,;!v#D $`?vax/1i{ j穯fYa4Wϻ|| ~Irm*]4ӹs^ ]ظ eb961냐(i+ #>: [:4vCDPz1 g?OP>4 gIt.71jyD1NWgSZ7:9[,) 5]ERX,\KS +Y.Y hῚkʃ[M秢v =O!`~%խ89YP"pMڷX{6Ϛo<X3A'0\/b^>kXzHڟbfQp9_Y=fi|$0`͙n)SW`!8mPxYÿb̴e~% ;OU]'Ӄ5Ok`fig`~,2is70<$1d V8m9»}Z9g)Xm(}|u/>5/Rj\tfj’ Ke%G|9=U"؊;PB:R r4bgԹ5`fߓZqr$ʂh] L.0>ɶ+Q["8 /ax֢Kwx\sa[WX;zi:ؘOzRpxW8>Tt1\H$‰_5X2a޽q`.GWy/vwX8 z2g}uBR&VD,u_N~2M]M}pxTGe6`Qa g.4=FW>>v<`M!v827ʇ,5p21';l)&&ÅAvრݠ(.yBd9q"(j1o¡xHYO8HE[$ee<5IZ}{S2 "Ϳ}Uaك`>lqr8n1TDku,Kޅ;c?aoaLE¿MsKbWEo*#j!BƗ~"Mы v#ʈn _ ܮpv0+^ Uؼ-VAIVp=?g#\koO=39jh&nrqٔ!A؀GFf_pBBᘌ\azv4\fH x8?}q;}~|;' L".g.B~\|d*N܎ey ^0rCQ+802$A[q^eUpQCC3-kwvWj1\%S"ޞG z_pDfԛLu=TND.Ǽ2*O!fAH+9 Sr3 p5\ڣ "U\ Cp+o*QL Q Ӑ-\q<ұ/ Fd8RxxQ \jk riE "ר 3k3 |]ZF7*iB޳c$<?> ԋpZAʦ1 W25 7v[D8 BWdHlUT]1"v_. tp=-zpw}+Yb7O.~ yDg$"<0#O[0|ISYmjpkOwfyw;}XRs );\7VIDx'~erRW ZTu0X~6#}pWn?2ztn%s|?cI5 \5g^BRgAXBC*gػ-mҥ~{X|lc$s+& @cְ[0]+'s2(x37&7MngT>9P]=9PX+CV୤1苊| vLl1*[m/6r˝AꁃOܺ:W n߯Zxt8d@{AŲK*nla?뢰kj;ILYfBA+AqPy 蓶J-&ByFK}DcfqxFS 0ܣW-ұ`)OPތ ,q k]'sIa`Aן$,K}aNlf`}HWh WI N% `U~1"GO3WmqJ1`AI3>Ҁs]`m) X{ DKWCN0NA V,.U~]yTAJJ{_/\?XK IE݌G0k1 VG&fCr-d֚OX hh3`.A#X* N L>&ZL1 3U,rO 0`YZ04uߟ`>=n ׃[VӃ[9!.e4Cv^^u \| EC$ ດKpYu)m_XF՟pɋ6 HqJ\F9y4^>s ?L۹p .ݰF8}!+ /(g,7_^hANDD߉ 6Or ]Ή;peOp=zBĽpg\RT4j v?}#'7k'5Dz}m ־@pUHpԞم"En>hinѭ.ѿdFvcVDp&+$í߹uoG)|ơ=fpmԂC"e঻ZNI6vm?2t,nKofēk9Fc J⯎ŀI. T=?նB;nمzM0>[vvM̚9~2SX_WvoAQ[}0k-P]5E1؟SY-ٕR(EcTJ$)%YR^P$Y-Yc}pry>_>SƏUX}G -t.H"m 3^*/Kђ [-ix ONs3|;v~8q̣ͤUhs}FEst%2NzʷD'yu`}uhF)OPaA6~ӕCZD\K _C]>n5U\ qakihiGCq (PaknYQ-6ao_eu)(r:], Zj'a/z~09DFL]T/1JN . sEޅZe,҉h, h"ּfct-锟݆_ܣFx\L|G댱U9hiNu}[:bzW$w"h&=Jlz}aDߢijU}o1~anˆ[-V1uwlrYwFf6\tx)F.U6~x>ƃK\nCkWF1"uwoAf<63̊b=E0V FZ E Ѿ~FK+;YY-a$Y uz#)?Qlՙ74q~柉f&raIv`QOČh# ^u}6c@ cґ~g,٘_6 14Es'-⁤P|vs&!$Ffv4j57/u63϶.(F#B&3ZZ7rw :ebr?Ѣ"$FD"?WzZJv蛂Nί_Bə&3U1kj g@O ^4@g 4CwÅ J T6}5FO޶n}=詭{} 'df!K}`zM::.@;Txݠ@C؈غ3h 9 < 351ՠg/fgモiT "a]?u.BCy:To?3E #64j*z8xlR?܂3O:AI/stO=# 0[ȥy96>=Z.^`h;r@/{0Bh2~c2Z-+ܢAs6͡׎/AA^CDž4- \owfJM3hnM4I KA0Qbx^Du K +zPp;hG޻lk*ңBU'uɊ`x:dT6#[=,(n/bo+ݐ|Qz!tµ4nlCiy7\EAm^EU}_miT>`s!f?K #!arЋu^X=]Sd`xJq:dZ,1n;豍 MO.㑂#0/Vڿ}woSok ּ4d.X8{g3F-~)(=bol#{!ɹ>9U Fx{ΗhU=`Tѥ <V;;V-2`mJ+FJ0pPʦGL6=:0B{Rʏ1b]p|L2G1⩖1Ŗu$"&q F.SuW>roHct3mXF^HĨ:\-1&%{1E |X F#t2Ibq~ߞ` 9EcZF1ʊ^LF>}? #Ϯ+Q1фs%3BʊJWQ6 4k:888v sO<4?%Sk4O)ڃ)i]&^: ˓D;Xa q5MJOtpPm+t lO%BrqMOd+ 螪@i5j`'QPyN #u'EaH0E!yrD^XR4:}s*Pۯ~ ZP드v\Ԗ1 O-*ai<[Qb/Fc;&&S)7?(<(Y73(W,˽0*-V6F"cץ̡@Delkˍ̂e;W%ڏh=HP`N?'3@~WONU{#y81'01U<H 'Kjw4 ଚh6|gnj snO.*œipg=ގĉM)'B`/{\Ixpl+B8IQ\N#yf阆SW^俜lO5`\(q; VĔa@0̺׎f <]Gfh=w]G4t*DXX`D ϽԮ+b,v0:PsDCh͞OEJeq?֢4dsvm#3>JLZ)I$#V4{qJ^DhMdkDvkh#xɬw G:izkw17;}N@*b ЬZR;Tvz_߁9~o2%:pԕz,m,Dcwm, ,h1`3cx$ (GU? A͕2>Dcz'/@V뺍;mP2jmsoҘQ0t:+v,Š2Y0X '饐1>|rrﰛfUB,0Kf/8]Rj0H;p& W&7OGU8j~hr߆FLʕ06'_+lZ!`?ł #Gon%Nd=2pAj?N2 r` h/"b8}8tGN&x7N>!8Մ:N<9yg\|;{^%I `W κ%Ga{*YXW0=+kaC*VZQx,& f:f8<6ȍ 'pT6^%ٿ!|qRg8;XРV=CvgݭDVtO[8Y\wwDӶt"8ᝓ2i۽# 4]:- 偆h-{ER4:/Sֽ[@}BӯkAa 뻣б;V[uW{Tl2Є'1A{U /4FlS4IKFFBr#J%N7AŃFȮ($颡{J@dƬ_~B+oQtWz̲.?<BYMv87Rl]| -߇/ZhCI\:X)Ot0凾KgJsBTZ w3Gu }6L/;"cV'-IJŠEZ\2z+Xoxb,+Z PfX8q&1K`[R2~8"h!_ Qϸ +|] M={)9V8 1}F&BX&KdЊrU"\%~^+VryZͩ-GKK˟u%:)'`ns{(&"9c9FR_M#`>׌} D8h1(-^ kДݷ{+D5Խ@ DsW&:oJkFD&q0}Jȑ 1D0jfjc2 \=Vaqbm3YAk -hI~ E*O6E:yMМ;0wv y\G Q Y'v<b.v+ЬnEZr$*#~4]VH?o8#X*ZRR14B6oҮTf7\AKVnͽ{ w،9H8*Z( ѦhߋѬK_;Dl,dќGtwJǞ4<-@-CU7P&9}^F&@w'50"ksg zsOJKg"Tj˕)t%6ԒuX <#3 FY%Z|hų#5aWE|Z8~aa 0ۥ*j7:2xꡟ+mK+ ٣+#v #%Ӡ^ZIh8jyxrӳ2歶A۶SjzW:7>7|2 tYe^NƗW`>޼3K= OU`8n8O}4 꼊,NZSk0yտ Jb5s@Sl)vO0<$]U]0'x`%L *Kan{Ƭ0_$T'ʧ>G~eE0rq'o KH0}"^DLcPq:2Jk{ϿQ:ՁtE~| ~ZW_`d=45> Fn>HЇBb 9=r@'TU}z;`"Ǯ@#c ԓ'aX?(K7X` `2FݹЈ1*Q5*1;0W i#UIQ wcKD0g&^ Ǩ 'EaԽRchy&?#_}S`F5:PԷ}sbTqiz+QL~. czLOcze4H[`1}1FsE^t#ę0j;,n<~f0 bjFT?W[IEԑ➐}abhk](>a)/x#* ^ԨVU%seEP^bfۊbg[`nyX~J^tc+%D^T^lO 2ĝ 5m4I ~8tw(hr\/: _ZG``x12M!.mP7w䜘 os`L̀>x@?MpE/DP\ɎS?g,(Gq'Yj`nGoj?N.qONQNqՐl ڔe7NT6od`uH2x E'zޯv*>zF̼mcNt&m'gz'h7N3'0ڨ.^ i,^b()ؐ ޕ7zNT9S$35+o&T|á sg.Bg5hBŝ036 TuB5yӨ;u#g.sbx/ (Ġfڨ{"̪/-߭ӿg ihoa\SpgB;">sN : ! PzSu67(v+1vTT)y3+G4鞻%vb+[QtJl*2ykKuf|y i܁W?qN#hZ;uR'l?=ds\3P%6 EmcN0dZlT=BӒ^vDzu1P)'z$ɾ@g~2*:ׇ Y/2=wT>"?Uv֨mAH+ζ7FM]jA}r L@^TCYQw9f'3 70{#42_~Y$h GO︴zDu*CE4V.T pt7DMF3_AU"T9'c6nU~(2OǚV C_g)}t{ލoʨ]hc[jPhE$+zp0> د|8?VYF`1ehPTy{&6!Llî@vγ~o"niT Mn;1o.n)jBLaxTJ]TPq捔M/zes,D)9Mg*  $*[J`ʒI `4w|#/4VF@KWܠoGQU!/0NHo Ag&n Y6eV=C J*")8c}F[Ic5+Դ[T 강;z0$yRfS0S(L_pȾ Cc0S?,<V, thgП2[@WUl)iw<$i9[=׎W$ B߾ctqg,j6q]0.G0QWEZ_C=0zoObĪilƖ1PWt1j(Fh;֙Q]4_rz-Q.rkdY#_ԏH2Ȏ2B!/݃iiA$~c`4eS12i:(p 2Eg `$W_cBg+0b-fclcy#,ۆO-ǛqWamKc$DQg#; (rdiwȝ].Fc4 cUbrkFaa׫7g|8z"47;-oƘiA7b3gbnEv43n=1 7w6bwDGnu5g铲F0N}C֛V Z#ߛX aJ=U*xk6T= {OmYhu~fuh[r;nO$ZۢIdlh/Y;nwy|TTAƖ,|{A3gm]B '25h*#y Sڕ/f`$$ 4 CӁ)֧a NX`iLRGgPgi˼}>V.;#)0c vƋp$-fY+wn{c}^CcC(U5߹E|I gEB}5^zbnx?6[|њ^VCC3d7 f%~8NN49-kzi8lm9;~8H: Npm9gG7,} KStuO8niQIYʨS6ڵHM-e9l2~/,*`bqՁE 8YeONmc8pୗ8XN-_ ۥSŎ0Ǣn充_Q]8'XwĕZ570]hfNdNLIۊ# kqjXSN^ɉ6fq"?Ds#WVvﺡ;"6`26tpvZ;yy xUu5_iKQO="0Λap-OΉ^Ck~vGj)kZ+pDk.gEv꣍.l=Uy3o ^w{׋V~/M2e,ZgZhַ:`2EoW0Qc6[z\Ox4FaK;c*Z}C/Ϭ2w4}P@#??dʊԽNYa~Ӯ1'޸>)UL yَ=6yYWFЪG1b]n:xzQ10˹rUhرULVGFAot ^dz | 60t)v?;vjOVXuS%cl9IN| ,hv 99|ΔK*o4h9Ӊ`{4K `zW̆X]L_t_|7zYG@[l⌆*~j:es VA%-X~In y:KiC*0T30 S m~,*vqvg~@tTnGay2xjx8k%EKB.b+ݘ9 tO2 ѲYdۛkg4Z6uy'R]N*`a҃v5֔~ad uo]!i?^QX"{c5}һu^֖FyFR:s9x-ZcTch խc澜?^闎HEvr"Ik`59~bV^eɊ7x?Z~XV~v*rɮ:K )Z3J{f4m7`oI!ًhnuA #Rc/2,Dv[:aAQied>=Wzsn. KȓPv}$ͱBxTEؠޠ[\;nCqP;?x0ٴ/C5ɓ%T XPJccޕ5C-[H` y>e>;yàʂ t?)^CI@?R9-އSア'\(|XreЦT>hD7_[$6B[M> fʧ c4̌?<=× =y}7 Qa;O<} ~(Ӻ0ҋ]uҐ-le9Cȓ_-h:fL FhZauஆS6 p"1=#,] t2gƭ'66P]'Y7{%8o V˿=/=au7+66J$. /U80[ܨM}b~*)NJ۹Oa歇mͪC8MGISLuBw| ͅu\j0VBC}0:)rB5H7{Gs> }C՘JjNM. t:vG#p/+x䅟}IX}z %m'y rn[]\NĽ05"A辦xZ 6C粎̱4j!L_Ga7ߴ7)B+[0ĵ %@3/DWZC݀9$\,ԅd7~Qn=[ 2Vk4?ˬ*E'|.jjb ŘDy%vKZmCy/lrRտ7W},}"~Mt7Wڨ{v[*ܗBڡmJ^6ot,&ߡ%s6x7%e|&ՃP~7?&^ޟC7Cq9!+sGՑj\q( s"m+Y_F{aIrkDs; _946Jo1 mߍoمjn0#OXn;GorIiI-N}Ӊ%?0v1Ѱ{O kJbUVUXiaK̤7a.r3Fud#{',]a}3n(pk`Uo0Ǜtlh,'[̇ehY<+nK[^,Vw70_~[ Km՗WgT]+,~}s3, oZG%a.fݽŖxIaxYyX*kтщ44eǂch~nb>̳M䎶2֢ܛ|0KI~d\ˀo$'@O͍{W.%,:%hy5>IЏz%pP!H}~~kK֫(p!?hhp>NFm%PZ95:ٷG#BQ'cwhplz2&c;/!mEDwޱB"jxJđδJ ))o,wrE}\yztt ^%I6kpuc?HVcMv^F/3XၤM96J?LNjZ)0bP(c1MOfWϔ`)}м#GXYU#s^hq-9R5#GDbmSRJ4ܐ &4۾ח[9QUqc(|vҝ6>6~VF%ijnp` 闥?gFֻN9qsX;{w ڵo=fLh6ZBFdMパ`om/;q_( fpFiZk\UGK24#o-k?q pLqeCNE_=-g+kc ZeK2BNJ&тg_(C¯=NAp[pol.NVI?|puɎUc8YuoPFɚ ,csdFp苛ݣTd͂t5%aՂѮo5]Ὂo) kc-k:Wqut}D>4 V ;z{quqYT2aG–}Ro^K1U$Ͷᔐ7š?[Z`#KੳZ8g2a研 H[$$vNM81ûDrvOb-k ޹zqo6N9y|ыh|"KNY@Ehѫ0 Q$[iGZ<䗏Gm|Q8)nH/ۀFcj~BHScNڒ VJd_QDȧ,e4F7* XRԕS'Do[8QcġWljx>$|fv4 ]|. digCBUtlqT5t0[t:B쨏tmjMA5E-1W~N _51 G_F@/ϪۇQO+m#S eyNGCvĿPBf[GZ-0RcǛ)qO:4܃fw~DF Rhf/:Z*&N@k2K~eymhAtGm$Z{)H5V|jB6HZkK&T>rzFLi@|ޏhEca8ShuΧtGC%vPK^@{N|xxǦ۾EpCkG}v:#Y?B$m7pCbux -_1,Yƣy1%vۼ2:򠍓JNqAp奻1.TU{vI;y Z5U)՜5[ߞMocPkK&c5nk 萴 F p?[30kaWSI%1jc9J:FQtco/0*vc)xK!7Ff9],кHEIc ^BAȕىUk#8r؍a*FKF(bd#G1@i]vJ12CׯG.<lY8"#492 #>ę Yb{YWac 60꫄҄qirJ)Fř[{c^?bjWbEc?1 I#PFk+tf1~!1p^)oÈagx*1 ̳-ݰp[^{V2 fഅ%ZA{;Z@ZmZaM>3D#]ɷ*=SMحf)_#uk.03WOf}'P3@RޅoOJc|* ^+37(0rV> jY)1f?ߘޅgqUsMȜA &hwQʪ(AT-gB}bayvg< =Wkx,!wPȾ/(m 5(g&1.9W 雫,kEˠGzMVMhHzϦAzfelN-ԣƸcύ':llGшhU+w]ʋ)|hd9)ȆW'bKK=PﵫT.:x7u =[(R>1~uvMn_D)C9>Ç{*Q{pCD3Z`sM{ڷͼ4/+.(ĻZl'.@acXCLv1 /e'o6K~!#]c0}~Z,TUl,||ĹlcGQwv룲p4M NN#DIC^K0*;%Km E̫-z9ʹxǮ#wJ%5PVU~Ew+g@m-Z@PKu73m,[LBoR蛠NKvEuVo lh2f6P/e<aVA$g}iAryhUv nqAN_Ŕy_Fc^[υ!(Ou.?n5xVo2 ]+.k&Uv#_6 ɿBlm}0OgtK[:6;0;M| Evt!ڑgq8V=x@<)+B|rlIv>?*7uvrUPZnT=iIُ7@|\&8{{2t/ly!Gfr`+ȯgwemנ\.|HtG1#o@'= ?y3~O0Tw<0 6B+)ف9rf1P7\mvWq^7iƏcSi_)n{h[ؾlnhiIʍޘ |j[osoNi1*7mar =U]҇ n4|ͅ)k#(b[eWo,Ln&N,>σ=g1wPRj6j{U\1[fpsЬ=-hL5ţULR \_{yѯ|1S A#WAA3LZ*z`B~G.)Gx#a.2mLؾ&Q[bS b0s͵@ &o4Re?觅ܫjOmE\QOj5euϗL]Y5MԼ&U3Gō {|Z7x*~cgǿ+aOt1X9J@ C~HBɖAh>ί 569f֜$3(hu71i=mؖ_ѢD0*ň.WTV.1(-XGM:|^Yw6$?F<:^4$;b/H)|?aAhGj `{{0jpr9Fڷ+*Z%_fvylWHD"1"b OGNj3<_`$ YkvU -虾 ehpfbhᵃs7`ahíFhFtTB'S  }!T{tx=RD#ͻ|2GKMp4]*՘5=Hfcxl6YBKp?$x:֢ެZ:[Ւ(zOQW9몵VsVs+6gNͅj3IMe/pKw(9'QrL _-VvD3?:bkO?z M;&N697+2Whq' h1 494cLsusN76<(>47{};J(vBR׹3 YxT1 #fj0}X}`RfVv$6W0&Vh`6K*Υ_ 53b;Q/NXh L>dRܙPFSq@uj ʟ=>U3;PUY{4/0U L$C^zM!{P 4=ԇ>1頑++(_1; 4UA=`B֤0|>oFߑ \ FdѴ䎇c"]8t 67[go= 㢋[.:4>勏Z행wQYRŠ?Sq?uu.ZN}`SbSctx`u235aL@܆$*;zP7'EvbѲX*Fz4c&jFk;or8˕r/|F *8UO 0f==6rV=b'X_a%Ѳs8>TUۊ_t U`Gs3}OG:9'9l`qGg6cq)hSu J=b0w]:85˶Rxƾ(%4N]w>9Kg`9tbW2N$(v s1_7,4gw/9L5}xzhQ>Hᔱ٬*F޿8r nZ:5hLP_8\3aSuc;p nm8"n/m<3e8crS>NM8Ia5u7R>/X 8to|QTvS>NX- *vԿK8.?SK~\3J^7ũz]9O ϶L[HqpJeu1AwI᥋Q }N)O'{Ĭfq785ًr!91g>8tdsA"xdexcBp~sԔsY֜Ϫ XqE8'Aca+9VlvΰFu JP@ d UP=S'\#eiX"R%W_56{&ID4TEƐk}EteA+}>\vB+r'nZ Oc,?ׅbS-Grã8ׇƚ'nq=J%0ҙK0j ۈHDZ`KDaDg'DaWvWc.mX~t F4܂z_n_Fk9/v7bLKȋ'q.ZYBBlx!lm~]_Ѻko:b᯵.PHC ΠjhJLjVOY|@kxAB?\45:Jw%`q *Q==}*nf~Z(;~~2$Q_k]CO$Ugg?p-tXս#RN{`:X}HT:;BuR򻚠>V_&ǡ|ZFo*ѣIRm w힝W43:JAU~25Sʎ籑4DOws{,[B=|Ft$w#شB+hHin ;F#98X4xg->"oUy+|=jӽ8s8j%=!]44؆%CVo@? } :$Q}ˡeNbwhKQLI{}°O6 MdžLOKAܑjjÙ)s}zn ,wV0R[E@zq>"#k^jԝ'cbԻw~$4P4Bx?4v8^|F{YP5罓}WH\`~+2M.6pW8j Ԟq܀OR6hĝlj~x< } cQKFИPs:. b6y[wo=җK6C@ -u$]J^J0lŇ8GhR%~aO twx\n3Y>[2Ф#J?|j{/oOfmV.Xrݨv7_DH!엎"#_\SD~FaT6U5,Fڶ'羊rM1/YbGS*;0^R1&&TR}S[t ぢ=0&kֳRǨNg_(d1N+EjT'=F|e 9R2!) #394ygã@rX/6JpMshXC-L:"*]Sh/'VK*4 S"Cj>&?UMx%Á0aY#b>svfI'ˡ(퇈4_mdeA0n|ce"-:l`rFXǬTPOK(]#*r6̌ܜ&`'@| $H̕ 0pLx >܅Jʽ/!8,'d8M&L7Cchp>'̀ß MҔ/"7b ?[@m;8U׮/B0{lGҍL2+FlD%Ų8d/xc4r{jQtWe)hyL LѿG aEa;΁hx[q/!hZ97S][&q:)b2Zn]=BSWö 'bf?3YU~üX3L'U;-l~C%3dzC_Nd#M$z/[T%mCn'\Vıeh*heYʜam&/4Pۻ6IQ̝`͂-*wF1;Pp9U8e@GQp^p?{3#^|]zRď;dO0)ݠWU %S TGI4\!vj﹐{'ߴL6B&FG#vJ msQ"}lW{HbhqjT!qUyq7R-xܽ AVOg+? # `̱ʯ[C+=60o,s9_NazM44hH{<] QnC6P-Iɝx5 ]0 hc_]/򧁷añ:w2Fi8vEiM͔l.w)8tqKe쀻w"nY];ʋfW+VJ0`mnJٙLaD$=] |'r$n""ܚKԿ r4=݀R-\k`V@n'B7O$0j5;hm0YHUʭnl'jY`c2#XR6 }N|]ʑ0ΠyqNwƀv̀ls.4xWL ߴdx엂U2*e$+/'r_q!>wfv܃)%ƭ/"uz\}tחt7lam*sevZ*\9,Bqׁ\4:#ye!}B=3o~2jVh6nzDHYhfr<lqh|JeX>j,M~r}hC%)ۤXt5\<|[Ma6 ߜ` Cݒ=M=47OǽvcqC]7| F YxQ2jhi:ߨfwfɳJ"lDԱbltBAÏ3,_.}|W_=rQqe7<@/DN}.aYj4F5jtܫ1|vqР`ԁ \\xo_31l-U7-k0F s/̩FnQ9a \YzcR)a+sX- #ޯj Ek11߿FF1BaKɭ6}5+?H6d;FB2WXf\h^24bU0rD)%rNp$`3li{9NytKF|q |10=k.HEW5~ovOv41qXpcG Ej[ eF9pq-Y~ƱC.qI8NDeÙB8ްo,'(Kģ\@;8<k: dzzT9X~#Uʯҋ3_p򧟦&`rL 5?%W1[tqK?qOfҜU¬)Y{8hT͜') {Q,gV2ۇdoЇ#7bJB]ᢎo'r 9r?5!Fsa*GDٚdZRNI OS8Eo Nrd{26 ΟwyXX A֚f.毶xSBۀxpyiT ^o}`Fce*]-É1g)^l2M]5U ɿLJy`;Κ8QeN]q)V kROl%,;=W 9"D`y$Tgk%vއhb-;h3&{t`n9^ب74&Ve)i40b_< ^9gh]9 K4ׯC!70E3,kPI_e1. 0o~'> d?3駘ח}w`A/ ,RaھQ,m թٟ9*y[-+h%eG hNʽ=NC#{5__+ے̶SGe=aƕ%oݧN{d׮uJuL*m֘Up4U|}/1>uF2?I18hN{jyfz U7$F}cQf9tOLl݁^Wq4+p-qJh^}[|O[%⠩@$as<9œuҋʪFm;SnȮ@^½k.+/ӂh>>аu- :t#wb]) , A]_!O@8$f>0䵈&>/ZA_8NTȡOZ<'aaL>"v=-|h?^xmjL\k&ɟxy43$ F r<0a`v hC槼爖<~?>:wq 52@bQnp>>n@?O\4\Ǽa#8XƓG/Y NԑV.4ڸ=Bs=Ao3Т oƞtTC|-WL4wL%כwןQInRfc%4>v{8)$J3NQ]1>|>n:E)]/~|IXD?3et[qR.O!j;Ϡ89X-N:q^R' v)kzN8Shzؠ.eӤ P}z"≓tV ˽eQ8[ZNXMCpFۼypI9{tCI8956=6.pUKVq±w8k32Ϙ'V~ᔔS8Q-~8 d֊I{o_[NZ8Cdm|PCzV^ea*ԋD?jT8RT/,C}G_ßY1ߍw٤h&3mhuV +Eݐ-<{_(Z_OjRP{-h7Mn>]-u<~e 9_`ϊGA5'_D3_ɽ=i:mnkTPDH3IF#oGc!MΈwTЈ% _#ޗ"vhYRkW%gU_up)Tg2fZ}l˼?QԳ?Pg{h{y2DҗC톞scvP24to[SjXll79<>]B? ΪoQ#!HW u%=乸ΛtyRF*Zt0 !.>h@sj9F>S_uQUhZ Fj=#\ȇ;p-KDˍh%w;6Zt`>hEXA-y,Iڏ;hQaLoEc#=h=$Z8(4F3m?}k;ZQdAN_2B6>4 ^ M4'=c#Fh])ZTҽ#? *5ZXopQqJ96_D?YOhEK$͝Ա8$oEcTj쿙aq}[^`4P)*9T͸n6ʽ?D4EcQeչ`Ee1Yr|alk 4{ݲ@s7]Gū;:#z*ySh:tR7ڤ&?:TQ)[w\QOrLgOj8g`N"UׁFL4_ R`J(xldWCY$qbw;mۥI'`Я&q1vlF{WT,? ^}\J= `X>luϗa? 55<4P;s1t6G3a v8M{_E @!˵ 2Ji&YJ?(t\a\>PDٮ9Ba:crBkI_qBsFF*>!:)VX E {2s{M.&=m pB3뛚ޙTE*dq6R 2zsc4K.8\3ztn{7[nzi<ۢG1J-S*׃@.[-/N|fuLaL=N\6i(u!cQA;";_mS =}9b ۷^c|"clVuJ%<;<2txX*S=/WA]zpL2n'g]#HY8V-+gi-^b_B澰J,gi9҇_hB?VMM8߀Z$ZѧtṵCqb%fXh =^y0-T K_+ t_+pl%Oxm0U5˟۴>ZX4z1vj Ld\^Vk>1}`j9ed\?B}HcKmDN& "<"țY t{{f=:# ݿ8={ *l]=Z})t^L$`O%6|e'6Klla{Svճ-Rf9熭Ani0{=Aw\!ȳ9_6je=ѽ:aYl32b0YSZa9;ʧfr`@~)Trj[dM/k+  ,OB~ͩ|mω-rjc歛]anmY }]܆0TݹR #m3:o>pGL/$')lt;as-J9%? 3,g788yY*)w.[`Oݿ EZu#q|/8" mdtaB* as f[.ܐ ?m p삩 TEjyEOMBö-#{Ψ66zc>I1 S0g5P !~. ]^ŝ0BJKRh{DnY]yNci& J5Pƈð@YP+X.NdJB0 J9_a^ϰXUʆUѷl)Y~lI+#)t#s_Kca>[XU/Lf?i^VE3LІipWf ?nsɣdlҡ0^ͯDaec%e:.oY\B}`s2U!}Bv?}US'7SH`0kI-JHOdzr&O'm#Vm3̟? ȫ?=Z k:lsï av[yMG߭0Þa:wdӝ:|[]Kz,SY7~].Iay+8StOb6ɐufWq,থFN$SӸUM*fUֿ|7ᅙ NT5},EfV)$O V,0}\Ұ8)C6}eaC_y qcW7^cCزh^5If0)IVή32'+vB/nQ v X^ޥsvC8٣sMoۊyTL"|{#h\P}UW=dwWOlX]yVj X8(ZG=^4ü?蚪aѧ So7{psL_d粫O|O4@ˤÂ)ĨzƤWX4A2ڹ:5Żz? w.b+; n֪U?a l.0WMƽ*tҍ0l;j/MէHAWbYkaa X(eunq{<kyȦZ=wu} gDvE}| 5>h:Tnй$-60?=۳FVL/Z{ `esdQI'܉W&Iݫ{s/(;!7f 2i)m(t0q,:vrp+3 @[X\=PU'd{&H;#۷ k)@jIJtڄBqPBOLQ#E]9y]ba֞q?T^%^_|w>0|si?Lх>IYKPbU.d ]j?\`mG_RL%`Pـ ]Wmb[>wC O1߽!B84~ hlwzm"k+r:=Xb,DZȂޱ| P6u}{~0?뇕2آb 4ɿWVh0b$W+z3y"\=60z(NPx+OvV*Թ(ݱgS~% v~88ܿ V.#yFlora3>ɍ^[Ob7$|]E+)M\HEwJXptKf `yMYsZqP}tqLf<4֟[! tMq=gh#\S]fcQ.n.nMYeXŚ,<>|?-;Xhpj1%i7NK>filZOԜ?]a]djN9N.z#m+%y8z1`,V9tFư>sl̉?r^#CNalDZ֚+N[VCpcfz䌥AZ\soqDvщac;TeێmcOj4oI#)~c;ݝHط~ΡX>9hr{^Frt:X'GnZaXD8l0/zc{%{t8}ڶnxSJ 8flk/뽑^;SP&_"V w~dJxrFFLĖ`m}=. =H]Oq{`O'Z>I~s'r6q躹PP "ߞAꜷ-Ӻai+0zCG PN8cG>=P>YWإ7md蜖ZE0Tr ѝ[ G\qgaLT7`œ.B>#?U \>|po=3ŷ^ WSwFұ__߿‹V0Z L?zVCR8gh=|0 5'/VARlk;9W~+^OǾNԼt$VqnikVqɯ߾܃sCC8Aiw7aφmTAɆc{#?c}QS.=7a{HO[ 6 [͟S~`@ κD0[ %H|Kک#yV0Adl!h#qq&ԡ ni1}``>6A%\-pmU&mI]h)AwEeEN}vTԚ`pyoQ1m3 ;l7>Qlˌc&|ŪK3a7V!hfNl>G?Gy4#墂OZ# s07=)%`'&n}4]Oett!LiGǚTN| gmtd ,C'M;:!' GL>a dos3CmR\(8v% ]?/M>~> Dگ5@ؖF7Ч0Is ǵo1y&ﻆ02sk`W @ZL#VWW K-D6pa w`۸R7g#HK0Frэ|z!y\BX%v=r p 7|ՁlMU3z8v%\WscHB껞8uP z{U!u jT)7/%e ).;Kr\[\6Tа_Π0jWcv#rKg7٪%k}c cP), GMIz'M'@ndo?[Q:+%65宰d>͘M*JBy~݂Bkx)L |pPLo.߯Gyq$4BH)L*SB~ mIq:HE!%(ߠ$ڙ+y;~tj90M8wg8#l7,Vzoئ# *(4ZoB:㵻:PhsZSh=z7SP߻`&Tdn,~VHqy>v+Zp>tof$hl?\g* }XۃR'< :y&T7'p=A_`×妈\#h+)y$BĭjZm$υR r\]^)C7E %fm '\cuO=g A3!#ݖKݯq]5}~Ixz_rjdxOdU ҂'FY"HNӶ&a{I|22c݅nĿ@ݕp%gyJqzyI_ 4~975vN= 59x2v Oᐄd=Tp_2d~h{W@ꕡWoepwwx_˪M V0 5g0U^<{99K݅mJƵϲ*`APjeg t &HzR3լX?~z;(~(}f 3tu^m{l5sc|FvK2oG<'`[ge7Nq7f~.мx} Xn|^ȱ<?UEm`QnK錹_hD|4ki[i\f~Gʞ Gta5!M]`W=8=c<}%wb9zԎŁ |zd&!yeh `:cKOB0𯓱\ w~@tS)iTx0O2)`G1&|cY3CH2k; $D'5mw9GͿ6=Ƭ=BGyЃEbl3SltNX .!쁤*leIedO?E9Ӡ S5!4%KH*|3PʋmoMqLAPOyt9f1N> ݻ?V`/)yƩ3N@qw|u4>T av:Pn`놟m.6ގ>(g}ek]Hr蝗B+r% 3-gN`&#e7e&i)Ɵ.II _Zqg1'Ӎ]䙘^OsP{Q l#5ױmhf h|P(XuDP⑾SkJ}1+?q{ʨx{C$>AooǾYbвێc8թ8JU0ѦrAMQ+oq`z_4{v$g m{5cw|*}Չtq mB66Bk15GZt(3=Y(/_5ڠqA;W ڵ7FmX6bۢKs`XˈL)-!?0w}ζV/Thۿ݀ܦ{f ;QX?mU1ş+&CKKq}yuf.0'~cv&ޯ^z塕 ]{a>@M>{. P DfE,009!F.i[ٙAr??% < L#0]-οHNyBXzs (Qo:aVR}afKvL> Tlf/M}ٳ@?t.w6Tm|0`Y`Xΐqd%TXT~T)6Ϛ0o`} $B}aB8/fjv5v<J̘kuRLGTr^k{ebqCwӡ6@]nxk0:d=w9tKE63sϭ.πw?6`*댇T!'#Zّx$#ΞvHuǚ7w9Ee<opF ~NSK8zJ;mtel[/ AmߠL7L\:Xĕ΄[r8n"plc Vr#ϱuZm#1rngWJ@yCdc<ľli쎹s;´A&zW,owR7 o_"qM8`,}0^RwnuA"^kamXU,|֗LH{~wB7^Uj OUZ &w%PgL!Z-/;#8J. IbU<ϯ"Tn)vN\9X}Ѳm eae)6$I@SQ`/,WJoD^7YjCMnYܝDVL8`zqAErK>5{"n!/C_}]E&(HLzW$Q%:IBQx$TLDJC|YҞZX=G$CG=0a?+YMЮ =@mfPDS#{ֺ[ZSvK| ]"260(%?;m5{ js7n^Ij3ӼJd-|NKمB]Q&:[%@v!zg$T򅵙*AuN0tζ ҝ׾NB58yWI?y[:͍Pe Ok m ]oPQɾ-pwRK58uecELO yԹ >J ȁ*2r  :}\vw61%n3`4"&vbɍNڠT#F&Sl[ (Т/}2Z$m<_]u$nw  9qmZK Ac0{S|dg-vbՇKa6cChKT ʒ#?w\|#>X@ Ps߁LSxu%LLq8prǵĜyfeU?oJ(:}zEƁo{,:W6ets e~Hi~}XES eqCzn(Ч}m$Z%t/*2{3Z,zQ[:*\+ A:lJЩwL&DDFy|Gme&gA }8} |ZC\~peyf=bAH:J (tNKb^g RϷ' Fm%WRF5"HX~?SX< :/N%%=ks\mwAwg wV&.7$Hڝ!Hv? h0,T ]. })vMyE QNeIeZk9;tTR3nC8Ity#oS:$ZeA*kO&Ջ-̐ē[?a;'Lga !!g^U S;DqBsO(=ӁSdq y0h/YLOu~$Mddm{"eq]b}YnhToՅؾG`>#@miffl5%Ͻ0YŸ>ѦB %i٥@imq3_8x*L'eq̬ؒpyF+`*nH7ga=䶆Q݇Kô 'Yi^ߵ6gl?Qe>Z .geaI7*>˫FzsY2TOG~J[nfUV]d:VK)d)oq%!B>!Y^ +-"_QHk$o"M.u&@DOn sbm(,0bWKY^?д{)3Tjw~ 6L,Z)2S(lB*G`,п(tNC7\EXJz}7B{9H5) S^5.ְ*,adBK&.-ӵO&(ZMd9: sZaZk1?Z|I|yE )7XZ^1)` UQ_ǛW2(tE#7a*7_` '4a0;A7 0Bb.7%4/o;s;LiYŕL>kcߎHI&(`j9^T+vA8vlK,BߧxgX0YP &Q|xy;f!ersw"Ljc2۸;602Tx'#ikNcԄNҋ[7ؖ`ob[omu< +Bro3t&ޛ0&t6f: ~peT >}H? ig\9 p@olm };zcCOL#rʼn>J)+t ^ ЋA]0 {_}VM*g`UrWH|YQ|&,^m9L ! z[• pi ;԰}[84w- bgt1ނ9O$\X`462*jڈ n{>K>dƕBlҳp51iҍؑk"dF`ξ\ 8Cm6<8eJ{?g56nFegҌ12aHa.7jً Ukh.g }ڄõ_ qB u~@M؜yb;kˇ&+Wl7cw|ê_?0~v>ʣe]K/FcmI_u K^gv#3ߋLC^}j'6τAɌT. ʫooQuD`ٙ< SOz vT]W=CcO=G5`g [s9:` xK~9I48hK6V ¶^c 5cWO8Jb2l.(˻ fw6heYǙet8O7TS?*Lȅ-WW"|7f +\`~mRg,ᤍRKi\<$zr.{%\3D3J8[4NBWg ׳(8#6O"U 5vZܦTb\H}ٚNН7]pPZ> ~K}q(:}g4bo­k6027@\3\y9GYf( >ᎆ&! )onweʲmh))2In&𙻠l-?z,;3lIO*eCG0J/eKk. }WPAsK@6T}|,2{W%ZiӵN}. ty@M & @C\%l.4&p5cw]Bp{ h+S; OWBC G_7(t(wttBZ9'5k3U0IS *8̞BaR4S&/DѫX*`_,țz -2y 20yU7K>!( b%s`0C{qu(IlXHҩ>z*ʾWc 9ᰐJ0a*Mmլqk4sͦ'`~:̨z_C܅5DE=vX>>v/9>@7M8u[Сc= [{bbf'iQFNcAK$L 9տ2bցYXr5H([E HҾWƋ5J6a"RJ̩z +n=7f7݊E_xNKQHn)C[ZKKH$V 'E|;cSVoq:~&m! p=e2Ŏ]cqɔC>Io>f-Rex2Hcª</[>_;m ީcY 'c#@g7Tm,MȜn?Ƿ_= ~ :$s"ب95p?|q78[bmϸ 1dq%GfN\Sję'.;BpJK"q|eKFp2WpH g<͂j#eێdpw3P>ӺqhE&'++GLq~[8;%L7(gq\EQ{vHӍw` Cs'hy`w.~g>[B] [7ȢsrV:t4ھ.z{s g('qBW3yۧ,qP4셓w*Rc1h> %U]v8}g"j5R]IލSI$jztXHZ_PhxǤ)4L.luӗ8k1A+Xݑt= ršx۾10rx9.Xj2y(/Bc~'L}I07ٚvtt]xSjFys`ď{0t䘤%loU,_;U_c-a}Ha}-s} MLʥH^y u\ 3,>7\9 ,ϐu:f{? oΎj k =SĒYsB[A.,WʨmIa);QV"R=*aLvSTwb\s7 +Yzp &0|-fc%"3 go da?CW=*fܖ[U \QN(}2*vyʜ8V5o6 M0 fk_M!~?]i !${hR{}jkkcWvMe|WJ6TIƨݢ;3~&7dl}iZ=t( 67qpQux.Wkэzz‡ ie2/ Cjp2Az ΦWWfDU$rq0~U^bdoV7^9y8)2gl8wyF7Xm&7Lyk{#{#`¾A:s.p1׽ qzZs,%\+K^,Ae|A0۟0 3wOr`;8 zGӂ W=4U[/8#&᱇F5'pi3.lcu?+pM fZ\αj=7jp`|n8!*omto*=3}Mp?Caxo>M&#[ >'Zg7+iz9]/S!bAP|?Ŀ _{zڅK|.` Ibݽfu3 ׇ)kJ#ݎtNwiX+ѷ) u=&D5'Oi37>"tQ$reC vW )꽺쭶e ~2q; ڟ7hNTi6ο*,]NV gwNVd A O,/έT$q} '^"kl}ΟrQb%HL*s{ʓ$lT6`0#'fidY::k?] a~|þ(ãLjv۷`wC- O2Toca^Z^]RЀYUvaZXXjg w92`zS/)+b}8 _\?uLQP3|ʶ J^z aQo 0:aHXam;3(?po7ʿ lm;`6qr6xHm鄁M6u7`qgޯ0&3>EˋCw!_`{v朒@S,S w*>?ky>?TSG[zחn @=.#_}Cqo)=ک !зN! FºhTV [VUɰ\>4!(;dQhW`G4oNϟʺ+)4۵ ^#ӿ0uQP) V>X ]V,ֻ/nR(h-mhmB[LT˳wRy/' s=YQHj>bfwc`:^1@γDaJa+IG~yuҭ[F t S›l|ްSa"k4#]jQ0DqҺL}XF!i*UU3t5\=CCU>5As3]ʿSð<*Es9'fj0S{d34ߌZjz~˙k6CW1LsxxCܛ%쁮ygN8÷+/auϫ_a NLvKCE>ڙ{WA^9ObGBXX)ibbESu@16_jϸG'vl7[.Iy`5pB,PM`.';\ g5 ػ(9,c˦l̩Tdri=hoB;Հ53xI rFMILȲF9Ԃ&~cY€wJL,"!q<k9ucy)&, jx\KWwL[]kb~U~,l`jA!F'\1ʑ=W侊CvsѯZgqٚat@v\f-ߛi ;>b'ϛ_hΔ"Ve=<ٵ`ˉ6ՋKq1Rc\ͫOm"0#l|{#6p|}ʚsly1{[5NK;TVntG8ҹ*qyfڃ%Nd.洂>Z{|ip ZAɄlt+ɈR񃥿7^YñRqjRXZ2pOO݉m8p{,CyG и]Iddž-yp&U@! 1zM}ɋNg⸙_$v6-'mw6`"$yh0n[|o5 }?HƢj ]۰}ǹ^l)жPU9Xhpf vgc|Fe}>=޿++Ss;ɡ"UOσ˞Pe3ٳ= 5#z+B԰Kbu6On Srgs,`o),?öOgNFHaq/ M*cB:gF}뮣Xrglg UǪ4}0xHbni;"sOL(h:3~=~Wz¿+BN|Ov2K07nkB!RM y,q`eM<{3;_bQՠ@l2ihG5]vƊ [PHj /T}ݢqzo֭ߡ{iӟӞu 4UՐD7XD/֤=FMP7bRrI=3 懔A|iԏq Ŏ]NP*/pl0]/8âOMj-CܕBrK YvC_dy b59: #_>R<5Nܱ25lgKb*N~;$>pIm3LO~ ʹacR4 4 lClfk`g+?9@+v~IZ܊۠2Rʉj=|s\qKuGpGEW6e~гqƋډ{YYCw6zm/ *#MߙZ5o2Z7ۤ%]OjgXwb{rQSyNNwaֳW6 o!jf9WLDl3ۢ{s?냬)]Km!݇]s-pgpk)ƾdMu6.7 y21s;Eda@n)zJwfƇ5G@ RH7Wݭ=ORMiiWcm"ueF/ _SowB{?>~]5[Kd!ߧ~M-fj^:ht֪`׃Ju~ߖ쿈Civd&ݷNyLpc>ƇN8[@~cKorDh7Vm>s 2j3۱JRtn!e6'QuH~1fw? 3"a;,5{wPuK'8Ek }J(DŽ+y CNցza4.2\Uu?Xm2F纥Sf po4Ezϱ&;cʅ}oۜDrޑXtȰL{[; mJ7 a !JÇ,+"ٱ̇eQ1ݹ]6޻}s u֐J{W: }V-5gpVTnH\j6^Dy|44}]Ί1R[Gva爊SIv#g"Rfr%qhcDqJPƮk'1E`1 4N`z?|; ^?+oQqr Y|Zu=ɺgGNn`uF~lb}P2ҭiO ORX,H [5NN@t{*N1* sϿ6<S6B%(.k.:Fz}+ȟoGط[l6rߒ j=,/_n.hB{ ܱ7AɘKW)Vxj.'߲ dq,IT5Cß@g tﻹ*Ӽ }ؔ?Šϛd|?jzT%*:ڟD@HeVK CSat "*kXA3Y4S* Er3աQyF3̴ y#anKmd!eXF0, !9' 5r=Ҧ} -l"q] 4=FVhp[& f$ \mljWI>t'FdcfO)*VYvdە)%;:SoxteElY~ə+ roj ](CKak09*z=r~Ϊht ZH6t;nPVi;ҎSp荩cn[-Al0m.]^@ $[pY~{6gErZqKVy4 wPkuK2q8wr]U^Z] 7tW)rl<PR;7V;~It>gCwӤ5sn? U*W8WS_R s=@!/9NRh/q:>>4.P=BHȹfl}eE{a*kҷ)$CE *EXz8^D}ZŃSϊQ6wm)i0 LEOa(̚!h(]')d5Ns.Tyfv0Rh%e)N4)? 6PTw SHjBaCe:,6\0XSh`a^/f̕ړyBST4CmǢCo|OG? 9渑% |D~X^kPDc~<8]/?N٬Ks_U3kEO+Tk}V :atb[7V0T.z'FûH Pߔ*HlPb-z7-`W|^ŰR ^kCȨy]4D M!£YSCQYmbd>L:זAarQ[Ū0@*9=ɤUqFG]IUBg\06շw_ʩ=HJnr<UrnK HLb*j&sZ:CR[0$)5"ٶAS'KTuh=P`ZO {ubY][E=_܋=u$Sakw􊥽1棸-v9^he;ֺ+ylٵ*0@_icEJ%bt(-MϘߡϛEc Tjk+B> 6O[^/@vٳ4couފfh{Y|G<? Yr~5ҭ̎e`Omɉ[Md1;qk܅PC_k= g|_vZ6璱t5, hF N*_zqZVi ʍz^BXTa4:~6pxdB* E:iPs -+,"wvf͌8aY*߿ ֑?wB3Imv~?޶8Uhyl`%Xq.:7VeObB8ťl|}ՑaeN6U^AUIM'*<64Pv8)Ub58u*uv~L8>l_X7\4 ,~7ձGd""؉W/<6$ľA*HW8NShm>)(Ҹ%ݮf"~ qgbΘV?) ƸM%q*[1Rt{zǔ}OG|V{>u/$/$awqxe?+dȨ%uVyb7AD68c{}@paHZS-TC/\KѤd sڰ90_8oT(gog : klC6(_-|`$KǻЊڻ_WIY͋}S8wSunU}Wŭ*جrnU,Uw h)ylYHҺ`f3AT]C\NxX&X܄raɊ[|0xx峝;,͊k_葟,C.L]0gTTBsICV] yg dF6ׯKg`Z-ݰz4",LFTt%ad`bXXc^-swTe-sl $iLw_WvAmrqRKNݓT|m۠^'==Ux:[5 iIko]L NE$ml2u;v\cӈ*}@D.@#4s)HxrY4dP5g="X}%ț<+W8 !U2o& ݋jQH[0bFXS{;JO=K]{yE 6FFv?lD} gve }t86_*1 6!8 ~禟A3'h|3iJ>@o$Ns bKCn.Zo:I/frBKW_5? ={\r%ḫw뱇Q9גq2jh";84Yҹc㩋 Q8A8'O˹0BGDQNH}*ld1jdQqx.ҝt܎qT8o[83]O#_a3ֱ~1ӽnc7bK7m[FRh:F҉AR );Tqc~WD&}-X딌w~Z[ ;Ѽ~#[7v Qh%ImZR<vܻxB ⤐lϥZr4T~ RQK3y}*Xi)v)偕O]%2OXW8oJ!LjRHoMj]`uS &Q l?C:ޥ5]0Y}E!Sn5ah->x=RhxknxShOcé3K`]փX̃`uK Tz +G/'(SfC(4^q2;8P ;%_Ry5j;_CۘbM]%uGu=.}zƫUb%T%mǏ`KBsCA.NA{JcYd  Zo&ڍ-OnÑ| X+To+[U_XW͗ŰwP̄%}ʒ]}&?~k>~]z{mcl)t|Zb/8ku(|܅m{=ӖĀQwGC[bs?sBY=Fm!s,$1Upe%lsf}G^ErFB{ l嶾zSǃ%ZʳVvmO+u ^$^spYNqi_Y\˛2{XrO O nn%E5iEcCy*mJqMy}ƻ Wdq1e*/o˞%h뛇q٬\Sf\xI-rWvWY{ r;ڹm6p9aB l+aiJxgV{*#H[ :>f\c,.o H.*me 9u&`*q5A7)}%jm.\`'-'ww¥Aqܞ uY }^\bcDj`gB2AsUPH248fk'tz6 >4"zhEN. -3y @T^:m/fΆB;}ՓC1P@ l6ﶃA/ngGJhOٝ/7aX9՝ Yi) QZFa2%\f^}UڠZ탦NeԺ}9p{ ^(h/堟F`m^Q^e͐j6YKYtJFW6;lX7rNƶpurtkv6R4.=ij{'%C=*Aq/heeGgj6C VVf!ψ]1[y.0=,=rLsEUo `db[0: 3'ͪ)ilmm KWFa5WJL,].~sN0/ǂ|àu{Lx-aAVQaTT5/ΞбJ0.IQ[PX:k6 sߑPhY.%Wr&AX<<.։RaG>14y#Ǚ`z]V~X]6G ٓ?`Eծ<0+8m ?\Mҧ|q}:Xm+%`n0$Fj#0l>3sNl~eӗS`3ؿ?aGQa%{Ps'ڟ' 3]ȃ0s?vY*Z5*UUnZ׼p>15ݞ>S\NNlhoD:As[9,NoQ︴yɮ6.I[ƕhQ=Wn%O~Y{3831ۋi8jn~7nye?rj9K'N/oW\LR8{ =rT*'PpuV_/~17t;pW9[J/2"FVϰⲎ8oy#$^ǥp+1E2qe7A1Ǣliwc$rW7}~Qїc$įK%pi/y^Au'Y87u.<t#f;f_<u*5pB`־P 6[Dw10i}slfbmߒkœ!9T&LzuI["A8JI6CՍ|/Zoa8DS\EQzTkr֍AlnӯJT*_%,u/ά]Y5GiKf$PU$[{K{tX@?Jn9HV6.Iy^+@=43YHj%fF}afG+@EC1::Ek}@h0:A`|=fJv]G,h܍@2VbBPL&P{ Mƭŕԇ|SS`3xUl)/|;'| Ta*ƥj~]hhh.vj}Juf|°~\*vLEۋbl1:I~T}å$± $,{OlEQ{o V1 ѥRavF t"'T&9Ki44(ס ;qʢ&iRϔQAGjGp%3>tƹE;JUY,1-*U$P3WT3e5].eKf,2ڦeY6Bc9NP|YwybߨM^$;/r?5dfxsL o򧞇5Rp2suׂ.TGoZ쇆#8 H^a7.X ׎pH湼0j%[5Vkc7\ H98'Oi㪴rm[9aIGijNUҡ'Xu/s+ fg`VR;g7js.kOٯь4Ĕm;g[]]p*<_o0"mHz B??MYpk\Ty<')"%ӄUźt/d'^w1ǹ."cQuT#./dӝ/&ܜ85003}dQ?\X` 7Nm>U Dx"rc"MlZG*y. j&qv;7͊I U.#(/Vc/iOT|l_qAi0.\o/YCիJ!)"IVMM# eobW?^~Wo8͌cOxӘv㦎qg8%ZjizpFr} I6>ne굞TK!O]hyp z|{fB-|eyT:rA\f*#&wYBLiHhreg`w9fV2y~aݮI0i@'2'Lg:6MjeE NXҚ +n_ν7o#P+ +;\`.^,y UsÔb VHPȄsV0.j =oUʛnp1@Z^' fjVҾ]#{`~H_L0c鋊ɰ5i4=gu"כ*_6s5'+`E:b ,k?PLu#0c\1x ֯NRqB^vr[Ю!ֳXfz~[zy죮kr[.IVxa_S8ՙҙ̧u.KkaO& LeQ 5ص:&lovxT2RwK?k˖2sypz?7N\~%=K_11z|Ĭg EaBنp{wy4*ʉ-?, wy/췼Թ"^tu'8cQ8(K_s ǯ1ܬڰ߼5mO2>K w_vZ95c/$$v:fH{3O;Zp7ݦl- j%EW[|?3 ܞmͻRxw;&{G]^9 ?Ĥy1dGdڏwHZ\8Qn>`6rTQ#U$VtDŽQϚG2F-S;E>Z:f|yOHU 8,"xer8w󪦆}r`m.nfm?XW- r#qm8o%1~oC!㽕|+?p98 $PqQޙ|XH) _^dtX}Y=g7F>!&Qo쏷P'&硵]C8=:DwU[]Jh }7p uj3`ΝfC}ϐ'o8K]/Vux4 r_߸ &b0s5x}E,zy!00$ %-0/ҕs3d#j֔ =LwaϾh3b ht[2 z]^ACz)3uN #( 0 \V# BOz;j(s~gx{q豜S LCjGoEm&00ENd Sw_V.O9i1hxZv[L驗JaH0}s!%V:Ύm{CBGeMQ.Nybo(8a+ -fיjSٶ xߓ5\QN O/6GiUv Ęe]ŞsN5`yKrPqHB KOA[iW$2'^{Z jwYXm"gJWy8OV}J2htݣ.x%$[o>?p -M9u8c+!zV4۽>(/BW[BmUq0bjVq(uEj:ERSnq_ p6xѼ0y4$f`i7:}\Y ~+Za.yhl ] pfC}4+%=3C84lAߵM$UIFrtˍ?J/ޛ-7+etlؑf3*9̇*c2gҕCFvbSKOe]wĖGBxU=ɘ3k2Vr}v> )jn`ԡG"(Z'uznj#n|lH5-jj>%\AH9[^B6}3> ע/}&^F}a\o^}/1(MNpVCܬ?B%JSǠ %")3Z?6+qn"g\URdV$quǾ7?i ՙyXpi6p= )jש߱Ţm$?>NrGMW"N'oKq#KNZ d{puKM%;ki˳ u ~#7ۘ4#z?~|܉Dht"-/b\z(w 9ϫZᦾwvJ.׈7Ҝ p)ԃC\* LV[uڞާq0\-bֆ%€Vh~yeEiTnl9[b}.Ԇk-?%( ڣc7ͰvkOS0A? xsw//]tOkAdJ(]<6HLaY t}b-9r+W݅DhQzrl:9ry aXC_`Nms x} A5՝!e#J/"?O!0/_߹}IqF*8&LB}Q*T̽|Ն*D X/";pٕMVȹ^0jiKJjF34ݗ^gI7yȹf;@2e[ fw ?e_C)aXY~?&x}X{I 3O}L]pBV",d;zYXJ,x ! cf`&-*Xhk 9X:''Q8Ӂֆb ~:f+O:E.i{~m`cGqGװ~]n/La^X>[,,ǞھاS|6x*@+34 Zg20Q$u@v>>INeX;?aS_Xy5~r l33*  8B65]JJg a%쮯01gݰnT<sxp*hn? /ap"rj]oY"|~O=VQ0-6kyB@kͧ1QOցm7aʘPU*Ǟ39/ 1Q-Ǚ4-e QFdء`|3 d[_P!b者iPo)yCpn; 2at&={p o޷CgvOnlB_!XsN6c0fgu]/XahߛUP{z+[E:x~FWBKXAX8Ac]"pʻ ϯ׺cz@O` X oNAe '~ᣊh1:9;Ϭ व 7sӃ@m^}l3R|\SW%qк.c7׷k 1vt/cs؈2$`>UE8S Z~ፆnbv*woР<^q,idwi #yKaE{qblK)z_W}wE9(H8{huQ}o+Z&q@Ǧ]B|!8<7*/i8Frв!ֽ>ӟ7sCZ7k}@#o>'mρK0q#w94T8%)?]XB4Q$Ifpw[(T䦉Չ cׯB4 c/a[D{ZH>m$ ?$q)SmZe[+Vjwc8}R [O~0?DFIa= ۼD\v`:V{xm8 P[e-sgH 8k~V *I h( 0n4_H"0AY$~.۳ H{֗\M7˿>軘cV"Ꮝwn;C c'%YepafXZ2U }ǯQx#a]ڷ˘"b5֍MeiO AT`sBXo| +[&Pq.=M̬F4597)r, k|_i,oAa-)֭>-V먼?+h?q5Sh…|#PXw aCi7i6/7J^%Pr  fa%QLVdM'dn쇋o`&>R 7-E`͐\:E~ i:*Jr矓hzGLF|l+c<_ab? GTm2Yұ-GV˯SJ"O kG[aUXO8Rlj n.+Ē[8TJR qxǩQ=M|=T~BNJ-&9 .2cP/vMAqgu)MM ᲏;ٰWྜ݋:omͱG&),[e2KîxyN*CH:~-$*5E8$;d~JԊ8,Xۋ3W*V=W?ex<"rx~ lЈhB҂|X*vV& .8dG ϓŊ؛x tjY80 7{QR-1N:w36B 3=vUs8T_>% cݽޫt9+ֶzk߉+wlŷ9na-D+N#S]P'{Tn.IW7OS!ąS7萒{ U$oZp.y}Ugc%4P\C1R73X"/q=#.~'r J@N=zN5=Bś8.slkkw .nU)SWqݼӡ|P1l+SBpxsٮ!\:n|<.z.ZEDRZT}۽Z=98O EJ>$5MW M.#81a|&qtEM89^d0|8Չf*#18Ք8.1?]~(X8zV- tEh2l o /4`uΒ|iVbJX^X `dX/ n,A*]h@ݤQ ړr&E*[Game{'l-vg_`װ#Sg$Xunq&W_˻cG#a!NuY X yVO)qEqX8_&_F;u(&p.h^xc^q~wCY8,Sp G٣:vNޡp0azC;r+DV6YV֨¦ {!:[o]DvW<^K8l8|?1փK|̱t2L ^DL v-{&!I=8ν# %{ذs[s؞ۜhS]D_I|5˛yӰO>lv4-V.\%E쒨/"67n@BgWGŪWUaeuǑtp U1t^Vڥ#`.<蓍}BSұ~,[z%b#ςૐul+WpLf8.15(FʑTG H9x-(ʼnq%\;]V䋫xť c!p"6awj7pP74%X3,(8^Ԑ=KE8q)^&zӋ+(Tqnہ8aF ^1'RY|T~3kFWqv*[/`0B ϸdCԨ瘾ŕ/NQpnm"qK$m<ٶn'"gK|"l8qcHN 5_ۇCfzj_%8 ur1]8)lCgcypܦ;L_GƧW8"I}{'VVMLĕK{?õ>3 i\ϻR[fX}P{Dj~a9\~<7sL292NUOi.c3$fKBl\Vy9?fH1nGR*\}хe8/zĕ]#'J+7Y÷$01UYߗ/ldf7 bkѷ> \yB;)u;T٧f%g6p٤Nn%4.e/lęS{mq1A!JIOoD^!-u۲HtFx g%/Ǝ6$qz5x%.CSXP5w cE83z֦-3&W&U(eO)}ysy*oeDٴwl;pXmM$tJ{=<:W8zs{`p[i62M U8 |ĵUةHaAEetU[[)7^z3uzI%UK&Xj9BPr~ed*IzS[~{`MCR̩'>H⡹0i K4$ҠWr|8F ]U]qGԧK&OJP%+q>Ńoamj~:$ sUhI6m48w¥@ԕ@U9Q d9Sч|<ҹ;׏"ٙ>Syor|z|N+I0jSHv. h-w@"VFKg2}`NjϑB*viV߃EN8e'V¢׌r{ zO~'f> >Ǿ]Y_э..rR=`e5+t?,_>; x9ޏ f?X 6nŌS ${8,O8a7 K%@NV4=$LJ l ֮]9d&rtkC$WR4kgϷj^XRr aXVF}pePo2.kk2r*§`Iv#q{JG[qR?߽M?Rv>O`!p3A,3~|SRW7K"]cP뵃7`ڭ_aQ֯ۤՌūH0);_d 3Oia9ûV !Qѵb ˯.`cm׿;N$5x!餮T~#6x\xY31^:)mU;rQ멳v6v7Cfs_,"$ڶ+2^1'rϭvvMvP?-]ȨEs^zA8+y 3pKk.p"6Xd?/z'mXq#ߒ֗e-cmM39eso(.~ ^8ubc$ys@#yHJbMu --g`QK1rn%l|[vT8{cwʘ@^LDhWak].;a#sgD6M6ގ_CMX+7FW#]f)-2T7pSKSx[YU_˫YBx:?n4~%\Ǐ8ӱ=OՖg<^4 t3\ Nsčumwipe/6٨.oKOxy$(k;Mp!P2e{_}XFAf r-)OL;ebl"9o!k¶j&\ssm&\p@l-;.\ŵh/BQuEz'+Zd4+;^}8E5;<0uLnC ^usM|201s|ʇ| 3K {{ jYu"%%pBD\{nt*lHCU%R2'TwOWUSu2q@"u=q6QsW`m};w %ҟA6'g$y8Ml}iƽ47?gĶ>gVJJ͜tUgJ`ͿJ\9Â\绉TIr򨱵T1[Ic5翌u\u$;}It ūy.۬ŵp9r"U=Dj !uz"us7\Sd#R|99HmP5j)WkFׯ\؉^_#qбML$R:<./:V9œX&T1:`: l>PSf(Zr~[;-F{$a@FV1)SC3eݙ؄^3.byS Uq:|. U2˜3+F@2+4JqT瀑MSg0km=_WB>I_W4&4U3C䥣4W%L|=Lt݂osW}Ƥ'# :Ar oh1$~EM ĖivvC$m[^'hmrC,>z%VWڞ%P9=/WQs%a>q?;ԲiJlYì-ě >rI,y9v-jnfѳb:Ø7+;XC=^ M7 R5$x,r+#9?$fGe!'O`*,jlÚhC |iܠU;56 8V߹?XxʨX221 _.ާeC0oSR,YxM+[zqL1k˭5wlaXyNU'YZSe>dG<%.f򥻳Myk)بhlK_ڊ;^L~\ Ren;bgo gzn A{ 7q˂(ל6|H:v/Hږ5iCGׇr^e{gAG4'IJ@ m\c7$ɀW19i} zZu1eMeUB@4`L! HLq<_~Z|_˱W{pm̅]*"2h . zY;v'(_M;S-<..@wHM ʹK4oL?PD ?FUׅJgps(-;Y k/1aQPrg3@]8Xg$.w#2 m̢#2+=puT7K|Ήv6lϧlXNn\~ƐH2p %ͨT$Qb|uN >-%2x;'O>s);Wp2J3F"ݬ%NV4jB _LK}{py0K2.NH }>Knc4ޭre"{Ŷ7q妏!lNYk;5M3?yi_3]S`Џ8UθrupDz|ڃq4! $'Ÿ"=J0䳴9e_® Nhez$r=3~&`a_7PXb!N>x8gz|8>EuL {O8R}v G?ܝnʈ"K 8"`X> u؝-Hop]#3@);v̽b )?ޔ^{y*5aw.yh]}>?'5**XW=u~(~!EY۴mv*NV'`S!~b?{Z[j! ҒH(+s\6gfqTG{ oZbOSbډ/#~_q<C c g@C@l~t%FiKz =a:.As3J}Pu Cĺd$,Xω}s?39_ _|)S{^Dq(u;454)s;Jϝj:!ƨ}OΜ*'mdTx ze5TܳܮW"]~_ < Ͱf]oTND.=P[ŁՁ0q"t@~֓W|")ݕt;2voBrV ?;ҭf14mGQNƴ%̯T3YIҭPih%sY.¹n@1UpG¬ bvQ+=:*=&? Ht}{@g4E0Y^Cۮҿ=m5,9зfnBEQe}_PN6Oۿ6C{mÖ/]Ђ;kCcؠa2rۖO u g;NYD ۜz{OA瘓Vgrǯs04> 3r/I |˯}8*u d.1p3c5=puVzM̩Ta ]rȗ;g?/-c;{_jR8d~ N*9gapͣ }_u~ +̼S j=*@L3a8btG\2ۜ~j b1AZ 唹C,'mAAd+mow:)-q7POmt[=?X}a>IZ7uqc3Ϭ%v)rbT{;։v"Rq=\&/mP8*rv`mVZiA?`~oG=yM \8ψs~xRIo,b/շvrvO'0q 줿 ~ 4`ѥuh-=4Uм-mzpϕRЧ}==I< kgZd.~=#OۑIlPlY+{d"@Jr&xAOb߯ji-Xz]d'dk0L|c΍A=^K{Q`%z f)^l_lr}*ξJ,#0<`Gy!Y;BU&!F_* ԕ4S.ƞ,Zs"2hIbvYmhb81֓~{6)v #Ya d=z5mwod6LW[7VV䃲?A3B'UA9M{ZKn8lqz~:4qm&{ n-xU]cƅӟp{IOXMQt2/;F\Iߓ30ЎK ΍?"m@l+5h|ٜmǏR /xfJN&eP.&3q`@lw}ߖMu9Q%Kkh8,#WH~-}lBB8CGVk".pQSV7k&~_tܿۢep^ȥ#XD*Y/iX*.&6 ?s(ۓXE3y})w=ąo#!_lIwJqՏwrg[%9tϬoqnF.눔,01ٞ(66f\УQL@PQ\az IBJ䥐Hi$?{bR:Ը|p.TuX~)7x?8m͛8zsbO؈ ν^cr[!bό$% y! K\ tsnl?3Ͽ[pve|E5]]ܒ\XL+#pSpV&!u<(iǥ4Xm?a%\t(2yjnik6 rf[} ;b#աtv+fB7SX:-uV|!3;F(xxcBs[hhs7|  nj|H/i5|Mno휘(u*<%* Ty!cV{{|DqCsZ U`e >BSM9FVgC 4֘DBm,83Y2WZ1C, }5TQ"reIl}~3Jh<׉u'MuP@>=N#¨W+j0,հqZί3c3= twȞ{=D-BXa2Ԋܻ zR?iwEQlJcRWˣ%X,Vu ̤|~cyw/ǁr/"SH-Zl. 0&z뿁1ٸvX.%ġ\~nua<\G&*\ʠ3I!`a@&PM݇c+RՏ"ݥ=8r'ѧ1 ; s~ٷ\b.@==0?v+di]b!igFu;d=Hv_iJlq:m͵MoT F/:àъ .M y+ێNE7)̩1+K*|]JcԲU3iLsM?;p EYu딪1`~ϵ8ZDtO`vWM?*@CPUp UUAo%P!qa<5V"v]axb`Q%mHJa(eU`4͊T}'6iiØхU {']G=[vN),GGOB+1*{[]ZbV/ssl`μ^*d&֜n$gt6ehҺc^TDA_P)SpDڽ^7%hSt/: wmVкqs(tRSҠVzlD)mОɕ.Kkr@9=rHqR9ouBv0פ^(L|cY?߹wi蚌 yG{`0[یaN310]Zqra @:jU̍CW|[q9=EO2Y Bʌٗ[7sAkh9p+# ';E3B[кれ[y6|ˁ.3T$\Jeef\HJ<5 Nf;VZ'r qAʾd7}[K5j~P c'BATSCZ#VCтM␾4?{h"fk͚smP2^ DhYք k/`䥨g9. -vY3s R__AǡeUPI>RJVo ռV2MNDQ=m1~]˗W֧,D}*T Uw$ryzZ0`N)L6`Pn_9BFOE!WR/al=$xnFJ/(mgrsZ0pC`R$1K>{7aVѧE{3BAI LJKo `Km#CaLjXz|N&=Z- fK_̊٥9PK_ƃ@c cO aUqX:IlYg|#ț9J٘a9Y+xƥ+ m42v”wGϖ.3QΦz/`}EyMQ9v2R[a4ŕîjDZpkCk" !Ss+\zDmT9u['ÅwL3RDk yeH~@?߬g`OtpqA¼ٗ'%7 gǩrDgYN'F_ܠG`Չ@C7Dw!l_LY%wX%Ji'ث !lȷXX:13陔Jg*7wԔYyY8q`GnuL91md'8=|}u$1]۱X?u'Ʊ~VRiNT2`) CEyNש@l.7@16PqZze&}\"W{4ә 7t'm6ޖM#BjD>}D UMRHd%2lu "P"v/Ij\IA=_\gՉTOvip66p{ևƧѸ_;Kߩ>!Htk1aVq %*,(HIH#UזH[Ul\Eh EB {D*YH~"ԓ)D&w _nDj[p/Ao5:rGdkq$G۸0m!kSK$RY;[J(t{S2/.uҤ6g~n#.V?r5Ꞔ\[Ytv[X. `i F2@0%i(#E/7 #٫d90[;T%\&C ZC%0 w|q#G}iBYj?E?vqs&yzm++նT/&{o-t'BTKU[=ή׭a]d:rXZB8CC̚)ԃv_ƀkðHGn@Ј6Nh>D-tOu?Y59AQ|OZzZH{l=>:k0ȇVb#m[G1tl&Dƾ{"|=xļO({"+=Oa4ן>eCGp$-=218]ԏd1E(jC/4wb瞤š11)]n.:1aKhSadL)Q%Z_O++u]~O9+}j4 r%锊wh )ܭ~X }1  ͒+6CI߆Lf{^X cEWCo&*U0p!fIhaêίG)ttkYrݼ8]]y]n|8G] W_oǘlE5*AK:f/LDs޲=."z.L'Y?A]_T C PvXV 8矿qL96'7Ѐ%tn~z+|7oEoD`7[$4?'6Uw3ŖZP#UH"'3 D#&B+">욉`hWtk4}+av9'MthtpjM\ø'_3m|U!0$C„Mvf2:B4(m6J/Q.&rU6=s;=vdoߴ&+PܔT&~k7V3zE'>fQσS"frۏ3֫g|"-Q=E?y's;1s 90^05/n|I \wg"IHףM-Mg|mKj|w@ 5$B_w wPJmVڡRDѳixcN}@YG{KL4d<λˍgTJ ӸW:W7P'k=x]lXՕcmMO}M_qNYRd!^,IOUS*kWq\2ol4fc5~<^:zFX^UOS ](O`3Cxf%Nܱ<|ڽľ90hEr ٚg`#|캟N[oLA>cd`8YtE|{`[A;J4OWeld}BoGC;$-*GRWG"5 o/ w]8 ȲW8$,GgR:C-/xs}z :$buiMFm/:Kogd5; ^fZ`j~0p֠*<:3?ECWi,_{ V‪\]r60C,1/A@JQt;y?jšG!1c(36~F>eBW.r@񱷶vw{@D L۵}Kz G`b,HVG"/d#D:#6"}F6>/@fu:aC"#}DiwDzӮrDڔ75~??7#]O%N{ 'l‚a"AΎ @˾ula0`؞RH~*5-Crמl[vXVx O?G9Kp@`g$ ;]CC]0ѳLwS>: {?[_֬K6? ;.^!I]@>dY1_u6^֖'ЫS]+%P͆8: G`JQX2!" 䵺s*]&5{f*]u@NF'+XS082-E7~Cb$7M?j?·+@;E;P6+ԕ-!cV0dIgwᄢA{%K^L^h٣dfمXuY6M<`[~eY{X4=w'_RnKs`?Q(X67 %1]wjG^P=~(rm'R;=}b`{Av,`HU.+z+ۊ(}8i>wM&?V?^#ŏ*/7,H8Цri|쿰?` mtphב%|Tv:2&itTg]_u/Tb ½X*|ڠ3SExd6?W8 gF7 }'ԗkNH1y$KG{JfQFw[a-/8^o=5DSqj2;J~5`J̓7anV/e{M,d1Xs!Dƽ3а.!dCaљ0,|kPA?^Y`Y9[~NףWX%t:JЂz:!E= ?9éO{3;,yC#>!0p=}=٧S'7LuHkc y{7qqWMPM+dv*j :M^}ϱ, Ep=,2jr:HZER#';c(G`R'@v&nOR݋@gO`80:#FcKE&$:$z=Pi ʘh·ݓbk ףi!+ɾFH g!Kի"0*e_ ~|M a\2 Jf*‰f:E!} G::Sֿ;FO T/#~@w3G1@7<;C|v23@ǎ3C]N_Ztsgb<.\ԣ\ =\' ؾx]ݎꦇ s3{ L4c˲7-yIrL/Wꍫ'в]). 0pjRhyՋ2!Qk2½'qFwB65iשs}|>> ٯ87φtiy0wԛ=Nrtt\N_O<}w kNEir[P9hfg;UcJRpU 3Ho%@?k 8+(%lZߑU6 z8)Ș1 G>._ێ]؃mMqYYw-NkyleǗ8՟!x#Ϊ 2F{F G%2q+weپj ڬ, #. :r7$fy# *bAs]$MQ=8pn<- E')h/yBW.UhH#RD}fپ2JdEdu}cM *!.u ۻ,JqDf=t|jVWV8=yx.S Xe|;)=U1"c meܼ|*.X ٛJ@u`+C~ѵE&hx:hUZr<1uH~{nf@^yV}XNq^>P'CCKzՃ XjڧZT[6 'Yh‹)bt_=!Ac0swҗ6*c Ë~2Uth]NW-m"W"S*ʶP`wUhnzQm& ?iԃp uP0Oѹ0~%lrDu@U9CR,cA b5̄J 6#V/+22]Hd;}O5ދǶU,4^6a̢n֥PwƁ<^P\@/F0m ]QzC1>$Z8mo.wBT6n ǚHg6:9~gG& cx1(8'gWcmΜG_ gӪ,ؐCa]R TюJ5}q'DZy!% mF)˅m,/WHy,ZӖrecSw>X&UhN8>SY~14{tbsSIl᜞ޖ8+=pLSW}aVe7~.kb4[b'uR[;Cƺ,1frf 65G_e,(Vr7kUZt'o,F¶S3`N['aYe֭; kՆm8\ђzv}/ܐ m{ktR?:㘮! SoҷC-WY=%"\ldmӂ/, |hSKTf ľQ~`5mъ @<`&yFD[X}aF_ExY,U ; }.se]=nYo=v;_;ژ|hgh14;Ņ$"Ќq_ xOs<M\m\?ᗼْV6N;q*LbY@|>;Fe)ll܄G 51M+Ys^d<1>l^rZ*k4=`U%PUz(3CK!{B\ *xi},i[u!o7F1jga10؄|,}.lYêpC8~;nBkz?rjQ؟+ ,?ƩO#r$V<> +cuhy!N.jh_2вmgW,Q|,몿΀*(nP7]VR0U-G G)49{K]1K>䢃qvq]effY`<71>ȏx#{Lb՝ֈ@W[ US:/6v s;N-Mx}*ȫ"o RӒΪfێyīV};N W~8=afuCR(*2 `7X5 >Wqi#'Qt/dj3Îc_ukS:&,d6/yLz>4dsoؼj uvYkam%;6 LO~c p)T(sH ~zF$R5y%tOև?ϻ;$8¾uf:,%[Kzc@>}+-y2Do:[Vq8+yH^y-\|U~bNrO/=#y6oh[>V=>I S@]#NMmCl 6iaZvz,Tݦ;k H~֔BFgy,^X'%[l=E(z\;ufBu;:x0`m:IWZ(*(,-aII**uæP?r1eۧϲs@N5)VfeA};x=b=:_(BӗP|F+uȞ[$'SMc5hHv? KmÔ&f/b[̽[奾1:/n6owdv9ŶuJ0ri?q5BJRmS,d?v mTj - kV}]OᆑEt, ͰJ7c6or{WbD,¯q5]͏VO2~o1[Evo *(AFQ@DB E DPAiF: ]˹=ٿg{3sM>O²z^Ok僽ݡR?U.ĹzHBz 0 QbM)uP}8sk[X-cd*nz-އ٩?cqT$" xDe7c8SsfU+ՠB?,"9 C. zá3[!ʽ攂0 Q0Н#EAb(i"{nwmXڸd֛w? WQ[֋ KڙUaPE_MʇiZvA 0AR0ԘR/oc@({NvJ&R8У;쟒>ru6ߠVO++ Hjl>pAaaF}y*ww;bfa9 us= B>}o?Ȗy)%s+WUqAz_24ĭ-S <%2zbXIg1JD29q7&fqfv?.1g~/6 pSR'.s+mqa().ܛ mL޶8cEgˇv59S{أc9u; ~\8,g;w+Iw[+$3E^ ׸WX9䡈8EݿQ٧3'b,$QldJ8u ۟ZBcqV6/|y.`L3\~noø5e%TR_9p|FD&R4eb[$ սB/όBIzfԇg? Cu5=1'vCڇWl*[*um*AP' Dž?B~A'b pc_zV֦ʷ=o9_p3Cq55l1LpSjSamvM fK19!5Y¯.Oac̼/j auC%`ɃJsaGLY, ~φi#fFJV-/oE h] bg`f e +2}#k_|>3S20$]T[L9Uǜ ӹd)\H0L+5${$ OԞn?-k.gyЫiWh,_|n> >J??\`pt[0ؙR_e W\?'Btgw9%?uIVE -Af C1cz0-[NtUٗ|PT:\s~o}`|.Oh?r4o,P P_XKP}j4%ׯiB:?K>xFbhd=qZat|,āOa%Ѝ:8<%H?+f z2lm2+i/9|HJTyaq0'5&ڤyzԻ0&fHn -۰.vHsj "#;IQ} o.&;aa2qAnܭAtT(I f>_V*{T o.(H-R6HT= wS,D9:ۯa"~ޥ0^nKGʊz0zZk^9˃מr]UϳH TR`g-5dh49YvڞDj;DP%"КÖH3oHm~3"u~eXL:R"<_)ij e:c'ԯsA=\5Z"uՅ.DTNLD7a<D?l;Eg\:gJ$}l}HC{n*&j=JQjz6$R B$tΆHsD017mw< )j;L~H"#F)"Ү'ƌw֔nmWyixeǻ*RDZN#q!"ǾYtDslj.IEOXTkiX#{XTe;>~L&ZbFix/do%R;<8H%غ|}NI5K4'Kpv||p8}}++~,wG[p?ֽ9qU)jVNj{E>-g@ ÙpÜ?$axIJ9gUƁ7I~ƱKǑ,3Ul;6< *QMywYW=۱,gʋCOLWyepW<Hٿ^} G.^TKDD~QZ'33I<sG[s櫓" `>'ß1=m5ƙ15O6JOv9mtǑi>Ŋw=FdL`3=TNbcfI=wlw(Ǿ#~al1gljzDm1\ 7 ,SJqm.$37cF u Z0HE x{O>6,$*GCHai](Wf2}Ձ3*Ll?.~xGWn,}TK;h|&Oj-RĦt6\//xI U;gh":|l?瘴-|{>9M{"7QiIec2-1~kƝDH>7q|_"܈:D#WRmϋŕ#sNl Qߺmg5 }ۅ–хD%T$. ?.ewS%G0,HN<6Ġ3$'8}1Qko[k ⢙jOp~m:ؠv@Cɾ )7C8#=5j\f-LZ-[Z7zhz퀋c qݪIa})q9 [CjݥM8a}V*.7)ZgFp0g5p ɉݒp>|:(FY$FJbg]/N=J|xt8>(|#e,lՍP5l.mer V.#%ۑ+R/ ~vQ4N}о26φ=©Ij^oI"|ĥˌ/u1+ۏVq.^z9S ߽sDžċ$ 3g{3u5(T^wlwVkfC< 7I]BK尻'`B=3¤aH1d~+]÷'_bBnnhJ'6+ LB["?;*5qw(cTńuǿncS Ŭ,,d.l3Tfo ]o:M@U+0ΥL'z7gsз5";\=􃻬0hʗFB|)~{ {qd;y4;` m~"~Zk]GJwbw XG/(aGц2gD7f.>Ky] c( ɥena^yṮd/]a]"en{`'i0!  ok+ a>=3RQY3a뚧.q:i'WBo֊'sjrFrOcSs7>I[:"~(Lt!릌)|^_/Dר\JۅaۡMh,O<`l0"Edtd%5lPJ OAו0XuC':mE1w)2:vP r%2Ш>&һr&EqU@_R-]|-r-Z 0~n.ǠF媕oFC3ݣŭƓ/=M{{t 5Xe7/zUN0r|#)? k?-jb{EbW!,0(X]W%d5glg@X#ClY 6!8{Fo{_2js HM}?~R^p<6.V^Op+߼$`#HѶu=j2we6^ @Rm8A]ǩV~|-9[%t4q3gGh}Kvc󮩒ns^@0HANPrj[x+X 1+Xkp ~_d7_r1dK.=4؛A+;퐐szĮ.C81!Fe)ڝ*l=wC nϽe;Ϳ `?mӜ;qp-UZ8ᅭXi]o@-cs'r|5؅\Ol1jB>S쎮q6R"т e+qLV:c6&Vz߈QgQ"zZmT /G+_+c߁U8&%5.,!ep?c6RVˣTcB\Z!+ ^QZ?ScJ?q5qgqnqp4X~:=)GWYD-$3Ⱋ£Og9.U8EӨi$q$_ٚH4-|U$zIS$QR q~#M1rMfr3Ax;UBčEvۿ,$:I֦IM/MVhRvuO7#<'Iv}+/INmh9V&m7Y4B^۟Dme5-[HV!az $-Dw kVծ$V$MtS$ZgҮ]$:f{Yj$$:a%jS=__ $ WLzgCEJFa?Lq  w|Nн}4YUo8M~YB/n?9%^h)7?O8w}39}k6H}5 fΎK3bLfÊp%hi*k7s]d3k.'ax?0jz6<,JzOҔEhPy7.3_]AG_lc0?sz-H0\E /i`<NdCIo49); G?X]G pPlwq4حV$~ cCGG`P0,z'wnuKD{uWj0?r$vHY$Qp 6}Z&RY}-#2i>4@ΛԣD-gG#T `Rx_q*jH\ h exQ[ ں} ꤠҫ+Z%!:~1pYz2}IM=~ kGHH5qfcˢF04"Lmc``,Sr:to#mj#H0j,=~GrfIYmΣݍ L;_7>KǿPώDs,(rǪ6dʡƱy;^ͻՁr6=,H~ݺ䪯lF_:GᱸSuD4JT.ɒ9{׼>,L);& _{FP S {c|{%A51;( NywR%֟֩xK@Q>Jo)zͷ.LcECw;'4yqO h+oW,35gE~,ub.RDK^y[VC_kx+cJ5Ǒ4μ: yr-oEUyEjӲs^mQ5h1;{2IzsG }V-|jgj;&gXa X6EvcJxyJ'N8/ڵ|4Z>2Y} 1Klzթ{k=*M=ϩ:_ f.d?ƼX]ʯ-!?ToɻcGׯ#&17UO2Ix/q48{{IK82X%zJ]{>̄|)훚Xwҕj>Z2"o~Cˎ*,xNOij59Ci֊{1vşۅKUaWhW{D{Oh<"EՌ'am1Ld=k.<6jqi)ۺ>{F?g ]6{0)SE 1]&V?,`~B {iJcᗠ+S3}5 VpD ϥGcp4Lv٫vPАz( tmWn@8 ?%I@r sh)u Zq-C4ZաVjw҅tVAA&ޥpH=gkW`{\ .&vbtGm%ƈbA 9Pٜm=D UbXȓ+tz%| X|<;S`ah\]Wk)qwQʸw *2o<m<˨iJ3EҴl]6"P_0{0gg^)yJY #oז7_MuP_:䆈W_g #v<< tpR0hV2I Գ(>n6+أ#DH;m;6:^f;uRw0[~h[ $Ze߽?''W>4E;KCiQ+`t^W5>V5^V|Irh6O8j*}нSҧB,3'i~MZN ާ*l_=~%%[ #0z޸d4,Z*GO1 e7ΐ! 9>=~'_,)Z2oC:"ߏ̷9&Rs0Ia䁇Pq?F:!=?=LwȥT\]K*<4䙭o?'Usx{> CttySX,/Igo9EdwbBfhD?^^WC/w]j*m o٤MF6jb@G7] %5'@_2)F&U 28D3ؗ{ߺ&{>tzO1$Suչ1s~?o_a_yyt>O5a[@pT~}z#_˶';`~"o ^I]qMǨkh֖Ѧo,,DNOa?[3oc,?"0zi/+0׺ޞH <=3 -rvGz"1OhaӘНEzvy4bry KWanD kW 'OciM ? ,SA̓Nq} M8}y)PeܯIrU*ۡ GE>Zy)(R13sjuӕ@!Oѵv%$xh>,258۶ @]Qќl/=x+&|KۙeyFanwMu͎z IoRV8 ;5 q45$]jrUY=]. [^$m6] |G-݅0~6(t)v*X4qf i)+`L bX>KSK$ʠJ ,617yήU‚/5{饤IUՖ{:t,-ҩg8l;dlIe*v4g!T.5Wj1A#c8MZ Fia+zj[y7-y; GX?;lCwbmRaإ6lVb'X0#逳tӞZڃì>xX%=YA*97(SU2ŴMjv:C?Q$RKZ 0R1h]N꾪JR򱏁X'k ?|Ëeʗ!'9/oea jlWfAbd G+)ejXfc_ouojCҺ╻yk Rlv$93LU}?qlYkx]t0[[b*^ ' 4 ; 1B쏮rT'> R HxkFwA^GsP{;T =_+-u//UZiMI0-q!!: *̽5]Ŕ *C3V= }Y37`T{-S;x",׋` ]a&czk)20N.kF0 tt]`iĢQ4(Myy 4W_vW°Ɵ*[@g#>LR 7~ު삖B3:C芧;s&wkjtdީL0h9;#v:#{BMZI/cv2w%H=F7@O7诳f9fg`Lt[*,F]?͞sP"4Lg9@a_,MU F_D쭩c>)< {cGFnP)}RÜzY>KO.c7w!?/G,;OgY%M4UI%ktYdKޏEqD+.pٱn}ͦ僔G ͐,/]UDxR\CpQBq~IE+H?{ .\Pt^gB-/Wz\P|eiN, wrp낐*K5>H|?/qdz#!8 agqzNG8M3A_mD.Ӯ78X8Lgl|pag;sqIHޓg&AZԵ_M)Ӥ`\pf-U¥)ՕA\`:Uz߄p>)hBo,R/&ȧB}tr% /ڪ{%q:`7SHі.;V+z/: Wjp~KW7+`⧆Pu5 ߋ=cfXu eq|悔Vհ* ݁E}C0`8"I.uj)fe7Ӌl$].[L"!i %~gߤ`v/?F#{vrɾ&!$/%;Ìs稇@_RgZ&ϻ]BwMJǯ\-&$TULa VBl>a10]gu/T|~ FV8'B핡πbŎ51Co|/m .$_#l;׍7`HyӮS}o˅kתLA|`H`"=g(߄GO}y.U-߿;bG>LIG{eRIWƠZiRi!99h3jitGߞއC]͠1Y50s'T{mS2a+z趽C[iDU -1e54Qh |TB@6:̻޼vJt=`N? f Cm:O&2xVXeK!W,˧=q''DҲTGݗxԧ.Œ0YnDG7 ͟WGi*CFTy^ҍ2EXFһ%NrBzøe`|tV, %pU**KL0'ߘstϰn@> JlRgeEwoV\Z0 XqrRinq4n>VHǍCL?3e(qqy$mFܸ']ִseq9sq 8[Y7- Ii. >˹YzNଵů8oQ5\H \AE\оG7rs-%:r7,^\SVf8\£\8D]aC9n'q`Ha\+dz7O+f?ҙAyDwy˞SۙoKH+Mݎ$6 \"#ա3RO\ _p늜7׸_5n٣_`~&<œkv_zf8߉mB-uFy`j=U<Џ9inzBI0e$ < n e ,vs23ӿRcKr)vZ/1#NyvB\ԁ>G'9&oP5$0"6&1 ;C죴M+ f}8H~jO?҅ȃʀ2qu>ջ:*2fQeJ(r~k籫oa0fK@f3o%su! +9%6'~g]6TPyOaC'#rtXҭU8k3Qwm5?#hR33erd&Z=F|JH˵vX0" m`[逌X+ 7V/%>$+ )-74sȂ ]xNGaf`OnRϧY]`&.,y|o==Yn k["b09Ʃvx?,D]ql,?)Xvf ܄c@Vx2L>љQzdm뗭#0w_ǻ0vzw%q6U, Ӂ.ÒxwhA,ڼ1[u{z:}ֵU<|Xx~q֊ .,TICe S0,~5Ǽʉ9 :Kp3 Va?jD^$2أj&ܯq;ŝ8pתH]hWv/\ ʹ-Oy-^j+{.bwC<̈́T׊1x-4rڽL;Jr{}6-n(88A͸}En}ⱎjU/V1n5a"ie8L =R6䢑ȋ8q8o5-{.h 6[K8j=S\  '*M68SN&UM5Ty~>YguB;)̸ ~bH6w@+qO!g=V>{[!giv?Ǚ8q!""Æ'=\82)8{utSLñE{(3F+qOgq+v?0Ӌ>!e$waj0ZHnl2$M}d4AJLKRW%\,]pJGrt9̅]iD\qB>q~;N% Br啷H{lI(ܰ5gE2rH[wI1D1I_cL0Fm<&S i BJdpmp:ߍsƆz0ږzx3oj)n]QWvXO ǺjܵMNI%$܅m=?ءw5t@iۖ>L9CbR 8hHf$ʍ%rcؿ*O!K6xzĥh5\逎8ª *x9>+A9K 0hV a3=zb&hͯY[8{/F} c(zkb'b #8)t3s!\婾xua\ 㭀}PyWSCUjKTO>`d5+Y(/kׇN+H+7žCdSm6HLyNevZq!=w3~Weq⢓/zsPԾ< 6 N˨.4l>X ;荺:Gz@fWB)50T9LZ 9¿6%''m.IF0I"~_De"O~5%"ŷ#Xa$>̳|IZnCvS1NƑаuӃts h 0 Ye`ۢE*QXHw)e ,mhI FOkޛ 3OYߠg(:ͽ)xļR#0RcoY:;ިQf2?_ Iw^tA屉a n ˢоjXZ``(.~lf҇e@-}Wjǝҟ^]ێ sexg/V TY{/,gg=iwL9mNwH>3-?䳋D$ی$*d/1\T=K|xkv-.$k˷O|)Y8?f)8S=q9ugv|b=,pj!Bbm6Nv^H7 I4v' ]vkǍK[ yoOO*iz ?*+u^)})t,W|خkYd>ܢtD$۲ItM8؃K ,#rrsצOMNA^DDeh tzx<V 8;btyc5# Xa%!J5AIS~Tw: RA_qҥ6dk?rbs+S ʰo DZ0]ނ1(W!7d8€ˡp|~H<ԡoXYJ&ޏ0ؕ{uH-"'R`ҩڝp!:w*\鄎,nд[SڑLT|*> G{\Be#}_.PF5NcЛ~X6Yn7AڧYӜ#P a;ج!?.u1 .;yrBmK% \W{ b3>X0W#ۢP]疥 WkI֐xqT;SUU.jm;aܿ!#_ī^GڝTau"XY=+]elO- )g .y\{!d% ף5#`ָg$: wfya?d_ '?fC? ~&[ \j_¦2 R@4;` &_H/:03/Z2˞RN90'@NK Q,J}@2V%^+Y?ofύ9/pC><< szTSHʱ3+|g<0u=u=tiu>.#a^{h3,n2+foma*wJ#_Bh'Y%Dx=Lt'l\17a;xA8 fI]7JDôk0MwYZ K~v-ksVQ$*}z,$%* ح{o39Y4s?~N z+i֛WxN5T/l/4d1!:H`NjAFW^`BA_',)f6uB,[y˖n[u9As " :sV[Nn(K6LP'5tÙ^X2,.YZԎ 8TIg M`* |#qf4pi0ŊjõعC'm~NqD2ԻɵͮبXj}07Ì ϼ!(m7::8+AÂn/JT+9R ޥt|ѻ-'m]p8{ķ9$k4ǾIWp$<\zOZަ;ELC86&Wzq%*>Sǃ_,+Ϩhv0=g1o∣KO|~ >GaW\op+L9O\&f1;:eu831 {q#(|b ǃ{>3??ɿ{pф'SH^36/SߎKcoEMCN=L)/;ny_`! `"V-:  2.X|3? ^my▱}-oڡ6 kS(aICV'<<9E]Swz,Huj_<k{0 _¯Yq{kX(>83f$a)B5̧'}H0|fϠYLgwneaC_v7џ)3m NqcI\jo3+.kgexȽXhqǣ.&QY P)"0Tt>,|{G=v}X|)^tIG%L %}ݲΆcq'vlIrcW+˘fKϘ`LֺګOioWӢ-WǰiQ]Vjs v|EI|&W1h$vm$pmo7׹CcpO[mDž|Ƕ)Vlw!Y tRG`@CSBlIN[ Uoiv5'{iIJSpZO8CXZNʼnڬq8IA{i 8|C XWQlNck$תJ+݊sY+w+qm=R^MCf]ӺӻיYpѼb3>ǽF2p(F]3@ѱddjhT:rѯ}-,潮BݎB{]5O6-Z أDա\[zuIy<(Wc R1O땊݌&PZtiܝ  #zCM\]}FH+RH5z߶HgNkN$r(QW; v4{c޻Ş\= +6{f(x}^>86DkH+oiՓ`!!k۸'le^U@lF+J"_\ +v f^>LD6VD*M΁ 2l^+GRku~)Y:.e6GX?zfX _8AX' _nD]<{KL"BX~U"o*J}#H>scE"=N"]蕔T'7rêR_Q\}H*lywvzvfN2 `»pKSW<)>9o0DM*=R R:gk2bJT~6b |)#eroㅙ^?1I( KYƂ6#™ <΀+3a]?J1կqpo_4>UJg!p`\(e9߉Jc81k*ۖ^? S>g8HtLd\sBY]vu~`&^(~ë͋Kj/s$Z$w{ CqzdDP#0}\$y[8++Kq@KD+SԳS i:R0ĕK79H5S>$:疏R$& <5piۿf$3ZO0>NXˮ vF8r42n;g7vr5+'|ᨒ;DH,՛8IҶ7,܁+w_`ɷ4ٗp15M\erޖS_՛ָzԮ~k\Yl܁4y엙7SXoî&~yjZz렄,ֻty@A@\"JՄvp~ 僘*ڧϒܶ^*^:IeI^ qh`6cHQ7Gq'VRʛ\(SkBwvKbWΗW2S\vA!`ǙWLi(bG}J NO*rUan~-xYL k5|̘aXS Rv"/|1V _ɶ2=ٹw6-}wʑB9z٧ p?X3&VҿR?X_D+> x'>U>1\)PsUV< QǜG9j-SO&Խ  Ul0!iq` \<]JuYC[!' tgpĹs.Y{'v\>R8'CMq0l8QGcU) *|g`_ks+ƹFgN@'slrPz}h5 *i9F,YJ 9+[?r9O'4J>pcjn(p(clGt 4L6=(q=vhvnsH?/&C ]-;+\zz _`Y̺D;dI?3|p[ytˊQb/T<&:Jj7n|Qc١ŀ)bk 2ۈӲ 9ļg|/3(CߡN>U"SM})F*1P>wO4ަmgjֹBRBP0= ]LyCY2)j t׳1۰[G%!k_Ou6=dMJ 2sgi௑Wh}/jjӖKn^kCġc:VxaǺ`h|#?i mv~ ("IGAYks0Pl[v AӮ0Gyp u(cwV9 lJ9exߏMC/rn`YR9(Vxׄ,P+1 hA# T8U:U[.,Ia鑐76E'^ oEfMTȽsY,*{y،'X9_ j,!B#UQ<097FM5۷\ :709tc-Y&%%uCۮL3uh$Fʉ @d@2Բwwe4h.4Iu;cRa[#S")r3<(32lwo`ٮRnl0zF F}rzUm/oez>pߨ_NUBejXr+ ^|6v82:uW^xHpb4`WrtMɄdQ Q]n[s 9F#cvnuG13=S%h_+ ڭ mܪBƓ?_Tn!vJ=V [缿CEN܈&3%Xtmݛig\|afȴmB>ef{~^abxcml%0j(2`.&!מ]Y<'cr4u"Y\obmxp6>{'0J(0QMâ+_pBmV}Ƨ;^TݩF/Ohͭ }:,{ ح>vV)D4xydT*bO_{C_G:82~/Zˈ\ފ;VL+1TF'6ۮ2c@V2Eyuf>eK/whk~2O –óyq5?l+=_޾=VL;,abb@z.֟V:K\%o:cI,)[t;[ah#){Yu*r .w1c0ʇneԿv(HYx ԶcN&Cq_f9CW.ᐍaDx​#Ň6=|쌮#)8brβ:ro3[bnA4+1x9?Np0Ճ*L^@!Gs'G~1áu 5sŲO/ϣ^w[ݺ9CbMaY[حD {[? pS8=S"Z]q <ʅ8C&N'+˿]3٧HH=\;V73 vg<1{bn1,x<-Ky&:+8hx?M8c FxaY.?<7Z냽q"6ES+!5!Le(-{w@ӿbЀY`!9AQE z~z [ͳXd|zoA,_d u mL}W`][1P2ם|27_4~tP>hb:0g^oP"G.Ga*ˇ!X^^$I lqW#z-̔wA#Hz2(X^SzfCTA+iSk$~CtbmDh^6z?jWWlOCzE42:/A􅲘5 v{qF>ޓ㭻bؤ%t>V㬄z ?k!\!vo?)|8`vtWn"&  :|"%QZEm%J"8 O$82bmPRN^* M^ eOR`WaxULHo.r;Έ^U=IMg {KvW$~$᳖iוߓh(rHt-,H޻/'y~;杔+ U+u5>Q%њrt؇DE&k\paUbFêF^N%1ph򥜓fu3kP$RF"H~:ќG.r!x3Z'h 9M;F)sO%Q/p@rw$e3Hww\AD@)폁? n$η޲Ý:*zo^3o=ARq%Q+Z+I&Q$<;wDY۰m՝Y[W5V%PGYI vOaa&o:e _YT y7ff^OS2p$E$7H8(ۍGD2-t?rԀ4>xmc;*y/q=Ll!_4+Dsl'r65 9 )IAI0D Y5o=\$ȕw.qgrLQe?O'ȃ%}ǡQs"6 |cv  X-5@u+FZhޭʸ/[zI3?/lkLr$i/x g2~t`?{ϖHxUfw$Pz"^]êkŃDB͋N5ǒDhy8\Eg:>ID\yDRu Bi&|u2&R>P8}t'Amy\s)|D|e+73By]/= _m}Ht.jʐ^olmgzAo5>C$\zQsH4 L{2>QD*o?57c7tA`vFξ }@ oK^J~ m~&TW=`u5XDy>KTσ H}'6}\ v&`Iў>V:2_}Be gkUaQPֱg&rlJF>^罛 `N$0 Zy(X[Nv*,L}U/ȇIݷanTViji7' qsxϵڎNq@ #u + e{B{B_ysmgsZW0Τ? -_Fn@^paV[L0mlg;,c$2 9wO9Zc g`h]Ud䒸^kp=`(e-e`Xs7bw9a-kR@@=js'=dAVc0N}Vyc$`6{0rӉzkg܀MDq*XΙqA8Q6DzNuovȼ>7&Qia,֡06GC|eF6sM" }<=:H1.پ$uqyZ{c$GW/Ucڷ7̵Oe?*dLz Fh#X17:x?lt骘31`'Qu#WQh1s5XI_Qs*qG@i CV4^U1ͤy}J{.a9#i+X.Ͽ~.|崅4KX35Q4?-zW;Y:a%q? ) 06JtNKbX^ ElSԿl#gjxv=?nx9sf_hОiDzc8x}ںC?!45qSO|Sh±pFfqC0 v]M oߣ6pΉH(|neu<ق?(ןa M %dIpei\y-]kWǍ'= A=,=e#]FQ_dp/곏6;A׋N|_kegR L긇_;lEq:7vlp嬕zO[|5SQm8@!(dÞ ԶJK鼯%qW7+5u{d~N~̫O$Jv"R^'e%Rw}RbNަ$IU@$4꜡$4s+'n懽?[Tvw"C.F%3"'Ɖas-Q3"K945nJ6Y-L4zAYf|Vɗ‰3TAjmfD)T{ތQ!R9G&TME">˼ Şݬ>.GC8u;k0T_o8ÅcbhB+Q˗X=M zʎdV$#c8f W-鴼w ƄbY% o5WKo6,Mb:\pAoẸ[C?.3 N5Ņԋ!mqJ&.isWr^G|Qǀ.Ov\[RU_2vb8)4pE)ES L\|RO{ډ%<2_킄OXmޖ^;Z*3 Nb-* ]) oRaWaW֙|(:l\ayg- 'ylŅ$)а0 24Kx> ;`|~d @UhǼ(9qҘDje7bF|;=mM^*{0'x|/=7%BC4D8"?x.Aó~PǛ*4y8s;T[ ׹sQM"^޹Q)FUwf;ATY{6G_V:qoէ,ogA"L&Lx)췹1P5l/V;Lۿ§0vrKJT|Ji nŷ`o&uh >ԏMgC(O÷`"HaA\whװ1}C n\EZ?n"J%daʢdǞOf"vC<z(ÂIP yFj'b~(g {\P@oM69%l3[Rl/'] ^[] zlѬv]=kk ȸ%,l8](njc7=g5/%`$X՛]]XJN2cuKuEدj0-ztCo* :YƨC܌]>(^M! UaO.2L;Zqh0Ѷ: ^8f2oo`Eq0/#rx l4~My;SxI ~ݍ?]GOŨ OWcwx%1hF#\\/eCЈ= [jo\O4r<}Th8zŪA 3ys 34nheK 2qW1_)-to\mj$Op\kz搜KձԸ3^MR%^<!ohqϥ*]?+\m.PjArs4W`O8G<L=}kPiyjr ŽqT 3eN 9]9=8U{S0.ȴġ&@\_8#W}/<[&[{p54yy矘ij*ˆ1awI<*v>s%j7UJF1N4;z]wvs!:o)>=$b׍ qV٣бIZ=6R8am9lŠWJl|q+{NLJy@^l'XPFCeU8}~\o歏`\a%U_~};;cGAvY*6+f[%fY:i"|Y&0wBٜr"' \_Q~ݺpH?<'('vB7?NcPB{w70ާj̫+n=*f/lԋ |eST w_cqM -vʪ _=RgRGBg)(p|\?LS~ B `.Or8e}`ӧ7AQ6$KPu=CְhDЊ,ф{55n8v.B0Z~L T@w(Ovy7T2ŒGixK^rQb+2<`X==E? LC i), 2 0|-'H>^~@Hw %PYN]wSDyt=kVc%\y ^};V #DTa? r;^y6o?GZ;_&|R@b0#RlӅ+n|`[\n0Br &*Z}R0h4, c~Q칂mJ0,JXtn MbcYj&k0dfUQ ːaRu)Xb`sZŸig}sG\„WK?M3} @ڵ]ƢNiKS`Ew 1AA $y .;5ahGMlM̆?TP M،% oy0e 3ٯs=Y7J3v09 "Le>;{V&7zügO) ż00{5Y{j$_~4K/ȩ F0=5O$4bWspP8j.Mof4vٸ6 W?BR/aNEXz[a(Ѩā1mbDX}tQ㠘k͡0!8Q[ѤYu Im[U,o̱>=/ۋav*ߠQA [(8,bi?o6Lm?OY@ 6<9wp!,/wڄGn b `#oc_^LAuLE̽{HsIq~ذ[I'ql47P ֗^ܣ@z[I_X{c܊3=m`NS|KS5VLOT "rVaMg,{'ސ<<124c23ׯ+i>β((hQ=e` }?&"wvk~ǰxí;Sxg{_bO_ϕ[m!{5<ίW1ΉmBF!_8qpfD$-Vji&~ ۳`KT>Tz>~uڨEcoTJS(Tz6lf\ v}DY3̡}6J$[Njc/3أxmPe-,N`_Əz/RHmJn;ppWD/|'X(}%Ovbv|~[r2nBD{dd'm`%A7ȐBFi\zp,Arm\*;w&h@pс5l i㷊VbXO{4U[hW\9ר)5"( J3}`-\4fT/ mVm vp](*Z7\~$Eм:ń -fGUBۭx7ͫ}%%_s$/O|nv=5l+m=4/]1]P˚r>MZsCSFp1jN|ȟ LOk&pݼ=*-C9Sw3w^;F~A[\i*W` G8dQhV;f}Q` ҕ~=4@:VaAY K'9Z/>sx=ɍw]! (G,xfô0/215%3>_ƭЗ=9%mRGT9ZNEJh :& WtIKQJ~nxvϵRwwWzXb̼\c^F֚s٨?Pa~8ρ_t] ?غzfh2 +Pnib&gny."5-D;.wUDQo]4/ j)T-էpQ>(՚e9"Փ;$DZm6H}3"JwkDjjN4J-’ĝ|fdpkǕ;qm{TDIDM>F\m2fwOS,%~9H||nW36;^YDLlj=pdʧB>L<7f_8 u_̕?]1wYPa±ͲO&硭T|Ft 9:NvÄbZv5"꾃7~A逸CkJx }Hy}fBg[f]!4]Aqcy 0aZ=Lp?g?2dnP]+lKϻy 2_܍O:o΃̩R0Ws:WS(#Ï)¡^ؽ.v> ƾVZgϦ87tm3aЋ3.6쁺Q?VG<7yT4ʼ䋆Y89?GZ`B?3u%PVM ^">]/ L$$* tbG(| Gi5rg")`Y [BcD |) 6H [+.zh?!]F6]s[u@YWaz<"61UJy{-#PHoYE',woӹ+!]dKdᾌnu-wp5lܒf>O=-[{hÇH" !#z8"훫9D \kUT"|=TIfەCq4q̠WWX.ju R׊<,MnSHys6xbH'8Bd|CuYHSP=ooiM*-ƇVԩJwDꎙ>nI FxHy7DR2lg'a!], m7O. ׼ pqu)x3F܃XVD2`dZ}+ze䌨~Q4SS541PurGT6#} Tb/xazehyXzCcq@qu.vW#|D_ر@1K7p'l~A;xgYX^L0 cʄa.Nf=c2WGb! ]8b]k 0<x@UeGt@Y2 Εr0+Qr?Xo*w/FN/+hz0!0uRnJhAa/[٬H45[W:x1HbZP^}tn@0e6PhzdK |ՅI0Hu[Z) .yCbOoJYx;, 6h  iq={8Otlɖ:j-lEU&Uh/M ymwvD#4J}8 T>r_ge %ok4 q[3|񆵏gб)^a8+-r[G9A! -U};1Cdu~ju>X>zy,JL V8 l B!fYz'JWh чYfPGMk w'&ٹV{%IX,NVi1y4C!Kh| (̤?띮Sg_,F͘ ~zx?)c(`[oqE=:ɪkdF\x"Q=cJJ՘EŦ X\R[a3Wv\Ĺ_ߤ%Z˄Fh@$gsd^$o{;,D`Goͨ .ɫ2ǵƺGN#l.~U#q=@,a]cE!·8{Q;P>>;u{޺<\8SR||72Yvwkä"EJsmP1$ "qQOwXr}HZ~ט>? FGp岽w_ 4fyvԸаg6H,ҷl@~fY9GE U ZjY<7.:~"(T?9 52rTTAYB@Zn+лo/ Ի)/M 3BW-ns";MmpzEh-p:=aO!Qb9 9qy';|2"EF`3tNs2=*ZςY^ihY5Gޭ g@[m(vJ`k  10}Q++ٴS;,}^͇&MʡCdh;Ll_y`oʃ Rp[VݛJ<plj+cЖӛ&&}xk IN8 ɖQDA`x 4.6쏨?=R6%r7sGEGӍ@ d ӹzbǁ\yjXk4ӭݬނ@lj T07Ch?qk+S f,;&YŒ6a"ݱW?e0iYM;G,/5I`1{Y< 3!L&,0>b~[LD1o8Y<i_1o;HaeT| ]v}g0g:HySf_F`䒹e,8:̗hmIEk8=0] v@>r5L^ZI9|IRaaiZf>yP4)PݫaB~_C!坕#9OL0aO}t3u~嚏vU/Y`z̷#ό_a]wr!bj@Su1-V?%9{lѓ5~XMFbC{ى-4?|JXd+ʆ2:aO\rwziuJWޮaY]c4Fvl g_@ܛ}+NJt+>ptyT]m>mZT1mw[!<"z wAboh!}_jޚ]WQgp[2b[&÷wXW,EjБyWgc qW8~H30Ƀ'E3ǿKC3*H9A>?U 2o/4{oub}Ӏ*l# ίwRct4! T1W͑?b '(C]уWB@ bh.ZOm{ۡ+PP<γC1\ޞl3JNPk6 ZPѿK {? J% `ӏ S´' #${т:vDžuXY4IF&qimH-MO}?CvfcCo.AJ3}{ zlEX^kzm 0lܔ{Z IN&6*t|v}.miz!1Pv+\n;AAsz"Uޛ8 &{Bjh1͘&^e5WP%,n0)'FOA㳬 0+_dui1_C6yCB\MG~G?Kg*_ auXٷe{+y4Hc+`lL{loslu8ճE"9u$nӜ;8\> &Œu/`֬7fhh.PbBcQwz4`f[[, /'H(_OnJv~,wu}T@*;+< eLvn]7A<$hzY?P?uL&Ҧ2̪,M~߾^)CRb].q\YNO]kij? 헨$2XDZ.m_&oH֞,FiTm²3m*A s:b/LG09w$2ȧV,x؋ nESö^qWi=V8*BM1g*)C!j7S|^rEm^W.( x@kY8^ls5}1= y!X1\)\66Dr:Iaw썣sOfٱ3SQɂm~mS0S?GbcBsoّH4"[ c=.s83zA(:( Α&UT+Ċoɶlohwgmڃoȏ]Rv/~PqOHj[}%w;KItXM jy{b,F{ ?/)W͚D8uq2h{{U"Z (pƸ`sf$= <"U8oqU%9*vQ8Yrřr%GGQ|/S gϼ.™ꁵXzbSH‰-q~aZ > ۿŗҚz#'N-%uёƒ,18z:Ԇ)NgV'͸d}w8ع#Fg Niэ6g$i32~~c>Ǒl'/~Y I]uY5y}8y'39v?ܦU|#B[{{Lql*C' WqF,>>$"/& LŠg551h>8+*#Ň LtA+H0%a3 64ϺgOԬPW%fETa7kV^lW\g!Dɺ=pr/iĪ9AǸh*QsŒ8ۣPPd]:OǴ бh5k~.. `īQHt ^xu/@q6j4(¾K$Xu-Ȗ#Nȴ.L{$E`2>uX<.W[\F;J}c9, ԺV_aP*G0A z?:Ip*;W6t[24ٳ_&U ֓YP^l1E~s:дJK{OX(; PKof׋>agO<]m c0+mJ3l"Xg ;2soÀ ]0f(Iw^Q3k>OxtϦ^q07FhGk*{v/'bX!)LC$0 tT!p 2 `GC')vbyltB܄/HL"đt c`M""֪뚼 dzo#ZfsC;mrɥ0nʴb#F #un. MU0rW(㵥WP7?$삵ӈ|bb=!D-V )_;Gsg$t#e)A ު{UĒj zE2^y$;|V`{ _`*Ysp}4_p=xf(\g<>#)RnfE=_%KC$1*7 sb(D^bǷ䕠zU3Mjaf*l[cذC6(g?KoZ#6~X8 ]SMϯJ|!aj Z_j=Pj!W~`\a8y{ǶtmqNKqW?]q`辥$ 8!/+ 2g8.J!B:_/,е)~:U aXœQal|. [,Hvk9st]o̪Uk6Y&e3vgJJ 68ǪcM0p턹R8E:>-*hX@`{:,u9(bz],-nׄImϱ̑unٻ%p{"t+܏MR)?R%R0fh"RE{\%R';DA-1%R}QbF/8O$NrЄHk\FMj#X :B ԅ+wZԿs$Rо<-D4vHys?/TS=z1p+KQ&=R$"nNч.DJ,CT~9J#2,'JN+6DO'qiys i &+D*D꓇ՒDlD[KFloT"RG\t{d4e_=Hy->cpHBq.[װR"UѤ;D_r;3aQĨn2ɇ3v<5(=#3'on׻Fz0zi˝ lNL饿.Cܤvv>z(t8,]!]?191*-儘IWZ |s9+]a϶ЃÚ,0T> :/*RkX}&6OpgzWl1Du &-7 01*%{ /^ٳ 꺬G~!!ү}p5 ׍'b`&Cf70+|~(RM~3m}2oO #)i/C[/Oy' ~AݕceVـ P&c>g3N&S){O?l?t2@Y,ݕ q CE9WÌɻ'|`j'NI4.3t4ӇqCz尠uC/7N$yC9 ûzTAgu.+~hL>7TYOӃ `Aߎ~ p%pT?-W:ٔQi{xkah/ŮSXsVZoެn70#jZ\aZ`#KtjeIKɎ[%G7p 4guLkֹDWݶQ8bhAZ-!bnΙd l'G&xn>f$R8Ȇ*?mB4_q[/u7Ήij؉[R_`tHa|S%GI"}(F"EI )w6o*'RO|Hعx#k۽jO) Ո4\?_;M`ڎטHJJd7ZOM(?yHOoH]'QH!.))e{]xʂz/5TbVJdE "S6&D*K?I`!U9t߸(dQwl# Y-#Twr~ү+P0Ї6^~o`&=~dø-;.O*;_O8F*hK"Ӱ tܿ9'r”\qc 2q-K&11JO9Gqyulb0\튭ŗ^Z`.]wV 2?Q߸IW`nC+>t}f_bjUhX+# B9mv=5O|x|k A.%~@ojF*hou.;gupzA},i >j7*N(Xo E=rZwu0&+*ˊێw@s ]h. XypH3r(&0\qHV?aM7 ֎]S}cNşq|[aztԑ YSa.t(@k}G b6g/]W~Ì@6b e[Ҫ2x"K?@y<) KưpJ̙v 冕DB? ?vG}h`Ϋ,|d2yڦKRr?Srd K&,1v2Nע6f]R.E[/sm[4=&&4w?n*ҁ&#i^%+^}R4u7W!՛#kNX]]&k]y#/)B#JgnBg[M V:\ PJxukf/0 w \SlLз]hx/iN6)]uxy~a ׾ck&gȺ{Q&TT 5nl6`S l9>cW7'O"ֽp|]a4lqHJ#m.CAﷰf)$S eݰƂBaȊ[aEu 鑶PAug+[ٻ.K=~)K=c Z2L)P59 b71J%vo$z#Z^a}&L}~yJin/?'(+fcRkd[bhl;RT#:zu3:v?z3,YCږXêR]͜ZI?ο,0[]@څsE=p.lps.TS`s2zXRLZ'Rj$~Zy u ..ܘkޟXTԁc"}A^B|8>z_?'e7>\֛4dJ.Lz֛ 4OTmcOn7ASeCG1Gɴ%=U%v!`&j"VŒZ;|06vCt__@=o*qO'^x)' \yMBQÉtm0`"&H9ԟmVogD]dvMgo&7 %[5_4!|᯾)v{p\s.3 _Ja`L 0,ʵ1̨DPj[0->k~ c0\ : ='dn?daQ`I5L-nAÞr 20O&lބ yA-gq:6NזYvŲ ,yӔ2f;`>lL{davAW[6Xch)}5/kai67[w3]oo3< $O5{J`I5a\_ZL+`輂8M2,J9^U\a~1l݃E%~0{ =TY/.'jOcVG"9Y.f2|3RB )X9E>aqMg|v5 ռIXr8aBk;-n0ݎPSc_U\}  }Uoay=o лXyBFzp7ZajN l梫m+eǟ=_2 Dž"]גj86 2=?V) BciTp{c̲/+VTd*M5g?=ϻo)[wpK{o2҇Oɟٞ1`n7F14 4"eH/So)=|}P݋Va+7W{IS Q$' y#DR6|9N<~nzzo*=n ?Ņ_ynS>)wFpcf8r>ӪI`#"%UT&)8$xi#6m|}ھ;*yt\$G8'wy=yKD${c.q|J@ :v0\Ɔj*Bm°cfKU,Ujg,GL{ _m-Jrj(ϑ7f I& :1waͯզ+lyMXW2²HÇ:X48-lܘID tkB+81Z&P󛄚^ϖ"aaYziLD4b<&J7qȻ$sa&Q=it\}~74ݽ%e.{gp#N&-9 H⌊:hg<*Pöq!{07ˏWqXcru8#[(MPS|1HBj#}9%u6v?GG&yksXȦ)sǞǴ?Bki[o/3G7aDA\l1E/RHyT1Wj7#iHOs{OMX| ŃJqwPGL9N{|H܏K)Q)uFn<.MĝkU';)8t'OnNƩ!5J"-?pVQׁղFFf),xyuo\8a>"/':t.RFӯlni%}܂[>{[q#%%NޜTrÍy,Q~"E]qH7U^joyE"e^šD*zFG#'Re6ٸC-_g\Kw$tVIX /6FbJĮZiERub=5]z5eݪMJ06nvj0DON MbFJMݙG>,,3ʱt] SϠFZE]]"eQzR7*2՘8b@l9uS^[OKn1`OM=MGFR!r ۲J2P3n2´1 u{jfcqg܆t}j+O9`z6 9+s5#VޤՏUAR=E%):k#w;쳉@ ` 0&n~g1уLܡ?5l 38͏ ]jҶ+>^8LW}V*`x"nlq2j *-EDmp>].x UIso8~w@_4og}F߰q: EoslAQ퇿NqN"d.sޔ]?v[XZ@_hPDj)/),44 oX#3D##n% y*ًS"8)O[зZbh~v'tQ}a=D}VK ?:-)Ն ;ҥ)XQq,?TJ{R/c= }X6~ѬIl[Xu v0g|^z^rZ &J\@'|.Gc?Ih GEZLkÿJjc!bMeNJV#18'CϫiΦȯWqyg/L\"fyR cY _Z0Sa5DܞoT!pl?>Lg V5&P"h= { mea_ Ǔ:I cH,0{!?k 9d yn̯<[9y*o#xto(YQ&bUG>9hYKUb9hJ-Ǭ]OCuY*Gj8/ٜ癦XY฾XTMI UN(8>"w;O\ه$)EB8.m^"L2Zq1æq|q%'{oJD*`$!?wy|R@IdkqTEW1IA_~N:m{h)&jO{-?r?ԡg# b3DZ `qCfgf*-p*,1XK\ Bo [ێ{~a g`M 'S-}qK%i&Ý6[*}<#eS7]ˊF3МO}cRfĔHJ(1ޑM 6 zBFz3/% P|W<}-DҲddgJPa۲!nǡ|u(V-Ħ4/C Sl[#. HjB׊L[),:e Μ1xT~%7OG @"P$yJJҳM΋ʑePSOV6uvV`ݓ7M?cN=c¶o跐6ya< <']=MlrRf{nNJCgFn S{ΐD`|s!T  *cO8c5`/G; 9})Ǡ*EƃwWv' _qK߉ZRtwq,-0NQ.T{ \DŽX^!xh*//0SM, |e0}5%|i] A5_uC= :E*3aV.^.%転zt=jn2Nz¬>r0b|x!]+Rm =-w`T.wС m̠{qsT{;j} k&)zk.-{wVŒCWtb8ʷ wg6k:_OT|P}DrdUrRăC/['4Fq@dLWU&6 \֣gx&`]_!h@GЦ9lIwb& ?QV/s@Etr z.NJ\3yξ rAr="PFɬC0tJi NlHKtبz2kx%CMٜ"`˞psSh&PGXgvv&bza/CmV&uw1NN;e sG2Rw+^[ ô[=`X۽40= @ΉWU*„n&*~㱶 Cr{agR)%kj=ab^WJ.~rUSg( ܳ`} Ojzy05)QW]*I?L#v0zJk>Ht!d߭&-3Ն *_4 rk- p8uNZmd)6Y lu7s$R|.]\.×|@L,5'֞]!8UFo#^Ғ/}Jsz |khMA{ihwP/v0x~'eLcuCx}kxu %t^*td0.L[jU@^09Kc/y?Aс^v[ SMڗaՊ%tf}yݘ?ָ[a0z U!/7+SbՎ 'ڧT8Vu(FJ|{Bm/?_x:Vd ZZ4;pnr) +i҆ƮpQ+k?geMi"_c}|סvás5q鋜ҚPyѬ ⅂/za9֝Urݠր7P`Ʋ'6?YL&ulpxoaQ"_-V)*K ?hJ8&ԔTVzy"x3滀3,?񒪑 eTߏ8 s$E6`˻Rg/(K)eBj}Dէn XQr,Dm^7c Pv^z82jmKGt!iG&$o Y<mMXl ŻRX$~ #8a+w.ΩIhۉCNp0FI kGI/ފ4["Y*hf5%9/"C?|* %.H=e›+2Ts9ᬄYtH*ĥs9 XcC9-Y;jӆf3Xa0yOX"gۙF'Q;wR,73BN5:_91[mt7bp_ȸ`6߆V@ghS[/Ht̄\2\X3yD6캞# b*qAZ^s+֐%o2Bpq`^iS$<H=pY>l[=|.(*9 OaS_+ӵBj\|Ձ%+>s8dq,"Mi)Lk7M1rf;ABQQ\ڜ ={< о[tZQ!rr<:b}d EzQeA \%} ru+4uLpPݠ*e9t\_- Nk/EW}ija]IakV9> 6EI CcCؚ^d/; ٌB/CC-uѴ#zL|c<F>_CKLIJ?m8;OBubN~B0?t޼ ќAVY0yy&3J9\!,u\הts q+EBE7w|[&Y7 ɺZ\hhw ROQGV`gt]VѼ)f[tSԥ\]'R5fo2S у4TPs$P@<50ʾQB< ict x;HȦ}߳$];kBgvc]ӻsϰCQ|j}%]$telUTQ<|M馋Фb2 IN4_aTiStS3g˻_;Fg);Y RA{ 0u"(zo}( 喏\לK&R[a*El]Nx'-ll!YWu5  Ï=XT!AĄ.r9rE=QVs>} hu3`}\X~TTq]ϟaOJ 0.[7 Աr.zv:}K=LNc=OV 'yv>d&=ؼeT(ƞNշݰDmHڽ.amGw8QuuR4ĺo#=/MI&br8U>qn749~nțU߻ GbŚ4I*u-d]44V"A0~\8}sBmp-|8 +eIIa{eOq:!a8Je8X\=;O:bW? 4aO0j#6Ί6PQ^Kv,\8;;/k.\ o=Qc8"u˶lq"Y}@n2} _ޱw2ov%g`V 3д;֎9Iߧ>vgpW#}KfkMކ8p';O@a/"M:ۖ[S.>|i1^w 1|6Эk9o@9߱|K.`} ?!! (8`kLTUvvd&hM[z# h@ )COy#,][x9bgT.?$<À1+$M[֧;Pݴ5B|sRI{`oU'ؕ[~ebTb3'N &:͚`E~dY,L-,.Cئ6lF,D>|j> 4%Q0<]lBD?gث׽ݛ޴>r˛kaPrU 3%v_9 H.gǯBkv0wUt;F@ś@MQEFͷ@@3"@mRFVXT@vcu@5;|zK.@=R9ɇ?NhJGh}:tCwh}Uǃ@cfy@q!GmIT ~|ִ; Ed fYT{]気ԧ8^k>/_{szU-qv :ėto $AGU>Z5PaJC?}u؛xׯ,?:-\#,Yv8UIfC HVړζF#L8`́wq2-S8*ىDڟgCu)݋E*ոQd;Evĩny)$}D8k#neTzf .<r@0 ;L֭]ub}o\J}{3Aͧ\nk_|ޟY*ž \)Bn`-gp!s;.H}?R.*(2+!쳁^XMag; z FU)_0 τ{J Erx\83QV)$_Yو__~e1M"\3L}|}7_J\Yips$DvW$ W?#[COq9HuSPuU8p!pwʐo~fNEDž|QH&xV~EW8+@gd&yq[CC/:ԯF0u˽RӴhAh6s- }A0!vn%&C=s{:FuOU 773Sȣ) yDu pIeL2hj̀nk3Ob{}] Ӟ/lVM)2Ʀw+ql^zO'j O yH8;RO`$+fB\nO-t/;_ $!KCuW̾WOt^g30gMXQZEebN[Hw07 ,%iAf.Y`.NY[kXC `]-!,!A$EY{3aFīk>|,(y# uk#0Ink5ͻMXlW F3 Y?H04y q>awW]v.܊{}ao5XZ0끑=,e%0wMR^w(Ir(=oM5>?3}՞S0tN?tFvnXz~'rZx.m țr0`7&ht9PPg} mN^Y/ a#ỏ?m |'pÁ1@J-?:ѱZMl#+'>Uxo)6$lxx ]L(?l'PEEkLQ^g- [A!ՙI>I2 J'|s_@#|㜲<-Z˜k5TrV2 t&]=q`q>E:8 Vt¦X ?IǨw^AwXq֟;>N Pkqe[!#;{ji;Ga]676)SZ9q&qEX٥A}V~fEâu.|E&J;% {1XM}*E`qf{1D%l  W>(.(@_" oO9at}f(&p@u`u'~UTXH%(d(G|:kTk8O<#< >i}'ކʠ:N<H,1ف$%T/R0kuП3qL-Ҷ4EftaNC *7ݸi~P éؐ; o{fzPsqW&agMV8#JC99Lpl%׀i F[ǐW\p9z6'Q]? = !dqBK=y;Fwax$,KO[Z`ɐ}P\Ɛ8 8>?RfRs3Z aL~f{z.yiJf8,E_ے ܲߊ*cݪ:LD(.%:D*r篸zb=#IH Etc.}5\|7^b RERYH}Wt2u?dҠHF0^ي)!٢2Bi2l{|<_ysx۹N+NGF)`&FGT|aWھ Ii?: p ^ " Uןe3n,Tލw$^ptz!DC8]{rfZ.-V"v+"@2 YΎ0/Ź04e.$znziqB/1F K I(9BD]6=&yC$%dUz׆.IzxMT~>\zK&ͱi$H,uGu:y1a%_ʮ-`6ۣX\ꆕc1AbqY:P/+`βc",fP2A:x0ò,|GF&GEqp=I~Qfe`_{اl?> &^ِ 㯂t6㟍ۼ:=E \Æ'ٰ^z&7>HJԄHil*SiA{z .M|Z =VVj*_~6p_>^^TrPWE2cǥg+in]׼Wx{C4{c׌# b T΋'Q!`I&CN媩x}=r B,4|~dafuI'\O>o8^Fao=gs0νd}MU# 6yMȗh*l ?`ZI3n}2J'rŰY?"W!o~ω/|;AQMf>'j11%H۟ sT13}-VYvo[B?|'˟G:?KgĮClJM5Y"iz6xnR{|+쵬F/xF FG>ҧh)T]2U W7ruC{4-3SADhmv("2"0`-S;'z`o+_R޸,R)z76 DEv`W vXq񻬳1@1;׸Ėɷd\ :a9? {` GNmB᤾#w&:NrrWӐ0@=׭6 sgѡwÆT qvKbeg)*~(FFs-AC/GAJlމ* '&/0fh?AR1 ՚jcTa5X8v%/kO#58 kB]pIEΩ@ SN+}3C#$k@MЖj2]q{r'Ҁߛ1V?ԦeYq>r3"c+0ʃEpBaESEhѝ>5QmM%9-Ηq֕Ik=^ S3#8pa'.LjOx|Ϸp,WrN&v<ͪb3b θ2A٥q=q(J)~ĶBG>3\8zLNn]ݬt'$ʐLByZ\yY3oWvj\lG'8RPߌ<]J9,wlܒ?SƍƲ8}\?NDV 2c78&H3d(0jFUTnѱ8sn}Ž'HYbvM! Uy{cjhlICEI4^{)}Q+E݋%_c>TY߻nL *ܱkIP KDnP 0_nWcv;#b ՇEUtFHya?ιe1zY,~f~T,!?d;硱o,٤13AV o?QfBLHQ{|F^<3LNůiC:3'JIޯD@e[[AkncP5]gHt=ޔڿ{ɢHH@zWB >ݩs JܙsEyjPQԻ=$ )~dy(-[9:_p 5%̫\wϖZ2N@g%5 0XmP f~sGk@uy1)Y)0ágh }tщMݲ#zi<=J?`cn1Pvht^ډamQjPt-͡{#y.o_}yAWAxVx (9ar[|-W sBE^(K,w#9`[ 57=VH* ^wzA + x|Q;CJ8Zʃqꚛ7a$[$ F{1Ao¶_8+wœ_fP>r|T{(s"8+tsQ_/΅51>23A]O~py~g.>3/hb;Ł3BQ85fbΓ?=.{ǷJ(SCߡ<;s7N>>ǙVX;"vL}AMv-.㨟;Y#0 KL*k8WcMĞƊ8 tk폟:tgbE^t`^G6R E dJ!Zl;\.WI Aww_!8-U I 3TlŘo87wLk/rѿg>P}*5*:#aƆ9q@LJaxYdG^SXBCOv= ~6-*{pN,9/ޘ^Obq}Y;`N!.Y:(KpfLJ̫5.JAi^Odj2- nGXy+ ]j`- 2Ԥ bC+>nTUQ rr@3q" 𶎰Bu-?CfXz9*XBOC0yPB/6=]l[]}5\bv^F=݌{b ۈ+wliK"T/t֙F, h_h-9qμg7s`'hv{ %|S/bi/i4ʑv@z@'l6-U1yK4;i7b!Y uL+|cqK+-_ށ1zzR]=a\N./[Fq=37M xEu;,ړ4eV *{V`.7W>,4h.Y2Cyğ\:{|uv}hrfblW`:w͍@*(p<];\!K[,tg,ٹӏ~%#.wVи1Sݪ{`TKi{0d8O@ΤdHjXr`7d}dnDrٟDr#H$/s@$;DT}*q?H%D2ױOH7^h ![zX))|z_v) %5I5"7fu"YA|A:RJCdctqH2O$dsw=rld6 DG/̅a>ѤY8Q_}M\+2 av * `޽N&^4ӆfL0xu](9*Y[7]z ?u,%3L*Ξ뎅2k0A|u?3헚ؼa{ T7I#e}Uy|R[f)$>r< F..t`Z|A8l1G`l]?i.5J>Ps2tK٨)dfLCa{{Tat2+BUOkE A59G:;B˹pEl<ʡ{ @3s>hIwy^No6&?j>NׂuX̢8G bl/Se $KK-=cǠ'@R՞N.Ȏ:%d%bc97n}c:=ROg$mHG#lfXyi3 +''tϪ mǵYSSQr f't {%4aK'{&{[@V:x)u׭s1=/ak62w2l+o וW, Tyex`kA29}&]BD`Wp2(s;2>ѧzKmY^өak܁MuW֐g:ɍw }&#?6)WڔJV5쳚%F0)G7-t*-C@;c1n.!,˻KNB7 MG^^Ճt{ Z߸ A]u'+H:xJ%e{(2FP}Pn#lυU9Б+c{5|OeP.z8D釨C-vNL9wVUBWLEA]z{!Ia@2wHx +/] TsCQ4Άٚ558Dwot aԉX {jEu93pĦZP&ug WIԆR) EoG\4`t."-Ô֚<ےL¢2-鮑ƠPeZI&`2{-o@p &}a=JB|XV)wGCɉWڸR+W|6![J*Cc l3qo4qVeT)xIs!ޯHv&1}l,=ui=οH AѬ}uPB[9hr]tT@?o@xe*oTd6k Ѕ\׋o1zelHb4 |UjI34*:? K<7$}la nz$M= r+*P㲧 ge NY?e`BUu2=f x?\:C:qKeEhc%dzdzI3`C.\R$8Z8 ]H)kI-l9wg-$oL "-A HI -jV z|zx 6ΉN%o̜VEu[ z?=ak;.)M9~-MŏgTjSQK{oa< OʴJw:ƃ5!KQVV]^Ht{IQ{&قŰMwI@lvy:cm-}co PSHL c6~L:MU5 '[Ɏȟ)R PL?S> E7Rֹ 3׶9v8?+L'?LH9+,Y2kt˸ڬ|UŒ8snnT坻0FR3F-G a쫙pqdJ&|m<8JT,sԹ+WkS6R^u̼j㪄c#W^Tw:#2?9Ze-~4gmQ٪P|AP7 y^{Y gB핶Rae_qƩR-uOnJʸ_,14 r}'o^S?FzcBvK: wqԧ͟O׾P?d3Lb=T0oKlaq|>ej>ӧxa^(ѸLv/+B \ FF8vh-.^ʹ:o3ipq@HհHQ94Ukv##;t*U⠀Fge"M{D$_%sG~:Hta |v qΪI+FH;eX=%5d> dcv2{S^_~қ㯒`b-|ƒkiFbn#9,ƾ|Ry$3{ACq 8om0V:uQhP7Ũ\zGv0q_шj\t"Ga~ء\,v2F>,6akP^/z&:h1k=<}hzy]:~N !yg`HqW= 7bUF}ܸX$uXΌf3+ Oayd΋ޡ<~m2WʃCwSwX=X֯}UkJ`VXW9vo- ![›~Ch lIr"njѸ]U]߹78܃V߆aiz,54s*\,`UD⊟,y)a#2)Xk ޛyh lf0z ] xvN1/Ɓ{ $q2 tۯw {i_s?_bui [<%Kc~&Lzs<5"GHDWb*ļZ-egᚬ8#d~1=}0i3 q/fF`M˙fO,ž7APd'aL\ғA ߾c­N8#jr ':xspp=C<6^S=lI)B6V4dbLE07kI)M ő8٢{8}Z .ѵ;x 8(ty/sP8RRtyJ-i^yخ٤3Mpu3 |zNJ*-7LEi\ܰHmsGJk\gbF;Hs{ęTT8xNLmu/[=. BRtFU+dLB ixT$;M&+A?0J&{:EGnC@ |E=Gأk͟0%hp6fy]' K`dv͆Fd ݡ*!ZܬACP-|) Er$,Xts譠8Sq_<7jHHm/]yWگX߅SAbz 4GO@I3*K0xAvΒqzy@KneQB=bk>Jot*|L^{jBS1!sHFωh$@͕zj2Pvq'$ 9@Gީ<*}˯V}ؐǦR UY|߰[jl)gx \+y?Z8ۇ-E,)e=lIT`Ă Kz X=8TH\_a[vBgxj -Vt8Xcq+C=9o|]n_Ke2_/aˮ(]n~vsEE(0KRqm{{ADK`/2%&r[,#^%aRQQ}H'/e%; ɫ律bBճp:X KwkP,gJ9cһGP^)K|2XusƤ;)k'C᎙DK?g*s՘<0_(bq1]{^;q|Ω{B\,Dd)0%+P>HowcW]5ۭtyC^&KB'ZL;x#8%癪;8i$δ3 :ðu% g??¬Ύ>(RM# ogiA2t𙺵96筰Bzɋ6޾x{B)vkMu"dWSN(HŠhkxJ[4aG^ ~]-]'[6´sӘ+#0!;_XUš~ZY :6'gtG%̠ #a}wُܿXYш%rwLJ@: M">BB$JȊRB ][=0*\ 0gKxG>.O߅rgLۋdVM2̋,СB6Q9h;Ik3{j<#g^\sRQkGC5 'pi:gwx%/Lt,Ƴd@=[2 gM|T,ʈ`=_ű,Wۡ޼tga J?C]t;c{@πtB̠4=.ڧuPyyg3H2`g?Pɾ8kwD801+דC&Au̠b`^\w~uW x<_582+G,+ب7N: lBd(,2–~# v)fd[$~zu:`= S3æ,ԓ>&sDըvq{'I. ga;%Eecp䰊Աr* u :"~JM%Z (誴٪'̰Q_Q)oנ5H F4^xJzM/'u 84]h޶i`cql_k}IF!^F–}U{)?s`-6<D;|`MrzƲOEl>x6fL{U`5wluNwڇ;sº}3~y%cҜF 1--"[ ?ta=oi 69/~_+x ]acYXecwגl qG_`)ik,S,V0R܍g{On?'JbOKfI n콺>qh|vHq C_?y7FFr;Fo Vcaˊc9q˘m=D?-r.eߕh.dU}+gjDq]tC4^qGK>jy+TO6Yu1S.&DOA^j8_KU# UO XmO˾boqHͮUŽgjdP gGϞKʸ)r Dz%ܳęRqI <\2o NKULKյzpCzn^%5_I\8 zX6Fs{ ?Gqys*6 ?|sf q}i6η|.ɄkbOc<=ʧ zdy\GYf?n[|Ɩ >gU޸pR9NSr~.=J5ZoK 2 DHx3o_-~H=m >M#;6TH?`̭ؐ4W>!M $MY]< uH/DEaXS?nk|&r@ˎ>3n NȈHÕOu ;W<ѩ;3Z/IO\CL+t?N1:c=79lغCpd&{ԧ >c{bk0%˻H!XyĶӦ/aQ o⎅W-8jJ3 9p򽔒<.w6(]#1ܮCP1#kbue 1b4с 'ùT&R1VDU,=_T]O%w<~h`k2_Ӭ a,\_ph&! 1/{wX1_o_^0˜mw,!x7h|h/Io9佃6nw_-{X,Cu0bAiܪt,8J$,lGD=mSi9ҁCME~:(\ 5SZ%^7 %Lv}'rڳpa^lJ}J5'6u;'4*| ӫbqCq!\q⟤8C$MH>m) rXt},w(uCC_9N:-, zI?n˔7G`=h7t=u*oJH}kst/=_nne R4_> 9(5J%c F{n7cW}!{E:;4؋nr}M 9,P>Ƥ0["y"5$$}mvb B9*6ZlfҘ =kgT ;Qȫ6 9d1bɏan\۳+P)qKs|ΧKɼrh9j ?AG"TmV'>qLStd$(2KUm4V^W!鉩4c Z$ɬ/YeG_B# 0s!7С\ ObN uD":F ޾3m*$ee 0(F,:xPf}/y=iY.RWNI߰RpKKz^OL^* aQb5GnXJxm;~Yf~rzoR0;giNi37UסWdaR(gH W( bN^i>q0T rI`5$$=%.]KAQNo{euއf'jWbY/ ';_0*?XuXy a6mGXh\SlԠ9~Zﰨ)o|f:ozby?sr>;w/ Kzj6ǯek NJ2X>@7Ć[{upưK%З*AH06Ipj]glٰF@j6Y,$)lQad _3Ywd~tvS:n{Elv'bׯ1hYW elZy{_ uaCmRXv&!7+^{4)X0c+#v];/m4úcxR;;e񳡇آ~G GI( (5ͼPV2F}Usr:6vs̞۾hkug69cʁu,&$79Dd]J}-"Z5jpjiR lbi̼; ?gCgpY>~N{)y5P.Nd,҉qk,qܹ~gq'-8Hop?qgw( P̫bO̴8|qy=NB Uy"PZ>.~Jsa,r2;E{_RzS|8O])Utd_t8g'pߎyp:oT<D#m q!znF_ݡ>86`ov{;I\ v:#cf68aO}p" ǒ.nq^y㚁.w}EOm ;s,4r=-ds sHZrHgݲ|Hr"9{ܦybB^g9;+I =O2HM}]b4Hʑge#n78e?CsqfWqNN}HV\rTe˄[{_R9I"iMq~\so 'ķL]7e5/֓*ܱU3ЧB$Q}n+GTZpO>B&B"Gt>W5])ԒKDW/9}qۙ*/=! in)=Gq.-FP~PW'/&d9B!a"?w0D8M*t)Ԡ]dg)[cֱq0_^v/t q;Nء8_I8' فs>'p$X &#|: S?%u Kf/}d `g]d$ߧ_ AjrqjzهwAK5Pb1dԛK_n}3t I29@fEef__Q&#l5C~cmG?FN@qIYYNB$fyz\ kQ2赂Xtzu  gFu˔ h_; ˟EK+aS;xfArNž! JAM'C$9$%X\%ai*#cG;8斨!=L \ֺs"o|<;x6 Ta}WQf| Œ-٦l鱐XۖMe3yf2f`1 ɉxC(ǤDŽR&lٜ=`}7o%>oxVΘfJ߼`pd_ȣ<-SK!eE\oeۅ+W qiS\ ` ޝg"i&ّy\ۚ{wc!n\xn7.5[9|ev(Dpk"d&ng6#G2b1\mI|.}kDޑ8?×*pwŠqN7!\\o9Nn2s}b7T#+pAԜ:nGatDqߨQ*pkmϋ)[] pC"G.3_kc9]_Ln*܇z˕ުBqS\R{doF5qqO,W@'ܙ'`0Gv*{&? n(rz}LvD,F}ݽ>B;_p|Oo68*3uwj`: Q8F8ݯgek4ęAJTzLUG6 7}R?Yܢ0Fەmgt #t),`X7>t^ &2~RPLXxaWyB0:Q74LB!{Lϔ#t.߹aDVu_y~fokES/8$A|eE0[y~&`qګ0$0@3I:ҹNC0bSh\7 C![LwVdZ)`?Fiu`>MUBa " Uޱ: }G&34hȅ^0/˃8.J ]!-a/B#c .h|u[40o(T[ĥNJnB}Nem = r_@)p*ݼSkZVR/Fj:ѽ< կ9-@{@19 v=u+TcLC^}QS3>D?> {;NCrṻ=}V<*Ut[ ~!LPtڿp 8wԚ0ex}117%qXiqrHm"`Z:NtTN1 ެc1Rv$f^yww9("K~qbgD)|o]1L,Hsf>o:%ha 5k33}PE y'x#8~ e4_^Ʊ3eBk35W6`q0F; #ނs17ɔL ~o7K RmqM8nf&' UwIzIo[%I[ps;jV"jw?UTVtc '"/qsDbg_Q"=+kXn~D7W9q[WrAkqL~28DVDl$y؇{^:/%Vkz߾Lz?Es.j#r%$S79^Dž=jzffn[ JVIkӳԗmǣDֵ"SBmMD{nIXcfo:8RwM i!yHzݞJnh%E^SHNnz|., ץ:ZX:Jz/7$\Z$gv2]5?Z4$ I0L970Cֻ{nuE v7[cP ̬H?9b.eM5=}-e\DbA2i^r<`_ploR,mqs{G2^'Fcw/QA KXrd ۉhj頹,~NI2=ĜXe tFcj 0,ʱoP*1k 5}{}$;u(ɏ!G $ \f*Ol n'maX"xT 6n%e`ڲ#ſίF@Dwoh+2q)KYWC޵?PKvU}I=S ;&bp`wm/谨zrpamПe)G{cĉNf(2~ULhÈH ܸ%s*wFLwW6 H@{ᙒC1)@ŜSn=܃PmbӪ<#y/qmACtb qIR|"BZafqHbt́#砢9 ,_{Lq>2 iRϱQ V/R><`u/ Z5ҷu"+,,;K +A:,n$V0׾_ fzsKNUs^OjV`]mHJrCY{kayν̱ўE }a罾',>e7UaY?+0#js 6øX`BYaQT݌ h*ZM1TX^fΫ psWXJ$?L-q7*Gh";w_ŠX6;.5+ט忓}aY:3ք bq҂6~q<1_XӄtqO#lQUVSYl,_: ll~׸2/,Pq~̰NXRb9_x {ˌ>}a87Jj&glެ2]XG`?+#*TöS9eHLF b f;Ex'[$.`>cX&=k"\\H ֚rૺǚ"?Cr$ (!?)`߳oW9&+_qbGNrL vYCʫHGwڸQA+?|pvu{-jeL4Y>^[[_=!S~yMNCWʟqr"SDzj'{7 X/8\ΪH|Վ 8~%Iox}B!.-?~VC{/OOqy<:?\+٬{.f_ $%⌱ճp\k]ݬ m- oSb ׂ.OlM}-Xb:JqdO88| ݓpWL(Ne/-ጁlo2+'qڎŘm;l+P?=5׻6p.ҕᢍ՟K8|JT$0}&^/ΚゖANc=vC+Sϊ^ +3E"g9qFo\yvhr%ο8T'S %pAFyDjuf3 NU|V4\b:.U6{ ?.s8zI!1[>}-_qmT627e(pZ% ΝcfN#q\W߷qjB70 ɑ1|կGqۀWq|/1_R2'Ž {iq5̈́\Ҹ@VLf' iH,.ܨQ3wq>[1tF_jڿ>Oo߹wh 0W^dx$|N qNX::w>ʱ\Vw.h{'B L,<: 5gK/C麗4'PF4G|F0zIbO^O i:n̈́*#?C!1hcn jM+ך׋!1Kt0iba0u+%/J4NA)r!:N(=O3,5ͨԄ9(>hxfM# 2x*d*ܮvlA%2wlOUU?#k+(682KQx6H(G(ZQ+˫>s`g%S8%Lד4Yοc?aX1o! ޹ cW%OC*{_i"I;ǑfTafy<,\K7utK25>NTzԶ0}g1zVa4wS{0P9 8`Nz%FKLtVf1Cǘ`cyVdLՀa;0ۯ! a~8<&B[A˃\1 aϑ_#c=)w:Z?ǒ2+0+RU0X;7$áZ JdD(WgYEחӒ‰꥿KgI\z&M^C'7ǥ HeaG-p4{e&Df_̆Peq s{NA+8ԪgE V>sxOK$Ǔ5-$~#=wL_BYak!j0"P$Is e*ћ^zd M{ތ,OPg3_`cDm޷AaMmp:.u#`#邠 uSitWgtILUh. ŗc  ±VN!܎pZOG:6}<- N3q X7+`Y'_<lag,evy\dAnjG =mkmY9W$] .4`ŠSx"BVV R:m[ן%X xҔo{ Ibl쐘u;EXD#owz-?T`vDB0Fu_/%pwgC- Q4fOOöQlmw㴅߾Ń/tmCM|RIǢs_*Fk YKVZasLUo0zu4.AL+?$L}><҈?`/5fz1:ȎM!Gdh8"R{7̳2h1 /l?0Wzl`:Q99J \6ܜ>b]7X2t^&X{RdSbF7R/pT0c{Ue|Ĵ%IVt=JwS$K kr:Cf*6(|=CBuٸҐ8wI 6 : ;eX &.Cx lS@'Up lzG3zزrىCP\ip+ԕ*G;B=*hֺA"LЏߟ=> 3V`ŰAo@UI Ӓ9( 7otZb}byng趃Ue.C:G+#,mZzwbVO?z'9!%y?UW5W K}91CŎ٫_P9a4?iDZLar\Jg_|..tx3~y}T=k`P.IQVE_j4*Eqf#N؃:3H:kTz /ic i e Hoo:*֖-aРVCi<Q˥#8uk Xd`h{ֹC١7٫pqL-=DPHke$9gl`H9 3)qcZPa1ES= 5vla+:wNY ~݅r9_c-ȉZHz]D bu|%</`sGn]s-D爵Y۹xB˪,;5yT34Q(xun`ZJ.nZ z'8LmR\/_lv@~E&\hW^ϒc5ha2 -z)$/CY^aаông³DZڮHV?8_Y GȈX1!Kv<Ƶ RmfؾB= Gk ;L{$^E0p`7"Pk20x?b7H m@jS.5H:Aʦw+!uE{ `ts6dԖxfߘ kC-[N,)Iv,+b8)]"v 7[*> `7y[QNW`+_/R?y'YXL`ǥri'U4xd}ţ };z~ܴրzғG5Y{~6EouO uTtשHC͢xKP/= ] +}jz^{1mOͦjP>'bZ'N~+H@GL|7K敄ϯ 4%=\O!6;ZD7_ЦcĖ 2<쥪TQl$v[/ 0V/<ElU[W;WM}PC~t5MqXQ7Cױ5{2=/ˊ=>}7`oy~Fe6,2z_P{,PS)4#\x'0P(0M58W#Ds0r߰9\4!*^85r1=#-<=[)R[#^]Opy $bg2OOFCfӕ~*~mҋ^ ,2(\.GfR=8Â3R-|z_ҟzEw(iMݾ/髏]S 4B/+`'.ǻcS84d.iP\OaˮFSRw)uЙ=n rx ⦝% .^ ŋZ]_Ҏ.|G(&( r~h٨&}+M 6zʔv8T\.c@|8GzhV\lC 8R6seR-o\ 1uùwkƍXn\PZz"칮ZlF> s9."T 2ӈϸ~Us,@ -mGM8i ٻ_\V|tian^V BâK" 79S .Ks߹dlrdd }hpJէs7'd.ܶEа6npŹ~3wp]x΋#|$Aa>/L?vZ~mAՁosTomORf<v;%sG6@FbXLFJEII eKal߷p  '9TCAzY =yvS : هc(l_ԝПj zڽ.ԅ[ e0g5&̾уV.uv_/"b/TH$|;I;^TAeGnx gD4l@VQǨ!lێ܁l*> mb}:tqR+bFkt_@[hPy>|~S#mbӱ~,Mq K]0vl݆7Zd X ;oG%<E&sHڹ{c+0tSr7S>8٢-k"rNjTBqdV-7V˙*dF% 0Ә6zhYaND#sLZ{`.LZԞ!}0zKF T_:G !9;J i}L|OFQnٻ=%̗ d)M_ $5N%|4E {RuT݌_6Q@}̈́@)45I;$v3<~g?SEF:T-}@~t~ U>t@b؍@Y{6X^sm>#=bG y5Ҳ(Jd $or٢ag|HGV@J7T(b*h@IZďsM@V7 iO g9N$ H;Ӥm l]we0lr%WLdIig :tM$6s۶KͩF@ svޑޝƪ4ȵ=r]ҁ3dԲz;k3/K˱OGg8Λ8S^O9ZudGF^a;5ssOgǒ[=5s'p\o$X.o;lU_}6>"]iƚ1ƻ38@Q& ྊM5dc˥K+q}rӇQo9{3TBMP㌖w$ tEgv/_Y f.C Qg|Xϑ~\n_Łx9}q1=9u8e>5!a5is=vznQR|_.J859l.ey6|N 'dnՌ%l'2?ES4ꌤ/ i1E$ I;X!ik >3'}Hqyyom>qRo")5\~4$ۛ Ib83F{I$44}/Jga "3)ZWj{xpptĂs[n)F;gt o|7 r^۱[ h4^e wEܠן9@O$er9&H"'/+^aTZ ʇ #E%DK&pG\OWTuO?Yfr<lZqcx(qI)" r!:QH%. ůbJN+V7>M<^AR+`xj8rƱ2 *KVQ}RaOC|@'&L!h%*Wu~^Bb5t6ӌ6=:%}邙8TP4¡w> tؐY p|{2 9<˕~^e~beNavwi /2Le5? utz_aiہ!cD+- IGGIȫ?2y7V5_={ZM~xpFS\0 Z<;kF/jW"*rǁ"^xs:qËc0=% |5sXiw >ˆyNY߷klV-879Xlɏj؟iiy/+Suc4/;NJ 5׏Aɛ"%q/7  )] I$4Ȑ1H*$2d& %It3̳}2p^\C~g>}γ~gLn^=/}32PNVG0";cp7 ZWCYmgK7b%$;=6 ._ :uhXW{:@V=ϑ\E~kͰ?/P/q{ 2kynK0h$S+j{UAjgV *_Ie2j~ ظ)tEd(}kԝ'?ցyah%znQw􈨷G1j@:S2 \zn_XWpWLwpW r tеZXf40.! Z.}Ec+tШ©vGū0^#)( f{WPN*ON(,~5-*\|q^ ԑ+sXX+)K.4ǫB}j މApX\۾=i+Fmzb j@&5VKF]Z٘ ~X\ guQ0y Or#L*j} +:lv.J!?ICcY"^u\ByQC.-YP^ HcU'^n;OPj? v2>G|Iz~% FLV@BM)u9vڢ1ZELC%Pܺ!ь2sZK0_q讖?ԢvѨv2k՗ι䆔oV1 >יF2y(yhnFue{Pl1oN?e}uہʵ$ٳo`F8"ܻ6)0MCSؼQqaIʼC? 촟XΡr#:¥ uT`@;#l_n?18G '(enoU{ U o3@S'2x*\NFR%:CbLN=}'%sqꢋ&M|^4{U^e4Ifnf mH}sr'7@Aqk1T}xT@e)_8Fk(i{"ܸݗиcΩc6(oLl޵aJkBm #' eDP߆c)qJ)XBٕ$#a|\Vx& zBjV=;ac7rG!S_*N,رòtA"?/_rWr"K#ih~|L\_ hܭ&E5#Wwk\FK> dè}{ZX`0z+~m2.WA=ʾeWîCLLp=s5~x<Sy00$zm;#b>؎/A9v &}&~ r-ϣZUh@KT74DOn~גQK!/!UāA[S lgOGo2..9N?}XS ;t2aJNTVsbL(:~>zǞNfvGCӅz}+e<%in#GץxEzLcV!;2.U[S9yRuu;Qf+RfhME;FUfF 87{,T &rb>娶;X'-p1i;|?}ǭhe JHѹ7U7me)]ҹ K6`R6^!;s6dpGp56r]m3eOnpB\.fTbW})},;Z4Xl B876c>Oȫ(]z&4t9Qv.z5Y͝j'iJE#gf/lPs |MOńް#'t` m,_{hㆈ.]P`ġ[N"ܑrE =ͳD^'"bMb4jHEɿw{?{a+FS_JAkcg~LE3 7fQQ}vLb5^V5y#҃۟\tѸy}!SlMqeVh^ORr_/ EVlZwL9,^u>)$i~^ ܔᔛOY[9H]R҃ >h}s#Qmy RњC;>^PU[ɈCbʁT{`{wʠ.u<-̅c-aYVo>y?w;Dm. ;$!/X?_2d=q/~1`{8mJkrM ƙN#Fo -Ajb+'O$a,9$7? 6햞9x"62Xc$#+Cϥ(&.UvYWk,fS_wڡ&˜bmVwA;bdۈ|< ,\ϐo> K,"|[^X*6RF,D(_}0a,ЖbZuRl6] [jܐO,^6Y!sBm~&Rȟ$bkY,/`ipx6+]Kj>&O^σ%mgvٜTRnihˠk9;~G[o=ʢeNF]c gHZZ\td/ (MQ^0HץSNj&0Igx0u5(?CXӖZ8BqLcK=s{{ }'ĕs`#h Ȃ~*0.~Ի|\o_nfxt$¨_^QVLq-FBt*&k95\eY ,jMÄ`(p\Bptadc<_q7|ڛ 8xU # l!7I-U8* An90~rO,l R}V,ؗ0~NH>_:p,\A+'';ҵ3hIX?hU6/^c02GsGp|}].Dzuf)&s~i d*| YJsͣwK[j]}ZYCAdOÈ?@HnA}8=tykvTš䓭6 &y<+KBOa#G<]~547º/X> {,OX~/ P '\'>=:Hfg`QP'HfՊ>Ϯ^uH{?=(~W"J͎Ia`O[a.S\*ޔoÆpSd!gXtV`)-uutatQ>X;#R_x $gOK9 HeRbԺ̢_!-uw \zy!b]"H5 >: X(ݗ;jUmhas|v}z(`Ґm> 8N:qhRSV寥C@)zI5aarx| sRR/b䨵qw=s-i@^%6QAjP04JIMVbFL:& `3]XTO -嫅Q0[OH_{'L|O.qUsyoZsWa2yLJ4q Lb\#at&CE.<51MM]vd5pv-0ӥauvDzBK$ua Wvf и3GI:%Qx9=0G[p>/Ԩ"fX =R2?0$.pW8FVnC4i].ζa'ĩ# 3a2Dܐif?yp,5M@@$9k9s[֊{ 'T٫c c,udJ_Rѩ L }0'ť+\;xsH* ƨs<&^f+k"`4o7WNdU0>&5Bd5(_L)E5Om_]y0VQ[sA\uYH.VU~he8PA&W"`5E6' €yt9%qԕ޷ɟ/H a>pjjB^6o~B)HNz~Wc{{)xuړ=/g xcUcZx)cx$;Lx ml237~R$s> ^3/o8 yOtK Y'@[)YAY=5vu>']s{xX8.52eI([}p`Bt¿ևC=o|8a[=;.;]`v4%B 0i ӿuw[{-xsVne zY lhֻfpUUOb"|9CojcfmA' SX \{jqƕqÒU? r7I$Oi v9ޅa3L ]6Y+"c<ՙ8 PZP jCх|4aZU‡̖VeN >QS1@[xi 4^°xnJmN |YU9( Y,U).QW?<B?\~N  lšv;h/v9/̐%atϤ֑y7)<;' mn\ď\TLAZJ\&4o\ eMsq8C5c({U! ^$Pr,k۳}p5o|Z4Oń pL$?Ri [F(s>˱R!|)8/r?SZ Г)I$کPpW t-R•sy'Sj\Ag&SԹy?~μ`~ST9_\?RQSܔvm-(33{5ӿQ?q[+;s+Y9;l;!V5ww;<ecodist/data/iris.vf.rda0000644000176200001440000000042613576512762014705 0ustar liggesusers r0b```b`f@& `d`aEzei |@d=.~اx:Uel?"+S-ՠ*\nI|O7 Y}޳}mUᅤݿं;k|/}\<\ PQp%Pu`uyԂ=Լ 7D,<3.Z "Qj*!acA,e9hdMI,.d;?Rϴgecodist/data/iris.fit.rda0000644000176200001440000000535413576512762015061 0ustar liggesusersWi8[ܕn2]E+zשh2"T( Mdj-L*?MSrxppn~CyZk?~kۘ:;A%htIL:U(a}w_T/ M; %D~J)$iF5r|IRW^NҥfJ̘ Uʛ򃑿WEűV׫I"qS~'oi/5Pt' nDk֋EOPi3MDJIJy>;=n&'NoĴx1C?Iu_9\*让4EęA(tJDRw9<}5bճI xeZK!)m!- (DC#+eIWm/HO/Aq~BX5욽InS6p?uxe!$J0kDž޳# q9W.kx}#^~􏆕@'llnPY)8gIbC>/{ƽWW tQDkJg@zT,2w5mĂh셜j0۠[#櫪Ώ@/hO76UL:o jy+a㨴34AOW(]7Y;ߧ-xG4y})Z =s+Ns]攌T͟kŁ=cwBWkƹ1B)|M=?k~d9C&x$/f:ߊ!s0!nw{mQ60Z$3ce{/0&Npd(dЩsf]9Nq JjJ%h˔Ő?qQjU?r!пA_RAoy:s\DJn ^ :CU\R8--* r| DYOXI |u2t;lk PQAў&Ǽ԰oXΠZ鹳5{Ɵ\)YПҺ C XܨIa@׉]kH:8Z$Ũdzq6껜$a究Pi{tV:58%'j0h5;' ڴ/UGad:>T=jY1mqr. @K-~u |knu r7LT|r%wL` ܡQj%;B+e_g<2qD!'F5Ͱ,¸k EdC|(A A'v_rnK{F|ˋE3BRrv< 8s4V|փ&g4:k˜{v,lK@n<1kծWǮ^ḼbcVVÜ5xZ>=Ǥ~/)ߎs$6vobjAn^}nR6> SZ~ȩ(h^%u,RtlJ6V[XM ]¦GEv&g8Bfi~!doRydB\>UjWtZ1a{T { WUc2d'9̯"?P̙^1 Q :/1 G`,),~4; ?Ncql損?#3 /6&*nUkq((fJ6/]YXO8p -[aG4inb`c￶>_#C>PP8޽ 07vѾ),ql}Kլjehqy-˛We$~U[]}1hm2\ȵ-yYzzaeiof2#/U~$WPFi<씮Z\q 6ę m _rz% Z-ʑg(^ S?h6hN[!G'tA2q,de{?, 5Oc`!2vYQGhf}`˭ 0BN6myQ*Wki&6Xq&_߶}Vtk* M)D⽑IS1'Jyz>,1nR~e9oI?} 9%Qv7wH%{3I4!s/~z'cf f$Ƥ93S.0#l әUZ_?\[yؗO|Cb}miߘ͖>[_=v>^W5`̍ecodist/man/0000755000176200001440000000000013576531531012470 5ustar liggesusersecodist/man/pmgram.Rd0000644000176200001440000001161513576512762014253 0ustar liggesusers\name{pmgram} \alias{pmgram} \title{ Partial Mantel correlogram } \description{ This function calculates simple and partial multivariate correlograms. } \usage{ pmgram(data, space, partial, breaks, nclass, stepsize, resids = FALSE, nperm = 1000) } \arguments{ \item{data}{ lower-triangular dissimilarity matrix. This can be either an object of class dist (treated as one column) or a matrix or data frame with one or two columns, each of which is an independent lower-triangular dissimilarity in vector form. } \item{space}{ lower-triangular matrix of geographic distances. } \item{partial}{ optional, lower-triangular dissimilarity matrix of ancillary data. } \item{breaks}{ locations of class breaks. If specified, overrides nclass and stepsize. } \item{nclass}{ number of distance classes. If not specified, Sturge's rule will be used to determine an appropriate number of classes. } \item{stepsize}{ width of each distance class. If not specified, nclass and the range of space.d will be used to calculate an appropriate default. } \item{resids}{ if resids=TRUE, will return the residuals for each distance class. Otherwise returns 0. } \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } } \details{ This function does four different analyses: If data has 1 column and partial is missing, calculates a multivariate correlogram for data. If data has 2 columns and partial is missing, calculates a Mantel cross-correlogram, calculating the Mantel r between the two columns for each distance class separately. If data has 1 column and partial exists, calculates a partial multivariate correlogram based on residuals of data ~ partial. If data has 2 columns and partial exists, does a partial Mantel cross-correlogram, calculating partial Mantel r for each distance class separately. The Iwt statistic used for the multivariate correlograms is not the standard Mantel r. For one variable, using Euclidean distance, this metric converges on the familiar Moran autocorrelation. Like the Moran autocorrelation function, this statistic usually falls between -1 and 1, but is not bounded by those limits. Unlike the Moran function, this correlogram can be used for multivariate data, and can be extended to partial tests. The comparisons in \code{vignette("dissimilarity", package="ecodist")} may help. } \value{ Returns a object of class mgram, which is a list containing two objects: mgram is a matrix with one row for each distance class and 4 columns: \item{lag }{midpoint of the distance class.} \item{ngroup }{number of distances in that class.} \item{piecer or Iwt }{Mantel r value or appropriate statistic (see Details).} \item{pval }{two-sided p-value.} resids is a vector of the residuals (if calculated) and can be accessed with the \code{residuals()} method. } \author{ Sarah Goslee } \seealso{ \code{\link{mgram}}, \code{\link{mantel}}, \code{\link{residuals.mgram}}, \code{\link{plot.mgram}} } \examples{ data(bump) par(mfrow=c(1, 2)) image(bump, col=gray(seq(0, 1, length=5))) z <- as.vector(bump) x <- rep(1:25, times=25) y <- rep(1:25, each=25) X <- col(bump) Y <- row(bump) # calculate dissimilarities for data and space geo.dist <- dist(cbind(as.vector(X), as.vector(Y))) value.dist <- dist(as.vector(bump)) ### pmgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### bump.pmgram <- pmgram(value.dist, geo.dist, nperm=10000) data(bump.pmgram) plot(bump.pmgram) #### Partial pmgram example # generate a simple surface # with complex nonlinear spatial pattern x <- matrix(1:25, nrow=25, ncol=25, byrow=FALSE) y <- matrix(1:25, nrow=25, ncol=25, byrow=TRUE) # create z1 and z2 as functions of x, y # and scale them to [0, 1] z1 <- x + 3*y z2 <- y - cos(x) z1 <- (z1 - min(z1)) / (max(z1) - min(z1)) z2 <- (z2 - min(z2)) / (max(z2) - min(z2)) z12 <- (z1 + z2*2)/3 # look at patterns layout(matrix(c( 1, 1, 2, 2, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 5, 5), nrow=4, byrow=TRUE)) image(z1, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) image(z2, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) image(z12, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) # analyze the pattern of z across space z1 <- as.vector(z1) z2 <- as.vector(z2) z12 <- as.vector(z12) z1.d <- dist(z1) z2.d <- dist(z2) z12.d <- dist(z12) space <- cbind(as.vector(x), as.vector(y)) space.d <- dist(space) # take partial correlogram without effects of z1 ### pmgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### z.no <- pmgram(z12.d, space.d, nperm=1000, resids=FALSE) ### save(z.no, file="ecodist/data/z.no.rda") data(z.no) plot(z.no) # take partial correlogram of z12 given z1 ### pmgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### z.z1 <- pmgram(z12.d, space.d, z2.d, nperm=1000, resids=FALSE) ### save(z.z1, file="ecodist/data/z.z1.rda") data(z.z1) plot(z.z1) } \keyword{ multivariate } ecodist/man/xmantel.Rd0000644000176200001440000000672713576512762014450 0ustar liggesusers\name{xmantel} \alias{xmantel} \title{ Cross-Mantel test } \description{ Simple and partial cross-Mantel tests, with options for ranked data and permutation tests. } \usage{ xmantel(formula = formula(data), data = sys.parent(), dims = NA, nperm = 1000, mrank = FALSE) } \arguments{ \item{formula}{ formula describing the test to be conducted. For this test, y ~ x will perform a simple Mantel test, while y ~ x + z1 + z2 + z3 will do a partial Mantel test of the relationship between x and y given z1, z2, z3. All variables should be either non-symmetric square cross-dissimilary matrices of class xdist, or vector forms thereof. } \item{data}{ an optional dataframe containing the variables in the model as columns of dissimilarities. By default the variables are taken from the current environment. } \item{dims}{ if the dissimilarity matrices are not square, the dimensions must be provided as \code{c(nrow, ncol)}} \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } \item{mrank}{ if this is set to FALSE (the default option), Pearson correlations will be used. If set to TRUE, the Spearman correlation (correlation ranked distances) will be used. } } \details{ If only one independent variable is given, the simple Mantel r (r12) is calculated. If more than one independent variable is given, the partial Mantel r (ryx|x1 ...) is calculated by permuting one of the original dissimilarity matrices. Note that the cross-dissimilarity functions are for research purposes, and are not well-tested. } \value{ \item{mantelr }{Mantel coefficient.} \item{pval1 }{one-tailed p-value (null hypothesis: r <= 0).} \item{pval2 }{one-tailed p-value (null hypothesis: r >= 0).} \item{pval3 }{two-tailed p-value (null hypothesis: r = 0).} } \author{ Sarah Goslee } \seealso{ \code{\link{xdistance}}, \code{\link{xmgram}} } \examples{ data(graze) ### EXAMPLE 1: Square matrices # take two subsets of sites with different dominant grass abundances # use cut-offs that produce equal numbers of sites dom1 <- subset(graze, POPR > 50 & DAGL < 20) # 8 sites dom2 <- subset(graze, POPR < 50 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd) xmantel(dom.xd ~ forest.xd + sitelocation.xd) plot(xmgram(dom.xd, sitelocation.xd)) ### EXAMPLE 2: Non-square matrices # take two subsets of sites with different dominant grass abundances # this produces a non-square matrix dom1 <- subset(graze, POPR > 45 & DAGL < 20) # 13 sites dom2 <- subset(graze, POPR < 45 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd, dims=c(13, 8)) xmantel(dom.xd ~ forest.xd + sitelocation.xd, dims=c(13, 8)) plot(xmgram(dom.xd, sitelocation.xd)) } \keyword{ multivariate } ecodist/man/nmds.Rd0000644000176200001440000001151413576512762013727 0ustar liggesusers\name{nmds} \alias{nmds} \title{ Non-metric multidimensional scaling } \description{ Non-metric multidimensional scaling. } \usage{ nmds(dmat, mindim = 1, maxdim = 2, nits = 10, iconf, epsilon = 1e-12, maxit = 500, trace = FALSE) } \arguments{ \item{dmat}{ lower-triangular dissimilarity matrix. } \item{mindim}{ optional, minimum number of dimensions to use. } \item{maxdim}{ optional, maximum number of dimensions to use. } \item{nits}{ optional, number of separate ordinations to use. } \item{iconf}{ optional, initial configuration. If not specified, then a random configuration is used. } \item{epsilon}{ optional, acceptable difference in stress. } \item{maxit}{ optional, maximum number of iterations. } \item{trace}{ if TRUE, will write progress indicator to the screen. } } \details{ The goal of NMDS is to find a configuration in a given number of dimensions which preserves rank-order dissimilarities as closely as possible. The number of dimensions must be specified in advance. Because NMDS is prone to finding local minima, several random starts must be used. Stress is used as the measure of goodness of fit. A lower stress indicates a better match between dissimilarity and ordination. As of ecodist 1.9, the stress calculation used is the same as in \code{MASS:isoMDS}. In previous versions it was monotonically related, so the same configurations were produced, but the absolute value was different. } \value{ \item{conf }{list of configurations.} \item{stress }{list of final stress values.} \item{r2 }{total variance explained by each configuration.} The first results are for the lowest number of dimensions (total number is (mindim - maxdim + 1) * nits). } \references{ Kruskal, J.B. 1964. Multidimensional scaling by optimizing goodness of fit to a nonmetric hypothesis. Psychometrika 29:1-27. Minchin, P.R. 1987. An evaluation of the relative robustness of techniques for ecological ordination. Vegetatio 96:89-108. } \author{ Sarah Goslee } \seealso{ \code{\link{plot.nmds}}, \code{\link{min.nmds}}, \code{\link{vf}}, \code{\link{addord}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) # rotate the configuration to maximize variance iris.rot <- princomp(iris.nmin)$scores # rotation preserves distance apart in ordination space cor(dist(iris.nmin), dist(iris.rot)) # fit the data to the ordination as vectors ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vf <- vf(iris.nmin, iris[,1:4], nperm=1000) ### save(iris.vf, file="ecodist/data/iris.vf.rda") data(iris.vf) # repeat for the rotated ordination ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vfrot <- vf(iris.rot, iris[,1:4], nperm=1000) ### save(iris.vfrot, file="ecodist/data/iris.vfrot.rda") data(iris.vfrot) par(mfrow=c(1,2)) plot(iris.nmin, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="NMDS") plot(iris.vf) plot(iris.rot, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="Rotated NMDS") plot(iris.vfrot) # generate new data points to add to the ordination # this might be new samples, or a second dataset iris.new <- structure(list(Sepal.Length = c(4.6, 4.9, 5.4, 5.2, 6, 6.5, 6, 6.8, 7.3), Sepal.Width = c(3.2, 3.5, 3.6, 2.3, 2.8, 3, 2.7, 3.1, 3.2), Petal.Length = c(1.2, 1.5, 1.5, 3.5, 4.1, 4.2, 4.8, 5, 5.7), Petal.Width = c(0.26, 0.26, 0.26, 1.2, 1.3, 1.4, 1.8, 2, 2), Species = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), .Label = c("setosa", "versicolor", "virginica"), class = "factor")), .Names = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"), class = "data.frame", row.names = c(NA, -9L)) # provide a dist object containing original and new data # provide a logical vector indicating which samples were used to # construct the original configuration iris.full <- rbind(iris, iris.new) all.d <- dist(iris.full[,1:4]) is.orig <- c(rep(TRUE, nrow(iris)), rep(FALSE, nrow(iris.new))) ### addord() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.fit <- addord(iris.nmin, iris.full[,1:4], all.d, is.orig, maxit=100) ### save(iris.fit, file="ecodist/data/iris.fit.rda") data(iris.fit) plot(iris.fit$conf, col=iris.full$Species, pch=c(18, 4)[is.orig + 1], xlab="NMDS 1", ylab="NMDS 2") title("Demo: adding points to an ordination") legend("bottomleft", c("Training set", "Added point"), pch=c(4, 18)) legend("topright", levels(iris$Species), fill=1:3) } \keyword{ multivariate } ecodist/man/z.no.Rd0000644000176200001440000000355113576512762013654 0ustar liggesusers\name{z.no} \alias{z.no} \docType{data} \title{Example for pmgram} \description{ An object of class mgram for use in the example for \code{\link{pmgram}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(z.no)} \format{ See \code{\link{pmgram}} for current format specification. } \author{ Sarah Goslee } \seealso{ \code{\link{pmgram}}, \code{\link{z.z1}}, } \examples{ #### Partial pmgram example # generate a simple surface # with complex nonlinear spatial pattern x <- matrix(1:25, nrow=25, ncol=25, byrow=FALSE) y <- matrix(1:25, nrow=25, ncol=25, byrow=TRUE) # create z1 and z2 as functions of x, y # and scale them to [0, 1] z1 <- x + 3*y z2 <- y - cos(x) z1 <- (z1 - min(z1)) / (max(z1) - min(z1)) z2 <- (z2 - min(z2)) / (max(z2) - min(z2)) z12 <- (z1 + z2*2)/3 # look at patterns layout(matrix(c( 1, 1, 2, 2, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 5, 5), nrow=4, byrow=TRUE)) image(z1, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) image(z2, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) image(z12, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) # analyze the pattern of z across space z1 <- as.vector(z1) z2 <- as.vector(z2) z12 <- as.vector(z12) z1.d <- dist(z1) z2.d <- dist(z2) z12.d <- dist(z12) space <- cbind(as.vector(x), as.vector(y)) space.d <- dist(space) # take partial correlogram without effects of z1 ### pgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### z.no <- pmgram(z12.d, space.d, nperm=1000, resids=FALSE) ### save(z.no, file="ecodist/data/z.no.rda") plot(z.no) # take partial correlogram of z12 given z1 ### pgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### z.z1 <- pmgram(z12.d, space.d, z2.d, nperm=1000, resids=FALSE) ### save(z.z1, file="ecodist/data/z.z1.rda") plot(z.z1) } \keyword{datasets} ecodist/man/mantel.Rd0000644000176200001440000001060013576512762014241 0ustar liggesusers\name{mantel} \alias{mantel} \title{ Mantel test } \description{ Simple and partial Mantel tests, with options for ranked data, permutation tests, and bootstrapped confidence limits. } \usage{ mantel(formula = formula(data), data = sys.parent(), nperm = 1000, mrank = FALSE, nboot = 500, pboot = 0.9, cboot = 0.95) } \arguments{ \item{formula}{ formula describing the test to be conducted. For this test, y ~ x will perform a simple Mantel test, while y ~ x + z1 + z2 + z3 will do a partial Mantel test of the relationship between x and y given z1, z2, z3. All variables can be either a distance matrix of class dist or vectors of dissimilarities. } \item{data}{ an optional dataframe containing the variables in the model as columns of dissimilarities. By default the variables are taken from the current environment. } \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } \item{mrank}{ if this is set to FALSE (the default option), Pearson correlations will be used. If set to TRUE, the Spearman correlation (correlation ranked distances) will be used. } \item{nboot}{ number of iterations to use for the bootstrapped confidence limits. If set to 0, the bootstrapping will be omitted. } \item{pboot}{ the level at which to resample the data for the bootstrapping procedure. } \item{cboot}{ the level of the confidence limits to estimate. } } \details{ If only one independent variable is given, the simple Mantel r (r12) is calculated. If more than one independent variable is given, the partial Mantel r (ryx|x1 ...) is calculated by permuting one of the original dissimilarity matrices. The bootstrapping is actually resampling without replacement, because duplication of samples is not useful in a dissimilarity context (the dissimilarity of a sample with itself is zero). Resampling within dissimilarity values is inappropriate, just as for permutation. } \value{ \item{mantelr }{Mantel coefficient.} \item{pval1 }{one-tailed p-value (null hypothesis: r <= 0).} \item{pval2 }{one-tailed p-value (null hypothesis: r >= 0).} \item{pval3 }{two-tailed p-value (null hypothesis: r = 0).} \item{llim }{lower confidence limit.} \item{ulim }{upper confidence limit.} } \references{ Mantel, N. 1967. The detection of disease clustering and a generalized regression approach. Cancer Research 27:209-220. Smouse, P.E., J.C. Long and R.R. Sokal. 1986. Multiple regression and correlation extensions of the Mantel test of matrix correspondence. Systematic Zoology 35:62 7-632. Goslee, S.C. and Urban, D.L. 2007. The ecodist package for dissimilarity-based analysis of ecological data. Journal of Statistical Software 22(7):1-19. Goslee, S.C. 2010. Correlation analysis of dissimilarity matrices. Plant Ecology 206(2):279-286. } \author{ Sarah Goslee } \seealso{ \code{\link{mgram}}, \code{\link{mgroup}} } \examples{ data(graze) grasses <- graze[, colnames(graze) \%in\% c("DAGL", "LOAR10", "LOPE", "POPR")] legumes <- graze[, colnames(graze) \%in\% c("LOCO6", "TRPR2", "TRRE3")] grasses.bc <- bcdist(grasses) legumes.bc <- bcdist(legumes) space.d <- dist(graze$sitelocation) forest.d <- dist(graze$forestpct) # Mantel test: is the difference in forest cover between sites # related to the difference in grass composition between sites? mantel(grasses.bc ~ forest.d) # Mantel test: is the geographic distance between sites # related to the difference in grass composition between sites? mantel(grasses.bc ~ space.d) # Partial Mantel test: is the difference in forest cover between sites # related to the difference in grass composition once the # linear effects of geographic distance are removed? mantel(grasses.bc ~ forest.d + space.d) # Mantel test: is the difference in forest cover between sites # related to the difference in legume composition between sites? mantel(legumes.bc ~ forest.d) # Mantel test: is the geographic distance between sites # related to the difference in legume composition between sites? mantel(legumes.bc ~ space.d) # Partial Mantel test: is the difference in forest cover between sites # related to the difference in legume composition once the # linear effects of geographic distance are removed? mantel(legumes.bc ~ forest.d + space.d) # Is there nonlinear pattern in the relationship with geographic distance? par(mfrow=c(2, 1)) plot(mgram(grasses.bc, space.d, nclass=8)) plot(mgram(legumes.bc, space.d, nclass=8)) } \keyword{ multivariate } ecodist/man/z.z1.Rd0000644000176200001440000000355113576512762013572 0ustar liggesusers\name{z.z1} \alias{z.z1} \docType{data} \title{Example for pmgram} \description{ An object of class mgram for use in the example for \code{\link{pmgram}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(z.z1)} \format{ See \code{\link{pmgram}} for current format specification. } \author{ Sarah Goslee } \seealso{ \code{\link{pmgram}}, \code{\link{z.no}}, } \examples{ #### Partial pmgram example # generate a simple surface # with complex nonlinear spatial pattern x <- matrix(1:25, nrow=25, ncol=25, byrow=FALSE) y <- matrix(1:25, nrow=25, ncol=25, byrow=TRUE) # create z1 and z2 as functions of x, y # and scale them to [0, 1] z1 <- x + 3*y z2 <- y - cos(x) z1 <- (z1 - min(z1)) / (max(z1) - min(z1)) z2 <- (z2 - min(z2)) / (max(z2) - min(z2)) z12 <- (z1 + z2*2)/3 # look at patterns layout(matrix(c( 1, 1, 2, 2, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 5, 5), nrow=4, byrow=TRUE)) image(z1, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) image(z2, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) image(z12, col=gray(seq(0, 1, length=20)), zlim=c(0,1)) # analyze the pattern of z across space z1 <- as.vector(z1) z2 <- as.vector(z2) z12 <- as.vector(z12) z1.d <- dist(z1) z2.d <- dist(z2) z12.d <- dist(z12) space <- cbind(as.vector(x), as.vector(y)) space.d <- dist(space) # take partial correlogram without effects of z1 ### pgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### z.no <- pmgram(z12.d, space.d, nperm=1000, resids=FALSE) ### save(z.no, file="ecodist/data/z.no.rda") plot(z.no) # take partial correlogram of z12 given z1 ### pgram() is time-consuming, so this was generated ### in advance and saved. ### set.seed(1234) ### z.z1 <- pmgram(z12.d, space.d, z2.d, nperm=1000, resids=FALSE) ### save(z.z1, file="ecodist/data/z.z1.rda") plot(z.z1) } \keyword{datasets} ecodist/man/iris.nmds.Rd0000644000176200001440000000141113576512762014667 0ustar liggesusers\name{iris.nmds} \alias{iris.nmds} \docType{data} \title{Example for nmds} \description{ An object of class nmds for use in the example for \code{\link{nmds}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(iris.nmds)} \format{ See \code{\link{nmds}} for current format specification. } \author{ Sarah Goslee } \seealso{ \code{\link{nmds}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) } \keyword{datasets} ecodist/man/addord.Rd0000644000176200001440000001056413576512762014227 0ustar liggesusers\name{addord} \alias{addord} \title{ Fit new points to an existing NMDS configuration. } \description{ Uses a brute force algorithm to find the location for each new point that minimizes overall stress. } \usage{ addord(origconf, fulldat, fulldist, isTrain, bfstep = 10, maxit = 50, epsilon = 1e-12) } \arguments{ \item{origconf}{ The original ordination configuration. } \item{fulldat}{ The dataset containing original and new points. } \item{fulldist}{ A dissimilarity matrix calculated on \code{fulldat}. } \item{isTrain}{ A boolean vector of length \code{nrow(fulldat)} indicating which rows were training data used in determining \code{origconf} (TRUE), or are new points (FALSE). } \item{bfstep}{ A tuning parameter for the brute force algorithm describing the size of grid to use. } \item{maxit}{ The maximum number of iterations to use. } \item{epsilon}{ Tolerance value for convergence. } } \details{ A region comprising the original ordination configuration plus one standard deviation is divided into a grid of \code{bfstep} rows and columns. For a new point, the grid cell with the lowest stress is identified. That cell is divided into a finer grid, and the lowest-stress cell identified. This process is repeated up to \code{maxit} times, or until stress changes less than \code{epsilon}. } \value{ \item{fullfitconf }{The new ordination configuration containing training and new points.} \item{stress }{The stress value for each point.} \item{isTrain }{The boolean vector indicating training set membership, for reference.} } \author{ Sarah Goslee } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) # rotate the configuration to maximize variance iris.rot <- princomp(iris.nmin)$scores # rotation preserves distance apart in ordination space cor(dist(iris.nmin), dist(iris.rot)) # fit the data to the ordination as vectors ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vf <- vf(iris.nmin, iris[,1:4], nperm=1000) ### save(iris.vf, file="ecodist/data/iris.vf.rda") data(iris.vf) # repeat for the rotated ordination ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vfrot <- vf(iris.rot, iris[,1:4], nperm=1000) ### save(iris.vfrot, file="ecodist/data/iris.vfrot.rda") data(iris.vfrot) par(mfrow=c(1,2)) plot(iris.nmin, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="NMDS") plot(iris.vf) plot(iris.rot, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="Rotated NMDS") plot(iris.vfrot) ####### addord example # generate new data points to add to the ordination # this might be new samples, or a second dataset iris.new <- structure(list(Sepal.Length = c(4.6, 4.9, 5.4, 5.2, 6, 6.5, 6, 6.8, 7.3), Sepal.Width = c(3.2, 3.5, 3.6, 2.3, 2.8, 3, 2.7, 3.1, 3.2), Petal.Length = c(1.2, 1.5, 1.5, 3.5, 4.1, 4.2, 4.8, 5, 5.7), Petal.Width = c(0.26, 0.26, 0.26, 1.2, 1.3, 1.4, 1.8, 2, 2), Species = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), .Label = c("setosa", "versicolor", "virginica"), class = "factor")), .Names = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"), class = "data.frame", row.names = c(NA, -9L)) # provide a dist object containing original and new data # provide a logical vector indicating which samples were used to # construct the original configuration iris.full <- rbind(iris, iris.new) all.d <- dist(iris.full[,1:4]) is.orig <- c(rep(TRUE, nrow(iris)), rep(FALSE, nrow(iris.new))) ### addord() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.fit <- addord(iris.nmin, iris.full[,1:4], all.d, is.orig, maxit=100) ### save(iris.fit, file="ecodist/data/iris.fit.rda") data(iris.fit) plot(iris.fit$conf, col=iris.full$Species, pch=c(18, 4)[is.orig + 1], xlab="NMDS 1", ylab="NMDS 2") title("Demo: adding points to an ordination") legend("bottomleft", c("Training set", "Added point"), pch=c(4, 18)) legend("topright", levels(iris$Species), fill=1:3) } \keyword{ multivariate } ecodist/man/plot.nmds.Rd0000644000176200001440000000225413576512762014705 0ustar liggesusers\name{plot.nmds} \alias{plot.nmds} \title{ Plot information about NMDS ordination } \description{ Graphical display of stress and r2 for NMDS ordination along number of dimensions. } \usage{ \method{plot}{nmds}(x, plot = TRUE, xlab = "Dimensions", \dots) } \arguments{ \item{x}{ an object of S3 class \code{nmds}, created by \code{nmds()} } \item{plot}{ optional, if TRUE a figure is produced } \item{xlab}{ optional, label for x axis of graph } \item{\dots}{ optional, other graphics parameters } } \value{ Produces a two-panel plot with stress and r2 for ordination by number of dimensions. Points show the mean value; lines indicate minimum and maximum. } \author{ Dean Urban } \seealso{ \code{\link{nmds}}} \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) } \keyword{ multivariate } \keyword{ hplot } ecodist/man/iris.vf.Rd0000644000176200001440000000266613576512762014356 0ustar liggesusers\name{iris.vf} \alias{iris.vf} \docType{data} \title{Example for vector fitting on ordination} \description{ An object of class vf for use in the examples for \code{\link{nmds}} and \code{\link{vf}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(iris.vf)} \format{ See \code{\link{vf}} for current format specification. } \author{ Sarah Goslee } \seealso{ \code{\link{nmds}}, \code{\link{vf}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) # rotate the configuration to maximize variance iris.rot <- princomp(iris.nmin)$scores # rotation preserves distance apart in ordination space cor(dist(iris.nmin), dist(iris.rot)) # fit the data to the ordination as vectors ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vf <- vf(iris.nmin, iris[,1:4], nperm=1000) ### save(iris.vf, file="ecodist/data/iris.vf.rda") data(iris.vf) plot(iris.nmin, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="NMDS") plot(iris.vf) } \keyword{datasets} ecodist/man/graze.Rd0000644000176200001440000000547413576512762014106 0ustar liggesusers\name{graze} \alias{graze} \docType{data} \title{ Site information and grazed vegetation data. } \description{ This data frame contains site location, landscape context and dominant plant species abundances for 25 of the plant species found in 50 grazed pastures in the northeastern United States. Elements are the mean values for canopy cover for ten 0.5 x 2 m quadrats. } \usage{data(graze)} \format{ A data frame with 50 observations on the following 25 variables. \describe{ \item{\code{sitelocation}}{Site location along a geographic gradient.} \item{\code{forestpct}}{Percentage forest cover within a 1-km radius.} \item{\code{ACMI2}}{Percentage canopy cover.} \item{\code{ANOD}}{Percentage canopy cover.} \item{\code{ASSY}}{Percentage canopy cover.} \item{\code{BRIN2}}{Percentage canopy cover.} \item{\code{CIAR4}}{Percentage canopy cover.} \item{\code{CIIN}}{Percentage canopy cover.} \item{\code{CIVU}}{Percentage canopy cover.} \item{\code{DAGL}}{Percentage canopy cover.} \item{\code{ELRE4}}{Percentage canopy cover.} \item{\code{GAMO}}{Percentage canopy cover.} \item{\code{LOAR10}}{Percentage canopy cover.} \item{\code{LOCO6}}{Percentage canopy cover.} \item{\code{LOPE}}{Percentage canopy cover.} \item{\code{OXST}}{Percentage canopy cover.} \item{\code{PLMA2}}{Percentage canopy cover.} \item{\code{POPR}}{Percentage canopy cover.} \item{\code{PRVU}}{Percentage canopy cover.} \item{\code{RAAC3}}{Percentage canopy cover.} \item{\code{RUCR}}{Percentage canopy cover.} \item{\code{SORU2}}{Percentage canopy cover.} \item{\code{STGR}}{Percentage canopy cover.} \item{\code{TAOF}}{Percentage canopy cover.} \item{\code{TRPR2}}{Percentage canopy cover.} \item{\code{TRRE3}}{Percentage canopy cover.} \item{\code{VEOF2}}{Percentage canopy cover.} } } \details{ Site locations fall along a southwest-northeast transect through the northeastern United States. This is a synthetic gradient calculated from latitude and longitude. Forest landcover is taken from the USGS 1992 National Land Cover Dataset. All forest classes were combined, and the percentage within 1 km of the sample sites was calculated using a GIS. } \source{ Details of these data are available in Tracy and Sanderson (2000) and Goslee and Sanderson (2010). The 1992 NLCD data can be obtained from http://www.mrlc.gov/. Species codes are from http://plants.usda.gov (2010). } \references{ Tracy, B.F. and M.A. Sanderson. 2000. Patterns of plant species richness in pasture lands of the northeast United States. Plant Ecology 149:169-180. Goslee, S.C., Sanderson, M.A. 2010. Landscape Context and Plant Community Composition in Grazed Agricultural Systems. Landscape Ecology 25:1029-1039. } \author{ Sarah Goslee } \examples{ data(graze) } \keyword{datasets} ecodist/man/mgroup.Rd0000644000176200001440000000302013576512762014270 0ustar liggesusers\name{mgroup} \alias{mgroup} \title{ Mantel test for groups } \description{ Simple and partial Mantel tests, with options for ranked data, permutation tests, and bootstrapped confidence limits. } \usage{ mgroup(edist, groups, nperm=1000) } \arguments{ \item{edist}{ a dist object or lower triangular distance vector. } \item{groups}{ a vector of group memberships (numeric, character, or factor), or a matrix or data frame with columns describing multiple sets of groups. } \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } } \details{ \code{mgroup} returns the Mantel correlations for group contrast matrices computed from cluster groups across a range of clustering levels. } \value{ \item{nclust }{Number of groups tested.} \item{mantelr }{Mantel coefficient.} \item{pval1 }{one-tailed p-value (null hypothesis: r <= 0).} } \references{ Legendre, P. and M. Fortin. 1989. Spatial pattern and ecological analysis. Vegetatio 80:107-138. } \author{ Sarah Goslee } \seealso{ \code{\link{mantel}} } \examples{ # Using a model matrix to test group membership data(iris) iris.d <- dist(iris[,1:4]) mgroup(iris.d, iris[,5]) # clustering-based example data(graze) graze.d <- dist(graze[, -c(1:2)]) graze.hclust <- hclust(graze.d) clust.groups <- data.frame( k2 = cutree(graze.hclust, k = 2), k4 = cutree(graze.hclust, k = 4), k6 = cutree(graze.hclust, k = 6), k8 = cutree(graze.hclust, k = 8)) mgroup(graze.d, clust.groups, nperm=1000) } \keyword{ multivariate } ecodist/man/corgen.Rd0000644000176200001440000000454013576512762014244 0ustar liggesusers\name{corgen} \alias{corgen} \title{ Generate correlated data } \description{ Generate correlated data of a given length. } \usage{ corgen(len, x, r, population = FALSE, epsilon = 0) } \arguments{ \item{len}{ Length of vectors. } \item{x}{ Independent data. If x is specified, the population parameter is automatically set to TRUE. } \item{r}{ Desired correlation between data vectors. } \item{population}{ TRUE for vectors drawn from two populations with correlation r, otherwise r is the sample correlation. } \item{epsilon}{ Desired tolerance. } } \value{ \item{x }{First data vector, either generated by corgen or given by the user. } \item{y }{Second data vector. } } \details{ Either x or len must be specified. If epsilon = 0, it has no effect, otherwise the sampling process is repeated until the sample correlation is within epsilon of r. This option allows the production of exactly-correlated data, within the limits of epsilon. Setting epsilon > 0 invalidates the population setting; data will be correlated within that range, rather than sampled from that population.If epsilon = 0, it has no effect, otherwise the sampling process is repeated until the sample correlation is within epsilon of r. This option allows the production of exactly-correlated data, within the limits of epsilon. Setting epsilon > 0 invalidates the population setting; data will be correlated within that range, rather than sampled from that population.If epsilon = 0, it has no effect, otherwise the sampling process is repeated until the sample correlation is within epsilon of r. This option allows the production of exactly-correlated data, within the limits of epsilon. Setting epsilon > 0 invalidates the population setting; data will be correlated within that range, rather than sampled from that population. } \author{ Sarah Goslee } \examples{ # create two random variables of length 100 with correlation # of 0.10 +/- 0.01 xy <- corgen(len=100, r=.1, epsilon=0.01) with(xy, cor(x, y)) # create two random variables of length 100 drawn from a population with # a correlation of -0.82 xy <- corgen(len=100, r=-0.82, population=TRUE) with(xy, cor(x, y)) # create a variable y within 0.01 of the given correlation to x x <- 1:100 y <- corgen(x=x, r=.5, epsilon=.01)$y cor(x, y) } \keyword{ distribution } ecodist/man/iris.fit.Rd0000644000176200001440000000465613576512762014526 0ustar liggesusers\name{iris.fit} \alias{iris.fit} \docType{data} \title{Example of adding to an ordination} \description{ A fitted ordination for use in the example for \code{\link{addord}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(iris.fit)} \format{ The format of this object is a list with: X1, X2, etc: ordination configuration: coordinates for each point. stress: goodness of fit for each point. isTrain: logical vector indicating whether each point was used in the original ordination. } \author{ Sarah Goslee } \seealso{ \code{\link{nmds}}, \code{\link{addord}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) # generate new data points to add to the ordination # this might be new samples, or a second dataset iris.new <- structure(list(Sepal.Length = c(4.6, 4.9, 5.4, 5.2, 6, 6.5, 6, 6.8, 7.3), Sepal.Width = c(3.2, 3.5, 3.6, 2.3, 2.8, 3, 2.7, 3.1, 3.2), Petal.Length = c(1.2, 1.5, 1.5, 3.5, 4.1, 4.2, 4.8, 5, 5.7), Petal.Width = c(0.26, 0.26, 0.26, 1.2, 1.3, 1.4, 1.8, 2, 2), Species = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), .Label = c("setosa", "versicolor", "virginica"), class = "factor")), .Names = c("Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species"), class = "data.frame", row.names = c(NA, -9L)) # provide a dist object containing original and new data # provide a logical vector indicating which samples were used to # construct the original configuration iris.full <- rbind(iris, iris.new) all.d <- dist(iris.full[,1:4]) is.orig <- c(rep(TRUE, nrow(iris)), rep(FALSE, nrow(iris.new))) ### addord() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.fit <- addord(iris.nmin, iris.full[,1:4], all.d, is.orig, maxit=100) ### save(iris.fit, file="ecodist/data/iris.fit.rda") data(iris.fit) plot(iris.fit$conf, col=iris.full$Species, pch=c(18, 4)[is.orig + 1], xlab="NMDS 1", ylab="NMDS 2") title("Demo: adding points to an ordination") legend("bottomleft", c("Training set", "Added point"), pch=c(4, 18)) legend("topright", levels(iris$Species), fill=1:3) } \keyword{datasets} ecodist/man/crosstab.Rd0000644000176200001440000000525513576512762014613 0ustar liggesusers\name{crosstab} \alias{crosstab} \title{ Data formatting } \description{ Converts field data of the form site, species, observation into a site by species data frame. } \usage{ crosstab(rowlab, collab, values, type = "sum", data, allrows, allcols, na.as.0 = TRUE, check.names = TRUE, \dots) } \arguments{ \item{rowlab}{ row labels, e.g. site names. } \item{collab}{ column labels, e.g. species names. } \item{values}{ data values. } \item{data}{ optional data frame from which to take rowlab, collab and/or values. } \item{type}{ function to use to combine data, one of "sum" (default), "min", "max", "mean", "count". } \item{allrows}{ optional, list of all desired row names that may not appear in rowlab. } \item{allcols}{ optional, list of all desired column names that may not appear in collab. } \item{na.as.0}{ if TRUE, all NA values are replaced with 0. } \item{check.names}{ if FALSE, data frame names are not checked for syntactic validity, so that they match the input categories. Otherwise make.names() is used to adjust them. } \item{\dots}{ optional arguments to the function specified in type, such as na.rm=TRUE} } \details{ Field data are often recorded as a separate row for each site-species combination. This function reformats such data into a data frame for further analysis based on unique row and column labels. The three vectors should all be the same length (including duplicates). The three vectors may also be provided as names of columns in the data frame specified by the data argument. If allrows or allcols exists, rows and/or columns of zeros are inserted for any elements of allrows/allcols not present in rowlab/collab. If values is missing the number of occurrences of combinations of rowlab and collab will be returned. Thus, crosstab(rowlab, collab) is equivalent to table(rowlab, collab). If type is "count", the unique combinations of rowlab, collab and values will be returned. } \value{ data frame with rowlab as row headings, collab as columns, and values as the data. } \author{ Sarah Goslee } \examples{ # Make a random example plotnames <- rep(1:5, each = 6) speciesnames <- rep(c("A", "B", "C"), 10) freqdata <- runif(30) # number of samples of each species and plot crosstab(plotnames, speciesnames) # can use the data argument speciesdata <- data.frame(plots = plotnames, species = speciesnames, freq = freqdata, stringsAsFactors=FALSE) # mean frequency by species and plot crosstab(plots, species, freq, data=speciesdata, type="mean") # can specify additional possible row or column levels crosstab(plots, species, freq, data=speciesdata, type="mean", allcols=LETTERS[1:5]) } \keyword{ manip } \keyword{ multivariate } ecodist/man/vf.Rd0000644000176200001440000000365613576512762013411 0ustar liggesusers\name{vf} \alias{vf} \title{ Vector fitting } \description{ Fits ancillary variables to an ordination configuration. } \usage{ vf(ord, vars, nperm = 100) } \arguments{ \item{ord}{ matrix containing a 2-dimensional ordination result with axes as columns. } \item{vars}{ matrix with ancillary variables as columns. } \item{nperm}{ number of permutation for the significance test. If nperm = 0, the test will be omitted. } } \details{ Vector fitting finds the maximum correlation of the individual variables with a configuration of samples in ordination space. } \value{ an object of class vf containing matrix with the first 2 columns containing the scores for every variable in each of the 2 dimensions of the ordination space. r is the maximum correlation of the variable with the ordination space, and pval is the result of the permutation test. } \references{ Jongman, R.H.G., C.J.F. ter Braak and O.F.R. van Tongeren. 1995. Data analysis in community and landscape ecology. Cambridge University Press, New York. } \author{ Sarah Goslee } \seealso{ \code{\link{plot.vf}} } \examples{ # Example of multivariate analysis using built-in iris dataset data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) # fit the data to the ordination as vectors ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vf <- vf(iris.nmin, iris[,1:4], nperm=1000) ### save(iris.vf, file="ecodist/data/iris.vf.rda") data(iris.vf) plot(iris.nmin, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="NMDS") plot(iris.vf) } \keyword{ multivariate } ecodist/man/mgram.Rd0000644000176200001440000000664213576512762014077 0ustar liggesusers\name{mgram} \alias{mgram} \title{ Mantel correlogram } \description{ Calculates simple Mantel correlograms. } \usage{ mgram(species.d, space.d, breaks, nclass, stepsize, nperm = 1000, mrank = FALSE, nboot = 500, pboot = 0.9, cboot = 0.95, alternative = "two.sided", trace = FALSE) } \arguments{ \item{species.d}{ lower-triangular dissimilarity matrix. } \item{space.d}{ lower-triangular matrix of geographic distances. } \item{breaks}{ locations of class breaks. If specified, overrides nclass and stepsize. } \item{nclass}{ number of distance classes. If not specified, Sturge's rule will be used to determine an appropriate number of classes. } \item{stepsize}{ width of each distance class. If not specified, nclass and the range of space.d will be used to calculate an appropriate default. } \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } \item{mrank}{ if this is set to FALSE (the default option), Pearson correlations will be used. If set to TRUE, the Spearman correlation (correlation ranked distances) will be used. } \item{nboot}{ number of iterations to use for the bootstrapped confidence limits. If set to 0, the bootstrapping will be omitted. } \item{pboot}{ the level at which to resample the data for the bootstrapping procedure. } \item{cboot}{ the level of the confidence limits to estimate. } \item{alternative}{ default is "two.sided", and returns p-values for H0: rM = 0. The alternative is "one.sided", which returns p-values for H0: rM <= 0. } \item{trace}{ if TRUE, returns progress indicators. } } \details{ This function calculates Mantel correlograms. The Mantel correlogram is essentially a multivariate autocorrelation function. The Mantel r represents the dissimilarity in variable composition (often species composition) at a particular lag distance. } \value{ Returns an object of class mgram, which is a list with two elements. mgram is a matrix with one row for each distance class and 6 columns: \item{lag }{midpoint of the distance class.} \item{ngroup }{number of distances in that class.} \item{mantelr }{Mantel r value.} \item{pval }{p-value for the test chosen.} \item{llim }{lower bound of confidence limit for mantelr.} \item{ulim }{upper bound of confidence limit for mantelr.} resids is NA for objects calculated by mgram(). } \references{ Legendre, P. and M. Fortin. 1989. Spatial pattern and ecological analysis. Vegetatio 80:107-138. } \author{ Sarah Goslee } \seealso{ \code{\link{mantel}}, \code{\link{plot.mgram}}, \code{\link{pmgram}} } \examples{ # generate a simple surface x <- matrix(1:10, nrow=10, ncol=10, byrow=FALSE) y <- matrix(1:10, nrow=10, ncol=10, byrow=TRUE) z <- x + 3*y image(z) # analyze the pattern of z across space space <- cbind(as.vector(x), as.vector(y)) z <- as.vector(z) space.d <- distance(space, "eucl") z.d <- distance(z, "eucl") z.mgram <- mgram(z.d, space.d, nperm=0) plot(z.mgram) # data(graze) space.d <- dist(graze$sitelocation) forest.d <- dist(graze$forestpct) grasses <- graze[, colnames(graze) \%in\% c("DAGL", "LOAR10", "LOPE", "POPR")] legumes <- graze[, colnames(graze) \%in\% c("LOCO6", "TRPR2", "TRRE3")] grasses.bc <- bcdist(grasses) legumes.bc <- bcdist(legumes) # Does the relationship of composition with distance vary for # grasses and legumes? par(mfrow=c(2, 1)) plot(mgram(grasses.bc, space.d, nclass=8)) plot(mgram(legumes.bc, space.d, nclass=8)) } \keyword{ multivariate } ecodist/man/xdistance.Rd0000644000176200001440000000605213576512762014751 0ustar liggesusers\name{xdistance} \alias{xdistance} \title{ Cross-distance between two datasets. } \description{ Pairwise dissimilarity calculation between rows of one dataset and rows of another, for instance across different sampling periods for the same set of sites. } \usage{ xdistance(x, y, method = "euclidean") } \arguments{ \item{x}{A site by species or other matrix or data frame.} \item{y}{A a second site by species dataset, which must have at least the same columns.} \item{method}{This function calls \code{\link{distance}} to do the calculations, and will accept any method used there, currently: "euclidean", "bray-curtis", "manhattan", "mahalanobis" (squared Mahalanobis distance), "jaccard", "difference", "sorensen", "gower", "modgower10" (modified Gower, base 10), "modgower2" (modified Gower, base 2). Partial matching will work for selecting a method.} } \details{ This function will calculate rowwise dissimilarities between any pair of matrices or data frames with the same number of columns. Note that the cross-dissimilarity functions are for research purposes, and are not well-tested. } \value{ A non-symmetric and possibly not square matrix of dissimilarities of class \code{xdist}, where \code{result <- xdistance(x, y)} produces a matrix with \code{result[a, b]} containing the dissimilarity between \code{x[a, ]} and \code{y[b, ]}. } \author{ Sarah Goslee } \seealso{ \code{\link{distance}}, \code{\link{xmantel}}, \code{\link{xmgram}}} \examples{ data(graze) ### EXAMPLE 1: Square matrices # take two subsets of sites with different dominant grass abundances # use cut-offs that produce equal numbers of sites dom1 <- subset(graze, POPR > 50 & DAGL < 20) # 8 sites dom2 <- subset(graze, POPR < 50 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd) xmantel(dom.xd ~ forest.xd + sitelocation.xd) plot(xmgram(dom.xd, sitelocation.xd)) ### EXAMPLE 2: Non-square matrices # take two subsets of sites with different dominant grass abundances # this produces a non-square matrix dom1 <- subset(graze, POPR > 45 & DAGL < 20) # 13 sites dom2 <- subset(graze, POPR < 45 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd, dims=c(13, 8)) xmantel(dom.xd ~ forest.xd + sitelocation.xd, dims=c(13, 8)) plot(xmgram(dom.xd, sitelocation.xd)) } \keyword{ multivariate } ecodist/man/bcdist.Rd0000644000176200001440000000242513576512762014237 0ustar liggesusers\name{bcdist} \alias{bcdist} \title{ Bray-Curtis distance } \description{ Returns the Bray-Curtis (also known as Sorenson, 1 - percent similarity) pairwise distances for the objects in the data. It is duplicated by functionality within \code{\link{distance}} but remains for backward compatibility and because it is substantially faster. } \usage{ bcdist(x, rmzero = FALSE) } \arguments{ \item{x}{ matrix or data frame with rows as samples and columns as variables (such as species). Distances will be calculated for each pair of rows. } \item{rmzero}{ If rmzero=TRUE, empty rows will be removed from the data before distances are calculated. Otherwise, the distance between two empty rows is assumed to be 0 (the default). } } \value{ This function returns a column-order lower-triangular distance matrix. The returned object has an attribute, Size, giving the number of objects, that is, nrow(x). The length of the vector that is returned is nrow(x)*(nrow(x)-1)/2. } \author{ Sarah Goslee } \seealso{ \code{\link{dist}}, \code{\link{distance}}} \examples{ data(graze) system.time(graze.bc <- bcdist(graze[, -c(1:2)])) # equivalent to but much faster than: system.time(graze.bc2 <- distance(graze[, -c(1:2)], "bray-curtis")) all.equal(graze.bc, graze.bc2) } \keyword{ multivariate } ecodist/man/MRM.Rd0000644000176200001440000000527013576531345013421 0ustar liggesusers\name{MRM} \alias{MRM} \title{ Multiple Regression on distance Matrices } \description{ Multiple regression on distance matrices (MRM) using permutation tests of significance for regression coefficients and R-squared. } \usage{ MRM(formula = formula(data), data = sys.parent(), nperm = 1000, method = "linear", mrank = FALSE) } \arguments{ \item{formula}{ formula describing the test to be conducted. } \item{data}{ an optional dataframe containing the variables in the model as columns of dissimilarities. By default the variables are taken from the current environment. } \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } \item{mrank}{ if this is set to FALSE (the default option), Pearson correlations will be used. If set to TRUE, the Spearman correlation (correlation ranked distances) will be used. } \item{method}{ if "linear", the default, uses multiple regression analysis. If "logistic", performs logistic regression with appropriate permutation testing. Note that this may be substantially slower.} } \details{ Performs multiple regression on distance matrices following the methods outlined in Legendre et al. 1994. Specificaly, the permutation test uses a pseudo-t test to assess significance, rather than using the regression coefficients directly. } \value{ \item{coef }{A matrix with regression coefficients and associated p-values from the permutation test (using the pseudo-t of Legendre et al. 1994).} \item{r.squared }{Regression R-squared and associated p-value from the permutation test (linear only). } \item{F.test }{F-statistic and p-value for overall F-test for lack of fit (linear only).} \item{dev }{Residual deviance, degrees of freedom, and associated p-value (logistic only).} } \references{ Lichstein, J. 2007. Multiple regression on distance matrices: A multivariate spatial analysis tool. Plant Ecology 188: 117-131. Legendre, P.; Lapointe, F. and Casgrain, P. 1994. Modeling brain evolution from behavior: A permutational regression approach. Evolution 48: 1487-1499. } \author{ Sarah Goslee } \seealso{ \code{\link{mantel}} } \examples{ data(graze) # Abundance of this grass is related to forest cover but not location MRM(dist(LOAR10) ~ dist(sitelocation) + dist(forestpct), data=graze, nperm=10) # Abundance of this legume is related to location but not forest cover MRM(dist(TRRE3) ~ dist(sitelocation) + dist(forestpct), data=graze, nperm=10) # Compare to presence/absence of grass LOAR10 using logistic regression LOAR10.presence <- ifelse(graze$LOAR10 > 0, 1, 0) MRM(dist(LOAR10.presence) ~ dist(sitelocation) + dist(forestpct), data=graze, nperm=10, method="logistic") } \keyword{ multivariate } ecodist/man/xmgram.Rd0000644000176200001440000000763213576512762014267 0ustar liggesusers\name{xmgram} \alias{xmgram} \title{Cross-Mantel correlogram } \description{ Calculates simple Mantel correlograms from cross-distance matrices. } \usage{ xmgram(species.xd, space.xd, breaks, nclass, stepsize, nperm = 1000, mrank = FALSE, alternative = "two.sided", trace = FALSE) } \arguments{ \item{species.xd}{ non-symmetric square cross-distance matrix. } \item{space.xd}{ non-symmetric square matrix of geographic distances. } \item{breaks}{ locations of class breaks. If specified, overrides nclass and stepsize. } \item{nclass}{ number of distance classes. If not specified, Sturge's rule will be used to determine an appropriate number of classes. } \item{stepsize}{ width of each distance class. If not specified, nclass and the range of space.d will be used to calculate an appropriate default. } \item{nperm}{ number of permutations to use. If set to 0, the permutation test will be omitted. } \item{mrank}{ if this is set to FALSE (the default option), Pearson correlations will be used. If set to TRUE, the Spearman correlation (correlation ranked distances) will be used. } \item{alternative}{ default is "two.sided", and returns p-values for H0: rM = 0. The alternative is "one.sided", which returns p-values for H0: rM <= 0. } \item{trace}{ if TRUE, returns progress indicators. } } \details{ This function calculates cross-Mantel correlograms. The Mantel correlogram is essentially a multivariate autocorrelation function. The Mantel r represents the dissimilarity in variable composition (often species composition) at a particular lag distance. Note that the cross-dissimilarity functions are for research purposes, and are not well-tested. } \value{ Returns an object of class mgram, which is a list with two elements. mgram is a matrix with one row for each distance class and 6 columns: \item{lag }{midpoint of the distance class.} \item{ngroup }{number of distances in that class.} \item{mantelr }{Mantel r value.} \item{pval }{p-value for the test chosen.} resids is NA for objects calculated by mgram(). } \references{ Legendre, P. and M. Fortin. 1989. Spatial pattern and ecological analysis. Vegetatio 80:107-138. } \author{ Sarah Goslee } \seealso{\code{\link{xdistance}} \code{\link{xmantel}}, \code{\link{plot.mgram}} } \examples{ # Need to develop a cross-dissimilarity example data(graze) ### EXAMPLE 1: Square matrices # take two subsets of sites with different dominant grass abundances # use cut-offs that produce equal numbers of sites dom1 <- subset(graze, POPR > 50 & DAGL < 20) # 8 sites dom2 <- subset(graze, POPR < 50 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd) xmantel(dom.xd ~ forest.xd + sitelocation.xd) plot(xmgram(dom.xd, sitelocation.xd)) ### EXAMPLE 2: Non-square matrices # take two subsets of sites with different dominant grass abundances # this produces a non-square matrix dom1 <- subset(graze, POPR > 45 & DAGL < 20) # 13 sites dom2 <- subset(graze, POPR < 45 & DAGL > 20) # 8 sites # first two columns are site info dom.xd <- xdistance(dom1[, -c(1,2)], dom2[, -c(1,2)], "bray") # environmental and spatial distances; preserve rownames forest.xd <- xdistance(dom1[, "forestpct", drop=FALSE], dom2[, "forestpct", drop=FALSE]) sitelocation.xd <- xdistance(dom1[, "sitelocation", drop=FALSE], dom2[, "sitelocation", drop=FALSE]) # permutes rows and columns of full nonsymmetric matrix xmantel(dom.xd ~ forest.xd, dims=c(13, 8)) xmantel(dom.xd ~ forest.xd + sitelocation.xd, dims=c(13, 8)) plot(xmgram(dom.xd, sitelocation.xd)) } \keyword{ multivariate } ecodist/man/bump.Rd0000644000176200001440000000106013576512762013724 0ustar liggesusers\name{bump} \alias{bump} \docType{data} \title{Nine-bump spatial pattern} \description{ A two-dimensional artificial "landscape" illustrating the kind of spatial pattern that might be seen across mountain peaks. } \usage{data(bump)} \format{ The format is: int [1:25, 1:25] 2 2 2 2 2 2 2 2 2 2 ... - attr(*, "dimnames")=List of 2 ..$ : chr [1:25] "1" "3" "5" "7" ... ..$ : chr [1:25] "V1" "V3" "V5" "V7" ... } \author{ Sarah Goslee } \seealso{ \code{\link{bump.pmgram}}, \code{\link{pmgram}} } \examples{ data(bump) image(bump) } \keyword{datasets} ecodist/man/fixdmat.Rd0000644000176200001440000000176313576512762014427 0ustar liggesusers\name{fixdmat} \alias{fixdmat} \title{ Distance matrix conversion } \description{ Convert a row-order lower-triangular distance matrix to a full symmetric matrix. } \usage{ fixdmat(v) } \arguments{ \item{v}{ lower-triangular distance matrix in row order. } } \details{ R distance functions such as dist and bcdist return a lower triangular distance matrix in column order. Some other programs return the lower triangular matrix in row order. To use this matrix in R functions, it must be converted from row order to column order. } \value{ full symmetric distance matrix. } \author{ Sarah Goslee } \seealso{ \code{\link{lower}}, \code{\link{full}} } \examples{ x.vec <- seq_len(6) x.vec # Make an R-style column order symmetric matrix full(x.vec) # Extract the lower triangle from a symmetric matrix # in column order lower(full(x.vec)) # Convert to or from a row order symmetric matrix fixdmat(x.vec) lower(fixdmat(x.vec)) fixdmat(c(1, 2, 4, 3, 5, 6)) } \keyword{ manip } \keyword{ multivariate } ecodist/man/lower.Rd0000644000176200001440000000215313576512762014115 0ustar liggesusers\name{lower} \alias{lower} \title{ Lower-triangular matrix } \description{ Convert a symmetric distance matrix to a column order lower triangular matrix. } \usage{ lower(m) } \arguments{ \item{m}{ a symmetric distance matrix. } } \details{ Converts a symmetric matrix, for example a dissimilarity matrix, into a column order lower-triangular matrix. This may be useful to format the input for certain clustering and ordination functions. Note that \code{lower()} used on a 1x1 matrix will return the single element, which may not be the correct behavior in all cases, while \code{full()} used on a single element will return a 2x2 matrix. } \value{ column order lower triangular matrix. } \author{ Sarah Goslee } \seealso{ \code{\link{full}}, \code{\link{fixdmat}} } \examples{ x.vec <- seq_len(6) x.vec # Make an R-style column order symmetric matrix full(x.vec) # Extract the lower triangle from a symmetric matrix # in column order lower(full(x.vec)) # Convert to or from a row order symmetric matrix fixdmat(x.vec) lower(fixdmat(x.vec)) fixdmat(c(1, 2, 4, 3, 5, 6)) } \keyword{ manip } \keyword{ multivariate } ecodist/man/iris.vfrot.Rd0000644000176200001440000000351613576512762015076 0ustar liggesusers\name{iris.vfrot} \alias{iris.vfrot} \docType{data} \title{Example for vector fitting on rotated ordination} \description{ An object of class vf for use in the examples for \code{\link{nmds}} and \code{\link{vf}}. Many of the functions in \code{ecodist} take a long time to run, so prepared examples have been included. } \usage{data(iris.vfrot)} \format{ See \code{\link{vf}} for current format specification. } \author{ Sarah Goslee } \seealso{ \code{\link{nmds}}, \code{\link{vf}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) # rotate the configuration to maximize variance iris.rot <- princomp(iris.nmin)$scores # rotation preserves distance apart in ordination space cor(dist(iris.nmin), dist(iris.rot)) # fit the data to the ordination as vectors ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vf <- vf(iris.nmin, iris[,1:4], nperm=1000) ### save(iris.vf, file="ecodist/data/iris.vf.rda") data(iris.vf) # repeat for the rotated ordination ### vf() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.vfrot <- vf(iris.rot, iris[,1:4], nperm=1000) ### save(iris.vfrot, file="ecodist/data/iris.vfrot.rda") data(iris.vfrot) par(mfrow=c(1,2)) plot(iris.nmin, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="NMDS") plot(iris.vf) plot(iris.rot, col=as.numeric(iris$Species), pch=as.numeric(iris$Species), main="Rotated NMDS") plot(iris.vfrot) } \keyword{datasets} ecodist/man/plot.mgram.Rd0000644000176200001440000000304413576512762015045 0ustar liggesusers\name{plot.mgram} \alias{plot.mgram} \title{ Plot a Mantel correlogram } \description{ Plot a Mantel correlogram from an object of S3 class \code{mgram}, using solid symbols for significant values. } \usage{ \method{plot}{mgram}(x, pval = 0.05, xlab = "Distance", ylab = "Mantel r", \dots) } \arguments{ \item{x}{ an object of class \code{mgram} } \item{pval}{ cut-off level for statistical significance. } \item{xlab}{ x-axis label. } \item{ylab}{ y-axis label. } \item{\dots}{ optional, any additional graphics parameters. } } \value{ draws a plot (graphics device must be active). } \author{ Sarah Goslee } \seealso{ \code{\link{mgram}} } \examples{ # generate a simple surface x <- matrix(1:10, nrow=10, ncol=10, byrow=FALSE) y <- matrix(1:10, nrow=10, ncol=10, byrow=TRUE) z <- x + 3*y image(z) # analyze the pattern of z across space space <- cbind(as.vector(x), as.vector(y)) z <- as.vector(z) space.d <- distance(space, "eucl") z.d <- distance(z, "eucl") z.mgram <- mgram(z.d, space.d, nperm=0) plot(z.mgram) # data(graze) space.d <- dist(graze$sitelocation) forest.d <- dist(graze$forestpct) grasses <- graze[, colnames(graze) \%in\% c("DAGL", "LOAR10", "LOPE", "POPR")] legumes <- graze[, colnames(graze) \%in\% c("LOCO6", "TRPR2", "TRRE3")] grasses.bc <- bcdist(grasses) legumes.bc <- bcdist(legumes) # Does the relationship of composition with distance vary for # grasses and legumes? par(mfrow=c(2, 1)) plot(mgram(grasses.bc, space.d, nclass=8)) plot(mgram(legumes.bc, space.d, nclass=8)) } \keyword{ multivariate } \keyword{ hplot } ecodist/man/min.nmds.Rd0000644000176200001440000000250513576512762014511 0ustar liggesusers\name{min.nmds} \alias{min.nmds} \alias{nmds.min} \title{ Find minimum stress configuration } \description{ Finds minimum stress configuration from output of nmds() } \usage{ \method{min}{nmds}(\dots, na.rm = FALSE, dims = 2) nmds.min(x, dims = 2) } \arguments{ \item{\dots}{ output from nmds() } \item{x}{ output from nmds() } \item{dims}{ desired dimensionality of result. If dims = 0 then the overall minimum stress configuration is chosen. By default, the best two-dimensional configuration is returned. } \item{na.rm}{Not used; there should be no NA values in a NMDS configuration.} } \value{ Configuration of minimum stress ordination (dataframe of coordinates). The stress and r^2 for the minimum stress configuration are stored as attributes. } \details{ For back-compatibility, the \code{nmds.min} function remains. } \author{ Sarah Goslee } \seealso{ \code{\link{nmds}} } \examples{ data(iris) iris.d <- dist(iris[,1:4]) ### nmds() is timeconsuming, so this was generated ### in advance and saved. ### set.seed(1234) ### iris.nmds <- nmds(iris.d, nits=20, mindim=1, maxdim=4) ### save(iris.nmds, file="ecodist/data/iris.nmds.rda") data(iris.nmds) # examine fit by number of dimensions plot(iris.nmds) # choose the best two-dimensional solution to work with iris.nmin <- min(iris.nmds, dims=2) } \keyword{ multivariate } ecodist/man/distance.Rd0000644000176200001440000000513313576512762014560 0ustar liggesusers\name{distance} \alias{distance} \title{ Calculate dissimilarity/distance metrics } \description{ This function calculates a variety of dissimilarity or distance metrics. Although it duplicates the functionality of dist() and bcdist(), it is written in such a way that new metrics can easily be added. distance() was written for extensibility and understandability, and is not necessarily an efficient choice for use with large matrices. } \usage{ distance(x, method = "euclidean", sprange=NULL, spweight=NULL, icov) } \arguments{ \item{x}{ matrix or data frame with rows as samples and columns as variables (such as species). Distances will be calculated for each pair of rows. } \item{method}{ Currently 7 dissimilarity metrics can be calculated: "euclidean", "bray-curtis", "manhattan", "mahalanobis" (squared Mahalanobis distance), "jaccard", "difference", "sorensen", "gower", "modgower10" (modified Gower, base 10), "modgower2" (modified Gower, base 2). Partial matching will work for selecting a method.} \item{sprange}{Gower dissimilarities offer the option of dividing by the species range. If sprange=NULL no range is used. If sprange is a vector of length nrow(x) it is used for standardizing the dissimilarities.} \item{spweight}{Euclidean, Manhattan, and Gower dissimilarities allow weighting. If spweight=NULL, no weighting is used. If spweight="absence", then W=0 if both species are absent and 1 otherwise, thus deleting joint absences.} \item{icov}{Optional covariance matrix; only used if method="mahalanobis" since Mahalanobis distance requires calculating the variance-covariance matrix for the entire dataset. Providing icov directly makes it possible to calculate distances for a subset of the full dataset.} } \value{ Returns a lower-triangular distance matrix as an object of class "dist". } \author{ Sarah Goslee } \seealso{ \code{\link{dist}}, \code{\link{bcdist}} } \examples{ data(iris) iris.bc <- distance(iris[, 1:4], "bray-curtis") # The effect of specifying icov: # calculate Mahalanobis distance for the full iris dataset iris.md <- full(distance(iris[, 1:4], "mahal")) iris.md[1, 2] # Mahalanobis distance between samples 1 and 2 # calculate Mahalanobis for just one species setosa.md <- full(distance(iris[iris$Species == "setosa", 1:4], "mahal")) setosa.md[1, 2] # Mahalanobis distance between samples 1 and 2 # use the covariance matrix for the full dataset to scale for one species setosa.scaled.md <- full(distance(iris[iris$Species == "setosa", 1:4], "mahal", icov=var(iris[,1:4]))) setosa.scaled.md[1, 2] # Mahalanobis distance between samples 1 and 2 } \keyword{ multivariate } ecodist/man/cor2m.Rd0000644000176200001440000000354613576512762014016 0ustar liggesusers\name{cor2m} \alias{cor2m} \title{ Two-matrix correlation table } \description{ Generate a correlation table between the variables of two data sets, originally for comparing species abundances and environmental variables. } \usage{ cor2m(x, y, trim = TRUE, alpha = 0.05) } \arguments{ \item{x}{ A matrix or data frame of environmental (or other) variables matching the sites of x } \item{y}{ A matrix or data frame of species (or other) variables } \item{trim}{ If trim is TRUE, set rho } \keyword{ package } ecodist/DESCRIPTION0000644000176200001440000000142213576700021013412 0ustar liggesusersPackage: ecodist Version: 2.0.3 Date: 2019-12-18 Title: Dissimilarity-Based Functions for Ecological Analysis Authors@R: c(person("Sarah", "Goslee", role = c("aut", "cre"), email = "Sarah.Goslee@usda.gov"), person("Dean", "Urban", role = "aut")) Author: Sarah Goslee [aut, cre], Dean Urban [aut] Maintainer: Sarah Goslee Depends: R (>= 3.0.0) LazyData: true Imports: stats, graphics Suggests: knitr, testthat VignetteBuilder: knitr Description: Dissimilarity-based analysis functions including ordination and Mantel test functions, intended for use with spatial and community data. License: GPL (>= 2) NeedsCompilation: yes Packaged: 2019-12-18 23:19:54 UTC; sarahg Repository: CRAN Date/Publication: 2019-12-19 13:50:09 UTC ecodist/build/0000755000176200001440000000000013576532032013011 5ustar liggesusersecodist/build/vignette.rds0000644000176200001440000000032213576532032015345 0ustar liggesusersmOA0l)>!Š 6!|U0Rmv!!3~5>bϻQ#g 4C WP5m:zXZwH=襢51jhzU,׾ecodist/build/partial.rdb0000644000176200001440000000710013576532032015134 0ustar liggesusers\[_lĉb€w옍 wvf! NԳӶnxm(B^y;ySR/Jt4Kk=1VV{Όӭ˭J2\ {XTFj>ʔTuƽ9hwTFckml.~+iIj.m#I5!j0I+狔Ȋ{c܅$+l%%71r8 X?㏿J i6)|[Y|mZ0"&MXLZ{ܾV}fҋ~¹*Ƥj|MO54x&B#'K)r~qLfy;s rŷ4Whao0ʢExGȟ/{3dH$ '0-ۣBfŭO|DR=@A(>T BW!+xltq.ϩżq@$٦[QE'S?, Ure hqBta z_u*m^ُh1=Ge^#Lt-js07uId-*Bҥu"W!+?F-S=hF6o%TYws! lVƲQ 译AN( rcF.f{>0D{?P8H?@A1w:@vL*2Qu)ą |!Q=E1=A =F)+SC@'V# ʤF/r0`'үj0`үэ?A 1vϚݫ64t&"t/6;CO) 1yģw Z"=C=/7] ֢LT#08kXM\591)է@l~ηޅ61C|S4b)u6)a^ޥճh)Py>@z&+9Jm!@s }0uE CD8D]5|U]Q/i1oKzm~;mfLԉgN<󠳋SoVj7$֥K(C.DS&JJ|VE נG ~,f±^L`ДnCjRQli|zcW\~\Z[UdUk&rRVH`XUVa/ۮ5 n),O7#QZ9 xZCjmnF\]d쒝%!*#ufѹ`g/G]Dz;K'׷9rǶR#+%F-¬!REeXOE ipJx^9]l $14|Pmɛ;+Nv9L,; (g\n$.&un) 0d36_Wİs/Egy0Jt<֕MA׽R[!2g%\ق("* 0c$]uu7ݤ'JPhk{ݘ!ġ<( '2{ٜaoQW5}NEbm-UYx-0ufrh\v4km*U;{6聁XI2߂,YV01HM{ޗC2sݶ"Vtz|rQǖfrsG ,9._=7/7 )m_}%[@DX}/X{+z`j#x0.\ RQLZIyBd(QY r#}bTGEziZfR,sb`AiN-J-۲/,4tؙ휎зt~޼%X㓡0F{gJ#5[kWs0 ϫY>nVN= wYo֞}EL]1{Njh91*h[},SHk%M5TVou[G=U:rGs'ֹU‚5$v16~{|:߰7_V.sȟ+sN.h,z8u'ENlu_\j=}!3ҝ-1io/j?Ȗi3C+@$DllH !WpoU֌4.uʃ_D㦶GT͍HDFU#9?FwoƄRB[^^6x'uO}/k[BfB VhL񴇣't[/wT&3u)|вz w*5fA-qZf4ܯsyItHGUaeHLR1*8)XOZ-Tn٢.>umy0#:uI 9,m\$L$tֈIMycycJN,`V߳{nxNٗqd4ڧL9_'D?bIJ';z=NtӔc|א4ӳ=t󏫆n{qdq7|x..5N4.ƪ=ڋ.yw6)/N [1GMv/%$kX:wnBxxު$UJ!ٖ#@blf9s;%&pHsd`eNGdIaR͢7kn6RT@6񇉈j){=^:'kr< uwHNڳI#u)XO=榧Ĕ5HPYOE=E>ҹskPǣs4cσdIq{g5Q;ȴU PxNG,+ᨩc9dٖ^f1񃖻&VDdgq? hF{eocic/(OfflO@0x-~Erp*݀R[MjZӫlwέ7N{ >ozIکg`/o]Db rkdފd>Yfn~ sݰ소Ƴh qJL @Q\DYP6o#va]-ծ\zz1衸Ss$0aop+ݻ \>ʷZ TE^-$+:;(^DWJאwEn_a,cnTSh9PyL zKV5k=|q#`:ʿ+'o 0] <- 1 expect_equal(as.vector(mantel(x.d ~ groups.d, nperm=0, nboot=0))[1], mgroup(x.d, groups.char, nperm=0)[1, 2]) expect_equal(as.vector(mantel(x.d ~ groups.d, nperm=0, nboot=0))[1], mgroup(x.d, groups.factor, nperm=0)[1, 2]) expect_equal(as.vector(mantel(x.d ~ groups.d, nperm=0, nboot=0))[1], mgroup(x.d, groups.numeric, nperm=0)[1, 2]) }) ecodist/tests/testthat/test-MRM.R0000644000176200001440000000043213576512762016456 0ustar liggesuserscontext("MRM") test_that("MRM coefficients match lm", { set.seed(888) y <- runif(11175) x1 <- runif(11175) x2 <- runif(11175) expect_equal(as.vector(MRM(y ~ x1 + x2, nperm=0)$coef[,1]), as.vector(coefficients(lm(y ~ x1 + x2)))) }) ecodist/tests/testthat/test-distance.R0000644000176200001440000000146413576512762017623 0ustar liggesuserscontext("distance") test_that("Euclidean distance is correct", { set.seed(888) x <- matrix(runif(50), ncol=5) d.ecodist <- distance(x, "euclidean") d.base <- dist(x) expect_equal(attributes(d.ecodist), attributes(d.base)[names(attributes(d.base)) != "call"]) expect_equal(as.vector(d.ecodist), as.vector(d.base)) }) test_that("Bray-Curtis distance is correct", { set.seed(888) x <- matrix(runif(50), ncol=5) expect_equal(distance(x, "bray"), bcdist(x)) }) test_that("Mahalanobis icov is correct", { set.seed(888) x <- matrix(runif(50), ncol=5) x.md <- full(distance(x, "mahal")) sub.md <- full(distance(x[1:5, ], "mahal", icov=cov(x))) expect_equal(x.md[1:5, 1:5], sub.md) }) ecodist/tests/testthat.R0000644000176200001440000000005013576512762015042 0ustar liggesuserslibrary(testthat) test_check("ecodist") ecodist/src/0000755000176200001440000000000013576532032012501 5ustar liggesusersecodist/src/ecodist.c0000644000176200001440000004524313576512762014317 0ustar liggesusers#include #include #include /* for dgemm */ #define RANDIN GetRNGstate() #define RANDOUT PutRNGstate() #define UNIF unif_rand() void bootstrap(double *x, double *y, int *n, int *xlen, int *nboot, double *pboot, double *bootcor, int *rarray, int *rmat, double *xdif, double *ydif) { int i, j, k, l; double r; double nsamp; double xmean, ymean; double xsum; double xxsum, yysum; /* Set random seed using Splus function */ RANDIN; for(i = 0; i < *nboot; i++) { /* Set up rarray. */ for(j = 0; j < *n; j++) { r = UNIF; if(r > *pboot) rarray[j] = 0; else rarray[j] = 1; } /* Turn rarray into a lower-triangular sampling matrix. */ /* 1 means include, 0 means omit. */ l = 0; for(j = 1; j < *n; j++) { for(k = 0; k < j; k++) { if(rarray[j] == 0 || rarray[k] == 0) rmat[l] = 0; else rmat[l] = 1; l++; } } nsamp = 0; for(j = 0; j < *xlen; j++) { nsamp += rmat[j]; } /* Calculate means for x and y. */ xmean = 0; ymean = 0; for(j = 0; j < *xlen; j++) { if(rmat[j] == 1) { xmean += x[j]; ymean += y[j]; } } xmean = xmean/nsamp; ymean = ymean/nsamp; /* Calculate deviations for x and y. */ for(j = 0; j < *xlen; j++) { if(rmat[j] == 1) { xdif[j] = x[j] - xmean; ydif[j] = y[j] - ymean; } else { xdif[j] = 0; ydif[j] = 0; } } xsum = 0; xxsum = 0; yysum = 0; for(j = 0; j < *xlen; j++) { if(rmat[j] == 1) { xsum += (xdif[j] * ydif[j]); xxsum += (xdif[j] * xdif[j]); yysum += (ydif[j] * ydif[j]); } } bootcor[i] = (xsum) / sqrt(xxsum * yysum); } /* Reset random seed using an Splus function. */ RANDOUT; } void permute(double *x, double *y, int *n, int *xlen, int *nperm, double *zstats, double *tmat, int *rarray) { int i, k, l, m; double cumsum; int temp; /* Set random seed using Splus function */ RANDIN; /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += x[k] * y[k]; } zstats[0] = cumsum / *xlen; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { /* Set up rarray. */ for(k = 0; k < *n; k++) { rarray[k] = k; } /* Convert x to a full matrix. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { tmat[k * *n + l] = x[m]; tmat[l * *n + k] = x[m]; m++; } } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*n - 1); k++) { l = *n - k - 1; m = (int)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Reorder x and take lower triangle. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { x[m] = tmat[rarray[k] * *n + rarray[l]]; m++; } } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += x[k] * y[k]; } zstats[i] = cumsum / *xlen; } /* Reset random seed using an Splus function. */ RANDOUT; } void permpart(double *hmat, double *bmat, double *omat, double *y, double *xcor, double *ycor, int *n, int *ncol, int *xlen, int *nperm, double *zstats, double *tmat, int *rarray) { int i, k, l, m; double cumsum; double bsum; double w1, w2; int temp; /* Set random seed using Splus function */ RANDIN; /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += xcor[k] * ycor[k]; } zstats[0] = cumsum / *xlen; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { /* Set up rarray. */ for(k = 0; k < *n; k++) { rarray[k] = k; } /* Convert y to a full matrix. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { tmat[k * *n + l] = y[m]; tmat[l * *n + k] = y[m]; m++; } } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*n - 1); k++) { l = *n - k - 1; m = (int)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Reorder y and take lower triangle. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { y[m] = tmat[rarray[k] * *n + rarray[l]]; m++; } } /* Calculate residuals for y */ /* Calculate bmat */ for(k = 0; k < *ncol; k++) { bmat[k] = 0; } for(k = 0; k < *ncol; k++) { for(l = 0; l < *xlen; l++) { bmat[k] = bmat[k] + hmat[l * *ncol + k] * y[l]; } } /* Calculate ycor (residuals) */ for(k = 0; k < *xlen; k++) { ycor[k] = 0; } for(k = 0; k < *xlen; k++) { bsum = 0; for(l = 0; l < *ncol; l++) { bsum = bsum + bmat[l] * omat[l * *xlen + k]; } ycor[k] = y[k] - bsum; } /* Standardize residuals so z = r */ w1 = 0; w2 = 0; for(k = 0; k < *xlen; k++) { w1 = w1 + ycor[k]; w2 = w2 + ycor[k] * ycor[k]; } w1 = w1 / *xlen; w2 = sqrt(w2 / *xlen - w1 * w1); for(k = 0; k < *xlen; k++) { ycor[k] = (ycor[k] - w1) / w2; } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += xcor[k] * ycor[k]; } zstats[i] = cumsum / *xlen; } /* Reset random seed using an Splus function. */ RANDOUT; } void bcdistc(double *x, int *pnrow, int *pncol, double *dist) { int i, j, k, l; int nrow, ncol; double sumi, sumj; double minsum; l = 0; nrow = *pnrow; ncol = *pncol; for(i = 0; i < (nrow - 1); i++) { for(j = (i + 1); j < (nrow); j++) { minsum = 0; sumi = 0; sumj = 0; for(k = 0; k < ncol; k++) { if(x[i * ncol + k] < x[j * ncol + k]) minsum += x[i * ncol + k]; else minsum += x[j * ncol + k]; sumi += x[i * ncol + k]; sumj += x[j * ncol + k]; } if((sumi + sumj) == 0) dist[l] = 0; else dist[l] = (1 - (2 * minsum) / (sumi + sumj)); l++; } } } void newpermone(double *x, int *dclass, int *n, int *xlen, int *nperm, double *zstats, double *tmat, int *rarray) { int i, k, l, m; double cumsum; int temp; /* Set random seed using Splus function */ RANDIN; /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { if(dclass[k] == 0) { cumsum += x[k]; } } zstats[0] = cumsum; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { /* Set up rarray. */ for(k = 0; k < *n; k++) { rarray[k] = k; } /* Convert x to a full matrix. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { tmat[k * *n + l] = x[m]; tmat[l * *n + k] = x[m]; m++; } } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*n - 1); k++) { l = *n - k - 1; m = (int)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Reorder x. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { x[m] = tmat[rarray[k] * *n + rarray[l]]; m++; } } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { if(dclass[k] == 0) { cumsum += x[k]; } } zstats[i] = cumsum; } /* Reset random seed using an Splus function. */ RANDOUT; } void newpermtwo(double *x, double *y, int *n, int *xlen, int *nperm, double *zstats, double *tmat, int *rarray) { int i, k, l, m; double cumsum; int temp; float naval = -9999; /* Set random seed using Splus function */ RANDIN; /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { if(x[k] != naval) { cumsum += x[k] * y[k]; } } zstats[0] = cumsum; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { /* Set up rarray. */ for(k = 0; k < *n; k++) { rarray[k] = k; } /* Convert x to a full matrix. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { tmat[k * *n + l] = x[m]; tmat[l * *n + k] = x[m]; m++; } } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*n - 1); k++) { l = *n - k - 1; m = (int)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Reorder x. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { x[m] = tmat[rarray[k] * *n + rarray[l]]; m++; } } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { if(x[k] != naval) { cumsum += x[k] * y[k]; } } zstats[i] = cumsum; } /* Reset random seed using an Splus function. */ RANDOUT; } void psum(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; dist[l] = thisval + thatval; l++; } } } } void pdiff(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; dist[l] = thisval - thatval; l++; } } } } void jpres(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; if((thisval > 0) & (thatval > 0)) { dist[l] = 1; } else { dist[l] = 0; } l++; } } } } void jabs(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; if((thisval == 0) & (thatval == 0)) { dist[l] = 1; } else { dist[l] = 0; } l++; } } } } void jfirst(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; if((thisval > 0) & (thatval == 0)) { dist[l] = 1; } else { dist[l] = 0; } l++; } } } } void jsec(double *x, int *pnrow, int *pncol, double *dist) { int row1, row2, col1; int nrow, ncol; int l; double thisval, thatval; l = 0; nrow = *pnrow; ncol = *pncol; for(col1 = 0; col1 < ncol; col1++) { for(row1 = 0; row1 < nrow; row1++) { thatval = x[row1 * ncol + col1]; for(row2 = 0; row2 < nrow; row2++) { thisval = x[row2 * ncol + col1]; if((thisval == 0) & (thatval > 0)) { dist[l] = 1; } else { dist[l] = 0; } l++; } } } } void mrmperm(double *x, double *y, int *p, int *nd, int *n, int *nperm, double *r2all, double *ball, double *fall, double *tmat, int *rarray, double *XX, double *XY, double *YY, double *b) { int i, k, l; int m; int temp; double SSE=0.0, SSTO=0.0, SSR=0.0; double r2=0, f=0; double btemp=0.0; int bcount = 0; char *transt = "T", *transn = "N"; double one = 1.0, zero = 0.0; int onei = 1; /* Set random seed using Splus function */ RANDIN; /* Start permutation routine */ for(i = 0; i < *nperm; i++) { /* first do the unpermuted values */ /* F77_CALL(dgemm)(transa, transb, &ncx, &ncy, &nrx, &one, x, &nrx, y, &nry, &zero, z, &ncx); */ /* take crossproduct t(X) %*% Y - WORKS */ F77_CALL(dgemm)(transt, transn, p, &onei, nd, &one, x, nd, y, nd, &zero, XY, p); /* take crossproduct t(Y) %*% (Y) - WORKS */ F77_CALL(dgemm)(transt, transn, &onei, &onei, nd, &one, y, nd, y, nd, &zero, YY, &onei); /* calculate regression coefficients XX %*% XY - WORKS */ F77_CALL(dgemm)(transn, transn, p, &onei, p, &one, XX, p, XY, p, &zero, b, p); /* calculate regression components - WORKS */ F77_CALL(dgemm)(transt, transn, &onei, &onei, p, &one, b, p, XY, p, &zero, &btemp, &onei); /* SSE - WORKS */ SSE = YY[0] - btemp; /* SSTO - WORKS */ SSTO = 0; for(k = 0; k < *nd; k++) { SSTO = SSTO + y[k]; } SSTO = YY[0] - (SSTO * SSTO) / *nd; SSR = SSTO - SSE; /* calculate R2 - WORKS */ r2 = 1 - SSE / SSTO; /* calculate F* - WORKS */ f = (SSR / (*p - 1)) / (SSE / (*nd - *p)); r2all[i] = r2; fall[i] = f; /* calculate pseudo-t for regression coefficients - WORKS*/ /* b / sqrt(1 - R2) */ for(k=0; k<*p; k++) { ball[bcount] = b[k] / sqrt(1 - r2); bcount++; } /* permute Y */ /* Set up rarray. */ for(k = 0; k < *n; k++) { rarray[k] = k; } /* Convert y to a full matrix. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { tmat[k * *n + l] = y[m]; tmat[l * *n + k] = y[m]; m++; } } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*n - 1); k++) { l = *n - k - 1; m = (int)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Reorder y. */ m = 0; for(k = 1; k < *n; k++) { for(l = 0; l < k; l++) { y[m] = tmat[rarray[k] * *n + rarray[l]]; m++; } } } /* Reset random seed using an Splus function. */ RANDOUT; } void xpermute(double *x, double *y, int *nrow, int *ncol, int *xlen, int *nperm, double *zstats, double *newx, int *rarray, int *carray) { int i, k, l, m; double cumsum; int temp; int newk, newl; /* Set random seed using Splus function */ RANDIN; /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += x[k] * y[k]; } zstats[0] = cumsum; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { cumsum = 0; /* Set up rarray. */ for(k = 0; k < *nrow; k++) { rarray[k] = k; } /* Set up carray. */ for(k = 0; k < *ncol; k++) { carray[k] = k; } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*nrow - 1); k++) { l = *nrow - k - 1; m = (long)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Randomize carray using an Splus function. */ for(k = 0; k < (*ncol - 1); k++) { l = *ncol - k - 1; m = (long)((float)l * UNIF); if(m > l) m = l; temp = carray[l]; carray[l] = carray[m]; carray[m] = temp; } /* Reorder x. */ /* loop thru the rows * swapping each value with its replacement */ for(k = 0; k < *nrow; k++) { } for(l = 0; l < *nrow; l++) { newl = rarray[l]; if(newl != l) { for(k = 0; k < *ncol; k++) { newx[k*(*nrow) + l] = x[k*(*nrow) + newl]; } } } /* now x has the original info and newx has swapped rows */ /* go thru x and set x identical to newx before swapping columns */ for(k = 0; k < *ncol; k++) { for(l = 0; l < *nrow; l++) { x[k*(*nrow) + l] = newx[k*(*nrow) + l]; } } /* loop thru the columns * swapping each value with its replacement */ for(k = 0; k < *ncol; k++) { } for(k = 0; k < *ncol; k++) { newk = carray[k]; if(newk != k) { for(l = 0; l < *nrow; l++) { newx[k*(*nrow) + l] = x[newk*(*nrow) + l]; } } } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += x[k] * y[k]; } zstats[i] = cumsum; } /* Reset random seed using an Splus function. */ RANDOUT; } void xpermpart(double *hmat, double *y, double *xcor, double *ycor, int *nrow, int *ncol, int *xlen, int *nperm, double *zstats, double *newy, int *rarray, int *carray) { int i, k, l, m; double cumsum; int temp; int newk, newl; /* Set random seed using Splus function */ RANDIN; /* Calculate residuals for y */ for(k = 0; k < *xlen; k++) { ycor[k] = 0; } for(k = 0; k < *xlen; k++) { for(l = 0; l < *xlen; l++) { ycor[k] = ycor[k] + hmat[k * *xlen + l] * y[l]; } } /* Calculate first z-statistic (unpermuted data). */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += xcor[k] * ycor[k]; } zstats[0] = cumsum; /* Start permutation routine */ for(i = 1; i < *nperm; i++) { /* Set up rarray. */ for(k = 0; k < *nrow; k++) { rarray[k] = k; } /* Set up carray. */ for(k = 0; k < *ncol; k++) { carray[k] = k; } /* Randomize rarray using an Splus function. */ for(k = 0; k < (*nrow - 1); k++) { l = *nrow - k - 1; m = (long)((float)l * UNIF); if(m > l) m = l; temp = rarray[l]; rarray[l] = rarray[m]; rarray[m] = temp; } /* Randomize carray using an Splus function. */ for(k = 0; k < (*ncol - 1); k++) { l = *ncol - k - 1; m = (long)((float)l * UNIF); if(m > l) m = l; temp = carray[l]; carray[l] = carray[m]; carray[m] = temp; } /* Reorder y. */ /* loop thru the rows * swapping each value with its replacement */ for(k = 0; k < *nrow; k++) { } for(l = 0; l < *nrow; l++) { newl = rarray[l]; if(newl != l) { for(k = 0; k < *ncol; k++) { newy[k*(*nrow) + l] = y[k*(*nrow) + newl]; } } } /* now y has the original info and newy has swapped rows */ /* go thru y and set y identical to newy before swapping columns */ for(k = 0; k < *ncol; k++) { for(l = 0; l < *nrow; l++) { y[k*(*nrow) + l] = newy[k*(*nrow) + l]; } } /* loop thru the columns * swapping each value with its replacement */ for(k = 0; k < *ncol; k++) { } for(k = 0; k < *ncol; k++) { newk = carray[k]; if(newk != k) { for(l = 0; l < *nrow; l++) { newy[k*(*nrow) + l] = y[newk*(*nrow) + l]; } } } /* Calculate residuals for y */ for(k = 0; k < *xlen; k++) { ycor[k] = 0; } for(k = 0; k < *xlen; k++) { for(l = 0; l < *xlen; l++) { ycor[k] = ycor[k] + hmat[k * *xlen + l] * y[l]; } } /* Calculate new sum of products. */ cumsum = 0; for(k = 0; k < *xlen; k++) { cumsum += xcor[k] * ycor[k]; } zstats[i] = cumsum; } /* Reset random seed using an Splus function. */ RANDOUT; } ecodist/src/init.c0000644000176200001440000000422413576512762013622 0ustar liggesusers#include // for NULL #include /* .C calls */ extern void bcdistc(void *, void *, void *, void *); extern void bootstrap(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); extern void jabs(void *, void *, void *, void *); extern void jfirst(void *, void *, void *, void *); extern void jpres(void *, void *, void *, void *); extern void jsec(void *, void *, void *, void *); extern void mrmperm(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); extern void newpermone(void *, void *, void *, void *, void *, void *, void *, void *); extern void newpermtwo(void *, void *, void *, void *, void *, void *, void *, void *); extern void pdiff(void *, void *, void *, void *); extern void permpart(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); extern void permute(void *, void *, void *, void *, void *, void *, void *, void *); extern void psum(void *, void *, void *, void *); extern void xpermute(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); extern void xpermpart(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *); static const R_CMethodDef CEntries[] = { {"bcdistc", (DL_FUNC) &bcdistc, 4}, {"bootstrap", (DL_FUNC) &bootstrap, 11}, {"jabs", (DL_FUNC) &jabs, 4}, {"jfirst", (DL_FUNC) &jfirst, 4}, {"jpres", (DL_FUNC) &jpres, 4}, {"jsec", (DL_FUNC) &jsec, 4}, {"mrmperm", (DL_FUNC) &mrmperm, 15}, {"newpermone", (DL_FUNC) &newpermone, 8}, {"newpermtwo", (DL_FUNC) &newpermtwo, 8}, {"pdiff", (DL_FUNC) &pdiff, 4}, {"permpart", (DL_FUNC) &permpart, 13}, {"permute", (DL_FUNC) &permute, 8}, {"psum", (DL_FUNC) &psum, 4}, {"xpermute", (DL_FUNC) &xpermute, 10}, {"xpermpart", (DL_FUNC) &xpermpart, 12}, {NULL, NULL, 0} }; void R_init_ecodist(DllInfo *dll) { R_registerRoutines(dll, CEntries, NULL, NULL, NULL); R_useDynamicSymbols(dll, FALSE); } ecodist/src/Makevars0000644000176200001440000000004013576512762014177 0ustar liggesusersPKG_LIBS=$(BLAS_LIBS) $(FLIBS) ecodist/vignettes/0000755000176200001440000000000013576532032013722 5ustar liggesusersecodist/vignettes/dissimilarity.Rmd0000644000176200001440000000621613576512762017271 0ustar liggesusers--- title: "Dissimilarity Cheat Sheet" author: "Sarah Goslee" date: "2017-07-12" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Dissimilarity Cheat Sheet} %\VignetteEngine{knitr::rmarkdown} --- **Things to do with dissimilarity matrices** _(ecodist functions are marked in **bold**)_ _(untested ideas marked with ?)_ Description | Notation | Name | R function ------------|----------|------|----------- Relationship between two matrices | D1 ~ D2 | Mantel test | **mantel**(D1 ~ D2) Relationship between two matrices given more | D1 ~ D2 | D3 ... Dn | Partial Mantel test | **mantel**(D1 ~ D2 + D3 + ...) ||| Spatial structure in one matrix | D1 x S | Mantel correlogram | **mgram**(D1, S) Spatial structure in one matrix given more | D1 | D2 ... Dn x S | Partial Mantel correlogram | **?mgram**(residuals(lm(D1 ~ D2 + ...)), space) Spatial structuce in one matrix | D1 x S | Multivariate correlogram | **pmgram**(D1, S) Spatial structure in one matrix given more | D1 | D2 ... Dn x S | Partial multivariate correlogram | **pmgram**(D1, S, D2) ||| Spatial structure in the relationship between two matrices | D1 ~ D2 x S | Mantel cross-correlogram | **pmgram**(cbind(lower(D1), lower(D2)), S) Spatial structure in the relationship between two matrices given more | D1 ~ D2 | D3 ... Dn x S | Partial Mantel cross-correlogram | **pmgram**(cbind(lower(D1), lower(D2)), S, D3) ||| Ordination of one matrix | | (N)MDS | **nmds**(y) or **pco**(y) Ordination of one matrix given more | | (Partial (N)MDS | **?nmds**(residuals(lm(y ~ z1 + ...))) ||| Grouping of items based on one matrix | | Cluster analysis | hclust(y) Grouping of items based on one matrix given more | | Partial cluster analysis | ?hclust(residuals(lm(y ~ z1 + ...))) Grouping of items given space | | Spatially-constrained cluster analysis | NA ||| Multiple regression | D1 ~ D2 | D3 ... Dn | Multiple regression on distance matrices | **MRM**(D1 ~ D2 + D3 + ...) **Ways to calculate dissimilarity matrices** Description | Result | R function ------------|--------|----------- From a site by sample matrix | Symmetric matrix with zero diagonals | dist(x) or **bcdist**(x) or **distance**(x) ----------------------------- **Things to do with cross-dissimilarity matrices** Description | Notation | Name | R function ------------|----------|------|----------- Relationship between two cross-dissimilarity matrices | D12 ~ D34 | Cross-Mantel test | **xmantel**(D12 ~ D34) Relationship between two cross-dissimilarity matrices given more | D12 ~ D34 | D56 ... Dn | Partial cross-Mantel test | **xmantel**(D12 ~ D34 + D56 + ...) ||| Spatial structure in one cross-dissimilarity matrix | D12 x S | Cross-Mantel correlogram | **xmgram**(D12, spaceX) Spatial structure in one cross-dissimilarity matrix given more | D12 | D34 ... Dn x S | Partial cross-Mantel correlogram | **?xmgram**(residuals(lm(D12 ~ D34 + ...)), spaceX) **Ways to calculate cross-dissimilarity matrices** Source | Result | R function -------|--------|----------- From 2 site by sample matrixes for the same sites and samples (e.g. different years) | nonsymmetric matrix with nonzero diagonals | **xdistance**(x, y) ecodist/R/0000755000176200001440000000000013576513300012110 5ustar liggesusersecodist/R/cor2m.R0000644000176200001440000000077413576512762013300 0ustar liggesusers# Correlate variables from 1 matrix with variables from another # matrix. If TRIM, set rho dmax] <- 1 ngroup <- length(space.dclass) - sum(space.dclass) answer.m[i,2] <- ngroup if(ngroup > 0) { mant <- mantel(species.d ~ space.dclass, nperm=nperm, mrank=mrank, nboot=nboot, pboot=pboot, cboot=cboot) answer.m[i,3] <- mant[1] if(alternative == "two.sided") answer.m[i,4] <- mant[4] else answer.m[i,4] <- mant[2] answer.m[i,5] <- mant[5] answer.m[i,6] <- mant[6] } if(trace) cat(i, "\t", answer.m[i,2], "\t", answer.m[i, 3], "\n") } results <- list(mgram = answer.m, resids = NA) class(results) <- "mgram" results } ecodist/R/corgen.R0000644000176200001440000000540013576512762013522 0ustar liggesuserscorgen <- function (len, x, r, population = FALSE, epsilon = 0) { # remember the sign of the correlation for later rsign <- sign(r) if (rsign == 0) rsign <- 1 r <- abs(r) # need to either specify x-data or the desired vector length if (missing(x)) { if (missing(len)) { stop("Must specify x or len.\n") } else { # if x wasn't given, sample it from a normal distribution x.rand <- TRUE x <- scale(rnorm(len)) x.orig <- x } } else { # can either draw from a population or simulate an exact # correlation (within epsilon), but not both if (population == TRUE) { # if x is given, population is set to FALSE warning("If x is specified population is ignored.\n") population <- FALSE } x.rand <- FALSE len <- length(x) x.orig <- x x <- scale(x) } if (epsilon != 0) { if (population == TRUE) { warning("If epsilon is specified population is ignored.\n") population <- FALSE } } ## Here's where the real work starts # First, draw y from a normal distribution y <- scale(rnorm(len)) if (!population & x.rand) { # if exact correlations are desired, use princomp to # create uncorrelated data # UNLESS x is given - princomp would trash the # specified x values xy <- princomp(cbind(x, y))$scores x <- xy[, 1] x.orig <- x y <- xy[, 2] } # create a new y based on x and the desired correlation a <- r/sqrt(1 - r^2) y <- x * a + y if (epsilon > 0) { itcounter <- 0 # check to see if cor(x, y) meets the given tolerances # this is kludgy, but works while (abs(cor(x, y) - r) > epsilon) { # sometimes takes too long or doesn't converge # with given starting point if(itcounter > 1000) { if(x.rand) { x <- scale(rnorm(len)) x.orig <- x itcounter <- 0 } else { # hopefully never get here stop("Doesn't converge.\n") } } itcounter <- itcounter + 1 # if not within epsilon, generate a new y y <- scale(rnorm(len)) if (!population & x.rand) { xy <- princomp(cbind(x, y))$scores x <- xy[, 1] x.orig <- x y <- xy[, 2] } a <- r/sqrt(1 - r^2) y <- x * a + y } } # return x and y with the correct sign of r restored list(x = x.orig, y = y * rsign) } ecodist/R/mantel.R0000644000176200001440000002036213576512762013531 0ustar liggesusersmantel <- function(formula = formula(data), data = sys.parent(), nperm = 1000, mrank = FALSE, nboot = 500, pboot = 0.9, cboot = 0.95) { # Mantel test # Written by Sarah C. Goslee # 27 June 2000 # Updated 5 April 2001 # # formula is y ~ x + n1 + n2 + n3 + ... # NOT y ~ x | n1 + n2 + n3 + ... # The | means something else in S-Plus formulas. # # Uses C for permutation and bootstrap routines. # # This version calculates partial coefficients by permuting the y matrix. # # Will calculate the simple correlation or n-th order partial correlation # between two distance matrices in either of two ways: Pearson (mrank=FALSE) # or Spearman (mrank=TRUE) # # A permutation test is used to calculate the significance of r. # The permutation test was designed to be relatively fast, but because of the # way this was done, there is a possibility of repeating permutations of # 1/n! where the distance matrix is n by n. In particular, for small matrices # n < 8 or so, it may be better to enumerate the permutations. # # # As an added bonus, this function offers the option of calculating # bootstrapped confidence limits for the correlation coefficient. # nboot is the number of iterations. # pboot is the level to resample at. # cboot is the desired confidence limit. # NOTE: This is not bootstrapping with replacement. That doesn't make # much sense for dissimilarities because of the possibility of duplicates. # The dissimilarity between a sample and itself is always zero. # # mantel returns a five-element list: # mantelr is the correlation. # pval1 is the one-sided p-value (null hypothesis r <= 0) (0 if nperm == 0). # pval2 is the one-sided p-value (null hypothesis r >= 0) (0 if nperm == 0). # pval3 is the two-sided p-value (null hypothesis r = 0) (0 if nperm == 0). # llim is the lower confidence limit. # ulim is the upper confidence limit. # # requires mantel.c (Included in ecodist.c.) # # Stuff R needs to be able to use a formula m <- match.call(expand.dots = FALSE) m2 <- match(c("formula", "data"), names(m), nomatch=0) m <- m[c(1, m2)] m[[1]] <- as.name("model.frame") m <- eval(m, parent.frame()) m <- as.matrix(m) # End of R stuff. m is now the data for the Mantel test as # columns y, x, n1, n2, n3, ... # Determine the size of the matrices & do some error checking. n <- (1 + sqrt(1 + 8 * nrow(m)))/2 if(abs(n - round(n)) > 0.0000001) stop("Matrix not square.\n") n <- round(n) if(ncol(m) < 2) stop("Not enough data. \n") # If there are only x and y, then use the data as is. if(dim(m)[[2]] == 2) { ymat <- as.vector(m[, 1]) xmat <- as.vector(m[, 2]) if(mrank) { ymat <- rank(ymat) xmat <- rank(xmat) } ycor <- ymat xcor <- xmat } else { ymat <- as.vector(m[, 1]) omat <- m[, -1] if(mrank) { ymat <- rank(ymat) omat <- apply(omat, 2, rank) } omat <- cbind(rep(1, length(ymat)), omat) xmat <- as.vector(omat[, 2]) omat <- omat[, -2] omat <- as.matrix(omat) ycor <- lm.fit(omat, ymat)$residuals xcor <- lm.fit(omat, xmat)$residuals } mantelr <- cor(xcor, ycor) # Convert matrices to column order for compatibility with C routines. xmat <- full(xmat) ymat <- full(ymat) xmat <- xmat[col(xmat) > row(xmat)] ymat <- ymat[col(ymat) > row(ymat)] if(dim(m)[[2]] > 2) { for(i in 2:dim(omat)[[2]]) { curcoll <- omat[, i] curcoll <- full(curcoll) curcoll <- curcoll[col(curcoll) > row(curcoll)] omat[, i] <- curcoll } } # If using a permutation test, start here: if(nperm > 0) { # Set up the arrays needed. zstats <- numeric(nperm) tmat <- matrix(0, n, n) rarray <- rep(0, n) if(dim(m)[[2]] == 2) { # Standardize the columns of the matrices so # that z = r and we can do 2-tailed tests. ncor <- length(xmat) w1 <- sum(xmat)/ncor w2 <- sum(xmat^2) w2 <- sqrt(w2/ncor - w1^2) xmat <- (xmat - w1)/w2 w1 <- sum(ymat)/ncor w2 <- sum(ymat^2) w2 <- sqrt(w2/ncor - w1^2) ymat <- (ymat - w1)/w2 cresults <- .C("permute", as.double(xmat), as.double(ymat), as.integer(n), as.integer(length(xmat)), as.integer(nperm), zstats = as.double(zstats), as.double(as.vector(tmat)), as.integer(rarray), PACKAGE = "ecodist") } else { tomat <- t(omat) hmat <- solve(tomat %*% omat) hmat <- hmat %*% tomat bmat <- rep(0, ncol(omat)) xcor <- as.vector(lm.fit(omat, xmat)$residuals) ycor <- as.vector(lm.fit(omat, ymat)$residuals) # Standardize the columns of the matrices so # that z = r and we can do 2-tailed tests. ncor <- length(xcor) w1 <- sum(xcor)/ncor w2 <- sum(xcor^2) w2 <- sqrt(w2/ncor - w1^2) xcor <- (xcor - w1)/w2 w1 <- sum(ycor)/ncor w2 <- sum(ycor^2) w2 <- sqrt(w2/ncor - w1^2) ycor <- (ycor - w1)/w2 cresults <- .C("permpart", as.double(as.vector(hmat)), bmat = as.double(bmat), as.double(as.vector(omat)), as.double(ymat), as.double(xcor), ycor = as.double(ycor), as.integer(n), as.integer(length(bmat)), as.integer(length(xmat)), as.integer(nperm), zstats = as.double(zstats), as.double(as.vector(tmat)), as.integer(rarray), PACKAGE = "ecodist") } zstats <- cresults$zstats # Calculate the p-values. pval1 <- length(zstats[zstats >= zstats[1]])/nperm pval2 <- length(zstats[zstats <= zstats[1]])/nperm pval3 <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } else { pval1 <- 0 pval2 <- 0 pval3 <- 0 } # If not using a permutation test, return 0 for the p-values. if(nboot > 0) { if(dim(m)[[2]] == 2) { ycor <- ymat xcor <- xmat } else { xcor <- as.vector(lm.fit(omat, xmat)$residuals) ycor <- as.vector(lm.fit(omat, ymat)$residuals) } bootcor <- numeric(nboot) rarray <- numeric(n) rmat <- numeric(length(xcor)) xdif <- numeric(length(xcor)) ydif <- numeric(length(xcor)) cresults <- .C("bootstrap", as.double(xcor), as.double(ycor), as.integer(n), as.integer(length(xcor)), as.integer(nboot), as.double(pboot), bootcor = as.double(bootcor), as.integer(rarray), as.integer(rmat), as.double(xdif), as.double(ydif), PACKAGE = "ecodist") bootcor <- cresults$bootcor bootcor <- sort(bootcor) pval <- (1 - cboot)/2 llim <- quantile(bootcor, pval) ulim <- quantile(bootcor, 1 - pval) } else { llim <- 0 ulim <- 0 } c(mantelr = mantelr, pval1 = pval1, pval2 = pval2, pval3 = pval3, llim = llim, ulim = ulim) } ecodist/R/nmds.R0000644000176200001440000000700613576512762013212 0ustar liggesusers# Non-metric multidimensional scaling function # using the majorization algorithm from # Borg & Groenen 1997, Modern Multidimensional Scaling. # # Sarah Goslee # 20 December 1999 # # dmat is a lower-triangular distance matrix. # mindim is the minimum number of dimensions to calculate. # maxdim is the maximum number of dimensions to calculate. # nits is the number of repetitions. # iconf is the initial configuration to use. # If iconf is not specified, then a random configuration is used. # epsilon and maxit specify stopping points. # Returns a list of configurations (conf) # and a vector of final stress values (stress), # along with the cumulative and incremental r^2 for each axis. # The first nits elements are for the lowest number of dimensions. # mindim, maxdim, nits are saved as part of the returned list # # stresscalc has been updated 2016-12-27 to be compatible with vegan::metaMDS # and MASS::isoMDS. # The method of finding the optimum is unchanged. sstress <- function(dmat, newconf) { # Calculates the stress-1 function for the original and # new NMDS configurations (Kruskal 1964). # Calculate stress based on isotonic regression # of distance matrices # uses stats::isoreg instead of MASS::Shepard dmat <- as.vector(dmat) dord <- order(dmat) cmat <- as.vector(dist(newconf, "minkowski", 2)) dmat <- dmat[dord] cmat <- cmat[dord] ir <- isoreg(dmat, cmat) dmat <- ir$y cmat <- ir$yf sstresscalc <- (dmat - cmat) ^ 2 sstresscalc <- sum(sstresscalc) / sum(dmat ^ 2) sqrt(sstresscalc) } nmdscalc <- function(dmat, ndim, iconf, epsilon, maxit, trace) { # This is the optimization routine for NMDS ordination. # Use front-end nmds. # not exported n <- (1 + sqrt(1 + 8 * length(dmat))) / 2 if(missing(iconf)) { iconf <- matrix(runif(n * ndim), nrow = n, ncol = ndim) } k <- 0 conf <- iconf stress2 <- sstress(dmat, iconf) stress1 <- stress2 + 1 + epsilon while(k < maxit && abs(stress1 - stress2) > epsilon) { stress1 <- stress2 dmat.full <- full(dmat) confd.full <- full(dist(conf)) confd2.full <- confd.full confd2.full[confd.full == 0] <- 1 b <- dmat.full / confd2.full b[confd.full == 0] <- 0 bsum <- apply(b, 2, sum) b <- -1 * b diag(b) <- bsum conf <- (1 / n) * b %*% conf stress2 <- sstress(dmat, conf) if(trace) cat(k, ",\t", stress1, "\n") k <- k + 1 } list(conf = conf, stress = stress1) } nmds <- function(dmat, mindim = 1, maxdim = 2, nits = 10, iconf, epsilon = 1e-12, maxit = 500, trace=FALSE) { conf <- list(1:((maxdim - mindim + 1) * nits)) stress <- list(1:((maxdim - mindim + 1) * nits)) r2 <- list(1:((maxdim - mindim + 1) * nits)) k <- 1 for(i in mindim:maxdim) { if(trace) cat("Number of dimensions: ", i, "\n") for(j in seq_len(nits)) { if(trace) cat("Iteration number: ", j, "\n") if(!missing(iconf) && ncol(iconf) == i) { nmdsr <- nmdscalc(dmat, ndim = i, iconf=iconf, epsilon=epsilon, maxit=maxit, trace=trace) } else { nmdsr <- nmdscalc(dmat, ndim = i, epsilon=epsilon, maxit=maxit, trace=trace) } conf[[k]] <- nmdsr$conf stress[[k]] <- nmdsr$stress r2[[k]] <- cor(dmat, dist(nmdsr$conf)) ^ 2 k <- k + 1 } } results <- list(conf = conf, stress = unlist(stress), r2 = unlist(r2), mindim=mindim, maxdim=maxdim, nits=nits) class(results) <- "nmds" results } ecodist/R/xdistance.R0000644000176200001440000000163313576512762014233 0ustar liggesusersxdistance <- function(x, y, method = "euclidean") { # calculate cross-dissimilarities between # rows of x and rows of y # returns a nonsymmetric matrix where # d[a, b] is the dissimilarity between # x[a, ] and y[b, ] # Sarah Goslee 2017-02-17, modified from legacy Splus code dated 01/01/01 if(is.null(ncol(x))) { x <- matrix(x, ncol=1) rownames(x) <- seq_len(nrow(x)) } if(is.null(ncol(y))) { y <- matrix(y, ncol=1) rownames(y) <- seq_len(nrow(y)) } if(!(ncol(x) == ncol(y))) stop("Matrices must have the same number of columns\n") x.names <- paste0("x", row.names(x)) y.names <- paste0("y", row.names(y)) x <- as.matrix(x) y <- as.matrix(y) d <- rbind(x, y) d <- full(distance(d, method=method)) d <- d[seq(1, nrow(x)), seq(nrow(x) + 1, nrow(x) + nrow(y)), drop=FALSE] rownames(d) <- x.names colnames(d) <- y.names class(d) <- "xdist" d } ecodist/R/lower.R0000644000176200001440000000037613576512762013404 0ustar liggesuserslower <- function(m) { # Takes the lower triangle of a matrix # Does NOT check for symmetric matrix m <- as.matrix(m) if(ncol(m) != nrow(m)) stop("Matrix not square.") if(ncol(m) == 1) { warning("Matrix is 1x1.") m } else m[col(m) < row(m)] } ecodist/R/fixdmat.R0000644000176200001440000000035313576512762013703 0ustar liggesusersfixdmat <- function(v) { # Converts a row-wise distance vector to a full distance matrix. n <- (1 + sqrt(1 + 8 * length(v)))/2 dist.m <- matrix(0, n, n) dist.m[row(dist.m) < col(dist.m)] <- v dist.m <- dist.m + t(dist.m) dist.m } ecodist/R/full.R0000644000176200001440000000052413576512762013211 0ustar liggesusersfull <- function(v) { # converts a lower-triangular distance vector to a symmetric matrix n <- (1 + sqrt(1 + 8 * length(v)))/2 if(abs(n - round(n)) > 0.0000001) stop("Matrix not square.") n <- round(n) full <- matrix(0, n, n) full[lower.tri(full)] <- v full2 <- t(full) diag(full2) <- 0 full + full2 } ecodist/R/pmgram.R0000644000176200001440000001734113576513160013530 0ustar liggesuserspmgram <- function(data, space, partial, breaks, nclass, stepsize, resids = FALSE, nperm = 1000) { epsilon <- 0.0000001 if(inherits(class(data), "dist")) { data <- as.matrix(as.vector(data)) } else { data <- as.matrix(data) } space <- as.vector(space) n <- ncol(full(space)) # This function does four different analyses: # If data has 1 column and partial is missing, # Multivariate correlogram # calculates a multivariate correlogram for data. # # If data has 2 columns and partial is missing, # Piecewise Mantel correlogram # calculates Mantel r between the two columns for each distance class. # # If data has 1 column and partial exists, # Partial multivariate correlogram # does a multivariate correlogram for the residuals over whole extent # # If data has 2 columns and partial exists, # Piecewise partial Mantel correlogram # calculate partial for each distance class separately # # results are: # 1 dmax # 2 ngroup # 3 piecewise mgram # 4 two-sided p-value # use breaks if it exists. # If nclass or stepsize aren't specified, use Sturge's rule to calculate nclass # classes are shifted so that they don't have to start with zero if(missing(breaks)) { if(missing(nclass)) { if(missing(stepsize)) { nclass <- round(1 + 3.3 * log10(length(space))) stepsize <- (max(space) - min(space)) / nclass } else { nclass <- round((max(space) - min(space))/stepsize) } } else { if(missing(stepsize)) { stepsize <- (max(space) - min(space)) / nclass } } breaks <- seq(0, stepsize * nclass, stepsize) } else { nclass <- length(breaks) - 1 } answer.m <- matrix(NA, nrow=nclass, ncol=4) dimnames(answer.m) <- list(NULL, c("lag", "ngroup", "pieceR", "pval")) answer.m[,4] <- rep(NA, nrow(answer.m)) # standardize so mean = 0, variance = 1 for(i in seq_len(ncol(data))) { thiscol <- data[,i] ydif <- thiscol - mean(thiscol) yvar <- sqrt(sum(ydif^2)/length(ydif)) thiscol <- ydif / yvar data[,i] <- thiscol } if(!missing(partial)) { partial <- as.matrix(as.vector(partial)) for(i in seq_len(ncol(partial))) { thiscol <- partial[,i] ydif <- thiscol - mean(thiscol) yvar <- sqrt(sum(ydif^2)/length(ydif)) thiscol <- ydif / yvar partial[,i] <- thiscol } } if(resids) { mgresids <- rep(0, length(space)) } else { mgresids <- NA } if(missing(partial)) { if(ncol(data) == 1) { colnames(answer.m)[3] <- "wtI" for(i in seq_len(nclass)) { dmin <- breaks[i] dmax <- breaks[i + 1] answer.m[i,1] <- (dmin + dmax) / 2 space.dclass <- rep(0, length(space)) space.dclass[space <= dmin] <- 1 space.dclass[space > dmax] <- 1 if(sum(space.dclass== 0) > 0) { ngroup <- length(space.dclass) - sum(space.dclass) answer.m[i,2] <- ngroup answer.m[i,3] <- (-1/ngroup) * sum(data[space.dclass == 0]) # similar to Moran's I if(resids == TRUE) { mgresids[space.dclass == 0] <- residuals(lm(data[space.dclass == 0] ~ space[space.dclass == 0])) } if(nperm > 0) { zstats <- rep(0, nperm) tmat <- matrix(0, n, n) rarray <- rep(0, n) # cat(i, "\t", answer.m[i,1], "\t", answer.m[i,2], "\t", answer.m[i,3], "\n") cresults <- .C("newpermone", as.double(data), as.integer(space.dclass), as.integer(n), as.integer(length(data)), as.integer(nperm), zstats = as.double(zstats), as.double(as.vector(tmat)), as.integer(rarray), PACKAGE = "ecodist") zstats <- cresults$zstats answer.m[i,4] <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } } } } else { for(i in seq_len(nclass)) { dmin <- breaks[i] dmax <- breaks[i + 1] answer.m[i,1] <- dmax space.dclass <- rep(0, length(space)) space.dclass[space <= dmin] <- 1 space.dclass[space > dmax] <- 1 if(sum(space.dclass== 0) > 0) { ngroup <- length(space.dclass) - sum(space.dclass) answer.m[i,2] <- ngroup if(ncol(data) == 2) { answer.m[i, 3] <- cor(data[space.dclass == 0, 1], data[space.dclass == 0, 2]) if(resids == TRUE) { mgresids[space.dclass == 0] <- residuals(lm(data[space.dclass == 0,1] ~ data[space.dclass == 0,2])) } if(nperm > 0) { if(is.na(answer.m[i, 3])) answer.m[i, 4] <- 1 else { zstats <- rep(0, nperm) tmat <- matrix(0, n, n) rarray <- rep(0, n) xmat <- data[,1] xmat[space.dclass == 1] <- -9999 # cat(i, "\t", answer.m[i,1], "\t", answer.m[i,2], "\t", answer.m[i,3], "\n") cresults <- .C("newpermtwo", as.double(xmat), as.double(data[,2]), as.integer(n), as.integer(length(xmat)), as.integer(nperm), zstats = as.double(zstats), as.double(as.vector(tmat)), as.integer(rarray), PACKAGE = "ecodist") zstats <- cresults$zstats answer.m[i,4] <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } } } } } } } else { if(ncol(data) == 1) { colnames(answer.m)[3] <- "wtI" for(i in seq_len(nclass)) { dmin <- breaks[i] dmax <- breaks[i + 1] answer.m[i,1] <- dmax space.dclass <- rep(0, length(space)) space.dclass[space <= dmin] <- 1 space.dclass[space > dmax] <- 1 ngroup <- sum(space.dclass== 0) answer.m[i,2] <- ngroup if(ngroup > 0) { ngroup <- sum(space.dclass== 0) data.lm <- residuals(lm(data ~ partial)) answer.m[i,3] <- (-1/ngroup) * sum(data.lm[space.dclass == 0]) # similar to Moran's I if(resids == TRUE) { mgresids[space.dclass == 0] <- residuals(lm(data[space.dclass == 0] ~ partial[space.dclass == 0])) } if(nperm > 0) { zstats <- rep(0, nperm) zstats[1] <- answer.m[i,3] for(j in 2:nperm) { xmat <- full(data) xsamp <- sample(ncol(xmat)) xmat <- xmat[xsamp, xsamp] xmat <- lower(xmat) data.lm <- residuals(lm(xmat ~ partial)) zstats[j] <- (-1/ngroup) * sum(data.lm[space.dclass == 0]) } answer.m[i,4] <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } } } } else { for(i in seq_len(nclass)) { dmin <- breaks[i] dmax <- breaks[i + 1] answer.m[i,1] <- (dmin + dmax) / 2 space.dclass <- rep(0, length(space)) space.dclass[space <= dmin] <- 1 space.dclass[space > dmax] <- 1 if(sum(space.dclass== 0) > 0) { ngroup <- length(space.dclass) - sum(space.dclass) answer.m[i,2] <- ngroup if(ncol(data) == 2) { data1.lm <- residuals(lm(data[space.dclass == 0,1] ~ partial[space.dclass == 0,])) data2.lm <- residuals(lm(data[space.dclass == 0,2] ~ partial[space.dclass == 0,])) answer.m[i, 3] <- cor(data1.lm, data2.lm) if(resids == TRUE) { mgresids[space.dclass == 0] <- residuals(lm(data1.lm ~ data2.lm)) } if(nperm > 0) { if(is.na(answer.m[i, 3])) answer.m[i, 4] <- 1 else { zstats <- rep(0, nperm) zstats[1] <- answer.m[i,3] for(j in 2:nperm) { xmat <- data[,1] xmat[space.dclass == 1] <- -9999 xmat <- full(xmat) xsamp <- sample(ncol(xmat)) xmat <- xmat[xsamp, xsamp] xmat <- lower(xmat) xmat <- xmat[xmat != -9999] data1.lm <- residuals(lm(xmat ~ partial[space.dclass == 0,])) zstats[j] <- cor(data1.lm, data2.lm) } answer.m[i,4] <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } } } } } } } results <- list(mgram = data.frame(answer.m), resids = mgresids) class(results) <- "mgram" results } ecodist/R/bcdist.R0000644000176200001440000000176213576512762013524 0ustar liggesusersbcdist <- function(x, rmzero = FALSE) { # Calculates Bray-Curtis distance (1 - percent similarity) for the # rows of a matrix. # # If rmzero = TRUE, all empty rows of the matrix will be removed before calculating # distances. Otherwise the distance between empty rows will be set to 0. # # Sarah C. Goslee, November 1997 # # The same functionality appears in distance(), but bcdist is substantially faster. x <- as.matrix(x) if(rmzero == TRUE) { xsum <- apply(x, 1, sum) x <- x[xsum > 0, ] } dist.v <- rep(0, (nrow(x) * (nrow(x) - 1))/2) cresults <- .C("bcdistc", as.double(as.vector(t(x))), as.integer(nrow(x)), as.integer(ncol(x)), dist.v = as.double(dist.v), PACKAGE = "ecodist") dist.v <- cresults$dist.v ## give the results attributes similar to dist() attr(dist.v, "Size") <- nrow(x) attr(dist.v, "Labels") <- rownames(x) attr(dist.v, "Diag") <- FALSE attr(dist.v, "Upper") <- FALSE attr(dist.v, "method") <- "bray-curtis" class(dist.v) <- "dist" dist.v } ecodist/R/plot.mgram.R0000644000176200001440000000113313576512762014324 0ustar liggesusersplot.mgram <- function(x, pval = 0.05, xlab = "Distance", ylab = "Mantel r", ...) { # x is the output from mgram # pval is the p-value to be considered signficant # ... are additional graphics parameters x <- x$mgram pval.v <- x[, 4] pval.v[is.na(pval.v)] <- 1 plot(x[, 1], x[, 3], type = "l", xlab = xlab, ylab = ylab, ...) points(x[pval.v <= pval, 1], x[pval.v <= pval, 3], pch = 16, cex=2) points(x[pval.v > pval, 1], x[pval.v > pval, 3], pch = 1, cex=2) abline(h=0, lty=2, col="gray") invisible() } ecodist/R/MRM.R0000644000176200001440000001235313576512762012705 0ustar liggesusersMRM <- function(formula = formula(data), data = sys.parent(), nperm = 1000, method="linear", mrank = FALSE) { # MRM: Multiple Regression on distance Matrices # Sarah Goslee 2008-07-18 # tests R^2 and regression coefficients using a # permutation test # added method argument # linear is the default, standard option # logistic adds capability to do logistic regression # - this will be much slower # mrank is ignored if method is not "linear" # Stuff R needs to be able to use a formula m <- match.call(expand.dots = FALSE) m2 <- match(c("formula", "data"), names(m), nomatch=0) m <- m[c(1, m2)] m[[1]] <- as.name("model.frame") m <- eval(m, parent.frame()) m <- as.matrix(m) # End of R stuff. m is now the data for the MRM test as # columns y, x, n1, n2, n3, ... # Determine the size of the matrices & do some error checking. n <- (1 + sqrt(1 + 8 * nrow(m)))/2 if(abs(n - round(n)) > 0.0000001) stop("Matrix not square.\n") n <- round(n) if(ncol(m) < 2) stop("Not enough data. \n") if(method == "linear") { if(mrank) { m <- apply(m, 2, rank) } # convert matrices to column order to ensure compatibility with C for(thiscol in seq_len(ncol(m))) { tempmat <- full(m[,thiscol]) m[,thiscol] <- tempmat[col(tempmat) > row(tempmat)] } # use matrix form to speed up calculations X <- m[ ,2:ncol(m), drop=FALSE] X <- cbind(rep(1, nrow(X)), X) Y <- m[ ,1, drop=FALSE] nd <- nrow(X) # only need to calculate (X'X)^-1 once XX <- crossprod(X) XX <- solve(XX) # will need to calculate Xy for each permutation XY <- crossprod(X, Y) YY <- crossprod(Y) # regression coefficients b <- XX %*% XY rownames(b) <- c("Int", colnames(X)[2:ncol(X)]) bXY <- crossprod(b, XY) SSE <- YY - bXY SSTO <- YY - sum(Y)^2/nd SSR = SSTO - SSE # R2 = 1 - SSE/SSTO R2 <- 1 - SSE/SSTO R2 <- as.vector(R2) # F* = MSR / MSE # MSR = SSR / (p - 1) # MSE = SSE / (n - p) p <- ncol(X) # number of parameters estimated F <- (SSR / (p - 1)) / (SSE / (nd - p)) R2.pval <- NA b.pval <- rep(NA, ncol(X)) F.pval <- NA if(nperm > 0) { R2.all <- numeric(nperm) # for regression coefficients, use pseudo-t of Legendre et al. 1994 b.all <- numeric(nperm*p) # try out an overall F-test for lack of fit F.all <- numeric(nperm) cresults <- .C("mrmperm", as.double(as.vector(X)), as.double(as.vector(Y)), as.integer(p), as.integer(nd), as.integer(n), as.integer(nperm), R2.all = as.double(R2.all), b.all = as.double(b.all), F.all = as.double(F.all), as.double(numeric(n*n)), as.integer(numeric(n)), as.double(as.vector(XX)), as.double(numeric(p)), as.double(0), as.double(numeric(p)), PACKAGE = "ecodist") R2.all <- cresults$R2.all R2.pval <- length(R2.all[R2.all >= R2.all[1]])/nperm F.all <- cresults$F.all F.pval <- length(F.all[F.all >= F.all[1]])/nperm # b.all contains pseudo-t of Legendre et al. 1994 b.all <- matrix(cresults$b.all, nrow=nperm, ncol=p, byrow=TRUE) b.pval <- apply(b.all, 2, function(x)length(x[abs(x) >= abs(x[1])])/nperm) } results <- list(coef=cbind(b, pval=b.pval), r.squared=c(R2=R2, pval = R2.pval),F.test=c(F=F, F.pval = F.pval)) } else { if(method == "logistic") { # extract data from formula object X <- m[ ,2:ncol(m), drop=FALSE] Y <- m[ ,1, drop=FALSE] colnames(Y) <- "Y" newdata <- data.frame(Y=Y, X) fit1 <- glm(Y ~ ., data=newdata, family=binomial(link = "logit")) # want to save coefficients, deviance & df b <- coefficients(fit1) dev <- summary(fit1)$deviance dev.df <- summary(fit1)$df.residual b.pval <- NA dev.pval <- NA if(nperm > 0) { b.all <- matrix(NA, nrow=nperm, ncol=length(b)) b.all[1,] <- b dev.all <- rep(NA, nperm) dev.all[1] <- dev for(i in 2:nperm) { newSample <- sample(n) newY <- full(Y) newY <- newY[newSample, newSample] newY <- lower(newY) newdata <- data.frame(Y=newY, X=X) newfit <- glm(Y ~ ., data=newdata, family=binomial(link = "logit")) b.all[i,] <- coefficients(newfit) dev.all[i] <- summary(newfit)$deviance } b.pval <- apply(b.all, 2, function(x) length(x[abs(x) >= abs(x[1])])/nperm) dev.pval <- length(dev.all[dev.all >= dev.all[1]])/nperm } results <- list(coef = cbind(b, pval = b.pval), dev = c(resid.dev = dev, resid.df = dev.df, dev.pval = dev.pval)) } else { stop("method must be 'linear' or 'logistic'\n") } } results } ecodist/R/distance.R0000644000176200001440000002005213576512762014037 0ustar liggesusersdistance <- function(x, method="euclidean", sprange=NULL, spweight=NULL, icov) { # calculates similarity and dissimilarity coefficients # as described in Legendre and Legendre 1998 # returns lower-triangle ### # Sarah Goslee # 2 March 2006 # revised 31 March 2008 # bug-fix 15 December 2008 ### # uses clever matrix math to calculate the pieces needed # by dissimilarity matrices, to make it easy to add new # indices. ### # to add a new metric: # add it to the commented list below # add it to the end of the METHODS <- c(...) list # add the code at the appropriate point at the bottom of # the function ### # Gower offers the option of dividing by the species range # if sprange=NULL no range is used # Euclidean, Manhattan, Gower allow weighting options # if spweight=NULL no weighting is used # if spweight="absence" then W is = 0 if both species are absent, # and 1 otherwise, thus deleting joint absences ### Available methods # 1: euclidean # 2: bray-curtis # 3: manhattan # 4: mahalanobis # 5: jaccard # 6: simple difference # 7: sorensen # 8: Gower # 9: Modified Gower base 10 (Anderson et al 2006) # 10: Modified Gower base 2 (Anderson et al 2006) ### Mahalanobis distance requires covariance matrix of full dataset, # making it impossible to calculate in chunks for a very large dataset. # Now can specify covariance matrix separately, to enable this. # argument icov. If missing, will be calculated from data as in previous version. pairedsum <- function(x) { ### paired sums ### returns an N by N by P matrix containing each ### combination of N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("psum", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } paireddiff <- function(x) { ### paired differences N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("pdiff", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } jointpresence <- function(x) { ### joint count of presences N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("jpres", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } jointabsence <- function(x) { ### joint count of absences N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("jabs", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } firstonly <- function(x) { ### present only in first sample N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("jfirst", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } secondonly <- function(x) { ### present only in second sample N <- nrow(x) P <- ncol(x) A <- numeric(N * N * P) A <- .C("jsec", as.double(as.vector(t(x))), as.integer(N), as.integer(P), A = as.double(A), PACKAGE = "ecodist")$A A <- array(A, dim=c(N, N, P)) A } x <- as.matrix(x) ## code borrowed from dist() METHODS <- c("euclidean", "bray-curtis", "manhattan", "mahalanobis", "jaccard", "difference", "sorensen", "gower", "modgower10", "modgower2") method <- pmatch(method, METHODS) if (is.na(method)) stop("invalid distance method") if (method == -1) stop("ambiguous distance method") N <- nrow(x) P <- ncol(x) if(method == 1) { # Euclidean distance A <- paireddiff(x) if(is.null(spweight)) { D <- sqrt(apply(A, 1:2, function(x)sum(x * x))) } else if(spweight[1] == "absence") { W <- ifelse(jointabsence(x)==1, 0, 1) D <- sqrt(apply((W^2)*A, 1:2, function(x)sum(x * x))) / apply(W, 1:2, sum) } else if(length(spweight) == ncol(x)) { W <- array(rep(spweight, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) D <- sqrt(apply((W^2)*A, 1:2, function(x)sum(x * x))) / apply(W, 1:2, sum) } else { stop("Unknown weighting method.\n") } } if(method == 2) { # Bray-Curtis distance A <- paireddiff(x) A <- apply(A, 1:2, function(x)sum(abs(x))) B <- pairedsum(x) B <- apply(B, 1:2, sum) D <- A / B } if(method == 3) { # unstandardized manhattan distance A <- paireddiff(x) if(is.null(spweight)) { D <- apply(A, 1:2, function(x)sum(abs(x))) } else if(spweight[1] == "absence") { W <- ifelse(jointabsence(x)==1, 0, 1) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else if(length(spweight) == ncol(x)) { W <- array(rep(spweight, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else { stop("Unknown weighting method.\n") } } if(method == 4) { # pairwise Mahalanobis distance # same as mahal() if(missing(icov)) { icov <- cov(x) } icov <- solve(icov) A <- paireddiff(x) A1 <- apply(A, 1, function(z)(z %*% icov %*% t(z))) D <- A1[seq(1, N*N, by=(N+1)), ] } if(method == 5) { # Jaccard distance A <- jointpresence(x) A <- apply(A, 1:2, sum) B <- firstonly(x) B <- apply(B, 1:2, sum) C <- secondonly(x) C <- apply(C, 1:2, sum) D <- 1 - A / (A + B + C) } if(method == 6) { # simple difference, NOT symmetric D <- paireddiff(x)[,,1, drop=TRUE] } if(method == 7) { # Sorensen distance A <- jointpresence(x) A <- apply(A, 1:2, sum) B <- firstonly(x) B <- apply(B, 1:2, sum) C <- secondonly(x) C <- apply(C, 1:2, sum) D <- 1 - (2*A) / (2*A + B + C) } if(method == 8) { # Gower distance # weighting A <- paireddiff(x) if(!is.null(sprange)) { if(length(sprange) == ncol(x)) { sprange <- array(rep(sprange, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) A <- A / sprange } else { stop("sprange not recognized.\n") } } if(is.null(spweight)) { D <- apply(A, 1:2, function(x)sum(abs(x))) } else if(spweight[1] == "absence") { W <- ifelse(jointabsence(x)==1, 0, 1) D <- apply(A*W, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else if(length(spweight) == ncol(x)) { W <- array(rep(spweight, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else { stop("Unknown weighting method.\n") } } if(method == 9) { # modified Gower, base 10 x <- ifelse(x == 0, 0, log10(x)) A <- paireddiff(x) if(is.null(spweight)) { D <- apply(A, 1:2, function(x)sum(abs(x))) } else if(spweight[1] == "absence") { W <- ifelse(jointabsence(x)==1, 0, 1) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else if(length(spweight) == ncol(x)) { W <- array(rep(spweight, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else { stop("Unknown weighting method.\n") } } if(method == 10) { # modified Gower, base 2 x <- ifelse(x == 0, 0, log2(x)) A <- paireddiff(x) if(is.null(spweight)) { D <- apply(A, 1:2, function(x)sum(abs(x))) } else if(spweight[1] == "absence") { W <- ifelse(jointabsence(x)==1, 0, 1) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else if(length(spweight) == ncol(x)) { W <- array(rep(spweight, each=nrow(x)^2), dim=c(nrow(x), nrow(x), ncol(x))) D <- apply(W*A, 1:2, function(x)sum(abs(x))) / apply(W, 1:2, sum) } else { stop("Unknown weighting method.\n") } } ## Make the results lower triangular D <- D[col(D) < row(D)] ## give the results attributes similar to dist() attr(D, "Size") <- N attr(D, "Labels") <- rownames(x) attr(D, "Diag") <- FALSE attr(D, "Upper") <- FALSE attr(D, "method") <- METHODS[method] class(D) <- "dist" D } ecodist/R/xmgram.R0000644000176200001440000000475513576512762013554 0ustar liggesusersxmgram <- function(species.xd, space.xd, breaks, nclass, stepsize, nperm = 1000, mrank = FALSE, alternative = "two.sided", trace = FALSE) # Cross-Mantel correlogram developed from mgram() # Sarah Goslee 2017-02-17 # # This function calculates a mantel correlogram for a full cross-distance (non-symmetric # but square) based on the geographic distances given in space.d, also a full cross-distance # (nonsymmetric but square) distance matrix. # nclass: number of distance classes # stepsize: width of distance classes # nperm: number of permutations for mantel test # # Default is two-tailed test (H0: rM = 0; alternative = "two.sided") # May also use one-sided test (H0: rM <= 0; alternative = "one.sided") { dims <- dim(species.xd) space.xd <- as.vector(space.xd) # use breaks if it exists. # If nclass or stepsize aren't specified, use Sturge's rule to calculate nclass # classes are shifted so that they don't have to start with zero if(missing(breaks)) { if (missing(nclass)) { if (missing(stepsize)) { nclass <- round(1 + 3.3 * log10(length(space.xd))) stepsize <- (max(space.xd) - min(space.xd))/nclass } else { nclass <- round((max(space.xd) - min(space.xd))/stepsize) } } else { if (missing(stepsize)) { stepsize <- (max(space.xd) - min(space.xd))/nclass } } breaks <- seq(0, stepsize * nclass, stepsize) } else { nclass <- length(breaks) - 1 } answer.m <- matrix(0, ncol=4, nrow=nclass) dimnames(answer.m) <- list(NULL, c("lag", "ngroup", "mantelr", "pval")) answer.m[,4] <- rep(1, nrow(answer.m)) for(i in seq_len(nclass)) { dmin <- breaks[i] dmax <- breaks[i + 1] answer.m[i,1] <- (dmin + dmax) / 2 space.dclass <- rep(0, length(space.xd)) space.dclass[space.xd <= dmin] <- 1 space.dclass[space.xd > dmax] <- 1 ngroup <- length(space.dclass) - sum(space.dclass) answer.m[i,2] <- ngroup if(ngroup > 0) { space.dclass <- matrix(space.dclass, nrow=dims[1], ncol=dims[2]) mant <- xmantel(species.xd ~ space.dclass, dims=dims, nperm=nperm, mrank=mrank) answer.m[i,3] <- mant[1] if(alternative == "two.sided") answer.m[i,4] <- mant[4] else answer.m[i,4] <- mant[2] } if(trace) cat(i, "\t", answer.m[i,2], "\t", answer.m[i, 3], "\n") } results <- list(mgram = answer.m, resids = NA) class(results) <- "mgram" results } ecodist/R/xmantel.R0000644000176200001440000001343613576512762013725 0ustar liggesusersxmantel <- function(formula = formula(data), data = sys.parent(), dims = NA, nperm = 1000, mrank = FALSE) { # Cross-mantel test # Written by Sarah C. Goslee # 01/01/01 # Updated 6 April 2001 # added to ecodist 10 July 2017 # # formula is y ~ x + n1 + n2 + n3 + ... # NOT y ~ x | n1 + n2 + n3 + ... # The | means something else in S-Plus formulas. # # Uses C for permutation and bootstrap routines. # # Cross-mantel is a variation of the standard Mantel test that # takes nonsymmetric full matrices such as those returned by # xdist and xbcdist. # # This version calculates partial coefficients by permuting the y matrix. # # Will calculate the simple correlation or n-th order partial correlation # between two distance matrices in either of two ways: Pearson (mrank=F) # or Spearman (mrank=T) # # A permutation test is used to calculate the significance of r. # The permutation test was designed to be relatively fast, but because of the # way this was done, there is a possibility of repeating permutations of # 1/n! where the distance matrix is n by n. In particular, for small matrices # n < 8 or so, it may be better to enumerate the permutations. # # # As an added bonus, this function offers the option of calculating # bootstrapped confidence limits for the correlation coefficient. # nboot is the number of iterations. # pboot is the level to resample at. # cboot is the desired confidence limit. # # xmantel returns a five-element list: # mantelr is the correlation. # pval1 is the one-sided p-value (null hypothesis r <= 0) (0 if nperm == 0). # pval2 is the one-sided p-value (null hypothesis r >= 0) (0 if nperm == 0). # pval3 is the two-sided p-value (null hypothesis r = 0) (0 if nperm == 0). # llim is the lower confidence limit. # ulim is the upper confidence limit. # Stuff R needs to be able to use a formula m <- match.call(expand.dots = FALSE) m2 <- match(c("formula", "data"), names(m), nomatch=0) m <- m[c(1, m2)] m[[1]] <- as.name("model.frame") m <- eval(m, parent.frame()) m <- as.matrix(m) # m is now the data for the Mantel test as # cbinded matrices # Determine the size of the matrices & do some error checking. # if dims is NA, matrices are assumed to be square # otherwise dims must be specified nr <- nrow(m) if(is.na(dims[1])) { nc <- nr } else { if(nr != dims[1]) stop("dims doesn't match data \n") nc <- dims[2] } nmat <- ncol(m) / nc if(round(nmat) != nmat) stop("Matrices don't match dims. \n") if(nmat < 2) stop("Not enough data. \n") # If there are only x and y, then use the data as is. if(nmat == 2) { ymat <- m[,1:nc] xmat <- m[,(nc+1):ncol(m)] if(mrank) { ymat <- rank(ymat) xmat <- rank(xmat) } ycor <- as.vector(ymat) xcor <- as.vector(xmat) } else { # If this is a partial Mantel test, get the regression residuals # for y ~ n1 + n2 + n3 + ... and x ~ n1 + n2 + n3 + ... ymat <- as.vector(m[,1:nc]) omat <- vector(nmat - 1, mode="list") for(i in seq(1, nmat - 1)) { omat[[i]] <- as.vector(m[, seq(i * nc + 1, (i+1) * nc)]) } omat <- do.call("cbind", omat) if(mrank) { ymat <- rank(ymat) omat <- apply(omat, 2, rank) } omat <- cbind(rep(1, length(ymat)), omat) xmat <- as.vector(omat[, 2]) omat <- omat[, -2] omat <- as.matrix(omat) ycor <- lm.fit(omat, ymat)$residuals xcor <- lm.fit(omat, xmat)$residuals } # Calculate the Mantel r mantelr <- cor(xcor, ycor) # Standardize the columns of the matrices so # that z = r and we can do 2-tailed tests. ncor <- length(xmat) w1 <- sum(xmat) / ncor w2 <- sum(xmat ^ 2) w2 <- sqrt(w2 / ncor - w1 ^ 2) xmat <- (xmat - w1) / w2 w1 <- sum(ymat) / ncor w2 <- sum(ymat ^ 2) w2 <- sqrt(w2 / ncor - w1 ^ 2) ymat <- (ymat - w1) / w2 if(nmat > 2) { for(i in 2:dim(omat)[[2]]){ curcoll <- omat[,i] w1 <- sum(curcoll) / ncor w2 <- sum(curcoll ^ 2) w2 <- sqrt(w2 / ncor - w1 ^ 2) curcoll <- (curcoll - w1) / w2 omat[,i] <- curcoll } } # If using a permutation test, start here: if(nperm > 0) { # Set up the arrays needed. zstats <- numeric(nperm) rarray <- rep(0, nr) carray <- rep(0, nc) if(nmat == 2) { cresults <- .C("xpermute", as.double(xmat), as.double(ymat), as.integer(nr), as.integer(nc), as.integer(length(xmat)), as.integer(nperm), zstats = as.double(zstats), as.double(xmat), as.integer(rarray), as.integer(carray), PACKAGE = "ecodist") } else { hmat <- solve((t(omat) %*% omat)) hmat <- omat %*% hmat %*% t(omat) hmat <- diag(dim(hmat)[[1]]) - hmat xcor <- as.vector(lm.fit(omat, xmat)$residuals) ycor <- rep(0, length(xcor)) cresults <- .C("xpermpart", as.double(as.vector(hmat)), as.double(as.vector(ymat)), as.double(xcor), as.double(ycor), as.integer(nr), as.integer(nc), as.integer(length(xmat)), as.integer(nperm), zstats = as.double(zstats), as.double(as.vector(ymat)), as.integer(rarray), as.integer(carray), PACKAGE = "ecodist") } zstats <- cresults$zstats # Calculate the p-values. pval1 <- length(zstats[zstats >= zstats[1]])/nperm pval2 <- length(zstats[zstats <= zstats[1]])/nperm pval3 <- length(zstats[abs(zstats) >= abs(zstats[1])])/nperm } # If not using a permutation test, return 0 for the p-values. else { pval1 <- 0 pval2 <- 0 pval3 <- 0 } # Return the Mantel r and the p-value. unlist(list(mantelr = mantelr, pval1 = pval1, pval2 = pval2, pval3 = pval3)) } ecodist/R/plot.nmds.R0000644000176200001440000000310313576512762014161 0ustar liggesusersplot.nmds <- function(x, plot=TRUE, xlab="Dimensions", ...) { # dlu, modified by scg 2017-05 # plot NMDS scores by dimension dims <- seq(x$mindim, x$maxdim, by=1) # summarize and plot the nmds object x: stress x.stress <- data.frame(matrix(x$stress, nrow=length(dims), byrow=TRUE)) colnames(x.stress) <- paste0("iter", sprintf("%02d", seq_len(x$nits))) x.stress$ndim <- dims x.stress$min <- apply(x.stress[, seq_len(x$nits)], 1, min, na.rm=TRUE) x.stress$mean <- apply(x.stress[, seq_len(x$nits)], 1, mean, na.rm=TRUE) x.stress$max <- apply(x.stress[, seq_len(x$nits)], 1, max, na.rm=TRUE) # summarize and plot the nmds object x: r2 x.r2 <- data.frame(matrix(x$r2, nrow=length(dims), byrow=TRUE)) colnames(x.r2) <- paste0("iter", sprintf("%02d", seq_len(x$nits))) x.r2$ndim <- dims x.r2$min <- apply(x.r2[, seq_len(x$nits)], 1, min, na.rm=TRUE) x.r2$mean <- apply(x.r2[, seq_len(x$nits)], 1, mean, na.rm=TRUE) x.r2$max <- apply(x.r2[, seq_len(x$nits)], 1, max, na.rm=TRUE) if(plot) { par(mfrow=c(1,2)) plot(dims, x.stress$mean, ylim=c(0, max(x.stress$max)), type="b", pch=19, lwd=2, xlab=xlab, ylab="Stress", xaxt="n", ...) axis(1, at=dims, labels=sprintf("%d", dims)) lines(dims, x.stress$min, type="l", lty=2) lines(dims, x.stress$max, type="l", lty=2) plot(dims, x.r2$mean, ylim=c(0, 1), type="b", pch=19, lwd=2, xlab=xlab, ylab=expression(r^2), xaxt="n", ...) axis(1, at=dims, labels=sprintf("%d", dims)) lines(dims, x.r2$min, type="l", lty=2) lines(dims, x.r2$max, type="l", lty=2) } invisible(list(stress=x.stress, r2=x.r2)) } ecodist/R/plot.vf.R0000644000176200001440000000075713576512762013647 0ustar liggesusersplot.vf <- function (x, pval = 1, cex = 0.8, ascale = 0.9, ...) { plotlim <- par()$usr plotlim <- min((plotlim[2] - plotlim[1]), (plotlim[4] - plotlim[3])) ascale <- ascale * (plotlim/2) x <- x[x[, 4] < pval, , drop=FALSE] for (i in 1:dim(x)[[1]]) { arrows(0, 0, x[i, 1] * x[i, 3] * ascale, x[i, 2] * x[i, 3] * ascale, ...) } text(x[, 1] * x[, 3] * (ascale * 1.1), x[, 2] * x[, 3] * (ascale * 1.1), dimnames(x)[[1]], cex = cex, ...) } ecodist/R/pco.R0000644000176200001440000000261313576512762013031 0ustar liggesuserspco <- function(x, negvals = "zero", dround=0) { # Principal coordinates analysis (classical scaling) # Sarah Goslee # x is a lower-triangular dissimilarity matrix. # negvals: if "zero" then negative eigenvalues are set to zero. # if "rm" then correction method 1 from Legendre & Anderson 1999 # dround is an attempt to correct for round-off error. n <- (1 + sqrt(1 + 8 * length(x)))/2 if(abs(n - round(n)) > 0.0000001) stop("Matrix not square.\n") n <- round(n) x <- full(x) dmat <- -0.5 * x * x # Double-center the dissimilarity matrix # Subtract row and column means and add the grand mean. dr <- matrix(apply(dmat, 1, mean), nrow=n, ncol=n) dmat <- dmat - (dr + t(dr)) + mean(dmat) deigen <- eigen(dmat) if(negvals == "rm") { c1 <- min(deigen$values) if(c1 < 0) { c1 <- abs(c1) x2 <- sqrt(x^2 + 2 * c1) diag(x2) <- 0 dmat <- -0.5 * x2 * x2 dr <- matrix(apply(dmat, 1, mean), nrow=n, ncol=n) dmat <- dmat - (dr + t(dr)) + mean(dmat) deigen <- eigen(dmat) } } else { deigen$values[deigen$values < 0] <- 0 } if(dround > 0) { deigen$values <- round(deigen$values, dround) deigen$vectors <- round(deigen$vectors, dround) } eigenscale <- deigen$values eigenscale[eigenscale > 0.000000001] <- sqrt(eigenscale[eigenscale > 0.000000001]) eigenscale[eigenscale <= 0.000000001] <- 1 deigen$vectors <- sweep(deigen$vectors, 2, eigenscale, "/") deigen } ecodist/R/crosstab.R0000644000176200001440000000645013576512762014073 0ustar liggesuserscrosstab <- function(rowlab, collab, values, type="sum", data, allrows, allcols, na.as.0 = TRUE, check.names=TRUE, ...) { # Converts field data in the form: # site, species, observation # into a site by species table # # By default, takes the sum of the data # Can also use "mean", "max" or "min" # Sarah C. Goslee # 24 Sept 2003 # ### # # if allrows or allcols exists, will expand the matrix to # include all of those elements into the rows or colums of # the results matrix # scg 20 Apr 2006 # # added data argument to simplify using data frames # added count option to type (length of matching data) # scg 2 Nov 2012 # # fixed bug with expanding single-row or single-column values using allrows or allcols # scg 17 Feb 2017 # added na.as.0 argument; scg 18 Apr 2017 # added check.names and data frame return 21 Jun 2017 if(!missing(data)) { if(mode(substitute(rowlab)) == "name") rowlab <- data[, deparse(substitute(rowlab))] if(mode(substitute(collab)) == "name") collab <- data[, deparse(substitute(collab))] if(!missing(values) & mode(substitute(values)) == "name") values <- data[, deparse(substitute(values))] } rowlab <- as.vector(rowlab) collab <- as.vector(collab) # if values are not provided, a count of combinations of rowlab and collab is returned # equivalent to table(rowlab, collab) if(missing(values)) { values <- rep(1, length(rowlab)) type <- "sum" } # if type is count and values are provided, combinations of unique values are counted if(type == "count") { values <- paste(rowlab, collab, values) values <- as.numeric(!duplicated(values)) type <- "sum" } values <- as.vector(values) results <- switch(type, mean = tapply(values, list(rowlab, collab), mean, ...), max = tapply(values, list(rowlab, collab), max, ...), min = tapply(values, list(rowlab, collab), min, ...), sum = tapply(values, list(rowlab, collab), sum, ...) ) if(!missing(allrows)) { allrows <- as.vector(allrows) allrows <- c(rownames(results), allrows) allrows <- sort(unique(allrows)) newrows <- allrows[!(allrows %in% rownames(results))] temp <- matrix(NA, ncol=ncol(results), nrow=length(newrows)) colnames(temp) <- colnames(results) rownames(temp) <- newrows results <- rbind(results, temp) if(is.numeric(rowlab)) { results <- results[order(as.numeric(rownames(results))), , drop=FALSE] } else { results <- results[order(rownames(results)), , drop = FALSE] } } if(!missing(allcols)) { allcols <- as.vector(allcols) allcols <- c(colnames(results), allcols) allcols <- sort(unique(allcols)) newcols <- allcols[!(allcols %in% colnames(results))] temp <- matrix(NA, nrow=nrow(results), ncol=length(newcols)) rownames(temp) <- rownames(results) colnames(temp) <- newcols results <- cbind(results, temp) if(is.numeric(collab)) { results <- results[, order(as.numeric(colnames(results))), drop=FALSE] } else { results <- results[, order(colnames(results)), drop = FALSE] } } if(na.as.0) results[is.na(results)] <- 0 data.frame(results, check.names=check.names) } ecodist/R/nmds.min.R0000644000176200001440000000175513576512762014001 0ustar liggesusersnmds.min <- function(x, dims=2) { # returns the minimum-stress configuration from nmds output. # (Results from nmds) # if dims==0, returns the overall lowest-stress configuration # Otherwise, returns the lowest-stress configuration of dimensionality dims # patched 2013-05-09 thanks to a bug report from Kellie Carim # superseded by min.nmds if(dims == 0) { x.min <- x$conf[x$stress == min(x$stress)] } else { x.dims <- sapply(x$conf, ncol) x$conf <- x$conf[x.dims == dims] x$stress <- x$stress[x.dims == dims] x$r2 <- x$r2[x.dims == dims] x.min <- x$conf[x$stress == min(x$stress)] } cat("Minimum stress for given dimensionality: ", x$stress[which.min(x$stress)], "\n") cat("r^2 for minimum stress configuration: ", x$r2[which.min(x$stress)], "\n") x.min <- x.min[[1]] x.min <- data.frame(x.min) attr(x.min, "stress") <- x$stress[which.min(x$stress)] attr(x.min, "r2") <- x$r2[which.min(x$stress)] x.min } ecodist/R/min.nmds.R0000644000176200001440000000206013576512762013767 0ustar liggesusersmin.nmds <- function(..., na.rm = FALSE, dims=2) { # returns the minimum-stress configuration from nmds output. # (Results from nmds) # if dims=0, returns the overall lowest-stress configuration # Otherwise, returns the lowest-stress configuration of dimensionality dims # patched 2013-05-09 thanks to a bug report from Kellie Carim # this function replaces nmds.min dots <- list(...) x <- dots[[1]] if(dims == 0) { x.min <- x$conf[x$stress == min(x$stress)] } else { x.dims <- sapply(x$conf, ncol) x$conf <- x$conf[x.dims == dims] x$stress <- x$stress[x.dims == dims] x$r2 <- x$r2[x.dims == dims] x.min <- x$conf[x$stress == min(x$stress)] } cat("Minimum stress for given dimensionality: ", x$stress[which.min(x$stress)], "\n") cat("r^2 for minimum stress configuration: ", x$r2[which.min(x$stress)], "\n") x.min <- x.min[[1]] x.min <- data.frame(x.min) attr(x.min, "stress") <- x$stress[which.min(x$stress)] attr(x.min, "r2") <- x$r2[which.min(x$stress)] x.min } ecodist/R/mgroup.R0000644000176200001440000000212113576512762013553 0ustar liggesusers# mgroup returns the Mantel correlations for group contrast # matrices computed from cluster groups across a range of # clustering levels. # The inputs are an ecological distance matrix # and a vector or matrix of cluster levels in any order. # # dlu # mgroup <- function(edist, groups, nperm=1000) { nl <- ncol(groups) if(is.null(nl)) { groups <- matrix(groups, ncol=1) nl <- 1 } outtable <- data.frame(nclust = rep(NA, nl), mantelr = rep(NA, nl), pval = rep(NA, nl)) for (i in seq_len(nl)) { # number of groups at this level: thisgroups <- groups[,i] if(is.factor(thisgroups)) { thisgroups <- as.numeric(thisgroups) } if(is.character(thisgroups)) { thisgroups <- as.numeric(factor(thisgroups)) } cl <- length(unique(groups[,i])) # create group contrast: gdist <- dist(thisgroups) gdist[gdist > 0] <- 1 # run mantel: m <- mantel(edist ~ gdist, nperm=nperm, nboot=0) outtable[["nclust"]][i] <- cl outtable[["mantelr"]][i] <- m[1] outtable[["pval"]][i] <- m[2] } outtable } ecodist/R/residuals.mgram.R0000644000176200001440000000012513576512762015341 0ustar liggesusersresiduals.mgram <- function(object, ...) { # for S3 "neatness" object$resids } ecodist/R/vf.R0000644000176200001440000000331013576512762012656 0ustar liggesusersvf <- function (ord, vars, nperm = 100) { vfcalc <- function(ord, vars) { lm.list <- apply(vars, 2, function(x, ord) lm(x ~ ord), ord = ord) coef.m <- sapply(lm.list, function(x) unlist(x$coefficients)) scores <- atan(coef.m[3, ]/coef.m[2, ]) scores <- t(rbind(cos(scores), sin(scores))) scores <- abs(scores) cor.m <- t(cor(ord, vars)) cor.m <- sign(cor.m) scores <- scores * cor.m coef.m <- lapply(lm.list, summary) r <- sapply(coef.m, function(x) sqrt(unlist(x$r.squared))) list(scores = scores, r = r) } ord <- as.matrix(ord) if(is.vector(vars)) { vars <- matrix(vars, ncol=1) colnames(vars) <- "var1" } else vars <- as.matrix(vars) nvars <- ncol(vars) if (any(is.na(vars))) { warning("NA values in variables will be removed\n") naindex <- apply(vars, 1, function(x) any(is.na(x))) ord <- ord[!naindex, ] vars <- vars[!naindex, ] } vf1 <- vfcalc(ord, vars) if (nperm > 0) { how.many <- rep(nrow(ord), nperm - 1) perm.ord <- lapply(how.many, function(x) sample(1:x)) r.list <- sapply(perm.ord, function(x, ord, vars, f) f(ord[x, ], vars)$r, ord = ord, vars = vars, f = vfcalc) if(nvars == 1) r.list <- matrix(r.list, nrow=1) r.list <- cbind(vf1$r, r.list) pval <- apply(r.list, 1, function(x, nperm) length(x[x >= x[1]])/nperm, nperm = nperm) } else pval <- rep(0, ncol(vars)) vfres <- cbind(vf1$scores, vf1$r, pval) dimnames(vfres)[[1]] <- dimnames(vars)[[2]] dimnames(vfres)[[2]] <- c(1:ncol(ord), "r", "pval") class(vfres) <- "vf" vfres } ecodist/R/addord.R0000644000176200001440000000645013576512762013510 0ustar liggesusersaddord <- function(origconf, fulldat, fulldist, isTrain, bfstep=10, maxit = 50, epsilon = 1e-12) { ## add new points to an ordination configuration ## by minimizing stress of new point location ## brute force, similar to PC-ORD method setgrid <- function(minvec, maxvec, nstep) { # find midpoints for each midlist <- vector(mode="list", length=length(minvec)) midlist <- lapply(seq_along(minvec), function(i){ thisstep <- (maxvec[i] - minvec[i])/nstep seq(minvec[i]+thisstep/2, maxvec[i]-thisstep/2, length=nstep) }) as.matrix(expand.grid(midlist)) } ########## if(missing(isTrain)) { isTrain <- c(rep(TRUE, nrow(origconf)), rep(FALSE, nrow(fulldat) - nrow(origconf))) } # set up extent to sample: +/- 1 sd osd <- apply(origconf, 2, sd) omin <- apply(origconf, 2, min) - osd omax <- apply(origconf, 2, max) + osd startgrid <- setgrid(omin, omax, bfstep) colnames(startgrid) <- colnames(origconf) # set up output objects fullfitconf <- data.frame(matrix(NA, nrow=nrow(fulldat), ncol=ncol(origconf))) colnames(fullfitconf) <- colnames(origconf) fullfitconf[isTrain, ] <- origconf stress.fullfit <- rep(NA, nrow(fullfitconf)) for(thispoint in seq_along(isTrain)) { if(!isTrain[thispoint]) { # fit a new point to the ordination configuration by brute force # 1. make a distance matrix that includes selected new point as the last row/col usethis <- isTrain + 0 usethis[thispoint] <- 2 # orig points are 1, focus point is 2, points to not use are 0 pointdist <- full(fulldist)[usethis > 0, usethis > 0] useord <- order(usethis[usethis > 0]) pointdist <- pointdist[useord, useord] pointdist <- lower(pointdist) # 2. which of the startgrid gives the lowest stress? pointstress <- apply(startgrid, 1, function(x) { pointconf <- rbind(origconf, x) sstress(pointdist, pointconf) }) conf <- startgrid[which.min(pointstress), ] stress2 <- min(pointstress) stress1 <- stress2 + 10 * epsilon # for stress, decreases thisstep <- (omax - omin) / (bfstep * 2) k <- 0 while(k < maxit && abs(stress1 - stress2) > epsilon) { # go finer and finer into the ordination space newmin <- as.vector(conf) - thisstep newmax <- as.vector(conf) + thisstep newgrid <- setgrid(newmin, newmax, bfstep) colnames(newgrid) <- colnames(origconf) # find stress for newgrid pointstress <- apply(newgrid, 1, function(x) { pointconf <- rbind(origconf, x) sstress(pointdist, pointconf) }) conf <- newgrid[which.min(pointstress), ] stress1 <- stress2 stress2 <- min(pointstress) thisstep <- (newmax - newmin) / (bfstep * 2) k <- k + 1 } fullfitconf[thispoint, ] <- conf stress.fullfit[thispoint] <- stress2 } } list(conf=fullfitconf, stress=stress.fullfit, isTrain=isTrain) } ecodist/MD50000644000176200001440000001035013576700021012214 0ustar liggesusers618d920319c4fca17a69510215a99ec8 *DESCRIPTION 92b7eabdaca7f4c268f89e0853207523 *NAMESPACE d2f1f4567ff445527d0f24bc77eb18f1 *R/MRM.R 46ede2c4d3401991a8ebb65990c90e87 *R/addord.R ae69c46352ed5e4ce2b3adbb6b3149ca *R/bcdist.R a3a0cc6bfb7ecc377d4cba84892ce45a *R/cor2m.R a6ac5872408b8e3203c99014a5a99f1f *R/corgen.R f6b193f93eb488caa65b3cc7ffeaaced *R/crosstab.R 4d1bc8e91f13cf801135cfe448e902a1 *R/distance.R 835e62b78a342d108b4532582710e698 *R/fixdmat.R a16a1c88648c2b858b3accc16c6a6cc0 *R/full.R 70f5dc838721bfd2abdfa8569793a78b *R/lower.R 44d3de7bdaaade63be5209f20917c838 *R/mantel.R 9a143d4d9279f69b094f7574d2c66213 *R/mgram.R c64a8b075dc791f39cabf5e6d4af6a84 *R/mgroup.R 3a1c387586fdd79a8776b410c9a8fead *R/min.nmds.R 4153165ca4e9440df838a8b1a3e1988d *R/nmds.R 6b0ad2411dd62150634433984ccf84b7 *R/nmds.min.R c6e5800257e552c9b04350a9f522b9d6 *R/pco.R 2429b18210e6eb4b65fae1af7c329e27 *R/plot.mgram.R bd8887f1c5246a9a47e8766290216b93 *R/plot.nmds.R f73448c19e487680d9eda76ba6967f78 *R/plot.vf.R 0fc5e24ab82611e55c3c2d279d2300d1 *R/pmgram.R 3edb216d47fc3f2394209d4ef7f40955 *R/residuals.mgram.R 42b2064bcfaf9a58e8ebcd02fc4d3d9e *R/vf.R 269c930c0114abd2c812c7370577d468 *R/xdistance.R deddb65651d99c96a582aa78f839752d *R/xmantel.R 87b3be79ba98bf8c1de0fdff7846e4eb *R/xmgram.R db33b4158c11a6862982c0deb9c6015a *README.md 5efda4a880b72d8866aeffd7407f794f *build/partial.rdb 94e8c2b6b678b180457fa163912d3d16 *build/vignette.rds 13c854d8d590fa79dc316628ab0b272a *data/bump.pmgram.rda 30d5b5d4e55edba01b24da1e0b460cba *data/bump.rda 6d3e215e51dab584c898839558991136 *data/graze.rda c6f3963d78b714e7184a7ea09ddf9814 *data/iris.fit.rda 487aff36b22f742501bd18d3054dfd18 *data/iris.nmds.rda cd86940eef6a822ecfd87569cb3ec77d *data/iris.vf.rda c8c954eb6921bedc8f9c24e833c08526 *data/iris.vfrot.rda b204771dff335c364aabb3a6e8f54be6 *data/z.no.rda 77a8d71949fae669d76c6a4ef95e66f5 *data/z.z1.rda f47f634fbe21cca4076998086898f770 *inst/CITATION 205271f3d799059e5f3eb4a3a3bbc568 *inst/doc/dissimilarity.Rmd 0f3ea7c17e878c3da478400172f76d9a *inst/doc/dissimilarity.html ce2ff773608bb738bd3e6a797e35e000 *man/MRM.Rd 697cee16af18f9cfc0888e1b49464c83 *man/addord.Rd 896281685766f866b18a647ca4686b05 *man/bcdist.Rd b5185d72e634620a362c362844dc8244 *man/bump.Rd ebb224fb20719ab6fab64031b0c12b14 *man/bump.pmgram.Rd e6b9ab94534537576561009f321d806c *man/cor2m.Rd 9b90d64da318102da8efc1de43e84f82 *man/corgen.Rd 400c1c34d4c579ed3e6c203d97a0757a *man/crosstab.Rd 24430cb4d9fc5343ae1a94a7d11a9563 *man/distance.Rd 81a6795b0f5396ef52c22ec614b97fa4 *man/ecodist-package.Rd 599455d49118abd375c58788d9c6291f *man/fixdmat.Rd 754485899ec74a1f60f2531a8be37127 *man/full.Rd caa6d24b2d4bb1e7b1fc83c39ce89a6c *man/graze.Rd 6053fb0e92af994b3dca4c3274cb532c *man/iris.fit.Rd be2e2868917138b9b1b3d44f81967206 *man/iris.nmds.Rd e4b5951132e9c8860cb88a350ff85658 *man/iris.vf.Rd d9db0830bb5b84e9e48b94847cade17d *man/iris.vfrot.Rd 6218940b6fdc911a672e1718488fa724 *man/lower.Rd 13671bb73e27e3785a8782ba9d419782 *man/mantel.Rd 331971ecb3387c814edac6fadfcceedb *man/mgram.Rd 104be3edc3f0ebbfd547c26660ea7df3 *man/mgroup.Rd 53043c4b5b64981c255a5d081b86142c *man/min.nmds.Rd 0362bfc7c7b01c6162b20f20159a9a48 *man/nmds.Rd 492e52c276d6c1a6684e1edffbf0f433 *man/pco.Rd 1a58c3415d985beac82eeb25767a39b9 *man/plot.mgram.Rd 9dfb72ca1556ab4b785b4c721777ae66 *man/plot.nmds.Rd 18b6edaf6860542e8b6a8adb29eff74a *man/plot.vf.Rd ecbbbf074b15ef20353d402044bb7748 *man/pmgram.Rd c197b9e39d0d96512923ffad02742ef3 *man/residuals.mgram.Rd 81ab32606567c225d4288d3bc341ea96 *man/vf.Rd 344d215a027627c44d8a1d2262e383c5 *man/xdistance.Rd 6214ce03553bbaa9950fa53c9750c46d *man/xmantel.Rd 826e19a0598836699d0486a35c185feb *man/xmgram.Rd d2c3e1dbf7218fe03c5224be0febb8d7 *man/z.no.Rd 3cf440ab38db7938ae6d2e130ab95a42 *man/z.z1.Rd 7ad45eea54b4e506438c8dd620473f96 *src/Makevars 925cb98d61564e4b1999b8950330e08a *src/ecodist.c 41278d00a33cc545da4aebc4e8f7ab43 *src/init.c 9ddd5708c58d58e3550696f3119e87ed *tests/testthat.R 80c568577c3aae89c23492c1caeb9b7d *tests/testthat/test-MRM.R abfb26f46bd56ae9975457597f9b0dd6 *tests/testthat/test-crosstab.R 3ea6ed914e3d4cdd9fb9b8dc1a912dbb *tests/testthat/test-distance.R 8bdf878f30f5cac8a974890afca58fc9 *tests/testthat/test-mantel.R 0360a6ade8130399a6be6f6588a1f751 *tests/testthat/test-mgroup.R 205271f3d799059e5f3eb4a3a3bbc568 *vignettes/dissimilarity.Rmd ecodist/inst/0000755000176200001440000000000013576532032012667 5ustar liggesusersecodist/inst/doc/0000755000176200001440000000000013576532032013434 5ustar liggesusersecodist/inst/doc/dissimilarity.Rmd0000644000176200001440000000621613576512762017003 0ustar liggesusers--- title: "Dissimilarity Cheat Sheet" author: "Sarah Goslee" date: "2017-07-12" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Dissimilarity Cheat Sheet} %\VignetteEngine{knitr::rmarkdown} --- **Things to do with dissimilarity matrices** _(ecodist functions are marked in **bold**)_ _(untested ideas marked with ?)_ Description | Notation | Name | R function ------------|----------|------|----------- Relationship between two matrices | D1 ~ D2 | Mantel test | **mantel**(D1 ~ D2) Relationship between two matrices given more | D1 ~ D2 | D3 ... Dn | Partial Mantel test | **mantel**(D1 ~ D2 + D3 + ...) ||| Spatial structure in one matrix | D1 x S | Mantel correlogram | **mgram**(D1, S) Spatial structure in one matrix given more | D1 | D2 ... Dn x S | Partial Mantel correlogram | **?mgram**(residuals(lm(D1 ~ D2 + ...)), space) Spatial structuce in one matrix | D1 x S | Multivariate correlogram | **pmgram**(D1, S) Spatial structure in one matrix given more | D1 | D2 ... Dn x S | Partial multivariate correlogram | **pmgram**(D1, S, D2) ||| Spatial structure in the relationship between two matrices | D1 ~ D2 x S | Mantel cross-correlogram | **pmgram**(cbind(lower(D1), lower(D2)), S) Spatial structure in the relationship between two matrices given more | D1 ~ D2 | D3 ... Dn x S | Partial Mantel cross-correlogram | **pmgram**(cbind(lower(D1), lower(D2)), S, D3) ||| Ordination of one matrix | | (N)MDS | **nmds**(y) or **pco**(y) Ordination of one matrix given more | | (Partial (N)MDS | **?nmds**(residuals(lm(y ~ z1 + ...))) ||| Grouping of items based on one matrix | | Cluster analysis | hclust(y) Grouping of items based on one matrix given more | | Partial cluster analysis | ?hclust(residuals(lm(y ~ z1 + ...))) Grouping of items given space | | Spatially-constrained cluster analysis | NA ||| Multiple regression | D1 ~ D2 | D3 ... Dn | Multiple regression on distance matrices | **MRM**(D1 ~ D2 + D3 + ...) **Ways to calculate dissimilarity matrices** Description | Result | R function ------------|--------|----------- From a site by sample matrix | Symmetric matrix with zero diagonals | dist(x) or **bcdist**(x) or **distance**(x) ----------------------------- **Things to do with cross-dissimilarity matrices** Description | Notation | Name | R function ------------|----------|------|----------- Relationship between two cross-dissimilarity matrices | D12 ~ D34 | Cross-Mantel test | **xmantel**(D12 ~ D34) Relationship between two cross-dissimilarity matrices given more | D12 ~ D34 | D56 ... Dn | Partial cross-Mantel test | **xmantel**(D12 ~ D34 + D56 + ...) ||| Spatial structure in one cross-dissimilarity matrix | D12 x S | Cross-Mantel correlogram | **xmgram**(D12, spaceX) Spatial structure in one cross-dissimilarity matrix given more | D12 | D34 ... Dn x S | Partial cross-Mantel correlogram | **?xmgram**(residuals(lm(D12 ~ D34 + ...)), spaceX) **Ways to calculate cross-dissimilarity matrices** Source | Result | R function -------|--------|----------- From 2 site by sample matrixes for the same sites and samples (e.g. different years) | nonsymmetric matrix with nonzero diagonals | **xdistance**(x, y) ecodist/inst/doc/dissimilarity.html0000644000176200001440000001551713576532032017221 0ustar liggesusers

Things to do with dissimilarity matrices

(ecodist functions are marked in bold)

(untested ideas marked with ?)

Description Notation Name R function
Relationship between two matrices D1 ~ D2 Mantel test mantel(D1 ~ D2)
Relationship between two matrices given more D1 ~ D2 | D3 … Dn Partial Mantel test mantel(D1 ~ D2 + D3 + …)
Spatial structure in one matrix D1 x S Mantel correlogram mgram(D1, S)
Spatial structure in one matrix given more D1 | D2 … Dn x S Partial Mantel correlogram ?mgram(residuals(lm(D1 ~ D2 + …)), space)
Spatial structuce in one matrix D1 x S Multivariate correlogram pmgram(D1, S)
Spatial structure in one matrix given more D1 | D2 … Dn x S Partial multivariate correlogram pmgram(D1, S, D2)
Spatial structure in the relationship between two matrices D1 ~ D2 x S Mantel cross-correlogram pmgram(cbind(lower(D1), lower(D2)), S)
Spatial structure in the relationship between two matrices given more D1 ~ D2 | D3 … Dn x S Partial Mantel cross-correlogram pmgram(cbind(lower(D1), lower(D2)), S, D3)
Ordination of one matrix (N)MDS nmds(y) or pco(y)
Ordination of one matrix given more (Partial (N)MDS ?nmds(residuals(lm(y ~ z1 + …)))
Grouping of items based on one matrix Cluster analysis hclust(y)
Grouping of items based on one matrix given more Partial cluster analysis ?hclust(residuals(lm(y ~ z1 + …)))
Grouping of items given space Spatially-constrained cluster analysis NA
Multiple regression D1 ~ D2 | D3 … Dn Multiple regression on distance matrices MRM(D1 ~ D2 + D3 + …)

Ways to calculate dissimilarity matrices

Description Result R function
From a site by sample matrix Symmetric matrix with zero diagonals dist(x) or bcdist(x) or distance(x)

Things to do with cross-dissimilarity matrices

Description Notation Name R function
Relationship between two cross-dissimilarity matrices D12 ~ D34 Cross-Mantel test xmantel(D12 ~ D34)
Relationship between two cross-dissimilarity matrices given more D12 ~ D34 | D56 … Dn Partial cross-Mantel test xmantel(D12 ~ D34 + D56 + …)
Spatial structure in one cross-dissimilarity matrix D12 x S Cross-Mantel correlogram xmgram(D12, spaceX)
Spatial structure in one cross-dissimilarity matrix given more D12 | D34 … Dn x S Partial cross-Mantel correlogram ?xmgram(residuals(lm(D12 ~ D34 + …)), spaceX)

Ways to calculate cross-dissimilarity matrices

Source Result R function
From 2 site by sample matrixes for the same sites and samples (e.g. different years) nonsymmetric matrix with nonzero diagonals xdistance(x, y)
ecodist/inst/CITATION0000644000176200001440000000110013576512762014024 0ustar liggesuserscitHeader("To cite package ecodist in publications use:") citEntry(entry="Article", title = "The ecodist package for dissimilarity-based analysis of ecological data", author = personList(as.person("Sarah C. Goslee"), as.person("Dean L. Urban")), journal = "Journal of Statistical Software", year = 2007, volume = 22, issue = 7, pages = "1-19", textVersion = paste("Goslee, S.C. and Urban, D.L. 2007.", "The ecodist package for dissimilarity-based analysis of ecological data.", "Journal of Statistical Software 22(7):1-19.") )