ggpubr/0000755000176200001440000000000014371467262011554 5ustar liggesusersggpubr/NAMESPACE0000644000176200001440000000661714370060431012767 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(drawDetails,splitText) S3method(print,ggscatterhist) S3method(print,ggsummarystats) S3method(print,ggsummarystats_list) export("%>%") export(add_summary) export(annotate_figure) export(as_ggplot) export(as_npc) export(as_npcx) export(as_npcy) export(background_image) export(bgcolor) export(border) export(change_palette) export(clean_table_theme) export(clean_theme) export(colnames_style) export(color_palette) export(compare_means) export(create_aes) export(desc_statby) export(facet) export(fill_palette) export(font) export(geom_bracket) export(geom_exec) export(geom_pwc) export(geom_signif) export(get_breaks) export(get_coord) export(get_legend) export(get_palette) export(get_summary_stats) export(ggadd) export(ggadjust_pvalue) export(ggarrange) export(ggballoonplot) export(ggbarplot) export(ggboxplot) export(ggdensity) export(ggdonutchart) export(ggdotchart) export(ggdotplot) export(ggecdf) export(ggerrorplot) export(ggexport) export(gghistogram) export(ggline) export(ggmaplot) export(ggpaired) export(ggpar) export(ggparagraph) export(ggpie) export(ggpubr_options) export(ggqqplot) export(ggscatter) export(ggscatterhist) export(ggstripchart) export(ggsummarystats) export(ggsummarytable) export(ggtext) export(ggtexttable) export(ggviolin) export(gradient_color) export(gradient_fill) export(grids) export(group_by) export(labs_pubr) export(mean_ci) export(mean_range) export(mean_sd) export(mean_se_) export(median_hilow_) export(median_iqr) export(median_mad) export(median_q1q3) export(median_range) export(mutate) export(npc_to_data_coord) export(rotate) export(rotate_x_text) export(rotate_y_text) export(rownames_style) export(rremove) export(set_palette) export(show_line_types) export(show_point_shapes) export(stat_anova_test) export(stat_bracket) export(stat_central_tendency) export(stat_chull) export(stat_compare_means) export(stat_conf_ellipse) export(stat_cor) export(stat_friedman_test) export(stat_kruskal_test) export(stat_mean) export(stat_overlay_normal_density) export(stat_pvalue_manual) export(stat_pwc) export(stat_regline_equation) export(stat_stars) export(stat_welch_anova_test) export(tab_add_border) export(tab_add_footnote) export(tab_add_hline) export(tab_add_title) export(tab_add_vline) export(tab_cell_crossout) export(tab_ncol) export(tab_nrow) export(table_cell_bg) export(table_cell_font) export(tbody_add_border) export(tbody_style) export(text_grob) export(thead_add_border) export(theme_classic2) export(theme_cleveland) export(theme_pubclean) export(theme_pubr) export(theme_transparent) export(ttheme) export(xscale) export(yscale) import(ggplot2) importFrom(dplyr,arrange) importFrom(dplyr,desc) importFrom(dplyr,distinct) importFrom(dplyr,do) importFrom(dplyr,everything) importFrom(dplyr,group_by) importFrom(dplyr,group_nest) importFrom(dplyr,mutate) importFrom(dplyr,mutate_if) importFrom(dplyr,pull) importFrom(dplyr,select) importFrom(dplyr,summarise) importFrom(ggsignif,geom_signif) importFrom(glue,glue) importFrom(grid,drawDetails) importFrom(magrittr,"%>%") importFrom(purrr,map) importFrom(purrr,map2) importFrom(rlang,"!!!") importFrom(rlang,"!!") importFrom(rlang,.data) importFrom(rlang,syms) importFrom(rstatix,df_arrange) importFrom(rstatix,df_group_by) importFrom(rstatix,df_nest_by) importFrom(rstatix,df_select) importFrom(rstatix,df_split_by) importFrom(rstatix,get_summary_stats) importFrom(tibble,as_tibble) importFrom(tidyr,unite) ggpubr/tools/0000755000176200001440000000000014332653662012712 5ustar liggesusersggpubr/tools/README-ordered-bar-plots-1.png0000644000176200001440000015023114334142172020027 0ustar liggesusersPNG  IHDR@MnEiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i@6G:@IDATx$E& Q""I0AgEEѿDEE}U<I% E$,yI|Kjizޝ{W;==]Uߪ:uI- " " " CD`UE@@4tUHR:U` @j" " " CG@U ," " " Hm@D@D@D`H*WE@D@D@$   @CW* # h\6 " " "0t$ ]" " " S@D@ `a_?ɓlfhl.\hVyaʔ)}fD`b'|b2SD`B@P9ߗ-T{6k%D&MbOs-|˺m-]\ɓ'_W%k9S" y$Q9RGWRuV^rL 2-_/ɋDfSy_, Ph*N@6@U>:D' hװ'" " "A@PAg?M4_J!" v "0Pzq'͙3ƪB͛gsXN" hC&`}# y{k_v_k='|r\cmᆶ+_J?9.L@HI#@`ܹvی3`uw ;lG}>6˗~vu׍=vmݞz)w3 s׾6VE4Bξk^{}ӟB?yc:3mu׵o}[}YfUW]._v{OSO=wxs}نSC~zOVZɖ[nUlڎ iUqE-Yge3wӎ=X 즛n-v뭷ڕW^.׏~#e]lUVi>h('hK.xȲ=v_}Wb/=[{oc) mE&UqE mY;;aw=϶n;[k'?I!E#C9${7'96׿>_K_}߰N:i\hRhC/~6{l?a D@0ն:W_#lm'79,a;KHw^.`tw.Ʋ.;0{_ w!h3v7oo| Ӡ]~/JGL g.-o}[2v?^Kg wv=yv饗уV]uՠEYm\a²XĀ\}a4fm")}' hW 8^ lFa@J~7/&lboq_r\.xv5״wz^g?Oo7H|aK4V?yǘ!%WUqGx=Yϲ7M۬Ynb-lvk-KӦMq}FQG4'k=ϵӧG>Q_'>aks̙viVtD` hא7X;s똹; vpAJ%a_״mF/}'=QN # "0$ c@_<}dZqW8eXD@ @n) ~K,a_|q?T" "04&54UAE` oe2Y.^{8[j)&czZkޜ~ 4&էʓ?v_UOR{\FXe q;nq>~izjIIh?ٞ "PM@P5#]!" " "0h0*T& `$M UqD@D@D@ Hf+D@D@D@& @BUj  F@PGD@D@DjFBD@D@D`4*T& `$M UqD@D@D@ Hf+D@D@D@& @BUj  F@PGD@D@DjFBD@D@D`4*T& `$M UqD@D@D@ Hf+D@D@D@& @BUj  F`B @wy͝;wU#" " "oJ` c7#'" " "0L(hՍ#" " "0J$X%+" " "0$ n(g" " " D@(U" " " K@֍r&" " "0J$X%+" " "0$ n(g" " " D@(U" " " K@֍r&" " "0J$X%+" " "0nzق-{ѧ k- 0 竳n=ʪa[/X:] " " "0 h lסJ " " "% @]" " " 㟀_*@$u L" " " ]%0]." " "0 HutI@Pt'0!RE,gw>De2,[n6iҤku% .u*266}vu@D@D@D`آ@D@D@D` Hcຝ' hׁr " " "0$1pND@D@D`@9cn'" " " HZu1E&ZZE{]t81n?hkj~C=42Νkvmᆶ+{mw߈kED@D@D@sh.̎?x;cꫯ]wuD?p;c:fϞm;I44$087]y啶[,?䓶>74>]w͜93@;cSN3fyg[â*jvec , ?dᮻ 96mZ mw=|翍6ȦOnfjԳseYp VD@D@jxSz>AsG۫^*[wuy4AJҊXc5NO 1Kv_={qMyoj|![?y_y&nSLos" " "S(16=W]uU0rG '>Xa:kְ)ᩧЅ:" Z:[)2"" " .<϶M7^ch~2eMܙ-GK0V^y߈ED@D@D@ ,2 B/{vO>6|s[}/>h.o]psK.dX" " " "PDSRteK/tDJ-mvW3g-\8rMh'4"}. t'o|w;`8BK%vm 7`m]D@D@D@D)1w_[|Ń'hv{]vˇrH(&lC=nV{m& jZPH`L ^mqg냰s[ne̓tI-k͟?0ZAD@D@D@z%0FмW[`n<9e=aFhD@D@D@D_\"hrYg2QAD@D@D@M`Ly'" " " MHjBMqD@D@D@5 @y&$58" " " 㚀q]}ʼ@PSqM@и>e^D@D@D  @M)& h\W2/" " "Є"$=_ЪqI6Y[K_oU| ?7Os*+V_&O g+aqO@и?sE8@d4*QE莀xj @@DAD@D@D;㥫E@D@D@& @UHꎗ$MJ",XX߉"yʷ*TEho'YcGJ |V۔rX K,ry vztxLȼkt - JM(" " " cF@И֍D@D@D@A CD@D@D`H3Ժ4(5| @cZ7&1# hPF" " " B@&&`>x5C=eXeZq [il䕰t@$P m߼ۧ<{nU^ D@D@D4E!" " "0HWե̊~PT" " " ㊀qU]ʬ@?HE!" " "0HWե̊~PT" " " ㊀qU]ʬ@?HE1Z=cn" " cJ@n ?湳+jUmMmLq_x[FJ-VLKuND@D`4*q"\zGe^y e/'k_eŃ" " &fT" " " %$O" " " Y*@  @%p$ hb֫J%" " "PB@P $" " "01 hĬW8Xއ&MG@IS,N/[CP%%] " X6@ .|&'Gz?ShL`5@7x}CK/͛gouQ. 1w\;#O9s;`Jkt "PM`i+lcKmphu ?wtϞ ?=" "0Tkqg+}_=î |?9;cm}N;ٵ^a$:d1Oؼ{fUd,|^V67:+"  @gyy[nJ뮳3gώ;9SlƌvynhH" " " /o}[m,L=^>{FmdӧOYjd۱t " " " \:蠃F.[oնzpoUVY%AhE@D@D@D1]G=ڻ#)" " "  ~7d[-N 'tMo[ϦMΟp   t%mOAe7T.?ukm_~{Ʈmu5" @k|{gXTll˼u79cX^I:_җ\sM; .[{\D@BzժSOU]E@&w_oS>,?{1^xå∀ vVi"|;Wy} &g7MO|v%U@" M/6fڪ&"0`j @K-Tؑ?^(ޜKbWqx$p9XkvgK<5^٩3{axm?l뮻n~sO~2`Ux%P['x~/Q~;k3D@@U|3i%Е2ga_k6h#qvuVZktsE@D`@ylo_>$alu_)"0;zXc׌3Kc|sgk @ t,%Еv#<2lyK؞{)@ :_(Hi,mKp5QD`$C9${1|馛@,lG3 " "5[JتJ G$P[?}_8/)CӃw޹D@D@D@D` 0x-oyKG9m?$u Xd̙c nm'D`pl#4@b.>zة" "0?xJ-g>kL4 }͜9x*-b<`e<^*_@0] @_җl饗6ޮ|1nj(ܹsl܇?a @m:$] @w} ]yFtW\q=@c7<QNID@D@D@ƈ@Wqg~xA/@}0FYmD@D@F]weO=TmE"ҏH裎:^~[a:+v KO60ePv~#P[b }C\A!K`r lf6k֬Qt $ ri+^ /RK(N;d뭷ވs"" "0N{'+hD L+Oo=}YZN`\`ܨ Icj+ v~kvC8;Þx_} PtAJ9[gu4t," " B3ϴٳgW.iӦU^ D -7s9_1}`l`y0 hN=V%ǀ@W>`袋lƌ^H8J-D@D@`_ʋ׍َQ!pM7ٯ~ʴQ` TV c. ?dGɅ +t@7p^NHLׁ 0PZ-l]tE$wuD@D@D@D @]|}meq~喳ۮ}.Opjxj6gΜq]w]UL`vpx% 9>D@D@D@DK'a׃s衇s{tA6>ett8,tI6m4[oϠYTXFЗ_~yn=oh 7N@ TD@D@D@Dr ߅Tz" " " "бP4լB$4t," " "0$ E5" " " ) @)   @CQ*@J@PJC" " " CA@PT )" " "бP4լB$4t," " "0$ E5" " " ) @)   @CQ*@J@PJC" " " CA@PT )" " "бP4լB$4t," " "0$ E5" " " ) @)   @CQ*@J@PJC" " " CA@PT )" " "бP4լB$4t," " "0$ E5" " " ) @)   @CQ*@J@PJC" " " CA@PT )" " "бP4լB$4t," " "0$ E5" " " ) @)   @CQ*@J@PJC" " " CA@PT )" " "бP4լB$4t," " "0$ E5" " " ) @)   @CQ*@J@PJC" " " CA@PT )" " "бP4լB^jZi~u," " " =Hhܹvaنnh+v}\X% " " " HO?ݎ=X;묳lٶN;Aj" " "  03뮻fΜw1$})،3γvۭSZ" " " CH`4@^x-bc6ӧ۬Yt " " " M oUVY%AiXc SpB{DF\hmV]?aD1.jKlmmQ4/XhS>'G|O)?( yǧ}I^sE?#Y}'։u+F^^㹁M2ŅΎB͛7/;|:O}}s\0?.6K{0m? Sjώ_ƟIS3ϜCeGMdž\7~@2#^\IעnQO^{{k|ؗtSaȤgE*'vwe]v^ێ89? " " " "PESRc_mlΜ9jk]wQ'#D{bn.ҧ4&0p&lC=nV{mgUDN"c'tM6[o=[s5mv 'd O8#h/GhO=?aCo1)sn/x lƌ]gGgimm]ǧ:B)Cp駇0l?I8묳~vhCMϚ5˖_~y{K_$wyg=+hvjE/jUzU˅_׷|oOo[SNm SO=( e7>Ŀ{׾ (( ]m?$  D@D@D@ZSu-Xxj#MOqK]{3:xܿIܿC@s^7Q_TܿK,D4>7%K.d#>j&^tZ@\츚?M717]k|pӏ3o7{k2N c("%"2:/" " "0a HUTDFE@D !iyy?͙3|N{z+l-Nx$+S~ $x[aO;;Sl뭷_?ͷU.]S} >u]gINv79t%lYgs&ߣH ?/~1^gD^mo݆m~Yw%]{*ڇw;qFG; @Q˝ܑ_jZP75s~TeCNַU';Ol; "-|z'_[0Ń?mݶ?Oӻ ùԇDD>AufO~w!Bkߦn|hu8PB\wlM;P.ȃ~+{8NhsuZ=y1 wu*ٺr~-½-K_HG|.00=Y?N||G/l 0q<Uu@/|!ħߧq3m>!OK[/K}h/cj64R> 宻ft_ͅ"1J ^+ӟ~w];C4 g`^Ue}c3AcMOx;_9/ŝYM;$ poFM 4`ؠ :ꨣs3uKn^/uʠCAv3ggxN3zסYm}򓟌ڟwӟtx|">o[;|` YS#/z׻6m'mO~՝4Ư᳟?ЇmAcu]wĽ_\H2wBFKk i0-mj06̶@}/hq|Pq>o;h{s8z.N$=h]mzU.}ZѴ3z4x%~7oXA f'̊d3r>h7y2,,}Le񥧠~GR\hgh~hSf3 l{ѮH9h-\?4*9 .3,>ȏ8[;U_?Сt(3eo?;4U#./}k-O4EeNh" iƫM|6OeY=Zx&f'{|B>cMyVNG#ݜ+UQ*8e bTW*ƥ41XL,,,4r/4nqܐ2=墢$k\3к6ycJWp BcNaE, yq*Pg]S Jr^iB@xAeUƯ,3?2N .NCi1`;{eVf 0in ,+D=@ԈOlYnw" r._:蠰[u]A*{~C:#nW].]&L uun zC9"XDa,t[mwC0\D귨ڎIǟkԓm 3{HBAQc(r/E{1pw&@1% T` 䅥ԕi\, c9&w0&ƒ~g^4/LƮhs[zL,im(m?Eـ2@xy+KށG?QsA6XzdS6bHHl XNnXr/~XgQw,b ,bMP]\Xeu _&/ ^PɏbxJӇ@` vG\ 0g) a@?Rr6ڇ1 G> }ecEg>46@4c30(fu4KLx53_ ֞]i:pyr_hFI鰱UNg!aWB?pMV3nL&eW#lS6ͼƗU:~bz+vP|Py6Iص>A0Imݢix0B\` ;B%;aִC$+φ(nc_}6U{n& ˥Aءm lxvEؙA鰱ᢓfƎbeCꏶ@?I1OIG,uXؐ lacPQlxC=2Vlڪlت $2^f` |SEsia( o||>΅>!ń ,}#c P]3= ~EQqǡIqJE4~gwb-Ҁ7ĠvN;ܢb-vUiv05Nl,hI MJ~QF."գk&Z>`ܐ3/K-쟰!lEKh\ ;f@IDATQǟ A}KIoΡ 1NI=pТNKR,D5 <;$( a))CS6%0v^NeIhѵMlHx\Pn7*&XF־Mmm>]Or-CX.c㓥]d?͐kiv8P%#+4=Y-sCc7 O>KBy]M k1ݡz^ϲдei fp̼C]/WHnp%#.eg`1./ iYSg'nf̪2a0qiKe'2v/+lݣ* )) RKPhOкdڕ:eJE@}BFM5hˡ|fzeT,P,adZr6y[˃6$LmPr@Y} >.TG{䙠ngVKSWd&Y'b\FuҌ0ƗZ3,x-#Khء C 4nGv8Lq*M^ٮêU; `?hc\ vfâ%:qL}_EH@S8㌠m/&={# S^@u7${o-_|/˻zĠa僯n|Fk__'>2k'+s-.@WGnpׅʻŸ8.I}pe3,y4H.|vg$.VjВ)?4{I ځO:Ĉ9? U¼{-F{6&>h@hE[^xA@{G&_>iw[Ls?)_aBA, o&7;p೵W [}=U܆ :/:nB`]dq,O\C:F4 "|:-xP&\%][e }s=?K< ƀ36:{5UWv2r`F֩1a;_^ɵ%s[>e31ׂP%4Eq6w!+f,:}>mU,on9f >gev2nN -p7 _)?KΌaGL1\UUMhU'MfI㆜^ҹw3\T2e2`S/+?n1%00SO:>7BEu\P&]ؽB|1X!"0II\ =#1?އ FM 5f#' E1o1OwB3ql ҿ*?@tw]~ؐuۘ7dG@[@A B AAD~`k&g mʦH~!'6iE )xѬl yЄ # hcb~K<5&YC{A7/K$Rz&g;_r'[ӭs/G5Hbɣn+7if ?#,e  wM,Ҏ#gJ5h^, ҽUghGÂ}? ,1GlA G:Qډ @1=VE1˧u,2v ?SI=ƀWhepf0(+{%Kd|Ђ ":o FF,>het4H,G1]?̇WLyߋ ]rQ|#Ǧ}'\b>x>ᙝs d8W٦ &si_owʭ_=G9#!k} iw/଎W?\\c`HaZ00 _Ym^ŁtZx4/:}ӫ,00 Adx}uD٪-TI7 F!#=` cP^l|&: ~=\,.-l%x g#/7_WpK ]8M}6N~Fck=bp,wn ?҄  x'cu{G~|FR,`<ߏE06R^(&;8g7|ݵ7*^)K# =xp³'`5HϊpA]j.;^mMC^i6#|.1MFpJ|Q'mS /}݄^7 6973np0ȆP0~NٔRho> /^+hlff(Oάw+4QcO!e 2KAeCf[i] : Mhi } =eN?PV4&6F,5d Ct7@}Ĭz/EUfZUf*rcm; z&Y1FMy#KU{+\rTvL]gC4&OqwYXL?l/>%S6`/ d,}+X^mscg_x.pч ,RnBwv7)Ok(Xk2?8ys4,]1ʥC(,`ʻ_Qv:xHh$˖.2#W\ƫBK] _K7T"ـ@Cr*4^_>{e,Q%{S?Aj,`&T&M60xp7p ,52DV<,;%AcLܧ,4)5dF4nqT#؀.j2)} b]VFx쾰MiMIc Vܛ>)qh{0Y8X>0Q7AQ *$?@gNI1{2Yz@7ϖշv/ٟF|Gh.E;/0Volož9 yF dVe0@"$f {`v(n.?Yt,YJ6OlY'`msFfv\0t'l}EBk3 B= 8!P0(i@{ iR4>Fdl&oߗyC{f6٭͊/H|&34x FypZ~^"JUM81+큗?^=H܏ YE;Ey6o|*@&.;xPzvYRk:zEFI'zqyӉvѣřK;EPP$\f ,Cy)(4B4&OϜ93h1%rbl /d-(:f"?%e^!f^;fydY`S&(9s0S7ò!$RO,3ye>4ܫ*e#,[)o ptq*Jf=^'(n^őgHH7YX1 V?'}+KА1Q&UQ p4~(đ-#kt$p  @1-:#fH^iejFum6r۫ BEo]Ꞵ 4i m w:7l0xN9!x(.~!33/""Z@I0tr̐3Xb 4iAc\>*6k,t;19$ݴ^4Hi{-?BKU@̣7l~48䁐uH;-mf<;0(Foy|DZz4Acε<,^|ea1SDF|/C#5A*j@褰(ہoe]TiXcf?>dz}Y  lY>d`&OcM?ڣ+{~g7B\ -:256l/6 bfwv`WT`𘷄F\li0.*?.K!1 Ǧ^ c{?돴г%m8P_}f6LWզ~LL̮ sK I@hvN;*vJu>狞^ʁ&l0?~'νxvwL󜤁g[!> @a䉉n?@4.Tyṉs.1ƴpi48f f_AgөAPt.mm#a3X^3$-MaVIzkX|ʷ ty'87l`%u,.'F>Gru.6PxF 0OM4tegКIS'r4 lo*EnmQa`;eB0Om{2y%4x3װAkB;yF M4H1Mݖ?E\KZKLnr8Ó5vTqWkVe#xIPoQfbTe?i/eE1i@ڬ+((v\puu^0c@wt.!54^SMjBz=3Of-Or}ȲPyEˠMG_4t2 i|v*/RmRSNh8ybݭu/ ?>$Fcz#O Qs*]h1M_Ł2ъ- }v9F3 q^O. ѦЗ !Da߃R6fЖIM ¸s.M#+\'Z2?lm(:bYI[Mht4. I:3fu€󒗼$׏$yxӛm۩u}/Ȫ:i<~?l@iN'Ŭ7&\DݢM0*G/ "DI<1# D.9s?LAAI .B/@yh^Ӵ7Z+!x,I A$CW/ŇPln{x?=Yr\з4 E˪z\0&' )lh؈ @ltc c}AuD`W )TD"h=Ż=Tnǰz:ǽa@DI1hPYr`F6scJ|Ep:$TCٲ}o Cv61<ڀdӫXF fftJ sؽU/l^mcHZĞ8 \elYy:dzګu=~g(up̟;bhW?Bj i@^#<0:dpY xf 禬O4Fx B h$Vy%1P|l ip ҌvA:1,/M:6PyqsrHTPv4Atzѽ~P' 0 ]fV> .ndR, @#PzM߻Ȳ^7+1v4 $ش QݰԂ,.,M7%?>D=lE}=L yףEh%tkUuA6q"U8 He<-Q ;>Ҭ .=dP׽Q4{#:t6Y݃-te(y83uN8 >e;~Ql^h-+K/hEM [\v[5qK v3,{2 e>s5߉anW5"ncrq560WFP`6jqYkz=ps#ЎdqR'`` uFͅvIc=2:d5Ko;e̍tͅv|kg%I vnѦ3y_=3\.g8;Ar;3pąk҃>Zs|#).қ+;48qsB}r.po[͗߹ε/6@lUv?p_OJt|5Dp(OصJIl<+76v=)OlG}I]voM us Xx\ Px;궫& MDV"E2ŨlW^෼%f<(2Nc6'&O Kk#e#ag3n T  ݑe:hIh ʌ8[pjg [p2{]vҴ+˞E,AQX{ТM[G3b ,i,P`>~x>OVA`Y-4`I,w hb!* Пu&MamuZ46e+L|bUTyyC XV7bGZuc\d]Inj+ a5N.ElvةDp6 hs;8^ב1dQ;ܢvUP;f&,t+!.xR*VO߳Ǩ(o5%; n,m(Rԫ =aIFݡ6e#]גOJOc)f,-KC,,0 x|on<묳r"˒'!n8O{M aԅp,qoQ7߆qNmWCK,4NR}Qa)5i,G .%橋9@K_ a%wK,s6w%LܥtL`mc o۷9]ތ迺}in0 !j-2|%#󬰬yA@~\q0 ᇪt5?z2*L|3Ĩ(Q=c@-9f \ 8BL%xҩ&Ty0b[*j<&ea66PGQBU;w;PA(8Kg_UȆd^[e |Ќ 4rkT2 ؆dt%[n| VP:eF [Vl`y,IC}cC?² ].n׎.uAR)K&\L/=ֈg>{Sw5]-HZ~ e)SyAz^wBB^xfBwy;*mEЙd*6g,)a4|@>" 3ay>g6ÂmـAgHï#keD5 l㦎:x"]6K 8͕匬LzgЏx2m kO\KK@~w\!DaSXag;o\%Ol.33}^IJaɊn6\D?dy>X.*4}1那kp7B0N>,쳙^pMT I,ayn2,€>(4#M` [Nva2 ;ziyc]qRf%03ClM1!G0w@g-Jhhb@0@(55moYxӗx.) N6l`pEa(N YC~a#5Elz KӴ#I@P`@s,D!> L0kB.MZ%oasx4-63 fZtvT<4ɢ #~f^ʉ*62#I6QC_SrDY6e]L:^1 G* HK!@y-3KB7mȒ# ?1>um 8~3_yG{hp04<({}D@#J( jt\aH#~znc1b<3˗M&=Fc4<eڱ4n(h;ќҏ3E#N0&uB? cɈ"`T?P#3#.a2y(6ƏFu4f? EK޳i),0Ag楔Dz,o bӺ;rheu-,4H`4HeioڰdIɦS{왶4hXŅZ:vD;}N@dg(乺(3O#U6g5/QlX-V%<w_Lr3#VeF7V%l|E.MvGv^WQIM=u̚"Iĕ笟-gZaZ?\SY~v:[˵b`uj2an0":`8c/U=˰{$o;up胙af;nvS+nfw=Fp؈˲ఛʍg?Nv6,?l88ksXygvd> *E paaA}9!8c!R`챛~ /8sCޥ;Vz?vyvf#4/.,+uA\bnG.aG'ϖ Ei`Ո ڂkBm6\ όk%̢]E8;QN4&]EvKNmq=uZvh1ؽ#OƲ?4|[z`<'87%7V(0t!"ejN,y}oIq#G8/䗺s./ۙ Ea$v<<㋝P. 8eeL( MƠ4-cO=jAϽlɫ񠌷P_2 I#sd+pOژk1͗a 8yf_.mE͗%A{&i`,m(m,rG 5)sA4~@BA3IL= mN g,Ǿ<w\`Po6, ysA7hWEL6܆)lzKgHt>]f ݦ$ިCx tuɚDZP _4k ӛNxeQ@a Lo6 &qpMJs 53rMSN cPLzcB~W|/i&Kv0@kJguWy)q&IuEwJ̙3Z$CCR"yu"mwp1GsD'C}xDsS6"&47pCp, >=?!h -x oUicG~q634 ewYe |*$31)Y*!Y1c#,ٕ9bL1?V鬉˻hKkfY !#l 1T- Z2,K,}A!@FB AF}N2lG^Ftae:K` 2 3KZ3Zp:4Я2pe8~]hiz##1V0%( h>@1!dCVD=u45hg8D[$4+'ˊg*1fG\OؙR6Jk.|}`K&W#n;E?%҄cWV6`g0z7~]980} lOx$fNǪ@ᚻe>o$wa}.x }.L5Ha;!;˂ !-vȵ9#\86vka Y?FӠ<.4fǒi޺{Fc40ް SIqx &+ a.ϸ,^ow -/^1- ^j Nld>(t? 9TǾO=W%V)yDtBv\vbQaY S' x|veH"4~Zu}T!5!>Vv݄">CdD̗$=&Ca 6u~  ah_ }o3Lk~?Bi|'˟S{"z|lN2|8Gk$/>!S&kK}Lt Wr@oR ck#@$2]g#q7gO֦! OLnlC~?KC8D$#uABzPg6f[hQ phH9z$9>HOLH0M' |YϵF@a¤ _`#sp0dqGI  sY~aVVF(~IC+/xA|# , R3jn/& N~K[gnMhīɮ]Ge|+m$oa[z¢m dgR[ 4%Y)um*|-Dp#V~rL}k/l 6#$ЁУ5H$X/[O@p"IjS*>_]A*,LVNZT+dJk]ܴ0K%ͽ1c\Kq$@Q!s@".9:}J BpxvE]{AG0TAzس$ D i",5\M'M 9~Ax' \<.Ò#jS8Ecʟ9>D]@)%cBM"f;?0ƀx4w*&T/ΖCBD#$;18u.!mr9`j6=ҷ[*Ǫ@ Щq>4o"&9&[N"> ! =>!B acBt ć(OFSiKSq,~hc=6ugr#d;=O6ϻ,!rށ/A>wS{L~jK5vO,JimcNSS^UDN-ʅVյξėO34[8%|B߮z γ8/7?L&.Wt}htVp7 rqJ;[|,]儐uTU_EXc'd m#'>@ ."T @7(u :mIN}N+ܨ1"l1EvfVmɼ3'panIQL} b)CdEJ]L 58|} @;̙v[ fsk5V;C,näӗa C!Sn lϖ[y@_Eڡ!ZfL0 ^-Lsi 6'A]mǛ1;6l v)ZQk- "\-=T?Nu! ">|o&L_9u+^B n=.@oh'l~!Ӛi@hO Zlc>SgKZ֩[.aF;">Yu3")imE̦ I5%L%چ}9uYo BC 1m!i֏ԻY[?lr0}O}{˿* plP'sW^JeV$V^ᯰ!ڦ<{` hu$\,"QqK2.u>u?[2{oX-Ne,YI 8GsG hoS4)5lcy q ? Az,rpچC-|zO =.b6`l:!I}-D:M%!D%uP]l? ?kKůjL3!A"k hUq}8ywcA;R?5imvɫ}3C$ _.bN 6Dk5HkZA貈,ID)?")}rwũ~$E)cW|l- 2T)ik#R"Q`8F+`\ ;N߹EЅH~l}kE#M18)f{/T~O) 'tS8}.Hׇv+EAYIV€!DP[^+ԝ7x]Qo7xcJqMT/DLA䎕f}s "DIPL)^?E&C0'rEhFQTm^oqHƻgdtH!"Xg8+/UHk" Ԅr-Ѻ/z(L&)E@hڵ! qv*ch(Q4PK_nd˿΋\uO&> Sh{Ǘ2o~ ֞/68Vd XcY?GZ׮q׻s *w>DVԨ|`˄ۥ躿]?̧a!T¾K~z8/T14[ p0>\Cus|?>i{HbN؄Hcm$Nkm]Fr#d!th28$uZ¸O ;-Cq5p@a1D"5r< PڒQ&.bNxo_LXsmC[(8D @9QcaCz%O9&9>f̠RVOW}ODш! QAf Xc{Oº@yo3t3ևkSrhkhm$qBέ@q|Z%!DQ@.uc*)!hTJI֠LcӮ+ %{p48g FTlӉ?V&P0H oZ}}ݷ3ii܇c£ge'h9, HBwi3D1_mL 2 @Nfz-04R &Jy183D`@ &c׸vMe\In~? hHKnmeyc6 3F#Y!L`%!k !}Ʈ:u+cȓ&3o@! Mx1If%Hoh/8_LVCqUm-sA-ҎD%m/l,uV>0PC8#,'{%x :fp4̮-=D48kpP|5i~յSMgc+h #zS5~;:1ZEs ~ڰ6ԣkkK4U1{d!]>"ڧI*l%S sJZ*&L)1pۘI6{'BO7|Ji8ҵ~eJ+6/q0\aM!;[G~ !>Cj2z>N9ڷ U6!k1Rh1A5WxDlLNƹ)v$}+!&VT)$CO#d@smD13fb/4MH6֫QL)m 0F{BIGQ !@4O!{j`sh~JIGä@daО'9tT8ȭoI ߺt>v`&!wœp IQv0^H CIa Sx\F>G;馛P z}Rhl] w A|]  cCq*Fah0'HAO0o,ʱNYMh ]R#E:F>DT&]YsЁMpkh]Rgpķ#jZBY~Wе>\![@ =k}&e5Lh,Ef72~ /ȱfa{ ZeM&R!ɄWmKIyB䳤qVjh"i MJNV"$i_hM|tiKNF{h""u;cFe[0oCh!uۉjX0۶/qLネ+'DP^gb`Lہ nƆHHϱJ44D[UdO}p!Yp) BRr6EgG!,C`_l„t6:1\8>@GCwᬡaH~/aK1vbHrtIMD$sgT$$ː#sA6997 C KhoB'#V麜H>7p"mo3d<[ۗM&IIuQ{e 7nC2DKk}Pb qn}]\\w :ڽME#]&.OSז}#)-SSaBpJh!&|*`]$bhɒ[ rO~c\b!>aŬڹX&`S~p0 lhsw|4suq/_VzIä L 8|aF Y\B \U,(Dr\WncЗ \3x{*-qZvuw5Rr`9W v.w$L3˟ɟ$a+t<&gX]SӫZ+@-~\\E~Bۧ߿\q=FYvA(ytN.Ggz<6% m>D*`mr^+ &o̾P&dI&j&Bݙm8_k< U࿴?.DXl{df%cZfl!(I> X}TS}3D4fab3LaOpaJKZ@ޠ94Y 3h2NLݬEa\nڬI l·Ltbѷhb7S0zY#DXwWb"]Ȫ8CHDp6FP}D(+-q)@A1Hj|AV-AVJso4I2D.}Fj(kzvy/Lm kܶ.azKyY ,eg#U2oj4 ZE!Ce9'Lf4 h_:+\.K}1ESŠ: 4Ia¬ol?u에~H MMF"Z0WCa yghp2啻L Ç#yoBE! P䳯\\ŔzY"ZlK"':02mJxB ͸BvMݥ0E dMYkT+CC@c4uz>aT?I,T׹=-\Hקq"`|a-7꾲 yڹe V AD-wƝBx*wװ|kpx i)p$O-zsM|.߅|K;9|ހN"IS';gπ4b`>vLW89L gUXݦB-/ }i>e >sqMҮoSPz4U;CCi`"] V&@6ўic1"Ll77,I4m6yw sl&Jb .dy:Ә NSSZa0~u:BtBվ{L8m,c۲%꩓Y)0h2B ]dɌa5`˩_Y `vl@EkLΤk m.$`eL{4+@{:Vi8GSWp΄A[[}?y 3 =IPNCD3)[*Ϲ5X>rqYHvmL|c[кo1GCEA BCʍK 򆈣k&i#O/7gSȪ}Ї)R$Θ<09KFEgύi{g>O^Ŷ'T =pVy-dav,oNKidCkmSLh};gOɴ]q$/)k9_@Lc_P"dZg?# ˴xSH"[[jw"d)8N=cJS(.-Q=<P0%A0r=aRHyzN_8 ˠ$ ڥ~@eP(ELeSn,AF#Np8l]3,u]`@ n: 5!Bm @`mcm r-lxLbÐbD ک U@z\O0TKAӷ*)4F )&ɹ>‹Nc~.z{L u!&<V־ 9|QPC3M=IKq`3S_C+s)ИmVlpx802p_J` [`VE2@c ͍ (*~'|#c}|>~?%69$p? iuspy^̦ײ|oۉ{]9w7[}P 눙;ftMM,Bt ua6Tۚ㽜| ƌ@NT==HΖn"2]6q C ?[wț LľmpBcscbd_u2(:w=D4N)Ց9!N} B?BPz"@ LbsFQ]9IZ:ƽO :m^|&A!+pJ|wBMǿSt!|+41U#E|L/سGc"'hc\:(3\RJx$K˜Ty@&| ~ki* nK18-Ҷ6' DXip:p`ȹ0Ar3hX< I><;(!@pJ |[E?]%i36/@?2 EX9gHrT֘CS/[״pI%cLߵ\beg]|~CqS0"id U @:S΅I5Kr kSΕ"tꨄm&hhQ',uAOyn@O3?" m$pQTWehMϿ&XVc9YY]T Ry}+w ~phMB=A`" -CD?#kA0$i6<(1CWyt*x60.ZR @Q ҲjVԑV"ik/)I\8ndbVsVbF:uVz,I3(|,>:d{(~\h>c|?84n|P}980h113F{WDN; X%"R,rmO.gu DCljo9J5sAKr:\1 l270Y*A%;q| gMw]Vesm2[u!Z#zh8!-F"Y3;M esooHޟy&_!Z6Tޔs!' ө~S>嚳"|;^["3v] Sϵzsbn+0Ćʮss($n)%8DdBե.^Kl~ =o9i#7+O>Ͷo&ԐӹR>g$ KiIW׳ Y6_,V,(Z:C `lA_/z3 }&pMu({R,/(|3MgZ&y >Mt0gk~a;vS5] @1n;ȱh \@!07pU! :akГ S3YD$1aOxB A"Qg0jB@ e HÚۅcfS.*~CKsKb\pm"Z7F&Vi.\.$86Hc_#O @)4*+s)?0ПSሜ%<6⻵)v Z% Ox3K(К0}%0!JLpB0J@6TޔsaܽHĢB?ǘ?ĕ9</ ȱ ^A#%9B)S^"l4rKa`<-nFG* 0*VQ F ,N .3C;Wq@e'iAT+}.424@D0NC ޭB`#(LM&$|x%(Hc1M}u@48/tr CQ ʑRڄY2iu??3ͭq"kh!@/Otċ*qt)|>/qbFą BMa-3R?j->_|O^0tlآHcbHacNkU}K @M6@!$+&^-wlBm[_&`6ӏ(@eY>0EmB#UN&xeD%@H,Ɠ0}&AKAZhu F: 2ß؞z *A|O:'= _' 00qp:#spXYc9Z*+HW>V{6s%T4@FN9 o 3o!N&C@kIҾ@iwp.;ЖfOH&0GBiJܾk?'4p@KIt#ez:vw'K`[&2| 9w Fwy$%J:IF*M@4~"οp'̢v,,rewfIM'&o|uw]ߕJ w68@$w~,11gvH7x6Qh\_"PrTo MK |5f1ƅЖK 0&r!Я.N& FAeݰR@)&¼XsPՊZ[FMnVOxv^NUZI4rh_c)RxCOSBS$(>Tkǎ?Yyj#q|i2j&TM-J=?!=߈M@B DfEh)>d%l2Mkhog@{Dz-PW?a+^U,D"4pKa^:di]8w`랓6 @]_~±X4ᴖOM#yJ~GJޗσ.y*pCfTƛ:ZdA;Lp񝋮?&,j숄Jt6 I@Zp :]Bk܄#|dF]i;RD4eQxdamm'?Th0d6HYsg*;@!23U ¶ôlJ;ihaH J1"Ep#GR$ .5pXudCמo$/LmVjŜ&PXڭ!(jN4|>ZPyd;gctwܑ4x|~h oMΰM󆐥,T"PREU:gO܈2H,x% bWtp D{%8P3/s{Xfޒd2d  2I)B>6Ɉ# ^$XR3K2Y`)iyk袍r~&[9&:|'/YųN!6Jp@L9gJʫ/΋,3>3__Nֻ1ur>Mdc2DL+Ce90IsgGg<)@[qpt,&}j"9:9|'/qn>Wi>D΅'te}o?ia@ƀodJp|3fNBAx&Sw?go!Du!m DS}; gۙ%;YXz&>y*RRDꇔ}x~ %ђEPÌb28& nj0M]4ψ+s[ U<8b?əzʵZ pl =Īo xЖ-ug`7&/~a\-kk/ܽEmU7/QTLIVLB@";|̥]ñ%NT xL}e1)8`ՉaM`8gȍN{Iz6;&ڧc)w@+2f((3VΊJ}])SH{^m<4A1͍\hg;=yMI`?y)DLQ)h5v 4PPiȡTPȻ_I E1@,0+ӓ}b@Frt}5(]PmcB'UӞv䏊qaț61H&4%1&R`u(jӹr7]~%D ͅ^C7ȞP5/ԋ2y5<(rD}m$U.twory)m5@JK8 7\m.)F8v]H3sH***2hĬtoNڕ6aHy*TܩN`mC4`I6z9xpv݄&"7ᗶ sH<:~ֲBlv3  tΑO̡[;rzrrrd_)dzԳ$s},n-9b2P* @y/瀰xgXH8UJ~@{M2VQ|9b! D@Iq"&y*py暵O:3ʁʁ~y2hV$ =IIM8T3poƬBG᤺Y컦_|y#q?9v%?c򿓔XDe&ߓ`˿K_#ߜ[|p'|Tbݯr #;Vdg6(`oy[қCLI:†z`0YJna{X󒗼d@׶_<oI}Lipo ~B45Sr^W9pfiORYG`JcKo * qdp 2t6 YH蝤z׻__L)f=2eppfGhF'T9P9P9Ɂ؄&|^6 m|P}%RY߄/)Q[l" |B&4C_Sj{p uCۄ\|ڄ9y+_M7!vZM l^'o]'b*UTTr LG;ci 0Il{ 3G&m7q#4$(gÇ !(|6~7~co}؇mgOozӛѥ vZo%aj(8Xrr`# ga;Lvy%]cL~D۹w$L&Ct%ju{݅ A!H_8y؏Xh)r (w~w&?(ۡ7]щN̡J91*EheO9?pmK VTTLp@@xMjS]QGS؞874!J>%p=g>sN ă.-GrseSu~@{#ZA_rG~GRRԑۯi>sܝ(@$JM7ݔ^`$ 3=>?XU"⎙yX IDATы^s_લ џ6?S?¥~Ё* qhE1FbFX+GδS'7~72QOFZyߞLtπ DK)R,v-o8YSmּUjL>)OIع&5߾;eB$ʯJ9@|j ' ggm[o=HU(CP|' B0/> b43ߡv'sʁs@#ؠs-4ycNe0X31XG1aĥR),SwHJ#׿r)9?GRj^^ z 3(/ti ⣍-tNdXrr<85`SRL1_bH{&˿K|8@?Mcqn___)%u׃0K&{&;9s %$%0ȒB~`9W+** H_D,ML͕u/Li@d}7GXx9@S'2ʙVo]wjo_W7__{ nk+*ΚsO# [Jmp?>tNscG׼y|.9^W9P9P9P90" 7 ̙[_%~S򗨿Gf)6UkelK1d mBTh\@@@@@b0qς=v 8|~=~G~s3 { !+U!nsPK؅+F Wx8,)) YܬhnkxT5@ʁʁkaR}$ 6Y4?ruEUTrWTTTTTY|%TrWTTTTTtd@@@@@@Ɂ*ܨg*g/Y9P9P9P9P9P9Pr @%7~@@@@@Yp @gKV7yc}7яzԣک88=i$yCG?_5/hЇ6OzғMoj&؏}ng;/yKO~|AW<]+*NU:Z_r:r8$||L?̓$Bj'~'j雾y[ޒ^,s뭷6?|s7oͧ}ڧTTj2/78|ٗ}]>>!i?3{򓟜LYy{Ӽoo>>y߽Η~n_co6OCDst 7|Bj~~y׻|G}T>\+*NU:Y_r8;o{,Awݼmok>?0 -uP|QJJrs]oXߠrd8=]~~yֳ;~o^פ A%3}m׽u]8FW8=Ti}ʁoo7ٟs=C>C7ISj#t2k_$p[drrp @#*VT47~7Ew}˷|KbMhѹ Oʚ[n?W&'&/TY9P9pxӟ0S= Oh@LW5p7z"k~v=;XUnrrx9 m[Zʁʁʁ]ۿ[Y$DCHTKjT調@}~@@@@@s]:+*****U/P_9P9P9P9P9P9pХ>rrrrrr9P΁*]:+*****U/P_9P9P9P9P9P9pХ>rrrrrr9P΁*]:+*****yIENDB`ggpubr/tools/README-lollipop-chart-rotate-1.png0000644000176200001440000026740414334142200020732 0ustar liggesusersPNG  IHDRHFiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i*b@IDATx Me9^2PB"&T*2499Ջ4QE$i"M$4Q"2s>s>s9םZq~3߾oggDTE@PEDh:"("XAPE@(KtRPE@PֿE@PEP.uHE@PE@ XE@PR@@ @!E@P%`PE@PJ%R]TE@Po@PE@(KtRPE@PֿE@PEP.uHE@PE@ XE@PR@@ @!E@P%`PE@PJ%R]T*p]/|{r98xzϊ"P<x'%o,Y&RefفjIkK&{5e²uqD;(*^s{/[3EDzt{ӔȗMe5cA6,ow҉-[V|"fey{\2Lld9SY")AI+)UC=ҍ7s[ ˘4V\3e6U6]/.\ozIv!GV[ JvT$hU;^%g+LSfڵ_~7%{ )^ZY3fMRa֭dɒ Bkܸ^B'ަ ))+VJ!\dPjG@C`܂_ecv!`\ ֮%7 ^ȐPn[nIEk2U_ <~evN8AZj%_}eRkO훷dMxƇ)*2tPg}䨣.]ҥKSj#-U%cǎ;."w|>ڵk{2d 80Oy2[3o O^gu]eΜ9.[Z/k['^:c~;ܹsoYf? 뮻.݆gLI~ŠI^?ʘ1c,?2jԨjz^ 6Q"ƍ?:t?֭O>YVZ%t|7DyfyǤu֑ToڜJuY NUFs|WK.Io -r aް0`}饗JӦMm.LxfI1Kvξ$8͓zI:u}W$eSL(elK#FH=䥗^?O?tIׯ//rd&MN;HY*lMwnL7n(^xp_ժU+ -DEAf)2OR-Z$u֕^zY-OTga;Qߤ{޽}iٳ5E _I׊PN^Q  ,4Z~ԝo ff:(1KC ]v*E֡Qꫯs9jw <oj -[|9Z%y[դ^}" 3ر^î_^_l,^Xxc]eP~ E駟4h5޽{[ۯZ6l %)QzhMdjJjd SG-3f̐?Co={vRV`T<-:v<ʼn j׮m#mڴK^{5,ǁ=I=c_yV38C!}ikEL ؖ7CyKW_hŬVը.U~BH3[RvwJ/'OiӦ YJ0T{p ז OIx=ž{i=]9 ŦM\Q#X = *̜9S:wN/p &iQ(G'@DE64b춖;Ns=ג//ąYCtf'I6uw̓/ba-5Uv2ڻ X; wUt`?o~G&'JHyHGΉ iA8=seOlx j֬YAMz$LV/+@|rg 7`C tI2audĉF0[a~I+҉FX 7$Ktv`ἰz\mQs/\63i5dGG+zתU:Ƚ)M=Al^|"MYVn@ oQ~WiذԬYS222uaC@1l~Z(3`nfo) N2իWbK*~/\~Pq0`z?Y']X6##;@{( ٛɟSݖ!&+> OQnUNyVh%"/5'IưA|d>gk[Ah<(D 느kƍJ*yn>s 1zE'C կ2;Hڅeo761$Z(HuF㳥E]AcƻN(c3Yyh5jKc%gS㍭eEpa=)e_LD7jٲe7kЗUz0q*Rǐ& a==t2)tڲBV([V~b8؄ČCĬҫˎK&Sz&$e%xD! HWdB!\(ش"P`1/4v*r_ʐ~aUHz;ɉO#I df\5seoo+N-VjZCj*{޲_%dBK^[ehN] 4[:q=$[ARD@ 8E"P^@<0yz:oE< \QPE!+#RE@((sTE@p(WG7("PP.OI("PPpToHPE< \QPE!\ސ"(@y@@ <<%"(@C@ =R!E@PpyxJ:GE@P p{zC"(%t"(% HE@PJ)E@P*J )"S9*"T8+#RE@((sTE@p(WG7("PP.OI("PPpToHPE< \QPE!\ސ"(@y@@ <իW?SQW@3RnJb!pʕ+O>X7w(J}z"l'zȦ "&{J v+J)=*@"_#/1#h{_t?H*Jy(@1#dzM"['x_LgH?K@qjiQeG@*_޿"$@h+5<֛|#m\/᯦J;gUX* ddd."=z:qEk{gyyeAתUK|i䮻ʷNiiicŻe@B v|7&?,tɺ$2o5+}o`vvXBF)]tYfIӦM^~yfaLQFr Ur=b9lGzl8?se/E!mX'Y-ܼB-YB('_>UDB!"g}v;cW_}Uum{N ~'O=;-N8Aw߄c'ᵢ0zRS Wx9Ψ".e7|6-7Zs%Q/QYFBbpHiӦG-uԑ}GO23sDÇnA0p[no9h,+{qoСҦMQ4o\jٴ)ycرұcGk.?O?̳~?pD۱p Z{v߶6l`W'xY9q[nEn&箻j n]tn4\T@򘞃ISvP?]2$7,ϢIF;#YYY{'wY]]߿]ٳg/gw:9eذa2c !0rI'IfͤI&rWZ[n̜9SnjYa5ٟs9f׆ٶaW\;`P$ޗ]iTN-Yw Iϐi"Jx{zT&h~qzGew^s5Ҷm[y뭷"&dֆO=T:u`Fo駟90aYƒ#\DSn*Ja(@ Dޞ9h~6MAR/'Y&Ue7H. [<3^+J)=(@!ңc]Ros$K$W+x T)p4E~F)"@e( FI[l&D#vқdvMۗ,ҧThK8>|G.Jٗ_~i7E^65YkL4(ږŊ@#.P2{=U0ۮ"ٯЃ7l TӰoVf?Q-сyj*eh$_pai?m"Gx$f( !3\˒31R[*ݔ!a)zpUA@׀S|䓟6„ ")5Lt,S wX]C,RWӹ/O_mߢ71%|6-߼FJ;d>˽G@R&qI@XC_ o&fr]wߘ~ ڥKv𓯿kf΃ֈ٘!Mg%~˷{뭷FRFu`N8!L?Ge";A#~7sϵa( IILhKvwl۷!,of~sŋK^I&/7V;{$1ļyL6jhĔ&P^ziTSZQ4~Q D(%%M5KJ$I鱨k&K+kWzV^(3:%릱# =$|2zhB"!  Ν;KzFJFȗ#Gq!#H 4d"맘^! CBDx6DF2&ѿ?.yd_y/1'M!CX|ZrϞ=mW dn$ҁh-s/8&'$Bi{%C_99cvwς:vhcfпyDŽ99ӟٝo2C͜9S0㓉xЈ=RFI8&I>t٨+/{{ܰV_O-2eLƎDtjhYe˖>K65$2 (xє!? Y1BHAqBP񄼾}rtm ,cH/u~ؖ.]* $ Ѯ:(]|iɸ.Cuqݻ +/&‘c9F7o._|jʖ_Pyi'pX\s56yZk/F{lDhͼ{EE2FL?U᥎ E 2̕F{Pm-f?I2ߖt֡gL11%hp_kkiXX 4V ff2:>fY~!'$ pp@|d'r9j!/ "CSs$;w\A[dM~1y|D& '#2za5xn4d4;U߼@X }buUy !ڸ/'N|ƌ%KY 8%CDߌ V0VGq\Eںu6n6}C%jx4I79ىu' | UɗS;\O@!`CB_X%Pr'_0C`^v]+5͇|h혼(/D/0!ش} #D7C=dØyXMwc%^O'O~gE uv#\~-U^-5nvF~ ]+71|X[E3իWKf"ŐK`vܦMی_Rx&"<8U HXz1Sstx̋j𐎹z Px֋'1؄oq*l㓟/zM()X 5l <'#R~fɸwo~8n 82s=PEȸIH&`%J ҕ%"ܗz@րrs!~r3q"P2tx&O .< o'iơ*x /x+L\7{S ZmK" JU u{RP Xϡ_И"W?6UI I8qC,n%AQQ%@QPr~e4E"6D;-Ֆy?ΔgJ)1zz\ V.q2X}oV6ГKyG-dmjZ%BvwxƆ[tu!`Fi K\|i\B7Ltx$ K/YohTow7*\%Q/plzZu1b91%%SiuPtůǕ{A&$#˂wl5CW_"5AM~! UD:mFR4⣏>i!nqYCPyռ,"1K,al >*_Q޹p!$DX& MTB^4H*ANI%g)'!'i IBe^{6$'m۶mDԲ. M\k xh"Px@Cٜkݱcc=f/o 0e4f6id?ْ298@һwoلߌ@#8썕>",U1vVuoW:"P(o=zf6#4Fӭ_ N:$Ȁ$l@EH,A"fIj@uZС3Ɔv]JB830)n< I͛7Ѳ0%$sSlJRҥSzC3gΌ xs05;!D9$Lx 3h pe&yN:H:BAJڷo/ ְq˜|HTL8S{m&}Hµw9 >V ۗ+ĺ]?{L; tx˗7kZ%A"P(o'={qɭFB>]ḺkҤITu8qI4hw"x yg嫯u1 Chh̑9F2A.d8y N"H _x)@w]Ǐ<[lJUщˆΓ&yIluWn>~8;$2vꦼN;-Ep!@7(Zomw^[%L[u:S@~AQ :90aSBŌ!Bl;ľh"Wnj&"P[b&$3@6QS/n^dJE"#ohK A&miq'}uo~YJW-ckr)ڻ_Hh1/^{%8[|ڵ_8_xn_NJ@ ؿ7ˤn'3 v*"_dV DѤ \6[婧[A93ϴR쵥ݨQ'CiѢ?;Ru"f-9qDnۦMƙ 6qz뭷^h8p޹sg}۾?d;yeVIvE(`&QU6QKZ`{$1WVfgHF)3aFmBC^32^`דּ Fx:Lè*Tbo~g9{=k<=:={F}m4dϐq50w~b^j>:*zM(3ZҮfj&sD @*_Z+ Ew04nX q\44vD[6_XI;z;QE8LE`{ o͍'1%eCLpIV^+/7w\nUqd]Y?+8#R ~\f["P_TQ})@G `r3}*wˉMgBLU8YݛI;$xet%t֊"$51%'%0a(w$>'[\07vYv.{N)I#4TZQPHh6MD7bA+kگ@Hz[$t݆TAކ""Uɺ8 f:Ƒ/6 ^}7MH=zJ%ty肄xR@q"dz1=KAglCΡnQ繤@q"݆@d* ē~!=_i i +I"(e˖y>;!BJÇKoBQy62)k֬)f df>C WcE|)C{9ijՒF[jU! " \Grz6~yώ;*E@$OZݕhu˥^ \4jӺ~#9DeںEBoGg@1 &BڣG?yڴiQI/VLZjIvl:ؘd,B[$4Bv#bAׯ_ߦ|G#pǤ$$21 -yx2v͊А2-M/ĝ&6=. BmK>1~~$4ɺ$ɾI;×dF +ņp!%"kEG/ý+&4o\ylDگ_?QT86_wVfd/k盺Iаa^e42̻sq͢l5hOQ8{WX31;vh3:6qݺub/z#\Y僙'y/SL6^jBV&^&,Y_߭W`S?hs;:cdGl(e(X٢ضW8O'Z"rtB4 Y4#C$HN _~ٚu!. ב/e&hɇ~h9W-|DH$c i I_3I$psε͚0YEN ?Ԇkm۶bB%ȯ^+Gƽ "]dtxϐ@~h&,ezFZ%JDuߒ +w?\w1b&FK"EC=37Ih5Z.Q4i"G;0S>B&26e͚5vͷvb{z2nA ) &lНMna'.;O;(ٶZ!sV 7enk65s$ШH-ca0R8/fT9bD@׀\m >>Zhb?8f9C{c_-}e˖-D/5yg/8G(Lͬ z4di2ŝK/WhŃ <@(wI+@0Ϭ bg8يg.@CZae%F@ x;>aYٞV}'Oo-3s`+/4%>y8 &~!o*8~K3ڪ_;ewʔ)c9ƚS ʮQFd-m'4 }뮻^sEuHٷg+o'H%kX˩XM"z|SVMX;XLАw)C[PL1nET챗Ty+ 9NB/?.a1ԙS}O8G [J&t pz@Aw &1R Ԭ#AlRx8tc=C $oN<ʃiYC@ ="@ן$5d 1ZԃhaȷJUIk v薒Fʓ@>$j"P6}d]v} br:̖-ID2QB +t[=(UK~\P7H sַ7a׋7ksxى$l"DR0U(% ѳb6(]s5yb1''rj0N%b(m+'aP#*M s*b[@BݖJ+9f Pw}w\T)/t x NC=dOݨѐ?FСCQu(@׋C8Y?E65nI2kġW֣qЊg@ Pi.9A ē&n_Є oo,Tcjh̕Bç aPiYG(:zɾwHΌMr[xCu O@B&$4^ :ݝN P)L>L2\xB}c!ol믏JL" + o!\#:ٓw.?(ō@xl%w]Iv?ۤ̐ ;J9J?EL]+f˒"PZ(oC21eԩ2|ptIWfԀ_MG\L* {WHNob)o9/R"bHOYfY%s&~پX&akNVZI\`w}gےEl_}Ua]Hcǎ'ڎKE$2Ǥm`Hh~:Kɺ _LbQ="P|T4N@&@$kȘ1cl2yC4Z]S,@"PHt7sD 6c9h2&_4I~z~W^4IN 3gΔ/S~}dz2ىЄ!qz9n f*M>]H^CC 2!駟&n@IDATً&/YnYfMī&4i֯yIUL 1 4RmM"} = ~m7xڥaE_Hr5cX#aBG%@!`4x +-L"1هg'sεFz]tIʓ/m1h7nh?uK&dI:y1AиѪ=/"^"aڼNǢ/7vA$МT>תU7bMؼVy; \߶ebA(@!`CGj6n5փ['b3 Τ!t~CN3j֬7|c5n4UH5`.{p&Zʕ+Z.ZxVL;ܰ$ۊs]wEj0sMUYWxd5K*Ƽ%9X5{#vڥ~"P6T!xUf͢g=ԉm3iذ% %T_I 4˗/TjժY3{!ψ#"Ǧ"<_ Y{ 7R_F ءHZ>)цtǙv{HNs=PJ%mh~֑ȭ;R6D̴y 0i0>'{YgY'(Z̾G'+Fy˖-} |*UW]e?xf*@q#J0E8xwz xvT8fFL`+jH뙉j"P(ox<."kV M f_{HLϺ.Y!_'Nhv]lsL昑XL$GkE0#/^X/-^ѬrOæ |Y3{z[sݭrOX[& /īe@BZp2{{6#{ud_VBܛ[zMIyI)%6YE81 kf{.O=%%:i" %ٶg>i_{v*T? bE !i fy( MWMZQez$c.%SѱOSSAECsu*]2yLK,cA}1GpBK.[XNVЀ1]mTɶK/ <wE_lMīcB9ђtWz8J%*J"V{&s֠3LhJ㷰1gx\v0/jJG%.qh"PFE@P/3ۍǍ̉F,1>|v4pvV? ԩ[~oVg^PPSoF|xH%Jvn`vC-iIP;.(Sx&s$9i q ْBkOH;}WP(} @PRD۴A."  z9>y-+YWW@"p OxG =KpxJx[%cfNlA &fI?w@Ao#Pf4`oa{^{ebXHf_/cD$HV={[|#LI e=DRKu~@&RHeo4qTM~ۑLO%ᙹQ%VJ2CEK$+Nx&O6뫴MfS-d5".{q!eBL(@/o>1Zp43ԞdTW?|Z54LRB̙I HhGtI6?A,cfQ˥#= =İaÄ̝RrȐ!@aW1VSCv!J Cb Pm/hu%4zH]n0k#dPc2A9֊?r4iE-< 9`q@Su9?<{l:4\NN?ua Y!ԁ!'%֢XRIH:** ёGikݺuhh0G֖>z/@NcK笻ӳ#_A x~s/~33seP"|n[sm&LnjO\R1TK % ;Hޒüio{[HSRE(m ;(븐be˖ի-9f&T )ւ`*EX'\GhNB#kq13o^Dx)ei̓ xc%b@aEA<+3 x ^h'{"ꪫ"xr"I/įR1jהpa~wUxy7͞!ig"@{DܬU$9h|ڥYf/bdmiw c!6cV<17@08(=kmƏ/}|`H2 -{w_~xۧfh8;8D("@҅ޭ tּ$<ʬ mn%xz傀YO}|ժU-懅HЎ۴ic5[H3-S ټ~G$#6|ٵfrߺĉ-!={mmxO>Q޿\ъ8Uj>h}y9[sE}mP NRl7+#^ͬ]i@M`+jHyWIzͨz F*|r+>m3ѠiH3? yƙ*O=3k_Ż;1Cg3k˞Y/ xsgW#?|/==ݶ5띞It+xJ䞙3sd|'2mڝm=yfwubA ,oKݼ-jiV^8+wZ0Ra"m H ~\D*C^88AcŬK3: =cə ]ֹѾ +hx'k=p/X0' mp_t݂'%?!}1Hhh&B{$ L2@񹮖+IÙ VBHK4B2mXp̘1O|A0`@;2iLXGt5rr.ު -Ǥf~CSdLY&y"YtbC˦ zIehE p J=۳gOY G6iӢ.%0_ЖI/!Y `xM]c&6Z5QF'|?%')Sr `$,41mFo=… m,lLXY |a%G #'Bz]"inYGwЧr[U!!=*}xe.A#[n=YČ:?hm$ѣG۬Cq fS-FG0%YΑL8\a~f]د}~Ùh89iժ5]C`ꪫ3ߊ@Q#hD{S`H~Tl =rPMN:>"P(' l3<3OmLD{￿%]Lԉ_qmA1O:~ fڷo/x6olXeyٲes1XCE%i~Wk #성1IC'Oe s[(J1Z_/?.=\0.YOG$gH;#z$JI=~x x4J(CdO >bn>ㄱ߶Ig}=,[𼆄F Sa~&"k8?a^`M Io.F%{\#m^@ xтYv^pD"!O2 :D 4RR$Θ1Z7/'^۩ 㺭J7|59[nj3_쳟̩*4Q23!o9m@] G+(%p1C?쳂oik(FyO91d}3q em</361Y:@yiazfYsbJgn9THA0o'\^fJF ԬdW!`Ȧ ϖ^$hSF"PV1C^?{h9_ݡ) 9~Fٿ~ZfMYvm:\Ѽ/^lr۷oo~Wk"Ƅ+D@cSGFe(g k(mVfΜW% *@"G@?U NpHN7&R.tRnfR`fz2UKc:;=p< FEr] &YEMNX|ˀG5ŔDt…:kN[O?f35lp # /@xIl;Ob 됖(켛ZdH8/&O$ɩRzA1ti^/*% ﷤-G8%akvqT란OP,ܺұZ// dg4`_]AڴicvРAV{FehѼ4 {C^x5];[e-uiiٶk՘yy!ᘑFx.E ?"YOY&R-ۜ$zd:='"K$'uJI3Vnr1M8Ly" A 'hl?q-7p m3ۚijղ_g<=Ft`L[UxU{f9ҧ!nx_G1gH!FΝ=G!y1W/E3$y c?$RǸggLz k DT,nt97FL`@+Rz5?*ہgxlN&K ِ]M'(ZNT-r71kzsu1_XTn{0'&\`6{mЎm F@ RF@ 8e*tд${q`룝Un-C Qћ+wp{d:aEr#fm,oHWF"Ea9/iǜ$@ݗy# *C3ٳ†xC<'ޜLYAxISh:Q+&Yщ)9="H?,KOI>qz9tp{$:!E@E ,ɺxK'_׀G [?{&U= `1!U1(" &uͮ9!_]sD̢kE슈((0LsNL00=u֭Z u,f'LE)Leܸ@lR:`o9?JSwܹC c l0`@Vlס [A8xDmdҥK3GɧAL$E2!PxJCXrI5{ƅc'c):F+`E+>NsXµ3ҕ'k DlUn UT{Dx[cC`!PڿE,i:KڈfGA]j;qd. KJ+ SPϞ=~""ka' ]N`m0(\2D%1mݱC2-_ɿ#5I]h˞]kAS~_Rz_~(ݻ݁C p m !4>Q0 !Nj@6d#F0$l(]ooHV^m'D}TfxfyŎ93=b(u,)ij,g foѼ]vQtA:qذa4m4ɸ K>h iYfFUcOt&xL]," ulM\k~w餓4RYIZiF}]ȑ#En:?iؗ,&;YgP$d'g}+Ty.{h QrR^4O/MJ.;Vaxqϸ@& 1@vIBC@lG[? ?`.A2"Ģ- $FA(øfC26VP Tp Z!I ^{,HRC'{ʗIbVv)X6ބ̭I&}g^=ۿI8MJx6y.N[.?vLA)/%O:/نӱcJ +x-.j}Z%zᇍ2#;4cxEq_y>a m$^_bfQ׾;>s ?qPƷj+%KWi M1`Xy).t=PNovRaj%@)ClAJZNK dJm7p?ĵ =IQ_}(\|qj컥D(뮻Nظ6lh?_`I"+ޒE_~m0;wAPisه@DEvZ#:J}$-y}{T<װƆV @Q pak}ƍKLbЛo) 2v$I{ 'V41X\()S~7`C d3(D\lSIdօTcG>,]>TƝx\@ID7r7S$6e)xby=U.{{Mz4!|@H$C{ʸ}5w"'|˝ˤME (gݤ|Cp wMS*[KVbo>W^rRKLƉ&`I٨_tsyiʸ!Y(FpMƢȆw R6~x_Lof+QDsDvM;D"]{DB#pnz\@ t){V-3f\iqrlیcΒZNقSKq:!Z7]`ɪt@9,IHCܔYAY4 s(t!MJN)qctNH˰.CJ/?^J_z^uF 0U`ɐPƔh\~_ aT}*UT Skem0,(9 P(f|YnGj 4P<-!dU *UTT[oza>j$Sǹ}CL% NkWZ"e#jVQ.`iRu fEGj5>} ~82ᆅ6DyGKnSRŐq2w\{K bH!U <A{-"a qƆ6Ж >w7LiMԅԊ[>HV֟oDkZ֔[C.`+Ԁf~Zw0e78!Mz GO LwH'ŚWII w!dόbAI%6s9F <-F1M4).Jmf#{eСQ̢QXW_5y /Pen3<ԕ>w kQ(TGyDĤy.{ qU<(YK-{ix煊YZ \Ƿzy΀} cE}%տx衇!r;'d>ԭF3Zo&5{$vx̪hYӱ3+ݑC ϰ$ !C('Qs Z>}Oz?~x`-I\P)7hDqQ1LMV*lHVACy0# }\md/<$h!$B4sLև6 PDIo |rW,X @WFa.xIbQԶio(< X锻 a$h iiyƳSQwJdw?_Jٿ&XN=@#U dϞ=0ʀKӦM3W\Q{^|Q6c_x/C͛n&Q.-r)ƒ$Ӹ.E &¢3g2nX, .e ;q$C kD7޶f8^7)Iwv@Dݏ E2taQTf8)ԬF$mVBm: [ ʩ:%˶@Jljz2=.Q[;׀4~Fl7vM+ 1ޫsY@7\rTO\X) 'sT1s (\W)nYbā)_B&q*ʗdԭOu|GPp'Scd-+T@޾K75PcLOM$q)l|2Y7κ9ՀZ&QMNC Ol$nE4J čJ$Ҭ|A\w@fŽL_?Gư.ӭ[7\.v@Dcy'_$=G~TeFi*>ݭDT ;qdN~- cP^2WTrd^;'kX3Lʘ}Ք@ {arlE>yJq XkRzٱEOE)u? pLڳ:dnvG1 0v^ENh@H0mAcHIK/Nm5f[EJPI۶!PzޚL}R),B`kҕ{!p1u4^ EC;pSB:b1%#)񉂧~5ҹsgXQp"Ç7JזBE<FR5>Qmz@lƗBZD#N6S*a@IDATl%J-DV&ʬl9Z/K^5wd$\ B{ΞoEXpRश4BmiDA?"޽{w/n_ @ 2- /aꪫ[] Tf:bFi$ˀam1"1 ZVRّBBQ9'l=:ҝ:2g†8@N?o{ņ@H j+ ć~q[ %=c ڵ0Q(L(%6mj(yc9KZll2ݴg[!(S*A@}1`휽P;:>xCKNVtG-ަVF mw]z%dXޠ/tkSk^MD!Nŷ~kj6CŸ.V4u y"=`SARW2 bV'vo%Gɍ~faѿjfр4(PK;2&aS3]aa1>گ_67ѝ@Pu_q^o-.ZQ .@&"p*dc |;` Pa2h)L0Aw.(o+(~;yd_S9K145j(93rmMld…& +H,vPdy X87EyS,]#xtsV9((7vLHE<)Susm߾}ofJ$Aa(ײu;P^z|8 m%A`mF6~L'xF ČYX6${7D;s]:D&-+iH:MKޱHYaX&r['l.:@CkoX1@}$U.[pPZ q=v袋LrCV,Ӫk}ƅlǖ#d:ۚ;v 6Ď٫LvPp?ԝo";^-yG]"u,cJD-|+mg#݁C p x=B$0\qZw}gO壏>;X_brrvXP&3 8 mC 9J˻Pa ^3ѣ̉[[a񀋜n'TbTp)>|;)>q/⓻jXHQH7B)us$f>Y>Se߼뮻fK>D4\Oc{gkfY暺=uY{~)iyI<ف=u9~*\+m?œt {hӢE O-u>jMAA۞ZqmhVr[Z!P^QͼMj)=2pSDd/6oXuIg\IX>}?Dk7U=qUQ,&G];@]"p]ޝNS4*{e)<@۪4hSą9r7DmCɟM!O"T-aOfRelKxDwܷC p 8~.7X@n!{G͟+ޢ٨Dn..{J/oIZt|HFR2nͦ!p݄u ;%ƳC)).40֭^a'I%ĕѻ8jkG׋C!"+%מ^V.^xF?(ů=-=/ݷC gp$7ḅ HUrUʔM=g +𴋵?q!8OH!  ܠM6f4l)VUR*lt)Cy 7VfE}h|Aɴim4[z1RMCKlƗ KE,Yb"B=dj?쳆gJ^a)))1ʖoVhSW^1D EEE2l0MɑGi)?裆D$(G!^w8XTJ'ԼC p 87zkI4cVK]38Ô\ 駟6J+0vjJcRC?V/zjTCZ''({W3(?jH~zSM OR4y! 8t"}]k%|Zb_A=c QLW]u#w=zeyOۜOQq]wuTsA}L ܪ}#FX 4 $XX$u!J ƍ3g}7M|UL4ԋm߾y?5ydܹKv$,jr7װȱRHʕ+c1n{$Z%h_"F_{6(.*u؅(Y?fs!`b N͖.-ݮ }_z[4Od@w՚iNde vN$^pV'ʈ7?Ml~0PfVIm/7*_emEFHp7` VrO>=#NFѡh q+e[e_1YjlRk(޸o6 1[FVօ($b){Y߂^HR|ž![8;(<ĕ{:7V5BV4 IboM7K`Sf\ܤkWn\r˶.sJޱJ-HW<ҴsTq9W({gF<2eʔo2D|f{ Pe0Ka +QL5 AHPmٲiA ns=%*AbyFYjXVr6$NrHݫ`,kPjt7JKWg;9d=NK n2qcXq MvРAfKLfHw/eԩS%9h|B6 ^ ~Ceθfwm/, ٳdG>'In#ףRV)2D)_Fw?@ZQq :wGa ox_SO=eKyw~TBygƅQl5nݺ \{mQXH0 .0nSO=|c}b[{9-IR(wy'a[6lh˘3f-Q<0`q3xf[,eHrD#2z*Xd^*w'Uˤ~H608IZ;vdľWJ/"BVPn@!Sō?KϤ>>T‚p eFhLH*?Ӎʼn5K|t̘1Fl]8$jCl$LGB%;0"G83Nr*\qN9.D?ҸQATwٌ@DݐA<:5l9DC`fm%~(*8HClX8&)fQ{UpJG[)_3Bz#C pZJ.<ׅDJڱV`mwn"3%Rz}JyRK7g @"<&[gpd4(ӂߑ聚P{}I-\o_w-G8 8T7%@m!5Eś9D<ݟ+^L"6Ȏ]%q![vV7lI#{Ν8>gS–HYj*8Ps饗Vy}衇0՝ ɀ[weM ej3'aÆƸwuWS9#w((烨 Z׼ysԩ_8Lu(3*L?=_||܃R@U.;tP9SG!w}MI pPvJB'L%_\iPGO⺺o}N yY _^GT֦"ݪ4ݑC!JQ/6me/=eIJUͬYL-iEOݛ2ygq>{1O-{d i|Դꪫ}_~e}zcO;4O\y=e98S%i=g}@*L)eֱwa|衇Xme˖y5[o5c9c?*vOj3.;~%̟16 暺=Rc.l^wb裏tNk7humR9l[J{^r^+Z¿_cSѵ94חC g8tLXy \X"xkumUJrq7Gъ+ Yڂud޼yB)w,^6$T䢋.wymrG ʴT5^zZBf؆IU>餓d:XXWk;/ň#9.zt$p4 < s̑]vtmO*-VJd vW*lWщ첏ĸ[:r5 = vpT@~-2ILVI1"Vo(oz<<ꫯwmPNLɁU!PY K [a"Dy3}J^ȓc"}ta_0sEaYIwwUY ,D};I,V.qoħD",BuY-!ŃFIǎSl]uNJ˼bi@E),%Wa;r8!DUFA&MJ˖Z @أ ElVqU4kΰloak$u"GwW|XYVǶ ~uxgMrW_}e/8g\x ~3lF~gѝ8wG@RB'vmKoP gT$%y&MZR9cnIJh7(4YxLfc+uJzܮooڌ;ZCT*g;o 4|m#d6K(6m|P7&$کxOEX 8"P'.ɓ'W?J׫$5=X~Ҁ }և̝;׸] bw%c$TIrZm ~X5 1sjXz(Jgaa&atWPzr]Xz ͥ𵙚Qj8j R'p x,%ZZ^JiT{$CvtUn:*#P'.pWLA+`S)gx=XkR{K%v7S*Ϊ !MzKb^}NVۧDvp k{!x ]}#dR8)•yǟ$A{};)"p@fl)xx %.\!=y2J S?7ZC #R)ȶ'@"#;778Dﳥě.j'@ԙ?ԺukS)$Ԑ7BEXo?{l{uq[{}ؾ~^m6z6gKN]G5BSeZrAﭶ3v2j!H :qASO>~3UTAuA*/nj3HՉ'hL|4[nIw} " *W^)^xKu]g,\`7ׂ'OC C X┗1A^25!oJMl_czm\Qa8ZX!2FL' Q _9[wy!sPRiCůSO=Uڶmk0,@5McfD7{_1E6#;L[(%'wJ׈4۰z9IX wJ' 堥1$Qn)t@D]g 믛xj"[e¥- F{c#pr!l2a`^2c PN[*?t%33<,L\g BfoAleTD_qȐ!reEO?-첋uQq ڰ:ƻNX'3 OZx?)vYCUt]t)Vq@"J[fv*C&Q};IX.h,GE[@Z:t![=QQ#,o0栃XjRzҤI0oXwv0/ꫯ#2PtZ]]sgGd8L0Y˛,Hf+(ѣG I`%B)|sOo(]{E.O>vaLH5kQrյ3daddI$P;S-(((XkDF-ԍA+8<KKCx# ݑC!wyg3ܝE ReyUW+%"! !4Dn^%f ? 3U|E_*ᥗ^23S-4` +`a^zf.(/8s)(XIs39[2إ pR=eF+^%x[D62[﷟+Z6h$a !P0 k"y7jaI@"9~(]w*X!J6("B(`O?gP4xǸq;_tEg\:޳$f%|E:V`>(laMm`-[4 ŋuE\!NJ~pi}cqM!ONqK,a4x&X0aQ(J cǎ7-M_ m,bH&qkw42cZ;!:(^T;f1eD.lvt>/#(4k!}&JPzh,+wH};U 0cA $'I!y$-;\$ޠQ(X$K"Ҏ_~QJg6mq*_Vn݌bl6iɻIB*ǍKn],pwy&֊KN3(P>Y!`:[8q"(JXnhb3JrsI&W6 k<K [j^s/Hq㈍~b0wquh5i&q!HDԕ~[o ׊i2SxtJӭ@?x…*OjO S%wO}i O*sR=VkМӧf5Tyj-z8[PZs _;Wk *VO]:c H4*CMtQs_-Ws]̹vZ\3fE{}bૉ`F]۞Z֦ƫ Oc˕~wk:|ٝo8+ock?7_Ft.^m"‰M $V;l8!+Yc26L qLu%_~1 K,lA]z >kM|q)҆mKXøSvk7]rj %_RƵt8$#U!pU講{%_.W*/MlfiDNA7&\ѹ^z߆Y8ro*Nb_"fpt%k%ھF!P3n)@#r;otk Z Q&VKD8Y{JW&EɪߖLm& 6.&[K\?(#7(@ QJ6]2g@92ⅲdڍQYP:Ҋ:Ǖ!V-v&4,N[$ܷC!XƠGʊ)oi]mu~^M{Mf&nf%u8+rv8@?d۫yvr|+]Vq;rttߐkU'WmC@TҎ-T U~yM]f"5:ԍNʊnR{jM+TO>jNA8Sp.Le֌묳2ի HCQ2b<( ' 'սQ̉C!g?#ej т %V%ZU%@/JWWV+Y*K]6pSw8?>H4l;>3נU 2QK.j[CHydr)$;!k[UCV{=%hDʪ^ӤSVɁSNL*+{BZt_;t@sA @2pM]v_|1-ki#Cj:Æ zm h!OLgK@Mg?av2SOj4WJ;z뭦*VjE9SkGy67)2n|{Bn'@&^1ߦϒb{^J~mH۞HY%h"Pȕ ل@U ”C .L  V#qR+0XnFyhtꫯ?А' W@3_l7t:t01]Ʉ1ڰJ!G+6s9rmn!|`5=zhZܢ5ͼZDfXXPc$6!M,ӽY9g,5W؆Lv2 6,7)YmC%*߬] $dXg7,C5)*Kz 'EyY1,DXJV!(RI /mҋ(^z#,Li,LSN ߪ.?`lDs/8餓_~o߾|",Vcؔ`[\ð.'V; XA!\ a+(ow-,MJVZ.AH^CY5dMɇݝLF*`e21g~" ,T~Xp"`ʗkGX6۔C;޽7>e+$(_*-ӻ8Ds^oٲpYd@3FX4o(\eE^b a+ !QalCخ]D5zGRDSoDiÕ2bԶ%-A"PopΝM 2)uE)e^\3+UUVq,?/qeؖ 6NJJ h\J珛Q,$?BO4G,UJ i% ^0qo wtXp` ft;!P$ ~l WM; &N./ʱDUk"y V.dVSa6e̱bV[me/ h=ksÆ sΩ~MUXX(>?%H5Lp?7aۉ.V?e%|;rV%t?I;F:KDMj GdH`d>#d"&M1J^\r=ㄤ'vlEJ&(o6C&6idx㍆ IJtE\>kle\Y 4Hz!};rH@mW3sl)lE6?'٢Bij_dkߠǭ]CٖqC. *IAsz-4tgW)[E4f,wk>0[zPZAA˚Hv<3fI-KX-ۨD7]A܆:hSP_QdSA{1]ytqv; V֣79!Udބ^q#ͥE㮹EYvF2O(38(I )JqO[ئCթj[XH4پtw;kj.**2xе̂UO>&W^1g@}@i'-1Dhxu?PՋ9F4YQ^LfDqNdq֬NJ ~.F0իW B$p( ps,z,.E|$+m-UP?Q˽Y;t)q](_^Xvev5N \US:ZYKL&Hv:O6ԘBF x! 5dn&]t7Dn6CheWKN[V4_ԏQzmz42M*Xp=%iŀQdȲkR￯yw;A`ռw/.hegH#ejv,i͚_5eS.b2ZʾQ2^)H=d'C!P//UJ9+^ )8+DLUǥ1l-ZpuNܕA e D  !ໃU@Pl#T dNC2KgQ|! (_e)+`;Tol?0tq?vaֵG_LQ}YCZo)Ǡ4R }yz)zA5-RCF$U%,XX(ۖTbop%2vש;q pm|AA@SOJWΑs 4tY@ Qb.kV^~e%ʏu-Tddka \(2>{\[aCIMYz^,gy!JJRL)S Ab'Ʉ8@yRކ\AI==Aq6ic|5t,k$7HKc)=cwر&! .WnņD,3@Pp|npqN#(-()cu]']t13X {Opㆆ s+ e#q S6BDJ/7ױ=zȊ+dԩ~S,rs^={lMegAX>ske/@"TV v^r,BiukF5%*7N T\'MȚtê)imC/"Ժ eߑD\V>JnTj)7*t u]ZABq|XTp~6 @QQJuR ){ς#8Ԧ96`>{mk\֪Kk׮sXԥF[n(h~\wqa[PNl77VraH*--OfIY!P-V/B,)Ԇ-T%{i{;~>['-)JHzaJ[׿UHB"XǏqLC7tPz(>؆^c&֍ŋI2rAD)Ry?QG廏 /1vx`G~q3`5( oyjtHB ad5kfd'LąIܲT\Y@M`E nt~>;j JCۛZ +Z8T͂mI ,`6Hg٪lO;GHK% ҇1ZPXg\ b&)(Z*(DX(kk<\VeL™]ۏ%{bTnZM$,P #(Xx(3g6M/\aK&$ KJ&KVӦM>#FnMڴ#F?dTsmIɤd0CPbfCUT>c,B9Y8#u@6!P|M*\ 7C6ؤ4tl'yb57Q$'@.hoL|˒_PLq}.h.nD&Cl+0QT$9ٱHb- (XD4l!5!ʌXm1 Se",u1(V'1E:>`'"#<(P5LmU %XXmb{x?3quv fQ۾ܷC (zt&`M_3zրw+RTv<;; R.)9h }{r} ʇdd_;j۶Cf bAG k?Ďk*,o\6>{LGi+PƼōM vE cķFPĖk2?p@Pƒ$9q*lz4nwB9J 7Ux"NM)OoĚ [GeR&_ǟĜ ʞsMm 0Tbf'3 ,8qd+&"%e4\4js`J]C e #.H, V?|I(_RK|k=Խ@IDATR(w4V2cu;q:m}Q+_ zht$\7(moRrF1`m܀b} @j 8pkn} !P4RMx@9_H?2.TT-Y=IDݖoNm\7)^\A 9;Y!1 Y[߄bd0 )hg/ E(TYO:ȅ ?0ƂND|A,ىC (Z0Q{&Z׃Ng^J?oU<&~\D -L?n|WЀ?P[ʸ̄%Q`L=K_M!P!<&B"H`!Cp7nܘK)V~w!)`m& I JLoT;RV`P K$Tg?^2XCQXxPU |SUM\lӔ"s=O6&h*-#T4] NYOWʇ0%+'%K+8#qis4lsPmr1>W\z0; RVĒ33 j=CU0\񸀃B&\X! g̘a'ejԅ3[%UO:߰"Q%hME+4.l<%a 2dXN^/VO.2 0ukEE!ѮwjҢߤt at QOf'N(`H@uq#(?ؔpKL<n߯{H,H7#+Bq1ǘR,~+(ս'6cމE϶]~{U3~"-5j%I35d6Vɳ|f!PW\olM-gKɒpbŋb֣BcȼSi(=•n Y@Z=PCȎC\B O?Q#H̪OB,C[aK%Bc\-3<lad•Mȅ5LPFz2{4!q]bމ w/s|f\#Y7ծXwy)cԄ& }޽{3.' 8J$=Nu@᪉ _jϲx?e^$`Dj!t_ۺG e >%ٰĀCPDV jMct .oHpݯ(<^%AAPS3 Jk ~嗕hQ(`+>cXp%  &Mf?l${衇L;<&V `[ *  ;ji!'[voMklb[,[HK #!x٬$wO7l;h4/6IK!'l!36 厕&y}~xE <'1li];Tȴi*(6׀kp6OOWN5>\{ h{Y=m Zdh}GlM[ك@f͒cxNTdhm5 (g}ְWE^|ŕ}&뜭_AKwuPmS}OD(12I#KF|PZbb(ÇG(\@C;{ .!4jW"۵jxѧ|TR6l1RX!$w=;nܸ&$! Q^P!BƺfەQW^yIn w,(VR}m_wM$âŚm/XĀĠQ(m\,JM#nk2?AҠ6̦p=dMJNxH~iܪ{Y@Z.O~ㆦ( qQ~mݬY37ZvqbEsʔ)~ 5a{ƪDfت;8py 8M h$vmq5fO! Vt*[H2;Mw}g2Q, 8p@}DݥYAt-'x͖4h͏&i#6$Po_Rye,&\S!inoJ)\j9GGX(>E_SِFWhfץp]zc( bϓ)5%jM&dsM 6t} Sz%x;1$Uj.7?C!P|zSjUsu_9&Wv!Z^T" 9هxg2HjRAvǎbrgn8~xŲɲl5z=;ΝiL&B H`F zmVԨ9s)1zhS.Ӓt-s@."r;'njт %VLҸެT-*WVA_8G%g}tݸw-Zdy.υM5[Lo k ^uwT"|q,IXVrh8%U_ ՘{sтZ#?^ǿp&~yHmVqx饗L={Nju٦W>SCCFjgebҥKCq]K)آ5jvI|?Y~lsٴ7IIJ6h) Z`wُ@e+Q3  [xpf- $- 4Hk` 1R3dciuhdȸu@LyyIw@R-|zDfDrk zLF[nY+oZl=w]rs@TmlqY?e/ϫXJDt4l qհ*5tN׫M!X4"|^f?m(c%%&Ak͎FK,E),ܰC VJ))YO)VJ)C}ٶݡޜ8?C!I)EuIV>$JU bEł " {P.Eދ @BHB|eosܥq!3ew߾v{Ifg|OEAe\^cj;{x&>EWDP0xQxdxV=ga7Gptn}?9#lӝZ~PPVA((f(9y;O~R`?zs eźe[?3p׮]r; DojE p>2`..=N/@/t"2 w r7 /%x!QQ@}Q[`¶a\˴QgS`>RC 9e ([*A@APvtw4,YBU۴iSڱcnfXVr*`勎[lRJ9/ڰN iny1cƈE4HepO+1̌l`kR  Bt8֢} }+" 6t㒫R5Tvq<]npU2f+f=4*`?%f̘AUT.^ֆaͺs[>{… zjo/,߷~[lnޯZMwMHzwExi˅ sr֦]@J ![Q/ᩛ1,M n36]fʜf̱y4~z),iӦ nrt(I#/ۏ>HL;H;B}gm]J2ҍ`={e:l_6t(#5xo%c`Y*|1Jwȓ12fN 쫮T/awϰVVkh CI¸>R9Ǐ +vA7Xp;c-ZH˝]`EY9"pYayeB-SPtʚ9geʜXwuAƍ!zw.~BZCBBeLz\rqO<)8%K‹UpժU#I=ޮ\cE;r>P'F`Y@@o :+@.!'\u@+MkinHAڰ/uߨ(*VX)A(k( IiwiI8JXPѶہ,csʒj8g]s\UޢOW;=ʿsX%JHS@i'ƛKMw:c\Sa8r\'cM12ޣJR"x@j!yRz3d+D(7!sn5sy"C#{2f-B-Y06+7P "XE4.qK~3|X*P/1B&^&pUF@PiGE@ ήyc"x7^ ]KgLAe@"]b@mTlh =T'kLs>*5EeV+)_sbn'c>ǜ=E3=cΠ2tղK2t /XTI&Q~hƍԞdR Bx9sTTXQx.W"8n\`M.Sg-t+.S^ާe)ה(?ybXwo4$oPJ%}/ Cah…B`u?/[L?\ D XkuގGp˖-+ӠlAhkڴ)}r:VaCr`}ۏgO8r܄g]ά1gZ\ :K>J Vyz@+L2ũ|U^=/4O]%%B| 1m/.hH&EZHAxB Փu=tsT`͑NJŒv6*nP &\BG!X3:.lIJO/_>`eCOp_F 9vq2=vk\/Fa{֌J%#,!kA( `}sz%Vߒ%K诿%C5J~Wh˖-._o PQt33`ޕ يkC ;"p7Ue`zo~Z~$斂em-hd#͛'?i[>8zĎm5hz^@ [l/{=,e ,E.̹ӵK3`v EjC%!kƌhWx̙3wM ,f"Mɬ'O$vu^!ӧOf9WR etcگ~` *o]un1.ʚXwoP J<@bTȲ;CPBd1c)C IbǛ[F KBR4Э"R}Y t= EsJ#QQȊ+^vEYnNQcx@:&_*BԩS={vʑ5GHxsuF=kwbwMH47 EYJW~>^CWk (c"p BB|[bI>U#l23o:^ύ_qDU=< 0ڬ(i &R2%  `k*t|( H(@)wDrqGsAN3BUU8ڹ-e^|r}F@pJ#SD B:}K@S%dfw0Q`poU~ΛR:7kE@H"n\DgVs:Yf?N/mO%'uoݛ"6>**J( +ƿ}BNG,HQ!K7K;ѥL|qaG@pcԨQJ'ȷu'͛7>cǎuw:@v:BgF.>Hǎs.u O}OgӦM#J"?`օ'xB6E =_m\GT_MYfkȑ#4~x뼱:uP駟&EkutN#mV+p^ai.ܸzuu ƞ: 5kAP k|{d3uVw  .Ќj/FknlL4I1lEKrEҷo_)?i= Kr"a҅Vۢb!Qf(uI^6G3Ϙ.O>IpM"\v7S㙓)锿TJ m^9sK(" [ЯkWիW;GC9A90ZnM>se<#ܷPHQB\p Cq7nXSCb;*!Qծ][{uڅ Ҹqㄴ(ˋ/ AJ|xiVr"D[l2,dqa%&ЧuqZR 'RC׺E[-R WdIQh`„&zbZw֬YԱMo¢Eo-Af8|p9U ;h gSr]/d}Hܨ _U.5l0tPx !!!܋˔)Ǐh5(ˢYS,88ғ38`7ϸ"-E*`m=lM˖-9sE@\g#{%P\‡vku>fkuԉjժ<5sLz߿i!X /xI7,flKhʖ-GN[{s]tIN#-!?"`G (li<1KJ?ei%u:$ ެt-S E TPbOw֍J7o&Xċ- &ĚСCR m*ŋw"Z*\ǚ2ڪUٳ &N(V'ې 5:.X5q?lw:BݻwӱgΜ7: 0=U\--!NawQr/9 Z҂2<\ G>_|XJA[tI'!*_~-N+w+vG?|8 89rp @uغ>\9KNhoG؆{饗삗O>}yytuGfܞFE \3qxz^ǡ߳:?6t\̒K';.^ :yO-Lu"kP%+`Lenu^ɮq}\Q,F9>sO sE CBCA 'NHs2 oƽw`keZsvpΰ(kv.}\xDٲ [ʜ9-tyap@P)\vql^uVٝJժq35qjyD߃NH*~oEk DC#D .I1ndO92Cdt\'Ok1AX(w$%.s&?^+L[kTvcgJѹWpjR=Mc\Õl2ࠫTT cE'4'"iD[\U$k+_"4 TU& Z+":H!( yzq0V%u|Шhd+T8{6*3CnR*@QP;f[_>wC3y/\\J)kYɊe(o,>o ؊+"Yۼ&:@a\OF]Ҷ|sMfkFAog]K{Z jPQE@;Y1Pħ#iٛ{{>p@@TB(O+gؒ @;TmҤ x^TB}pWCEسgO^CP"[lAvX]Me|rAs(B^+⫯*D߄Jwމ,\|q2d!`m B/("p!pnLߣ^rFnF&҉olRݻwwPZ T9v`'|{guNYNQO?4_WI"('ۙ囟.\BWo.Β#sg,.hLp?M/K/)/  KPٲeW^!.(S2xv m\sow2nQQu D 5_\c?3O !\֪Z`,?BK.tA7xF! JA<;$q <$Ay !9R^4k.PY'XrOl \jU7݄("QW(#f)p]N[, +b|\"!UuBCT ؆OC|nZXP$PJXk.`%{;Ծ}{Q6hGd4x{_ eN Ɂ79(_ŎUV9(_4z;9mgË!k`%l3sx7B{)@ZB C׵_,`y:%(=O G jћ\#( ؆ 9>j147jHFD2CԱcGBf8E +yen(t| h,ߓ9sFzqkŊl8 f#x;:ƾ˳ƈ!c0nr{E@P!P]Ўo4Q߰65+R_e'PEM%*ݞQ׀mΝ[Π :{AӦMcC|9 9r WtoI$6lp"<hzlPVvuu?fCE@HJ2gBٳ:cx8 E sԨP>);ىz5eтmleyQlC*K,Ttisbqj՜#vI2a,`sIG? 'NVZQi۶mXM@Zѣ-7wqo!!!΋J*ƍ%tr_ti gg3u(@r %y܈z~ؘ6/7-SSk뷲%BOX缝LQ UN<3tP /,Ƚ{Jz65Zj;#CPF#0&ѣ27u_(͛7S^dJ܇'A / iM @1A1#AHks='9PQ/^4}3zFBǙ[B͌׭"(ɁH DUq:R t*TȊ\a|9/9֤[%PZ׀|=i$(V@, ~gsΛ9 u|r +6 /.\(9n9sfo3`<֋͛'ʹH"(=IBǙwg3sVPF xv~*V% /X#'#X=V9iݏ{| %4(*uk}Z@C2þ7sV3a k;FD4`.atYE:Hȳ ,/}E@ 77l ;%9TZ۵- 7 jǁN5aׯ[qqayUOB9eʔwLqg3[E@PlϖnM׮r:ٳg@y3:U+_̮AX1  "(@F)5)V  @e;^Q 8!ĉnja$p*("\ĭh,AUT9ONjX0?`jJ 2{.qL oT)wNJρWI!""R1a"(>"V8L6|]=Uꑲ%yN?&dg )][PE ʶG4o>wyߝ| M-؂ s,RpR#拌)h}|yE@H(p9uFunLԹvJ*B:ڵD,w(E9+o|wL|ה/_XݑK/IR%,t`X1 zCTSQE )W evsA>\ZݜN&uA'97!ݕQt (x筠B7'(1`!}ꩧqRHd o:,^0.5Q^{GN"( ͫNqYk\Q ͨl|hnzNuӔl[UmO|~Ĩ ]ljR{rP#GtY,!Cȹu 0a_^5 Fe˖QNM("ݴvO-Pe.5VjAVpQ_+S(+h8yaT"JVr{͚5tw\F@иqcʓ'.\XH u!;Ԋ+dg7!5 D +*(b.$PF{Z_nE 1 AWFp^^or<Se`\ jW05ku\e0ٮd+:E-F8 Zh*A7i֭7u;vнK+Wugyƣ R@9qz"(wT ,)S,a(^,]رc3ǯ:ծ]["cu_P ?,2@t]ٺK.dct`iS i(e#aȷܿEMSlU' 3]Dg_h:m߾=}r Jtذamڴ+pΜ9S{]X/4*޾};e;2N:8p!WPR1/FUK'by:%(!8 | 9rwQe7.E 89Mai7֬j3ξΝ"kP;;'rg̘14j(_Nf͚ɺo&6a( -[Y @IDAT0Eh센N)*LW-O`/ºn 'QO߆ދ"( ՇPN%a&@s~z@"Z)OE@P'|dY4[7 F5ͣCO`vbU$l=D'pFEE71hy3UE ET.M5A7ТisU'h.d? Bt (ro:;(@jA`tU0@,5_وb Dӗ͟No')+{{k壇~OPD*{'>HlBsȻ9^F^\V?v1NPlTGnN??$c.Bxz9~gQt|e˖%0 A4i҄~GZtJ/U֭BZ?qDa 5j8k7[$dߛ6lH(WYX1j޼9\R%=UhQ/xڅ?)88X]v].E@Hl<{stò|N5zzz eaXGOVrK^'nTz7kɸY^  $(SRV' <$,,pQTcǎ%F@aر9[X㓒s}*@#Bn={1m?Qn5MMǤZφR7|.E] HիWK׸8.hŢ8An_PϞ= TXӣF]t YOD߷o/^<.@81ziȑ4tP۹sg!CP=(SɓѣRNhʕ-j@CZhAʕUVQʕț7(msܸqcwvTۋ f#Xm0Bj.d`aQW bwQ7Xz-(KXP4\"cǎboߞFTp#˝E@ye +W^I`Q2ŋ 26/$ԵkWo4{.ؒ/:#kv"Eb5G(V<}( Pm*> :tH,9s >"0ua&X-f(M(?"҇(`f` +L0ARXuԑca;t;QHE#D]C'$7GZNsĚe'|38Td$K1/YZΗ r|ՅB}][wb,8XFj_D0EĪ0C W0$֐bɬn"\h+=?{A)`9?E M!ױ҄/s<7x8L(! *! }P9UvA7(&lm o$K,TtisܹSgjdF:0(.UƍG/3<#[fk_ ?/EqW6]|9 @!u^Dy#@+{m6QXwVQE cs'Ыk7Әz5infDmrnCKY4nnYl)&d(U" JHyGUJ0A9AO.kUTŊ>BBB_~&-_(`DM#4o,JpMF:#GP~Gz`ױɁEʕ]m% jr{}>? ²}t_P,-XNOݬ͓XTB"N7NY̕+Pn|c0rxizj,^.< ~QQE .sM;2+ (˝ Z:[R4r9w]M~5zc"m֬LEcN:Xޔ\lPt(Qo\MToOAkvVQE )@ ǹs1N7Zxp+bۮxaj[pTHpR$0芀"DNm \2^Qxc3h^jQ^*AY&ےBUPEB`j?NC:M9Ȫ|̓%ōf9AcKTتN_S$j5#D*"4 (>LV ]*b#U N@05C.`k!L AT3jE'|`.(DH<;x#H"( pr(_o"~dj)a?Ǫ[ ꫯҰa4M&h/8~q!|(7Lرo4AINfLY3 Wз{3͙mh鵾Kzt${}8[hA˥K矧+Jh\*">}V+`KoשFOX/._U+H}8-)4 \H֬$ r\Z[-H߶j'BtRdg,Lpªԭ[7ZB[=HA)mڴI[( {r0QPn#F o^:yJZ~ڮ]Pkf\cÆ - Fg+Y.!x.+37ߔc&?S(giHe!ҟfN*#pӎ. DUًxw[KY!CNs^FNS H󎞔6ebKzr?T'⛁u3F)t ; _bm 0ACYC! 1$O<ԳgOǏ+Wj25 X\9B w /`SB_SNr]~]t5̙3 VZre1Ǟ={ º1ƍ]픏^֎"lLmw(RQB9i W5;zN:pg bnS̖?k QHNϴZĦ߶H޼yEYsiqsɕ;Edn >Y-W"hiӦfNbg'9> >T"kzF^MxbsP6(JJ^eb&ujM9"zݙP 璔 J1+7}[r ։]T'7g Q]kKX4@&N8Zj%nm۶r1آãG6>҈XաCX6ֱhj+y9~۷O,{u(@F k#f,v3WoFOT(M&M攣\3Ѫ.md}xj$#+ `uA'7ٮ]; RB5ku:vXVztkJZβJF$ HuBi ]bÇWQZX6Qھ1_E@Pw^3# 9)Z:(Ju $.('ǢT|qlYe+0!AfQ=wE@Pn kH=% '(T˛֯EAS(B =m u>"unEO-_G]lNj'P?BY`*G05"x ZW/ "{.YM^*nOu Ͼ_ePM 7ߟc?X7n~2!>1k8(Ja +sm%3Qy|2X(|m=TۈRXJ Pful$X{i8L}8jYf*@je'= jK7Nm 9.rF-CR6mխ`m5}])iƃ%.QlJȘӐ5 /27hE@=)mQCkV pKBieC!G0wܸ&Ǖ׻oI*ٮYF!h !X}W jr央s*HXBAiz(BX}p l9W_,7zͷ}v) c#FKE@o;EH;2Z* TAcfDFQ uDQ 8}aaaB0JrѢE$K.-.asEpcvʕtaׯOXFk0Yڹ4Úq7c%){lJ!XöM;r*"x  K\*r*DB WFUBP8\K~ia Ͼe'@ZdɒbmZ۰+wǎ4rH0`\X zBXʞրݺu#|͚5KXڳc駟ʼdFP]ˆƍ]۵k"xF`ɛ*T뙛К{.i/{ YM(( +XE׀w&MX  x! gXv7]ÇQ kƓ&M%X VXV֌|*ݻK$4Xj׮-?q3LMv+\NXEP@٫{iE2߲rߏ[Ofmٲ؛Z~#@iĈ^պunf(]2 .m(.Xᰘ|M~&߹s-[L"]|y_J.HW2BR7κkSTț:.[4/nv~hn'+|Ur^6(jömۊrC`Tf$sβn=3$gΜ)ks>aWn]{O>q[P!9%5e➶"8ҙn.Ӥui6lR9}ׄM1]:{N*B6]t)]p|u|9d%6m^{M"-"s]vAPՓO>I ,p.0,x>(#Pk9Wșs1ZrSbIԯbW}\D.p-w9L[4GX$)F*Y& Ow4/_.9O"<(qDE޽ fS~.rLԅnϲTsygH/%v-2r_PNKP;L0`z5ø[k9@X0!h2X[U1NKP;cPj~Ϻ(_C_eF$Mu[^{=UtG6E qH0Hr\STdߚ٨h&Zpì{/7AleqR(TwHڵٔ?ZPy 5QQӨX$wX(e|:t4ryE@HFkjJ2'`1ְ$s߯g#@2|2dT"(Dt+֯_/Dta;w9>q~CCC _~ *"p{aaȚыn"~T0+7mM="ݞJWMAX(|C-[ZjѴiӄpcǎ %HժUTRz)i2u  6O?PA+[lNt CիGP} E@Hvd,+&Y̕3eGOһw}byAFpqk)%٦Mʕ+_r~„fßޢE iUF .teѢEiƍ'l;/ɓ'z6[7a͚5|q"((HH#@(()ϫNǰ=)E [4o)UJ1 CYꕤeӓs0 ivٳL2r?͛7ۋZPih֬YP^XS̛7ꫯ*H_xQp}cmG.]{0C#ݺu Y\(Ljk.]Z@XbEq'e<|p=;ם#4ͨ A0\V#TW p=7UVZEpРAfٟ>}/=JYN}]bxQQⲄ4q:ÁXtgDeeBulk#iR 2x|<(D6$!ի 7srXpYC`iB r/E:j(9OFNV7J\fqpyC0/8wA`]XjcAʕ+-4.P~;djǧ|1 /*}gGcz'b ? 3kܸq>5 *"#W)4-{1슅_֗ 窔\RrNt:2j6\7Ҥz(>F*(`23 dF"{hcP=zl"]|qsEiժl j0"68aUSX}=Խ{wyծ]ii"jnNXV^B* ǁ %K1ü WUE=%ƍu=߽{+ËVҍ2oTk|NSrkLKp4b g7oWm\o < b-.hC0ŋ]BAQ4gQ<^…b.6V. %6v'T_|]|yei}\V/80 Pp[Lŋ%>R/"1vkW־Bbu{@ZE`,Rf(&Jea|߂plN^էω.U Z±8%s]z@Tu'y(=w9HAZ6" n4c ]VՌmĮM;\P*ZƋ]<^4~G!X׶ͺt@b=A@T?("x p)mV>,\w@=PdEgZ-DS;*y#N Je IjƳ15ޑkD@TAkp",9(ܚƍ yرZ{Jm\]?йs$h s۷O,RX̞~?C,B0f )KH7T{ J AHCzGEq 050DKbUb j޼yԠAYE;#kXc6KX;n׮X'u70,mD7 h::awgϞemo5ҵb^$s}x}YQPFnGĹ"<塻硕Ri<{{^fBڑl5I 4hDI#5l^D"9RRI N:E 6hb"B[A3rhd"'4\}A# XN 1Ao&L4ҰTE IMr,k/7 +]㶾=w]11Y6F4wѺq]ZPPQQQm,Iw<Ú,vHF}!0+5^8TE y`t䙄r #Wߨv|]T{FU]ư[iE7d ^yphT{?=]#(@G+S8*v dchr# PxZy88| %(;/B87X%qN~:ZPEJw* xjݙPβ q1G]AY2ԏy \y@rq9I*$S'SE?e%_G\vY,v(e݄S>@,j%FA'?zE@PRn?B[kͅ6J2Ct?yPN `@QPV\@b>_(P "J%eP 8 iEы胊YCC\JIBJjX[k\sKSFbDq:|ʅZ`Zv+@"oek4 ^_D?=:wTW#pPy ԅvA.n(YKQDvA35!胺(aW b>(8b(iY~}BMhE@HpI#ᮼa pfOA#ly'ԤJ#AXɄ1*OAX{q!%#ׯ_ҞRPeSJ +5Auhԁ(vF"0>={V&@r#G |Ʀp *o=fJ٢$%JoBo۶MAEg8B-e"GpVu^X^RM 秩S C |q;E 6tLLb_ؐSNuZ˃~Q nZ(4#Q0ƅLI&1Ɓo߾Rz @@B]@%jCk(ekg8,UP+[EP T w9lW05k-=©E*Kĵ$?j'#]vիPNP_|͛#uִ~߿XPP Qؽ{B9b  (nԭ~ dž"o޼-^ ZEj#-1jUkٜeԺO7n,0|v;::Z+>c… ue\@&Sk//A)~Mz?p#M7&#ܒ%KB0(F4 YfQǎkhe X@;v(A9oߞʕ+G~-=>uB博_Ӈfĝ ~֘s˸a񣟯+>(iRx,~Tc|9m@]հJfJKʑ'\e锶'!LwSuM7oL%]:$ճ`ŋ;w% va5eX8={Q _}Ys3)JpZsz ^a;=.F̘.2(`2`ѭ"p'#jguW˓~hQ"%) &\vok#Ct{#3Jɋ*ŗʗ//AL|.]4U\Y8|ug.--[~l/ U Cj*qȳgIE@t6(ҠA=zpzH9ح}̾ K^EP@zh-P.G-_#lE1tb"F#:(<;ɇFA'ΙF-Mެ(fX;wepa{(x(hc~Z'|l#}Y/:by3nE@sY#%Kʐ#r}w\Ou#jVVts?5?Oqw{yڦ5<L_ͦ_ſPҍJz >Gu'9A j@3JG;Kl2ƍdTj֬YeDpٲeΝ3SVPl:Z^U$jx}]Jn1s/TT`7 Xzcy%SO=%J=Ԃݻ7X n//w-[JgСRKxV0bZ!*1`mc|;r hE@|7ClS[?)Qc\(1d[Tҥ AB DTBu,TӂŎ:TO>Ō#XVA/8a# p)&9sf 0RB-3giҭ"B`c2dQ -Ԓ~jِjHy8ҼpZzo+QmZѹ5a!P**`?^@K5jԠ`;ݽ{XXCU/i]GFu*ԒF6mH}g(=z]1qOa'**`{. :,9JZ[/ݻӎ;;pC (|xW\>HY$zڹѣGōmҒqZ5o\###a PQG:rfpBE_h@I{GԀ֤.(mM9"z+[Ɔ)Krd6^|njYwBpCR*UފeD@cBqqqZ_~Lq5IYNÄ }kHcYI +ޙ~NФIIA,>(Z.]PTTbto.5@ޜ}Q@}PEYP1+$$yQyHAB3UE5OdzݜuuvUteWGPt:>ܣf2Qj` BYIcTP} b;ˌ3h"s jA.6m:TP:/-*"-r~~StR[r KD@p:>SѣÈP2(S{znvI teҨQ fذaxa@ kԲF}h޽&OLPШ/ /-ULd5>FgBĻ/xu{'$-p|m]5]H! :,b X~5)4nX\СK,_].%'PG|P٥[^=B9I͛2mRpp0v3=X2}vQgMfҶoޜ"pmf"8"n:ac hҼ pPN9Ԍ ~|%MnT6tjEY.s*;h|`׮]H ۴i#Pf WXl/LXÆ Ϙh!eІҏX k_aLpz"njнN:~Yv8֊VS( UE )H]lGw"J ۨ ~ë)nꂾP>PP׋%8uTهDHԴiSY+իXgϖv4@:wLٳgaC# e\LZz4 @7{B.-vw>]~8O>IW\`[|椢8i> mj_](ev=Htމ0o"kwŃ'H޽%= n]vQ||< ><ՙ?ܵhB1~ gI5_WԦot gi|xrz>Tl\ya4z^(!9f`\rܮ0%ֈ(ZD! 8 !ь:uw+_xԨQC"׺QFa}K/ .2d^=5 :66V )T[ 4pGFFG4,|ަ"@粥(/@E_p>v;[4I=&cHLl޺ϐ9sH!.t|$ Z.ra_D>m zU$]WuaS1_|" P"(r(DrFĉ)..Nr07hzFvZ/P  s='޽{ZsFOP}tUHEY /h~OQ/?PlxܶާTBnٲ%mٲEc\_D<&MD?h†E_|!"}FR> &د{;P]z:.pZ6|5k&Qtd񿑑=+8:lemC.Lz(NmڴIHQU*m_XP4!0ga:rP z;h W?I$p hGJPo@,ā25Ly(OY쪘;vZ?UF(8k,O~Z'N* \g JQ^n̵Q,Ҕ2#%\<"se"Q0 UV4~x!JFMfBR}@68qGA \R%6l^:9}A^pfϞ| >T?HJBX((R`ABu-ԗBGK~UPJ;Yٙ>L<Mq֭kmK@E`{Yeڪd1Z۱Mmr?}Ps\TnpPNZGs[4Tvz\Ue [oIm'No//Cy|'Hym&J81@f`p73g  ƍsuDi3l=.]0S0**yYCFgPCyB{6idΝԿھ}po^P (@o!C O׌@ "_k yM 2|vu~6VWH-nr!!:Zſk>ӧSLL|আA0uTQpnݺUg޼yԺuk'O Q6mK]0'A 7::Zs0,eOē{8v~icǎ9R.6&DZP'b!hCEp޸q#,XP,^Bkի'#/h}my f)VQ|'~^e#_ڼ&!|_.iex [e+ U`(_$VgHP˖-#(8'cHG 7vaQm}3w)yÛylܻwo$ر}AaoB#QدX"߿.h\P7o^@DB}E.Qd$8k2B.A$dmmB@iaփa Bѣ}ײ5]((i'cHG/XX ;u]`Y}.^(i\o@i^$'T"m$ Q?&P4/0P/ca< eӴ"aԸq7-K[N~ܨ.; zg~\z@64hﯮ[]"E(!!Ғ@r: 051Er:o&YnCcmXcFp17<(H"Z̙3kjZbfc3 /E RHx{mɞlِ.Q\*)jhHeU$׳9GS,lvOPlypE(7M&P"X5FQCA"mU8uaɺ;( m ͙3GǓy΃8sb/,^XyֲeKAt}AnHa%#3֣;/_+ o~" H**`{dׯ!Q(3&YV0ܩ9rvy2-ZDǎpmc]룸mj}\ AOe%+kX3f mۖ4itd^f\/"qšk$ `њ 9Q :i֕SGWci"v7Z0/[uX)UT@GlZiG `oQv>>F0@mE-,'j{\7GxM~ +EGږ/_/q*QcW+6|V6^kqj|JNv8_VP!sgg۲e-yq0/65&"H,Sk9*`/ 'VX/"@P8׷r M U '*2JPfqp4nH]ЁLnpƂCǤ+-^TB S HOU.?jsԻP?B\*/ǔ8 \Ϩ J-)?8t[Ɋ@#prJWܸI/^s^J$cp*txn-ZPH#r%DPtwJP+VH(VA^zIG:y7wա"=lq7{zߨ 1o!.tx(OVCB"/k׮·2}ej;rpQU9/6_~"tR5jT *H.o5d6V'N3d VFJ /! +'A;LF# 8!r_Èx/+oIcPŸt钔D]hSSGN\70^z+V",RI,;bx!qͷpPNɵs23V;I팱#SМmJO."h>zjy##O0YuM( AAPRxXFN>M- CX\FR>^{ͥ߿]avĉBKJorwߥ!Cty4BIC%*)SVUP) NXX"_\#*mgpGjl ucr iUd勺K**tzPƅµ ʗ/o_}Vhڵ n]Wn]!amPΛ7PH\\/Qa"^R yןƮKYf3͛+DM6yA~k&:}t!С(ѣG`e0A.\H |q;v,ܑ#Gq"8 naP%+P%'[`i?mz+u"Xt>no&uh`[E\1(ןN#wrWv?B@p:=,X{כ5k}GR{σxO>DEEI-|qncf M6 (-XPhFC#+O7u׎{]?mWUPБtu垫VeUD8oܮI)|UP %K$Hz"E[d2 ] s҆:2!Ԇ6bҊ܍iݶmlY ePz /IEP]d>^ =WW b.jX,χPXcƌ![c .\ &CP`VՕ`Bí BB0VZ؇544T{_?[FJ9n*" )DGԪFEْ^ٲ<pi?`}[ꦏ# 8/(G}ud2A5?Xju\(0"!"ڝ aEAsvd}n^DMcy„ 4p@qOšZ87Q'O$I!@ q9[iKOv-To" \kT}fDN**t~H́h" xR駟u[XUV&zՔåߵk$?\FH1HA`tlݺzRXp'%Bp2!Q$砫/*"Tn=2%9M0JGTL?ԩSxdVWQ,9Fg=C=:1jQ+%d3M/@nFfK+ o7g.*]9s{QcU:WDz5WPslw fY]PAzvujT<}dTZp>[3E@q`jD0X~zT4w.H9Y%pP6رcRe+nJoFp@,6=eլ5*S۷*\jAvJdތ"X@ô?y0ؙ3Cڦ*`7?Zx~6jTx^xJĪ^ua?~=EP/3oF@Q8fE@PUt"(aԛ1 M,Qʈ*R0rCUIpCQ|,]碳RE@p8+TC͛tz_WW$b!O+eU tٳYf4~~!Aq<4`d7 4VX@8ҭ[72:gС aWv@B1t#ΡChTLi ϟ?/0TxuW1ntv[e }9RMFK.ÇS˖-} YٳӧӲe$ 9::ڎbh7mD3f̠S vmڴqp LhcjD ϡMwضm ۊ-j۷oAT/^lo ޖU7f͚%XDEE!U[|lC 6 0 ~|޼yҶP-`+g?Nk׮ѹsgZ|C$!0sLݾ};+W._[k֬V*UPJWƨv'8tϟBBBܹsbʡu4\F@ A%6H biHh+8p܆sR'c8"0j(*Vce_~LzӖYs zĆvЊNm *UTbX*uؑBCC@PpmSRH;(T!ACɿp?II.^(Wη\U;B~Z:(qrׂ^)Sػ"jn;(qr~j5~5lٲ%ׂբ:(]D*,%`\aqAoܸQւ:g(3Cf}D;b(0B3^\E7n]z~mqC#u =Y7@Im/l$$&Xݙ[`_B2[6miMfR>~ƍ .Ӷm[C;.7Plٲv K.m[dC@P-`x :..Ne!ѨXSWI{Xփ m@PGE@PC@2[YPE@p*`E@PE PqȊ"([TF("(*VGVE@P" -4z@PE@8Tg:"("Un"(@! 8ՑE![o믿N\F B ffFe%IGXX}m޼"""aÆBݻw:A{'3<#cݛf̘aۊ$2{}( v&rwϞ=4i$RLL >`ۉzH<"Ν;Ν;Gr(gbŊ/P엏M'(:u֮]KUVCW5kЁ|Ҷb Zle *30رc3sLQ{իKVQnU(>@ѢEm%K$PYgϞ\rQvh l|ءC'"Ft 8i"[@ZM&arrhRJ94+V̮G(Q¹IP5dz""Pi/:u^!:wq'kE[T{WBয়~7l`_#_>mٲ}nJgΜ"VT9=OPaƅ … 4b:}4 4H AAAԸqc;w.M0A&2Ut"tԉzEtRZ`U\Y6 cM?~<ϟrΝkw(W\R">Lºs ֭[dr(O?5"`E@-`+(Y/Xn6EEE .׮]菂* y(\(ѤI*^8Q/)S&]o.PtcWPDҥK3D`GJre$@i(aEvP|"(@54("(*EPWE@PҀ*4("(*EPWE@PҀ*4("(*EPWE@PҀbLZeImIENDB`ggpubr/tools/README-ggpubr-1.png0000644000176200001440000012143614334142165015777 0ustar liggesusersPNG  IHDR@FiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i'֒f@IDATx \UO]t:{ր "0ut a8n (˰o@$!!+ٷN:IkUw^s^S^kyUt{{VԽ,(B04G(A7$c    &C(||@@@M0"@3  & oIA@@ 0(|L2  P  @`1Dg@@L@ !@:0ytLHh"~A@@KZ䆀7KWh ͇" ERM,RL*6R눢Kz[Q ]Yߐ{S* PC&$eeCKș-5E/?y{Yޕ{o79JښNz?v3 R=b O SIUWҒꊓ|uͲ/(يR I+zQ( `&87lc  %oکA@D L@ K4hxPCf9(#F /vt=%xԥrMF{&A=:ny捻 MMMziܹp8Fv buo@@k6# H`ڵO~jjjFv1\{rJz+%'> ڵk~r:'pw$ހ@ `K?ѣI w PII y__H*nٳgS]]}s*M\py<~G?QUUU>G>rڴi"{[[Kx &pF! /з-+.nFz!J`S5\C侀>PwwRG _~+OSZl*R_/ 8ȓܓ,h"?HP:[%ۊ+h```G}T x'-}O37xC9/ /'9NEO}SJwA/hŊO~B韔ս|qHUzgB]Du&\]^؛`֬Y3tM4지g_C-V؜ݞdNcoN>8 F_ۏ={wluM@(8soW(.na"P;|΢zk7LOl駟׺ܐbc$rH;亂nI={پp:%K(;܋Mwshbw77 ׾F%%?dG?md~C/ ~r> wW}ou͋aHP(D_W}O\tGi@aw4@.;vLQgd/[lQ%rNJ={=QtaOM歭]y@i !L%+P&@@@@@$I}d,xtbρgR8 TZ^!&OPjii1bع F)?( )h4x"`h뭷ҥKA`$?=DKx )lO픟AEPZg@ S*   wv@> |mY}t.X 4* E/2SSlV 6M!Gb֟oi @@@ 9(|p@@ A ӈA@rP."pVhu o@ U[^H'GPT#J4d+鋯eb9 ?Dmo~}r:]0(|CL#   @'烻   `PF @@OwA`&ҭΨҝ.τ@OWz:e(e/9mVt:}eL3 6h4BDT2K4fsS+(еzv"$wzoyQuu5-[:;;Gʔu?͝;o' #77Q?H57d翿~+m= 3}{~M~޲w7|c/AER;(Ћ}q!bJozꩧ{>L_|q?) @v߳aMT^׻vF?zqqR! ke 9&}daý~n@2yU۷oロnv袋ϧGymF/R29{WV744LX@Ty {[2" Y FԵduk'lb|l^AGG ժUt:.e…4|Z"IwܡX,6 )NxmEowS\V Ȑm5;בk'R6sTFG> dB TWW(ʊ5y}{`W:q{9[R$WO]{VS3}f1smx&9p/9l^M[,6*:?MƇHlnK)x<|lժ W_zvsڴipï<ڱl A^gRr_t;&G hgŻ _\|KҺ c uogcl}}}o|~_̙3y]v)?^{-ٓXe|C@|X*r*=rju%հ/3: dB@qE敺t.MJ w eC;%0^pSLN===T^ߨJ\ҥKi(~(g͚E-R~duQxL(qϩjV"a^miwچ\G/g׾W?}QVa;)K2U~xf4'*zw.ٞ׽;=\СCO(E@ϱ?}2X~/dj^߹cD>$ Q"gdufKd+I>H@^^HbmvoG;w\W{L/ub?x_.zqⳍǨ'\*_v ^=J2%wnrڏdڄZʶ~ؽ/U[x\O?tEtMHt++zlu]ٳgŋG\.O;[`w#=hzI T-vϦ!qO|4B s&%N:x sKV-{vw?p⹔AEȫ[1c[NY݋1[d?YI=/gLh$W>@{ں&q` ꌍ`$4xu8 gՙ2-NN/*gT'Uh׀a?8^fAa' (Pp^ ƯW3xf`g#Wx?/x>0}~Zua qRm8FVjSe{yj{LJЎ @xr04G"2?R.ad{xxmj@$ $9p[QѤAFU㵭x(mm͡ 7}hA^ٿJr#MN %Sl?1@[ߪ̷.^$4PCӎ`]kgnEi9n)M3J|tԳ?xh4Qz8˝lRu$_H;++\j,Ňwr?9Ԗ~ۺzh'A y8nQ9N~| +u¾fUI=9Fz.3(|cͧF# vyIg?~T1YlDՋɫ6 qQ@ (Ddp]dU?@o;,+{Q{E<żN|-+5Bvs[81[y~ l *qxyG8u.9 DBԵFkygi`wO#_ڂO _s xx McxᙥJB'#%.@{?US.-pp/s8}4^_4unx<"Au ? KibǿL~:$H:ץꚈ&(CpNG^l2J'Z?^F#^n {hO=|r0m|Js004i\QdDK&( ('=W?0'_V~x[?гa|s=قtc9O[KG O+ @n(_LΪ"A6ԧhݛe37poh# ˭~UIlSrn8N |2T']#(|=d7ۨn+T+u"^A&םJpߠ@O[z5 @ygm9b+t}4oP?SI?kXO/)%_S抌96@ߞh+պF QN3vu5/ 2SPƞ_Cn'eŚdЛn{d%`*39+gV/ &e{;Z$z <0U!Wd c?d&&_nwOU: tmQ5==n$o(q$jy"3yE$o}P׻^dd𔐿kSjgBi˛%~~!$쑔JG%!]ծFdG($wE]Kv]J MG`KG7 w;'YY/r#~E'{% olWT{6$X=5Jچ@ŏF#ؕH:T@⥊j]!Ȟoc2ilk} 8N?5d*XzZ!{ѐB}Zr~ ҡ({+}"fb[_DݿPa)^!&C&% }q?!,U7dur~ᷰvA j>%V{ YUlŇ9"#hV=:{{qK9L&^f줜]n4%ɋ:|e?\t8s ?wlѲJַuXO}}MT6+)ǶDv׶|-+Ś^] A%]$ԯnqZTR q)]_^ک$'q׈~*-d㽃}^ݛJu]wTi"^%s_TQ6ӾqDy\ r'"ePk]t/ <ّ~& L_F{\{*sssPz=.Ro:$mw4B߹3̭cbu*~p͋0o(| @ &eן/.6Cl}m7U|MS:9bý@O @qV 4va~̡ld`@ATh8,9>KE+x&/8O4JNM nmi@۠4eWYMNm#ȅCrTs$r(_ȉxS"fޒV{N"nڛE+yS` 8 @3YwRNUsAT* _ vߠ`9+ԎP*Kb+=U.崙Cm]58Mm8ik7"9>~BH&o07Rޡ9jYZB@#WiDB4ؼRϴ ==7qz\ h3kb_>Aɶ)Pْy_}G2cEKDFrHh4  &YoC8PQ F_mP G` J;pBg?T{+(|HE_tʹx?ϳlRhW `qsIYb{ܔ@ 3 #q3=IR>3F vv~ZUT2*wgABZ8{kЀ~ @w +v7z~e[)s {E̿Fz^v4f`cz㩉xVP\դz[o/xK6d lGd/P uO,GΨ̝v!H,yyQw{A2$9 y&[F&oضtYk,ž(e[O{n%!k{Mk/1o491gxQAO5H@ $C^9[ke%9kdB/ O,i`u.H1F}4po?ڢQN{)oC6:k _gftqe?Yw$F϶HY좇slI \CrbW%k _wSf\%M+|5ϫ(:UY@s¾f6؛/+{oN0B(`p9L%̮8z"Mأullo"!v%Ah7kt*7KHE6(-"H.zk{3ՓUoWd9*'B+̈́)cR6 2DȶhMT$k_c`;cYUDt ,s7"L@v:8 Li(—stK&ϤvVu.W;NGo0ĩm|jsx[->mHP񁏆2Ď@1 ? jƨwzoyQuu5-[:;%l;TʩE/ڰa1-:wAQ]N,:To 6VBꂣ:|~VPY[ ýNB:ϻ¿[詧{wy:|0]|Is4w}ѪUhԩtEݻ ]Me`:SX6~1it 1&jw)j5gvp/=D7D" tw߮(?yڶmKq /~ ʗ/ O*_POSj?yUZs|!G#!^nfh |}e68*|Y;Nˆ.\ϟO+V6&×+m _ KpwOSE{ItH[`? ^U߿)ꆆjmM$ϔQ8~n+Sd!Cl'\3ٜ.WAm}>ܖDÖHC֗T(!^Ȱy<Polժ ?V;P <@gώ^ ]]]dW1*p'x*mbǮiz(S)֔"tq277I;bش5B:* y~>@1*|ArhұE_T е^K---_bΝ{Iv"G.PyC@+dYORz8P^yjHm7o%Gɿ ;EZ ɜk[ ʊkyʔ)qpOOOYϦ.Rq׿~Z-!ԅ=$z8q|5ͅuXsG$!_˫dqL%ײh}ԧh}(d*zH$2j(r~/<^իW,?NMMM#/|B_>@[GNAxP# D^tIb7C^^H׮];ȑ#sN%/=/"n|.6? *ܐk!3xOQ#ޤ&eאAduVۢ|1B1*O?]Q7t566R{{;]tW_=["ɶŋG>}% @/A|>G>6R_=')d*Z{~(|OjU> 9^"8%˕@:Q=裴r[zSOO|4i$HoD$KN,Ȼ|xllȊyawmbw @5;BЯ)FT!$_I~xoSQ$׻XkȮ4u1܃k8,oi|I- 照lKcށgN$ǻzOki\Z*{=N2 PhਖPAT491 \&5f _ءQ͹5ΟAhN::*C)q僯Y8*bs9pC12(|#ϮǶ~݆p̑~ےb%AV\V:GThW#d+sM~kAwt-nvvS(G QR# >%uV6w+# @zz;]WoBuG:vzi1NȦ堣h${K砋B:6:ʪ1V  TEk _sSb|8B[0񁁼檗DţڈOgг8v-i5C^4!_kcH|³ ?;~x:B_NC?abZǻ ʈ@wRAkIsK]Vg q~*r*~Nxo~LǗ=ڻrݕPBZK>`X7FI=}A矹{/ac|621)nr՟R{a{Ƒ Ÿ;ٞU,n!aZmjoA ![Z=PWý@~Ȣ݄$iN 'c_QN_;3/( y߮{GdWmP{qO!OOBu5~|`P>|1W.3XK܍m8O>rK4& 8F)9fx7XKѣ~!NtM'Bb({lq6I%TicP. PŸN-qC'ݩDŅI)ڔxJ5?Epo/,3QMr,2XK } HP! 4yKxR8+ibO=)%F/$ SгWp#F# p2$mQ$F漑fPƙK]D쒷޹ %UQisᐺ1vyIK=dhEi1-VAkz2-2ㆧ$ 덞~&Is9>S{W:XeE9U."eR ?URìll- 켵 Q1س8*Jߥa4# @ 4Z>6ؓRg(Ya71YlH݇j6.z ԉ{`rX2c n?»&f/tG{z!= o֓ؐuPmu I-N zpS Pvv\B wR߮1F@_ V9d7q/6wF oY$iN+|@y >bNf?G#> yP4<ȭيgRgEliOgFB?3tqwbm`<3bo~>Vg#"n/x3u<0H{ tGks6n'+|$  $V-\kPcoRm-}-MiZ+9A~2 rBٺrl3|-—M`9_m OPIJ;]PI.3WTV얧rVm5ɏ$!]9ǿꔙZ)2OP4ا{Y5W,a^9eP܍4g5D@5' +JlLJU79>BfIq{ {B?(|ϡG >84Mm&gf+JWq1"q8 0PFE  Q۠_ a1u+TN+ec{nǐC`NLsJBt&गPz)) iNn&Prmބ{C1'kU2%vKk ?MӰKKQd{%ʄ9zr`J4S䎄';: QODU! +b1BylqUبՈo&fh8itR76/` {"DHý@׏1=@Z K_= Gw dɃ^8*]s`$J[;{TjQ͈d\\ J'wsz)~?]q4uTiVXntv иl!&;g!|DCv6ګB6kQ|mMرct7ի鬳΢3QGy{aGr'aXERb'+&OL]w\.z'dtAKB@|VOT4GE:K34+V^i_W6Nش|fϞMǏW?)S |[XSTDw5f嶳ݩH,yeVg+yRɴeY E -/ ^\P/YӟDڲJ6ˌ4a<6)%.Zj4B$G<!zR@Z[ַSO+8qB'e&rA:X4x">vR eG-R@Z …Y}/z5G+fFt}/1G!l^DKt`ns'~?}_'7YHgΜ92^@,~AbǦr;]}sڂ%{ I#{NT$ Q{\.P6A*q5ً,{—HΊ%Y A`g?Yr:ʏ([Wpo6U> 1ؓb!1!ZH'O KGe{ t'= $qtt7w1'\/Xy_NwkA q3RҜxc_Np kqIeR ,b͡<07T~;G?JG:b|'K^qeFO&N29UVrLq_+ y9@fLoVWmQ| ,Z ?!s*>A/zk8~oYEobg(>.f $UӦM_$" &oY6,x\nbbm \dsd`+A>bsM&Æ{u8I~tYڵk ;K.MTMFX ٰڀ.y*H~\D:qh%Q\ۡ8~ԭl)Hݎ̂e#u$믿$?M'Ϧk10iΈi$ H'طG`oJ\}z#ѰcKKM>]W鮻R1ߺu KK JMŚ)?L7"_?7Ҋ~[۬}[H'yM}U,el] }LZ{(`P~OOPҤICi/oe#!)b_QdKt-+|# 41b"Ytp'xUt9*y[q⥬%m]]o>(|%'w}W0\0QFc[OÞ~%fLS`voG?@OV!=jkV&&e/Vwy'W.b+iʕn{b# Qϰ nGWls|D5>^4ܯ<pHh@0)+|s5бch֭+(qB_ߦN^@IDATv- 1Ow,Fp8>2'bCQbC ) {ZP$&-R$—6%g{9_$I^nf7o⿿l2L 率nIA1I D Kv&M[Ҏ%A |}<>Ƕ~g_Zw闿%m޼j ]Vr-{jX3[l1믿^qO]t!ӟT1>:X8iK#V%6nXinb,z.A>:k8B5ka-+i [T[ 3 i-5k( Z\\dJtwSO=(nyG!K/ѥ^:9uoo/=C ?r ޽[?YA/H<#F+( ;s0m{ ՜j1w,M!HY{<@;q raժUʪ.pB?>X"~ٳgL?8(^>vs\w#K$NdW}\OoۗAesope9+)6={Y(ݡ}e^ŝ~w~ŵO,bթz\^Q>(J/%]]CVԻvRB sG@>#uչ-l$?z(V*qp/4x>^?Ģ8PFYKwŸ6*W~]QcKUUUB?я~DǏ|/mtrVǙƍNN wdBE$ƶ. dɤyOҿ#D2[ln6[T6뉪ẆEf9wCr!./rZ`Axe4vE.e $|n_׊XK8߱3'9 8(!pwQ䇢L+-xK^:V+oKJV+gCY:jK(H@Z _Vֲ/+?c[d _c# +;X+/ώ3,<1 _u78ekmVzUAٷXhx:7C[ڒҌ$Ot>d멣C9Wҗv Ye/z' (#׭T  P?EX߰dD'cgo׎ HvnE߸ _lۧQSb*3,#G([c kOnI;w . cߊR* QUNKFrwO/=p*7p/Z@4d+dsM֒X t8LpKmhATM-YHKዢ;J\ ~z?$Ie.QIHPs=W(d%/~9CEEEA' E[9~o H{z%X ={9kaT9~N#֖"xҕ;OüdTŏp(_/_>]\$ύ7ިXƍmӟNsx.I‰eNTa5 9_qT;qًg` ;#ivXWxXYf)a~ݺ*Ϙ1^[[(# QY)IO)IsS4.q%< Rcd0r<J7lw6}ek]Vڲ[d~go=Vuuuq}>&- 6i*}]%*л])q lEOfb`D _,n7=30J_WS.^I=iN=$m[Ng^+JkRQGmb7d=s\_zٔ|/nt7wY{=CK.1%D H|kLaORʏފ9[-R&kl5 wBy]>^oKf9fC$ivSV2nMO~2s})x z_#`9%G,q~SY4>|φ{__xJ-јQ\G.= ~/zL@Z _?яcz[q qR A 68IWbtC!u t'ie5Wހ c:A! ?'g?3JKhc{s:p —9UL:{ 絽{$TW_ز՟,b^ ,p#4=+]YA{pHݺ1[̢/pVDF*LJj/z'O-իWSSS?9sʵAg: :NBJJዕ: x9v +wϋ}'i(ؼ巽x2XkwFG^.[L~72͋/H_ƥ~/ M@\$%(}PZ9^+p$J6v+"R+rsయҁoDWNQKf\M!M.UH6}}} /({#Թhɒ%F>'~MF>e%$_ZtviZX }MO8=븠 )+|w\k׮q={H󠘏>vɫvAa$)s~gZؐIټq3]o HYዲKu/Jk_;2Zs-ݺf\L{ֶ~Ȼ~מ1 qw)nQM-a/잇m}MMC_v3iwټdF+E`/ Kcό^Li"Y53(<7Rw{%1ᒩi=SmKfQNVGfd Um5fgRHӠd3h3+yRY3C tmdɚdNQ:׺*FUiv7gW_dacB7dPhQп lIN&<ؔ9a.(-p|QBǞ*$  ,k]u-kH$mfZ`ae ;H6o˶v42b%{o{T.? :Ÿn'# Yh$|}玽#/,[6O>V)d&$o=Rx0 2ܩ|ж~[2(|| & R撗6(= *Y7d׹:+o/}U$"L4%:_QC`IuusU[:Q^Ÿ~Yȶ 4=GuFoR!p[)ney߹APKQD 3qAk|(^#y/ 8D͎ _S=4S|!ucj"w|L\{sf7\&tgyM r)/L@qVp\k?L'őbu? Je-;'mN0Uhd( p4<4C>ST}6_`^CO+LhXPzL~)ʛhE6]>k W^_`J^L170GiVd(5D;9aNGR^Af.3;5P("JBP0X-btFpĮA񈵾gG2P.rr;D<&.fЧf4(vcJŸcJ`7 }Z)ǟls!M){P3ɳ`OVuN>.&)D7xW/rtid( 0^YgEo$_/0nlr{mZTUA9VkWE`(a V9aE5H>:| /#KC4 Ѿ>(|Cή:26;&a4>_k7@tV G@<7丧wo' FjrGؓ)03Ҵ>Sf(6XMG<<Y7y=\g(Gc[%P*4j3[:H>$f%$afQR/2zؓ_]Cᘥf4)aT?i+Ut.m߲k'N.~M(\LU|8-nC LaLJ Y\uLJfл깇7@*$Ox=JuIB _qdR97Jn HSɐr6tH}Yek)S ؄lj@!`/ Q]4hV^/|4oL_|qJn!)UXځ8|ٿa〉si[i^?jt|`0Tఱd%y-PtC1oNw}7~tEO<m۶^z1|K\s ]q4{7*'yyG7e4lx 2=OӼɾ9]*N0k[ک<؊jl7@( M9bē&WZEN~e ˰pB?>Xb7o7|~i&6׵u(-N+hMt+d(qYe%$ǚkgOFuV_m9pO捘ɼ*S]]GrohhĮ:K.}>uvVILtȄ@[ymSVʮzވz  SPTF 05LoLxWHT9OT2-Bă>*)SPww8){zz<߸\~Gb+ ?ڷU5J6+`/5B&'`ivs}jlVeGikg77l|mopl^(pVCAc{wyUAO:YF^XF5"*}/6( LΈ\WHpu*gdFY;D2T.KO! ^*Fɫ¿ I]vX#G(g\p5(O ntGz~[UZ#򱞄ݕ㤃}k#`gY4xopK(*O?DtMHtӹKW_}﮻FqH^P+o(v~jNSͫwv6k3uF!IKV;y-7ȳn^%ԩS)/_>ʷG+Wf72<6N)Bt >`->Ǭt?}z gPbE| yYG#0P yW3f̠uQ[[/L^6"~ ! QhgB4u-(Y)ŀĀ[sŨ{@{2Q\C cJ9( l>,Bhݸ|>ףU^dw6s]J3֭7>kEsy[LQs+F*r#y8VRͥ5|sg"jbsgQT+X1ΪHmj4g6 ?ũ TL@:$+MEXҺ"&eKJ7p/"<{ ŌV6 If"./( =1v\SKVE,L%n$ؗ2>>O||$P6U |1{3v A`֏}={0h|bS3ye?c$'3^>$Iwvm5uNW]`'ݨ|*P0[+1ƣ9:+Iyޫq4-'?=8C$' i\}0y%ܭɃӥXtSM4i3*?o|wS`? ^!g#socc$Lp=R%d9}pE>U= cG#?lulʧe,(DLMu|ߧ<\.ZZ^הI$ ީy(|Do8BŇGBz.}P4},'u7捃n d)O!k~(aouI\P'`/l{{Bǣbk[:@WU`ZN}/uNWɔۉYYQS<*D@g5gT L=b8±m e, ^sl8loq#cJ2%o3nèBufKVGOjE7bH;Ϋ3R:Ucĺoj/!G6[NhDQsPjI[eF5u2ep.yg-g0DoQ D|vAY%ٽQB.lzVm*Y:؏qLdɘeA-Og=d6/z;.J#:7v#Oz)=t;Z$=K>g uV~VB^OatЋ{(|a#/''J{1SGc SR KĊ4<;F? 民xɣɔT@DuQ_G⼹~( mEq^:+;6{Z{b*XŪgW+V)ɴ+Ŕ42)c@k\r֭"w[qtiοAwG2@ f,Z̽%8A0f6>Gnc?fE0Ǿ (j4%ZdݽdE/Z4\?\G޿l )F>tUiR*jfMhfljp[4p`%sy: QSi^żX|K9bРcHF0 {[.+m0HSG٫9]~6z݇-0}Ƶ-94DVdwHɖCIԶA受L"e${NJմNOV u/Ո%`*0{JI3c#(dO+Vvy%pw lC>pK,ɰֽ̡lQT(p6/[vS9E(#L g?"{>E *(V֐5U% {cOG9bD$?A+9% {Z{KK N\ k1z%&8#pb)Ͼ^qmwgV3jc9d9T.wy}i{0lG+~}-Ħx7_7ΆwȺ:@UovʸTrxeO"Ys)/$ "h?VSQ G`Bz]:nt g?Acr/L-hɢ1߅` טdIJ{!w1,_)k_{ C@6ee MTjc;uڤ`Ջ `b4}\)tA ܓk/#w,V~tKH}Jhlh凄$>ar6=`26QjWPgy)y ~j7Uc8%jFK,q}8bWRc3դ̃{J>v' |1pqcm廚6g=_x`<_G2aD@Jxvn.68U`7 ׹Zl\ fmԲ~X?,J*+8GA 6DJN9)l16 NX5Y 0+uB"?FszNg^^77C[v^{8]EQk > T6 |^G 켟<#"Á%(dSˮ?GS~!? IOҨd%#340QM2 T2aeG?(z+YG<GaDKJW|A;NDяƶ}HRhN fJxkŞAyw!ebb@."A$OWgjPE `si?.N &Y~v'.gEOK)PD O=4URxI_ ǐ 09y=q MJ>/axȄc 0yeT& '/폄}UTa}P/;3I^~)Jcfe4,-f@]lMt失BnC,oRF:})F zl܏懽olM[$1=uUdB1LIԴθ]\@k^[JWB白,#A"O'WAQP;1\W˦ uVO ۥI#"wV(}).^ M("(EHEtK*O]6z 7 |M&-{y"}< z 'Sv&#JBCuΪ9}v*MF7 3rT;{ޖD iBaw_^~ F( ZǏk/A bZXcZ$BrSLBad}bO'Mг`ݶ#W~R-Q0f^FlM.]"~4e_Iz PAʫzFeQr% /%I,7B?=+4z \ޡsr1y1NVd< n=F@~Qןd%ݿi'M?{5@YF*Ҭ %eȳQJ~HgI"#Cێb5#;NR% Ao]fmq7;0g(86ZkˎxiI,eB+ F+K^MSOtE㥱1Qc_*`HuW{c!.%!o(.SfH O^sۃʔՌ8 8KfJ.B%9SğlE{ʞRvl3+'ƌ^9;' i(Ͼv,Ǭ Z"*M;,cDgG?Y`eB6ҧKC }o:,ߜ:A~F0f[.\MK [{8X7SG7k@"tjM A>#l| Xx\! Ӏ̢1 W]n/Hy*:b?B,}e3\M)ΐbH3{io[ 64QM bОH+꣱Ê|oRwZ!~K0L2 B5/-9/?pLb+{|d7 7 T`0:/&M9Ν1$AO&4(S3;촩yc h%$R]MeQͪ (k~ʘzPT2Ei4ϡs("&u!Uɍ>+)SG,4v̍j6eÔCNg:rQ!^51+(LNc5f<%!v%~VެtЁS'POUC&[>R'vF=Lꃁ?=3L^ull.|FxeLCz*A}K5<X3}MwȜRIC #s8*?C3~KAFs5$RW}򢶏2\~&%l(SUI™6b%۩Z,V|(l~O3*1`_\;QP<:,$AL!f{EX)J/Z BScjc-ɔ2+4ŏBDi~A izC >\{)ͯc|vsmRzh7nzUm,$rg^NU6 p`rٜǐ 壀IX/ ^jWTa}JE[]gԲj?,SS_Ҩn"{!gQM`}rv9+ng7tRnTT++kSt&ҰO~tP K?L\Kf>w6rY->e}vc͚~B* '|3yv"ôl^z2qp"-eh烉!=.K@edL _(FwZ9l'O ye[C7x2(]0#34ub4I `0a1Zq.]JO?4YH[o>6muիW 7@<=3Ѕ^H_~%͙Y"98R׷ʨ}9¾sreV|/Q @,"{7XgǗ yM=%4~Ǒ:EA%rȌHغu+͝;W/2Uݻiƌ#3gΤc=^zgx7Z֩r2N6o ( )wt S2YM]qAᑓF 37S>W{x=0?;b:l$Lj<>ؚ2|@9yWi|Auz(CHӯRl_D7rrWS෶*z*qK #BnZz_Mx|9~ݩGUIX|4,iKJN|V4S]*?k\^zK#~#zdrț2qH:5c%>cqvne]G.LLV)f1fäR^D _q+ƒ[0ZO' #?ފt\ߑwڍ}@뾋)Ŝ: 3&6DAG;}Tw 7x#PUq%Ms<%-`}Wuh*EC?vD́pɱEցRD~AAZ갱onnޙF@E9:==u޼y峰? #%!Ax@ox'›my?usy{DA@g``&YfMwc:ӻOxU/JdIDAT5v?V_yɹ  tYtD >Z _TRRo&?>]}oK_5r-ŋSc~fۓ DL:1A`0^9m2Z,j0I#C {_|*0aY,:3g `{߮zw7]~J3gO=M2zbxO( ^yźt\`{#,`-AQ沷44ӎ@&FWOЄV x:aIy%mEA' [hKcpxج>(=rbW}\;5enC}9cF>ְZ[aC t҈\ejy\2kRri>z7eNJ6x;f-d#ڢMN+WʩUte̢o`Ą&sf;fGRzB#yGjjEiǽ\9 hL]GVhEYmR t ?oީƊJ/OQ'ɂӍm4IalG܇z`12Ei_mlf/u!2g}t1z|G14'/[e]6~4=e70#)?xkȰ QVtL\j_dNAnP˦&`J;ͷ ?@4M|T8zJ;P=,3Ƹ-i )I!]:eM!\0e%oG̜G[ 5O:{^\O/h'2}YJի0FM+$o'' odI^*ye3MJmԊjпiԴf2N"gΙG-d9ɚ>\MwnG9V*Y2"{[!mf/Zkپs?IƵ~l$ۈQ Y3f(}pׂg=֣ 9} y5,|V/u_@B G. m*ߒ6 ؆ ○o۞)28wy3NYLQğmw7o* +"?c(yVnK_)3aGj/YDI+7QyybqF=_gjJwƿRDS^' {%RǔR2߁B2ZsU7jƽTWxX&~.N+Y}N(} .$Kڄ[cǎkת=kf5yPmm-q\=kXn6?@Mp4&WЯ;m[!kt1voӭ\yrt(>wtGH-`Zzj @5|y7z~xS=Htl[\ ||<>|pucæ̏ЎS ]nU8Qk("P '<4fZQGw!/k.XYbF?2?`miE: M,;drK˃: v8fEEU[]A x1qn/i徳yc2,90|m1jt=/h,5]GJ.s:%[uGy5];&t&@.GJps&A9h eASyᇏ?nFC feUf5H-x܇6Um@_x<Ӊg[גчm3/h,\5A?|&ܯýz] QPq,(UZW\1 2Lù]'ځL@=Udd#/K:| yg#Eu7k9Ɖ!-Dx༅?4/26U)Ɋ yDW`yێ:(4*6.dJL|=LJS9bǤ47=E`cWٲ4 dލs]V_FUN;mx T vǽ[Tmkێ{hS%PVOA/ui'XCCu0YO58Vj7 jƘU4&PEvOMTF}R0^:aIAjSu_gǪh_C20>ɢ20Ev&[3+G*ÍxЧв$3+ ivZ:vl`LC { 5PC^\C֬*=|L'Jp젪4"KRJ7dh/&A# qý2\+K8ș@@u _jmmGCA@8E@~tKA@G@8tn:*,,$^j0l޼hC_@vA kf4"=&UsN )##&5)tG}ߖoVZV^-A"Ali3/} 'L?x)UUI2  l?Qm%дi_@uu5}ߥ\?~<7!^/q} 'ʕ+o'y5_|񅲷Odĉs|g(//{1vw\@>/O*G%m۶ݻ׿ҏsI|'t-BO=-];v,]vez `~衇uY~wyD-DG$X՛oIt=PUUK*OnzGG%~sыJ_T2,\P}l}uBꫯSrdw@xr7kP(ScK΃D駟V*́Z. ? N.F Ν0p~hG~uIp@xkZyyywŋkP0WqXҮ|rQGiL%҅1>o-[*Cg|'P˝M&q>kJ KY端8 [YL_ gկ 7x# N.F` E&-C !/ҕW^IcƌȳwfW9rgk|;W,YH )eWWWGńڿy^v nIT|N:餀x`RK!yk3!7nq/FSNUKL sٲe+@` 9Ok뮻Y>Jwj9/Vd*a= {vr J@UL xb^6aG5j}v=Yo{{v1hSLѰpO.G Xy9VAaR߻M[fw*4C/\rL`6Ԡ׿+xOɤ{]uUH^ |>9O==gGޖ=\o''#0|ڶL1kQ'CKvJltaL7{&MDspS.zE !0`2~ /#ϯnBd>~wkVLTEɄطWb?,?}VaN5k9?;v3mn`#)?2VByGKE(C u={+!ŚGtX*e<Q35O?t:O +{\r%j8񥭔03R)A~nV lXf~@w29׬{󬌇 Jl4 .f65Vd%NKfEx; @0xsSN9Esz;mL7ߨ-X: QۯSSSS>@}~OEDB0a!`|ީc„ LeǞ8{=YYBh wDD$k-)-fe(,xOeŠ|z*'oo7h_$Y`:+V WV]wA,Y11LwOēWKl)a~ezLߗPd~ #aX _Xi$v=噆w2:CB D| @ J{3SA@A $  d  _A@A ,]A@D3 aC࣏>"< ]&<D/i!lK"A`D` ٟ'7\78>0yGn "3gTNB6`r0JA@ :+~aq/U:w7)??heXnINd<^xRv9(Ufr-ʋ{;[?ST*= @,I*'v [,`88'Qq썌=+RpBM^{-8544PSSJ^'ዜNc*G}oѢEu4* w}{߿rң>ɕ@w۝YNA 8G,Av.9WgQE*Jj nC)vKE-_\ٷoS zrvApks\.0׮k$hP辖A@]$C^Ĉ?7/O>Y-s$ZFg3t>vE~{hƍ{\s:?ӈXSOU}k#G@C)AYxy; Vc+>-[.bu{---꣠gyg$^?~?( wMgA[ }D)}5kh\ADD  |/{=/yNN1u.ӝwyjߧ'xB)qM^~eE{UW_FW ]wz`徯*lN0bߵ  0 lw϶)g^~|=_xlWA tD 8󩶶VYI_MM ,*@ DYҏR p<j%2> 0 @reZƍK.KC@~ 4HA@?~LDA@A uC" A@c*%  Qi  ~DS)QA@:DGݐHA@#K9IENDB`ggpubr/tools/README-ggpubr-box-plot-dot-plots-strip-charts-1.png0000644000176200001440000005334014334142170024077 0ustar liggesusersPNG  IHDR@FiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i'֒f@IDATxEw6XrIEQ@`<@?wljy S=AP@$؜8Ά 3~q~NwWWۜ$L  1];* ?@@L@ 7 @𣠑" |@~42UD@ Q @F @@ QT@> D? *" @o@( GA#SE@  (hd ,&P\U%PeX}/nE29R]~Lcv4V;74r8e*0}Y[\A"<s"%9>GEzֱ  p:=kv׵CVת;zZ]u`hܿW5-&tˎ9)Lm0U( 6R Gg)+v7,8~Ԃձ!ܽ]?]|?8M#G`֬YreIvvjt뗞*7rp(Kf9CcRFxF۔mΐ.kt~&΃{?;"X~c tIIlKʍ v.]H\\m"'9hKPcvw=z|nJ~͏n':}w2~x۷s[V P.#J/cK.ÇrgKzzGN*L5Tѣp Z[r)Fٳg7uaga@N\qg5Q^^.7x<䓲sNy7w2ٸq޽[JKK/RsF/4h$o݃ΧW\)~l'{}$;bnyeݺu2o<С`ll9Y*֬Y#_~\qܹsacF)ƍ3gʞ={ 6Ȝ9sD!Co!G'xBSӳ>HPzd…~\?75[Q)?jkNV6V=?ir1TI7l~WUTTȕW^C墋.2LԥnݺIV6l\ǂ R~deKeJ=de$>vGRꫯ۾^H{g"΂\òknv-ZߊRߕS ӵkWoe2@}tXsy>3't|,K/oVRRR~ xРA~:tu\By5M0A233 үAEϴʫrwjUTPٿg>zj);묳d~[q R]S&:7I~ 36IIIY?.;}!UǗk߬mkIݻ{5|ǎ2|pw3"@Em,-}gUW]%\gg( --M~GPݳo+&M/Xj΄դQPP Cu5wq?ZnJn{XV2}^ijmНlwzj|||Ι\>޹W^\3yDTk޲PgᾏkzGE_^Wk{~X6k+ ǹ;}$ifm ۪t>k|r2$9}B1]{}öt~hX'O6}Qb hB7ouɻ-[YA3Uәg͛7Խ .@Pį:՜}dIGH;)6pEµMc{׏Z,5 egaEVCC]W322Du{ĉr-}QAGP?l*I=QUQ3)$M},~/?L?RRٯlƌYZ[Ugjů ˰khyO}=U1\-=}^8g6t8z9tٰƂ?}\YOU>uz;*E Nvg{3`W8JHyuN9 ʹu:t~3V  ~0TӔ*ݻW6V]mrh`KתZ]g꒶zm~ /=sճe=\X\ZrtY4sWKgIH\T\ҏF*[Y@m!&L(m" @BoYd̘1C^}UYrwyL6Mf͚%̞=[v%cƌ L,  @Hײh"eȐ!z!+**䪫m۶gk׮_~YGַd2o<;vϕcC@8*3s=W%}WWE8tKz,X 2nܸ%ۿ۷̝;ם  .3|&=zKWXXO>].B޽۴i}jtQ>$%%%}vwá= ^! GWWXw{Wܫ4w¯3-[ V#F7  qA@a o8p@}Y9餓DRQ;Y\PScY-ӐkFTou։ _UU%tO 4^ _Uw֭Rx@-w?DmSw2 K~8 Yb/֫(μ,4+@/#P6pxD[Hm% 4M,Yl6-ݛ=ڰT @O D?Bj! )@`@ GhR-@<# mX Sy@"T K@ {j0 @ #a |O @P^ K@ r{֮`e^OOZ.c~#1Ƙ|7Dlq|HbKJ6ʒSqX^tn[KZGe$̐#kQ>n͸6D@o%#T3 pI̭C.ykMRvx$3`*8W߲ؒSiQDFRh =ثc歹W\l16cU"w7%+ iѸ%hlu@+s`c| B/@9GD "v.{j[*Fc~0!@hZo@ 8"N~9RUUۜNs͔BR_ZB @2@ b[IsS M, @1 38MSVh'GSkSW@ K#7OwdKep uɐ Rqn+%ݸRtb@d8xQj@ pNh@槤hk$13s8 6m[ێ4ׂ37Kܵx[{M{yO Z"A 3A<%>: *P ^*$MGЍV2֢VZqYjX; NCZ4,𣡕#X ϬzOL|`ΰSg6X^Ȓ(hVV [(/(ZwxU(> [(,pVKiz%\]#JuoX^`sR]]IrbmNc!kMbbK?WyhoK|%D "e~U/^˄X5`c"c!@J}"PXR%j~&<bn$}>nKbK8^0 $b5F dQ&|(/ǂO7 LJtګ߇ D?"J  Pa- *'/΃ %nĎȐ hluXA@{|.ڻKTwOg!#T iL%~8E,"`jw_-RZ{o#J @M&$@/%}%DQ gYZl:!h] GkSo@ b LGrA@|S7C zUR]=Xbp lzR7([%­/ԻJ{AOS=u$.Wz(Rzܤ+5j1l]zK o0wzR{C^}Ĝ6Z=|)uj?Hܐ^VJuk-L2%­ϋ$2EZٴ eWyH*W$2: ɝ';৤m~U-ےSn[%F+37KbDyNb?` %K)E:_Ͻy钿!̝fqGZ͖#YK~y PYضΐM{Umgj[eΙNμ,=bx:eo~ TO{ZOjvy$W!JHB+ u% j,"@Em"{~iq^z@SzԺDb$μlIe'@=GFCD}W v>< /# ` )B ?2Yy?m iOj@L!~9Vp˳R-Ix$k0F voD})@fQjV^O 9'K_N{z 텣eQf4:흡7up]e*g*ZNcb/FsreI؞IY3 #X9s{9C[}8ǴzKp(:p%%eϙ!OJEY@6g0!@ pI?ڔ! %@"!@ G^R#@^$$  ya GÏ8a@@i!7nKZZ$''ː!CdZԩSO>!&L6,  ! rJVV2gر`ʕRO6Mf͚%̞=[v%cƌlߍ $P AIU)?39xC"vgΜ)k/ѣG|2`7o;֜ %`/#+&IXR{Ԩ< ',?^/55UZn-zi,X 2n8w/}sӘA[{B?"Ȩ@!=W_}<%Kݻ{ѓm&mڴуvÇ=d{Ӫ @bbERzSldT ND@H~M璒y7|HWsۖ-[z|uo_wM11!`:,D@ƿJBy+]w2\#@UO/Xv!$&&ՉV[ix4TyᒝNԩ{@UN)&5LxRUXH]r+̘4Yz?j*)--5SO*UAAe#)ޥCpBkFWyNqqqҪU+wQ[;U^)y[=Ш&/m8z9fNGbk&M+_{h"=[jRXX(wٳG;4hagjP3}u3yB,Pv[);8}-IJvq:j@瀯7+uh^w[x~fFFu_? ﯹ9 "Z힓S뼗~i3]d@>|'jgU ;?T/#G@?eOyrm_UW6B,PvDħo8rU&*FG; O瀯K~<裍[oK/xNꞾ jzw=zx=7𺅠o@ $/aBk U=ɓ'%\"L2̫{_]ҥK!xU}5>.̓Dz5M]?{yGh_E}jNj4~ZV0!-NG{h3D ktbr$@h_u 5W=Wk>ږoM &1۷MU١Nj J"Y=`/09 +@y'G]tK3f_p*Q)IH?Wcm5ml6[(k\O.&Mr׭[7Q~k.dԀ;egB s<;wکO?⩞L ңCjUiL `n/gffՙ|IWCW2mM,ua5iimNJ8ǖՆm-$fHC |ƸOJJ>~աC7ީ}&\eR# 4 ` 8+3~>-}>W/馛ϫ}ZZ5(W_֭[o(*›nX@kUu~i?~5믿G{ߢE kԚR"W \(N=[(:__]塇K^^2D/ܨ* @l8.4!vWހSiŊ>j?~Y @SDv2ڪq: r_יSNX haj@K.RQQѸ @L#cy)1A@~  [BZEރr<` ~`EnVxu6yh:qjo=Ba2C[U"hgP@vFzW򧟌cX׺#!t:Zgue~<  5[)j ӁTK^%{$qT4_2C[EՖ$I{WtqΞG:[;U7E+RCRiqTMO$O2AE16"U:$7^i)rSi\Iu&n/^AZ+E޺i/*TmHd 󊪭3ڶe'ӂ}J<}<#@?E;^T䮐=Y_A8J*i3ctVK߇>㱹[u,s+l%w,!PVJWl ^*eHR1t_T>whq^„! !`N'JKp1iҼ͓@\o{" `e"U;^ٕvQF|@*rIBuF'oG{q\l#ejCޠ=s[v6bb)R]vH;^,1qƎyT1, 'Ib!GA#7TŕYrגrX?./*lnz2oTϘN]<S)L X~`=-ۢC޽Nd墼Ў"Q׻k#q-Hp,˥܅e -X*j?mSԚI,[P`Sܡʿr*{   w(ᾌFr X[Wi8}RE T|`UE[$D2%׼G낕fB Rڲ~a'd-ȗWWK rpd@.9?_͋t ՞MM&΍Hq4k;`҃sxMP!6m2`oL(@7aPO#c婪koڟkjPv"VN{۴T @cc!@x> 2*QT䬘(<b$*@Ԗ^X@F_JKGY {^]oIeZօ#`Z2"E;<^kj/Lc'@o[TU “_Q)v#*K%C'ptHݿXXJN*"YK&=&hӫ7|>3KFVEd=Tx 6=-RD'#tTUoS71!@xi~XN@Ff d~ ͑AzBWAjIڈ!PB˝k=Y"gȐW^}IIJ;4:1ZO{&-Ն>.!S90ے8!B}dP[%+_˔V®$jLfGE[$>4**y+:ohJڤ9o2!0gfjX2;<8i`)'.^~)U=o @ _ۧ?%;KOw~iٝm@ @z$r`F Q&@kpD)@hI| 5g++>V @&p8䢋.'zՠXN*} 0axmG &_ r뭷ʗ_~Yk)M&f͒^{MfϞ-v1cgr @!勵rJ$33SڶmUk/ѣG?0`̛7OƎ   P@x ԩZJzU HBB7νҷo_;w;ʑ*{;,),c~/ic۵[0L #<"ڵSl۶mҦM={nԱcG9|g~|ǥw۷ц}w0ҦU9TV;ddGa~evUUÃֺ= ~}^qjҵl+guS%&oI{6K;ÒU^ >޹57 B~ߐQllh_9ٴ1k>§zL_%w;9)fڶ͚Il+j%2HikA\IR%G]ۻw4ƼB鐜d’Q$@  :t z)KZڱw  $?{ۤ$îFاWPMC}wۗh?Ca{UL @ xJY}-sRw< (`3QFxgrgسglذA~k.?hyjFsOi޼vm2|pꪫV`g%K#-Կ_ܫ|'W&Jh'r~ &*"EAB"`KK=gc Lc;ثzj h~lM{}i:{  ztZv*j]VV^j<}&By{NwC;=rˀ4_fbq#eΞc{rA׎"1]@Ba 9xjȭ~`mimLM~T]ֳ1%@0%Reΐi)ܯͰ .S ɷ@Bl|zY/ewQQ&y9;WR@"Uom -\ *.J  F~94  J  F~94  J  F~94  J  F#p:Ud֝T2IDAT'|\}fk&ʃ4J3FEN3aU_s# 2~5x}.a>YeHc@|k[PJ?=+~-RH@zmOONoڝ z/q'0 `Y:Y_8L{߶"^@"@ yj٤o K-1%CEK(   [)> }Qb@,.=|7Yyf&9XZ&w$Wf֢R.@ *Q̡dZ.j,*C}7ڂp4@M9U1ݙ-` 붸fCHl i9 !@CY>L5a:#, Aj՗ RG=duN-es܉MP,!q9wK}~Շ9Cl|@ 08<5^<_TdМ#ɜ@I߹LK D8&@?faam[#92m(S=wq.GULSx!rJzic޿Q7hm(6 @8p劣?JJ\τ @}קcu{ 4EDL Ed^yqV wW.ա @ #i_1na@j}r߹EA#%}Jރ^e-k#@B.@9yKdԖ  ! 2R; T:5UD:C7D%( f %,VEGM%V{,O4gHcX* ~T4s`+6.8pXpk @0{^պOvjXPoF w[$PI@@|K>:tn޲6p/3 `>ᛯML_6IdE$#u$Iq/7DYͭ߄jݽ 9+ @(Jm @a RJm @a RJm +\t@"K^՞;Ra2Y/-7:/vD0gke^(yyyҢE<[`֭ү_?yWeҤI~ p*{  `9嚌# 7=֭[_SݘhHo>2d69\\֬Y#=zmFFhO3GA@ \+9Aj4KQ]]cQV]g ?t֦:RqqL:U#2aɩ%%%cO}}֛!+#J@}Eĉ#^T&ߑ)SOInܼ"jڑPi/^{MOwʘ1c_~juO))){g&:***D 믿>:Ov̙3G3e2{lyGD|ʃ)a.Sg+i&5S۝VsFqS;(XbSé={:_9T>|ߞ{װe]YCʻVƍsWC]۷̝;םVsfڵrI'WĚYR7xC:u$V={FE@P#|I/**{~xSm6Qc.9Q>dW_ y7J˖-{o< LQ.Ο?_**OPT] ~z B 7?HfVV՜To(/_\?{駥}]'xfV,G@vT5j8@gM~5W$ՠ(`H(7 />u&K{ت^d'z#>}~ z6,pSى:t_pRZIKK/g~ߋ+ػ6oj˖-$@ԙz飏>*! ol#K^dݻZR}L 甚/vs;@ ^]5|衇\|Yd`3f?j(Q,^]={Ȇ KD۷ˠAGȬYD}5 А/7|S&OcJY9R|4o\,E]﨑?zON;M\[o)ڣށ.+J[>eK3g Aٲڸ +5+rW}~p\M޽{+e˖کq.RW_iMh7tJPG{gfRs}}gu# lXNXʴPWT5 R"0\Ai@J Ko4 EV2E@\|sA@ ()  =( P/[zWMW.  bk@,)@dQh@ Dzҍ7(ꍊvYiVnA:u$mڴK.Dv鹉WiP/]nX޺ңG=K/TpL <R<[rFRrKyy1U`k Qs9G _4}tƍ-͙3GnvDpi…R"&zI?*7o-[Zʍ"`UZr"dիWg]tяޱ}_]T`WV<5?^?SG}*%?zu@MuSI0 4Zϊz#^K7%G,)!CU%J=_|rQg`IMMuI~ɒ%jQc۶mz0׿%yyyOu]_h}W\6m$'|zf}# ?d5n*ڵ3>>>^̮DusήE~}YvySOܹs{uСNU]9u޽f  I6X]@r㚓`Zj]߹]SN,X@U5hBT`/..G*`BJXN@WeWXftqɪUN{4өw8p˔)SD]=zC;/;9|wrrIJJɓ'ˌ3\ W_ߏ8qw}]w%v]t/33Sԥyu6٫GԤ﫠? ԏJP=UO|kX[o%~P|#@%;*u/_u;dرұcGw*xoذAOW}YfɈ#{WTW*^3|)++?_?ٳgUA&M NVP{]SVVJ8kRTW6@?' '@%9! `Z.零i(  Β@0ߴMC@?p im  @$'@L+@7mP0@'@%9! `Zi! 8ɺbIENDB`ggpubr/tools/README-ggpubr-box-plot-dot-plots-strip-charts-2.png0000644000176200001440000007136014334142170024102 0ustar liggesusersPNG  IHDR@FiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i'֒f@IDATxTǟb٢aaERD0 BEb (b`bRݝv}sx8wbwfv~,xιE8jaA:4@@@@(d4@@7  !@ ?:M(| @NFA@@    CD(d4@@7  !@ ?:M(| @NFA@@    CD2zrZqlI%k̲Ad,Nu>R.'ӡ:"| {e&֜͠ꮀƒL*IcE'_a>)[V~  Q ~ `R kU[}v!`ppE1UX곣 -?U;Cxh0(…VZ7WђSU_fUkuc4 ju.K|I95lF~^rP@3|`!i;w.]wuNu]ΫOi\IyGO' ꉃݮ*,V%~una\ )A]PC>"q1ty-ܮL,)>L7?d4AttCTrä%ZnV"222ׯ(8Cv~ݽv TaMqjԨ1o8p6\% g w"J,'DZr%hт(W=,X .bbb̟.]8LNDI:J]1DXq'{y h4gΜ ӹ` }R^J1Ξ=ڴiCC֭[?i@;""_.ٰa(5v}R5(%%&L@6Ne7tPi{bƌqꫯhpB4i9K!qpfpM `֭[믧oX!ϟ?{1MbVX!CЬYѣsΝ;'{4c :{,+r{뭷 zghă~2OfI)hO9c\qҧ}.HMRbˌJJJhĈnɓiѢEtUWif&޴iS*2DZխIJ]a"*( ~%{Rd|kt‚ߕVtM+Z"@Zާ"ƕDJNƯzL%#W~+¶S N:%o4i҄/^,ei ¯₂㥢/d{jn:uDyg\s -]⤁π;w,%%%/ͥ_|Qݵ^KO?֮*MYt_Z" _D*u/Y[:V*'N [l0qK.W.5re&#-?D&WlW.gɮ3Kʊ?L|qi?YdvB[jEO<9r3ӛoI&!{衇8'x '}z+tJN\ܝիmAhrŎ&*cÆ -3GuSL!رuslUoXGק|Nd| 89L}Ia5>',!6hOɰ aMZ!&/7׭['}dTB.*o̫qU)ykˢciWMl8JlL s'@fޛgEl֮oߛyytٲeI%:;vH+>3oFfm/Wظ͓.ݘ%:3|~rɞA4`'ؐy[#//ObU>P^=;7a|҄/OQQQUF#~ux(6wܸq-y/w}WIG%w!]~u>?>r84h g`\Gfͤ5 hرrsb[wkdtų!;ո2,;[u~ڵۧy=^ip7a;w4_E JKK?g}~gRE~74i$_@@?qԩS=K._W涔+#GT+V=W_)5jp.L;vM6UĿJDDrj—,Y"?~\n駟*III2*''G[r"pYXfK/U(:]T^]amڴ1fϞ]a"ʔΝ;+ 4P|A%99Y[Y8O>JTT ?e4xG )K ,EQϞ=˥^JV]wE:Ikז˗/vQF4]DFFR^^+Y ¯T}YĠ$x뭷x)66ƏO)))4zhKh$ī5:t!CнK3U `I]RU_z:e\VbbĉryY>Էo_6ld24UϦMok V,bIW_} Kb(![qW_X~[nzM7x#2X~uyە[-fҲ͛7K7h zW'|bh /oV;*0 6Poذrv;/Vf͚Q~nԣGo0覛nK7 OWbQD| +e˨K.ZypӮ](<<h{ږU~VSLoϊZI,X/r t 0@FYiALƍ+xeT{Gwy'uQnR2]$ezG +PrmW/\*nMY90ٰ#σ{ʾ'u0r3|qd$qԨQr֩S ÇE2'd+0OGnn7&3<  PX;6Y*;5ΝKԿTNlAWY?Ծ}{++NV8Q7,wyR [Z 7xuώ4i"ԙ'e?W_THH?x`yx ߼ N;#yϫ^bv9bϳvvݺu}²p_W3rR1b{9, :TN\^ի(֎W_?Ver*e\?.жP+|^[rFJvgs?T,W<{%Gǿ8~ڴirvK̙#XXAa'ڪKū!< TUE5FnYo{朆?o a6zGi֬Y2UW]%gѣG™3gmJxp O>W<`g8[Τx u4RCͮZjr_{rvno)V&|Qf++LZXo}< HKK?#ųVb̯:$-y)ұ%2-:YueYz{V8r<0VVDlHųuu+˗deeӧgtKVli ju1zꩧ,s=YVgl^fެ^Vyyыr2mc{ȱ+C~m )+QTo@uZrorVD[1<#gJNБop;G}$T/<ccP>Qgp?`}lB^u|ɓ㡈uE,J9%"~md>|"&\B-nPx(wH{P:&'OT9}C(NE(mNe:a&9 (/Nd;| _",eW N^"Ze/vDhP'NA[ 1 P;M8%fؾm3j)X*x6qLWQ۹nN+5u13A'$$o/R2acW)_*FEli-Wxŀg<+1PRBWCxzrca<[WsU6ڱ."WxOX;^`w>' Uz2=z*am2Wyߋ BE28oST$ @N{l#H?'NjرZ?CW垢ߕO@`"fe2yȍ˱v^!Gp^v@Oʞe֎F\Qߙ& ?藀OyɳwkNJ\=GJgYW?Tyu^y|G앍06*|o/|ذIճlV斷9'lV†<Sp  |v7^&|2={ͫ|}*+v>{lM̖l׹N oww~=V޳WSǝo2D|LE305/A@@l h+E0lqJgyv{Z@@@>3ug,]=2f<0.9@;j)nT  !@@|J ߧQV)(|Fe   PZA@@}@;j)nT  !@@|J ߧQV)(|Fe   PZA@@}@;j)nT  !@@|J ߧQV)(|Fe   PZA@@}@;j)nT  !@@|J ߧQV)(|Fe   PZA@@"|Z*;駟ѣ4h ݻ2M:Oݻww:[nyQiT^=MҪȩ)I3|!@3g%''?L{K/yL>|IڶmS+J /A髯^zщ'Y"<h (A䢣1 ) Y)))ѣͅN2EQa@[Rzue̙8{n%**JYjc4ʠ<2ܕ\@l`AM@(WJLL4iӦd2f t뭷s=G є-g nA.$Xhlْ."Fv}wTiΌo A 8 7^|EubfMbbjժE> KtԵkWYX97ҍ7H.w}ԢE +7oNgϞV#@x@l@ A/4~x  C=bٝ>ڼy3 tT_F 5jnݚ&NHsEDİ`ڵ5e+ƍ˕W]&C @(++:e]F EFF;R?5//O.^ׯ_/y@uI<咿~vUN <!(|v DO4Q  :$NH   iP&@@@@`NыH7||^ E` F5P:Ư9o U4ʵCKv @@~(  v@ہ 6 `3b޼yNÇV$X&~ː!CtŗҢEhڵԵkWkFzhر6۷~n6lh)A_g˗/oIZbF|0aPڵk Mx@@^x;O_}ՋN8m۶QFh2E]D?9}eԳgO{(++~a-{1z);;2 y1m۶k.Mx@A hB)BkdVZ)K,QV\ѳҩS'd2iY{HW:uu0  `ݻ(eժU2^̨޽{+uMyGo"JYY ,^SZno Ç+H?СCʥ^#k7r޽-[Ȱŋڷozf?@|IoIi7ߤGs̑i]p̀  .^Voٲ%,nf{e9s6nHF2GqtI,34rHe~i BAj5mڔ~<=~QK.JLbVOb-6mڐ |@ 5FM9͛7'ރ/))фȑ#2Ө6@e^-f͚E%%%՘yРAt}ɭ^6ƌcNGF{yyytwXzkdhՓJR`6HIMM "Kxx@@"GvBijժ%7nl%>Yy)<<\9߬SNQ:u4a0{^d#ɓ'I2\r%j|]>?4X'ک,µ~cg TVMN,ӳ=;[;5p^ujB5To߼ ѧO.-8Og7;r~x a,͚5Ґ^|Tg:a5/ xӡC:,qEEEr`a<88pH7Gw}WSx;abdcy6H P -7#&/.13g"+bb(CUĹx[z3bUR)J^TĪrW(9ݔ)S A=gOs:$phmaoN&ڵ#qPTgR=ޫ⳪lK|ΕիӋ/Hl 8~8%''۵!WﻳVxIb; pljȈOſ#)y]AWV3Q&f̘Qw|k|Ϟu:կWߕ}#*{eH({k;"S+}k!غC&MQXGX`ujM~qY^ig 9i\'W_|@``sa&o ! -aЭ&2sV m`#˅8b{-ַz/Z{!+  &a(@@H _@@@= Ł @W x8U+q'}6v;+}7%| |JETDK.(q&8#(|= d0P  z$=|= d cǎxݲtB=zL tѢEvZڵ+]s56owi/p,ҀxH8x U+..#G믿7ٓN>M_==4w\/U4yd];v,-[."s<7 ioV˲/"?ޗբ&Y͛>ă>6mDrBK.%BNMMf͚ѬYhĈC=DpH!:N `ӎX'dOiժUeazԶm[z駥v$A#GʞӰrׯ}wRUs$#|/}kywd2hԨQo>ԩ;j Zhf 36m?LW_}5ߟfϞMu@I ߛtQn Ot)n)O_ :К5k䞿]?$>c0d֭[)..7n,xMݻ'/?4l0JKK\^*}V}>+~6en Fxf]*{ :ޛG}nf%6xժU_|\ELϫ z+}rK<0_;"z[߳+Kl1n4~,f[λaQQQ*{N_p  sP>G86_@_؆>p #>эDlToxcjp Pp #>эDXP;u#/\ O8~T   QPʼn@@@@/ @@RG Jߣ80~}[カuh [z)O@}xt  NMCMX{C/'`W2|Mӊ.!xA@@  @cM  sJ~>0LW\ ?x-!PVJPJVZb?;@QQ -x5A@@Ĉ1 `Ib> ݈F@+X PAэhTLF{A,@()2S#uP]OjBj=@P2RNҶ2+]ACd#z} (t4@@ `?-&~h rM M[k^GA@ uE8 ,kp  I ?8 (| x@@@ 8 @gU   != x@@%( )d7$5%CdM8|K ߷Q/*M"Kmm[X-o  ~!7K?8g9SҀ@?t=ԤIJLLnrrr4i„ Bkצk2224ip]wEWO?>cڸq#]ve'NHsΥO>͛GfL|j_ъ+hԽ{w)dII 9/g۶miӦI?`fΜ9Զm[Zp!]~~d[  ^%`%'l눉 C t?h %}UskϜ9#),YBQQQ4diӆZnM7@@@ q5SU?(:ȧ3|@͛7M͕3SҕW^I͚5<ӯWT6lHAr%3 <߆]'7RQQ}Gf򤡞9jժe6ʬ   toI|ƌtIz뭷SNݺup ëy.-Ouoo/P2RɴaH 8\M᳒_,}WR'%%VHYvv6%$$h5mڔ^~esom~w(wQ{N/#%+]#Ἆִ&,T<>Uǎ#̷FtڵkeOOO'ɤe>sx;?}k41ᏼ ߧ{9OW{/YnhBߟ❕+WIѣsN۷9    ¿曩Zj=߾};=GRwQ*qё#G(--ƌCzoR|ܟ6o,ճr_fdGL4{ls|/99ˉp@@5Crs? +#=|ry/7nl##[@glÁ@X O[!LR&Ұ&_  AL-+s|C d <>]Zh;'@{"yA<jW^M6Qaa|[:Kq@@@E%-Њ+Roժ͹x&@@@@VŋӜ9shĈk $!DZ%7Kʯ擒mX2T}V=ߎ AnY Mko+1 ']/Qĭ N+|~5-o)Sa@JsvR)魞-E |$24jV`̤KJiidH |hOղV,?#k.:)&&F#ܰaӄ  1Q| EGa p <+zH9OShO(| 0Oz_ZK g(믿Z֭[C[C@ߨ2ci3jJ_t-B\R!M`M.5"cK2R?Vax.1 уѣG<~I@J w{T^pD[T ҄dmܽojfrW_}itUW/i$~?m2A Mbߵy,"mC~ voS6a~ I`:8.+f.)^z}]h˖-RF~-ѿ袋p CZkLYaJ.J偂DŽ@A0syqK|\c`Uso&}tWӨQdKY[i͚5^`! "(/lOٻɴk]A˧ қzw?q MY 7 ل#=N+ӧOe|[Hܹ3^  @/:|6N,' (8dWJ״w>/1mYٺ |KLLի/bSۙ3ghٲeij}8&(F9SI~U@ᇅ=C'N$3fLu֥@dT hͤܝsOGVpxO ѤLʎ 89o!{9QӧSJJ T  OϧZݥUYm%nꋡcRHGW h4WXnP/RUR,^Aylg%g¾-PK ?s-s7QxtJҚ/-3~dEӷӨT|<SEy{e{ >c_۰aСCME')wϹyJVRp/~C $PΦ'xf<Á5m5mOSLP2=fu`H@Ji[qd8$OT__ P+)±8*ƍSIUB 'PxO*<&XxNmWjS! zmySq MS(2Ad¯"n~H'<% fV@@rv"勮?«7Z^xS9Sd+X  pT4MmFqM.BIDAT%p.8@xJ ]*N+6&~"bⴟ걁߮of!惀7 JWi<6^\[C~ȅ04цN׮kcZʭ&QAW > c1e r(gT%M8n|ֈ@ɴaFWRuj(|ϱDI  NP eRMjikўgy4%u- @@̀jCB@(04nIw>@FXEQV> \av>۠ ?: "@ :ew蔼l"Q[JL8 *.ў< "e&+e^)B{* .s1fo.LƢrN^tzT4V,+^WS=5MҷxS/"l3>Squ +`qƕY^F^ӨE-rMUQr"|dx!5APzrJWS)"i@=<;ڦ9`*>mWTp{`?SeYg(X".7EM~HTݦ t68ʧӈd#F{'Rjһ)#Ú,ph ?D;膔-?S;0$Rn:]m^4mcDUW>|{7Њ6zWeߚM/P}')gT=4! Ӽ%r@o9 3P(oUr@ށiT@HṋB~hVya?ga^ޑjDA;bⳔUsKVR8 Th5Lj[-i>WyRs5Rfo{b!\:I?ձ62]fĊk1c4V^MG /P߿ի'eB^OMM 3 OΣY['WR[M$?$` So |Ai7j(' ֪UFZp꧴: S)em`P^p҄/<3&=|KlWiٲeTZ5nͳV艉83h  kSK<"q< srrhw^i׵kW3ڤ$Z|ٯ>?t-[>4sL3@m*H.F3@TvfTJ9_Z_6@ 8 \e]FG:w!˳t{I @}9eI::w?M&^kqEƵЄ \|*+'Nʕ+޽5/s|߾}e4vI&MN? TNeڞ-l_eWgALn~aZ~R~~cǎRя7~G%ի9RMo:4:|QԍJA|C >z?Y᳛={617oN2|ƌS_@@@u>U|zyz ۴B PXDWV ~"=|?DOŬ칼7(eTxs({{Q(|t"((dUL6LE[v' Ƀ@/,{+em@Ir*:J(|u\$Yi\ u]SV3i!-*E oqw<'[Q2E1^3QV9A @pأnӒZҠDTMlԈpci}mOSL2Gk ?PcAPt^d2}ju.tΒ)M a>|7ʅe~BX4"-#pj.@UfҞ\j-׉n1" OBwPp29>ğ\Z]?p 'ܿ|#%\z2FXGyeNAC4 vP%ª)2f#Y~Ō! E.&>gq ˍ_j4r ʪ Ζʞ=ٻ^"cI?DB ~&prJ-*$2KJ4a(/:M9߰74sJY]#;5 KKзqԫ~Z#U]Gq>1w0e TWxw1/pHёD Ոt;@H'Os_E(':שEo^C:4D#ly2SzCx,g҄ujWprx/O| b,(oEUGG -P"ry6Հ^.@v?r|DY[W<00EU '=|3E (uŕNsoxt ^ (@>ݯRIJqG @kX(xNWt<aY_i  ~$G@@|EV^"ϙ4**7zt]RJQբQԣ~@C-  SP^ꘇVmAKW{oV6-7)(|/vm)hl{EXC(N @@ @{RrxPEĕ_)%$P:iwқ[Pbۥ}m[D2 O ?X-\NhړcӕMax(| ؒ7g{;QD۴ ݖ;|2P6X ^![L$ÁNK7nnN>M۞޶mM6M*͙3ڶmK ./V"8g̘Aɴi&jѢ %K=!CڴiC[|V~[iݔSZBWZF7l 8 矧 8l^z6| 6T:/Fv1sZZq:M ϙ4:_H]u@@ee@=g˓zEԪUF[NiK~1!mpZ&;jwزiۥžb9U]S'xgʕԷo_3G;wҤI„o[+njuIU a0zߩ- 2P]~Y9M۵,>߬bރK˅a⑼sxP%;k;JE?n8:rј1cW^4rP':WhcȞށ܎o^Qeo   t/x_>Ry~yy9P~anbe@wwlC[B ɉ %%5kӤI8ݳ>ߧS@ |~8tDWw1p_~e2CMKīa@{JՁ.`qΝ]0`>:_HW4iHW6M\1LJkr!ͳzuwKQrffVx8Mٙl8&cyAܿl*{n溳fe6{G~P}^uA@6tWlUOtjz   ĝk46j@/1:^PH7Jukd_?LonCz}k0(|m-IGk/P/` Pȗ^̽֌F}y@@ x`<}rK8ɓ-/+P@~p[hkx/@>uE/$^{]?K;jeǀ@@@ۮ`mj&КahKF5N_)j (k^`HKP p)ixG "^@ r)AL J0`7^ HA#! T`krE@Bxly{;nnLLݝ3Y9sv9=$ P+6$PfV6@l &Hi%ֳ_z@}{ʪ1k!4Y+&ӱaSv ۬`6 D ~XjAlTxVvojg }W.rr@zR{ܱ֞eZ=@ ;K!zCr 8o򯴮!k1 `Uv_G6[6dkײY `GrP !^dD%@~T|l 78N@Q1  {8QJ@ G xCD)@J# 7D@ *~T|l 78N@Q1 hV|>9tTTTxCR" `@rr̝;7ln- c ֭['K,'ŽCw=|I;#f.'ڕ`7|wٽ(EcZj%Q*п9vXXf% $!]t4i{6->@/_.ҡCy6b۷_^͛l‘  {Q`@"J?rVhH௿/JfflٲYߗ'OJZZ<1hvh@Uތph Ç<?]זG'@t֮rYt[:v(ܸq2޹s<ѯ_? z3da_~Yrss~3 H^^y(..NyYjTUUAVKYuSkVwߕ^6l`ӿ[ //j_\\lm6w^y<wjٱ^7J`w^gʘ1cdϞ=_re`& h;Ή|v xQQv~BX'>++ELǰ}V>{g`uYxq&Ol;5f2aUM}d߾}yoN:%4571t11*yfIMMBѣG*ۍ6#^'m_VV&V=~SxY>5'Uիj׀]`HRRG SMhuU1pD^Hxh' | >n(usz&B~AAϗΝ;U5'W͊ԩS -jv|eYfY_B@baR;Ek!('HڂO?5}_gee&=SL [mu ;aO`ڵA[9ҾɩNdi3SRR'{i5vڅ6Lvv)S~w,^@^G7]bSC$*hu~,ݻwM7 mpJLL4u{@/^anx租~ … rSEܹs2h /ܹS4k>$@!?-[ȢEZ6 З^j&wҦMYVρw'>MK#F5[n!CN{t t,KG߹-li۶m}9{Vʕ+_#SN}HrFs?eڴir1󨝞hZzzzܿ#͙3<3==)XlY$!1obR;W]߾};l;F+ ׮]3C^8 6 )1p]ǃ  a%S@%@w4 8"@wL@p]ǃ  V2E@]|wJt׻\" G xRF@Lk#ЬtF9xuT_]RSS%99Y&M$ϟ^EKӧӠ.}g5먋o񆤥<^yI 8gKxJB^{5hg̘QcJy+W֮]kN~73޽{e;t3PJ%;; Ĥy  6L%))Snr(' wZ֭4ca̙O޸qh`?Oĉ͕+L> :\իrдo ڤ'/yhm,:# J~SrD333u't D^ILL?zN<Ξ=k;Te֬Yf?(zĉ毨Hlg6+?]+|Io HNj>>>fLWߵkWdU_tL|ᇲo>suWh_JJYàjuh޽{,@&m$.\>MΟz)s޼y ^tip!8O_}:rѼV  ;JxN@[k~YYY50SzzF{y>40>3fioj0`׼_֭eѢEi&"|A L>܏͕7nÇpB2]rEj^>Ik߾}91ГKVVi-%~|6ۺu<l JvxU@޽[^6;v?^t%}>_3g|můw)F2ŋqmkrr=7n={g haUɚ\@ *pڵkfKڐOvSW<0Եy `>KrB@TP0@ gIN VCC@Oo%9! Zk C@>} k=4 @Y  P0@?g 秣IENDB`ggpubr/tools/README-ggpubr-box-plot-dot-plots-strip-charts-3.png0000644000176200001440000011173414334142171024104 0ustar liggesusersPNG  IHDR@FiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i'֒f@IDATxSEM{H" RD E?ذHQ@DPDE{̲d7I$@$@$&$@$@$@ *l" P;@$@$@@ ?n2H$@$@T @& HA_ 2ٳf+V=dؤC8vPj.M ƌBر#ٰ>m$qu0s$ 2GH#G`Z=U'uQԁ}8qߤNyخ"'poilơC%=ڞ}{vx0m,nˏPߍϓls#óVqonխdݑΣpJ)S4,$.&sLQ6 *@l# @ *@lc"CPPΝ; ?ǻ6@8pQQQ)7nݼy3f;)ӧOZwۍqRkeP-cI3/_bŊaÆȞ=;~d QҥKWJdӚĵkРA̘1lUK>SNE2eдiS*U ~iiy#@+?~aZhSN%j @̙QdI 02uȺu3hѢxpi:yd{p4x NAF?<{=߿_~%$LR#wa}v#޽[[ d.U2.]իCƎ?nϞ=׌1"mO8e!ߏsBȤW,fQ,{E6mtdzx EGZي?ϟ?k֬-Xɜ>\%@*1)YdATeN!Ynr2JOj4+3SVjhG}Tmr%gf}N,ϓi"S!˖-=,VW=7n% JC"~"zrk,pPνȖ\͋"+W(v1.]4OtWXYfS ˣd?}tDGGCʖ-f͚"##mҙ &h,@DV0HFDF]vŕ+WtG8duCΜ9ys/n),+MėD$\!@ -I}/jر5jT 8gy_eٝeZ^e_̩28VeKƍpWP@=@}vH݇ qF|us޲@. H.# mN.6JsȑRxΏ*r\GcԺ ݄%ܷPolgs|XJԟhӵ8?)іыBOJ$0ͱcPHx^I{ ?n}< U*;,\o gb\pyjIG )Gd%'!!!w#kyHMbN8ԙ@\f{ĭߓ@@|Ӎd d?7֪]Op8M|襓lW5OG.pPFs EN{Ff9$@$@$E"|M$@$@F74!  /"|M$@$@F74!  /"|M$@$@F74!  /"|M$@$@F74!  /"|M$@$@F74!  /"|M$@$@F74!  /"|M$@$@F74!  /"|M$@$@F74!  /"|M$@$@F74!  /"|M$@$@F74!  /"|M$@$@F74!  /+q\zՋ8Y4 _)ŋ?7'i֊HHH9h  05*|SVHHC = o+G$@$@!@̅HHLM ߄g߾}0`Ν;v1b 7o;zTg_Lk׮6mٲ%={ ,wƍmOúu;SEș3'~جD(AsCSx 绉;ۮ=aj$ڴiV|7{iCr"&/"ɿLӦMw}'uqɗ/_~xgFڵ 7bW$t"EP~}H{DV\իke/OjӾ|G($@$`z"$g@D^P.]*U+U:ݺuaZ)S&9"'(Iۋ"VhQ(sN?; D4lROgAz4*JSD:1 (6)K,"2,ut(ѣGgEŊuFCuIGF\qI' SN(:L e4_r _:Sv&z$<&,4_F~ml2>H'IعsgATRJ(VXlFѣG1QKG˗}sw1? mn'ӕRE$5͛gE^ןhQ+V@WL8E;#2zJ'/]VqSt PBډ1kEC^MrʥkԨ|&Me*c@^ !1rH䳌 mL(|TZUO(uU+"3Ro׮ܽ({kNӦMuDGZKQX_~&T֭[urI-2)_)]i#!`s>Q]yh_֊EF32QkznvܸqxWqǚQ ^\#܅2$ejkL+G: s0\QJ-cǎգ{1̘1C?XDA$`5'ڴJ!뇌e'U"NnqKK8 342/e@&rg=>SFxZވEF:g #G=*ΔL9D:I>x˔C8>KgK+C&Oq_IAbd5dp:D!$E<ŔWYFqEFjz쟫#yߋ7&%@Rֱ{Vo6J'=*/ɴ+xH|JF9pb9Xܳ0e.SI]L2$%VDIKdj'Lzg5}BL%`:ePD;֑dB,%z~&wXOc)]Ry x _5hq,3c-xy(je.2 $e w"U E*|&fB.eh-SER'ob4n J!  p _r2_/k%Њ"kt*q%,'@0)HHH 1CG}TkQ2gP$.ѽ̭4Z~&  HLp/U3î.K<!  HHH;Ý  HHH;Ý  HHH;Ý  HHH;Ý  HHH;Ý  HHH;Ý  HHH;Ý  HHH;Ý  HHH;Ý  HHH;Ý  HHH;Ý  HHH;Ý  HHH;Ý  H7 v4o> Nѭ[7a3g/_/_ƍ7<%Ko7@?`n5J#йsgSN |Μ93z衏׫WuEZPfMQFl޽;D'w|6;N$wq$@%q-¸e"~W(K"   $VHHJ ?y= *|I" ~Z z  T>pXE  H+*$@$@$}&$@$@$VTi%IHH0$oUe˖zdzL2y ,H 9rBܹiyj"aTE?쳦+D$Ut~C|4ȍb5IHH -Bג j @ZPᧅ%  !@=Qިfҥ-[6o2I>h9Ho`ZiƔbH~ VФ#7$  O =^K$@h޼y"˖-È#wt`D'xe.]u:y$ I&̙3 0|pm֏=7$AAjm$%K9-i_z"2%#|6]ք7iG=ԯ_HH#|S̗/_"{AΜ9){I$iO:(= ܝ _F%J /dCTtY&RVH2O$  @'`hŋczJrVOx>(( Xڷo}7$@$@$@we9x =RMپ}՗/_ysD/^#8@_"K_($@$@$@ Ezɓ'뿸Ue)իWڵk'O={V5cB$@$@$:;k]@{ZG{Y||r!}<8W   6—-xUyy"EhѢ}Ŋ!o߾3gҧOS׸:1 8ES/ԩS ȟ??t GHHH0le&.PBz)L%^I-K*?#4UV(^*}]uV> k^Uwk,  2he2qPƍAu06kl#pmǎ:6Ԣx)=l@$@$MZͺJTrN 0 &r ʿB# S}SD$ Tpf)$d?s~N6=$\lN11Y = 5c o'{*|t&*|g(1 [ 8qBwa̒'@<! nP 6!*D9 ,[ #FH ݎ͛=$@ ޱ!j;3/p?O}YSbbb0j(;v 2={66oެiN긜;w.1M9R5klق{BBΜ9ӧ8$`eǮx$U'u)'@y,j.qа .N?>; 0G˗qywFqh=HN<36K֮]kl4*lv|GGzPn]ȖYNӨQ#l6s,YйsgGNtYL!O`ҥZhE 6, #="'Obذaz+f٩! 0|pm֗2ʗ”)SPF M: X㏨ц 4%K`Ľ8|<6H9=L3hG$@$@Kgljn@_ڶmDLZ᧖# pX,mۛOgE 4qyPƋIHRI 22cFV;?W5-^۷2g^ ;ĝI4$@$@$J'OƱ'7op:!wM;n%@V̌HH )+[CE6*ޑ.L-{-EǭXn0_L @ @boΝ=w $>+G:Ux0Mӄ ܍֑h屡DXj'XGbM:y $M|x $" O=@GgK.Q8W.=y1?#gAb\ɓZx==Q]vCl(B(n2`('oG2d%<$*|'Ab2j\r|EPeƌ.^L`ر>}:>/Gδ57 uwdz<9j*{Pệ_+W.˗ڵQ% E7S$^~^|N$ǕH0y- L 'IHRG@:mZD*LF7|ɢ2o*|l O_~A![ p5r#R;׉r3ƎI#ftTx6jǽ._Б@]8S'wX|9.\sι+Kcrݻwǡ1 m+{i5 [x/TB6;ڶiׯyGo{Ou떮էߕY0m4|X0Hɠ}YOEӷ'p(zǫyjƚӧѽx$k3Nzws߆/ݒ"@ϯ [ny"WdLLIwވv {G;Vܗ)];w͛7 *d0 kdk\q/e˖]!ZM'l8"}ެOݻXI g\|Y's:s ݎޯ Ĕ:%!]U]]?~<uTqH<n{_t9s&6mނ[fG  ]F\ۏuֹ 0-'Q{ [z!󘤖Q¿ÂHRAؾc7 S * *|a6<ÜK#\&܂l% Tw`p/?CgXIr1}"R.ضm̙C-uoVc'OrfPǁ$@X` V'wY_xi 2D_i!(n;ݦ5ltirz  ȃtФFL2ϔފYf" "GoS0vXǡ~5\߿}AB'Ot 7ېm6 %K"[lhݺ5;lI +в,!*#5o}(֜JQLy?ӷ>s=Y9qD|ذazxi7o hذ!Q>1cFRI(y'Oѿcג5pD[t))`;}}ҿT5)Hn(Z˘={6>C4k Ee3gNV#_|8/($@' ֺŋ@AIIêVT)ekr.?)@&;v1 6|СCzxq_I $ [>d{\8cz[ u\xU?+2H͛]LYalSUːl' Aq[ >Dy1Pbꩧ#78ݽg޽{k+V(}8s +sSZz}0cH q%6f*`+:txo=[lU+b(dP^K#4PFtM _B~ڌ"E˜٩^z,o_xY—?~G ߐ YjZm{ې?[$>GMmV. GCDu+IC4 A_M+B'4HmNcR7~"^%3ٿ_~$g  -x{hdU WDR v۷cq!*DQp5|S<ԫQ܊c{#qĮxV܅t:w^F NQKZ 㬲wW y:uTX0)90uǏS#F&=w\&OU~ w֞OYPLFdz_-d $@i!믿M֨[jަqu*]ȂZsVm^[z}/ª!(v!I+ `gQRؕcwR;u߿l /-}eG vDo٬vl̑ܜM'|'(V*a0O_Q6 Qvmَ?mN ,-[~kVxV9T+s[oݲ6n},W^&] ~%MVVV cڗQXQ92Qd30 *|V$0k,mƿ| & wzY?@]xqX<[hU{E0dw1nk_j,郒j[]%"L4 LoC ji [6?r%K~zemaXٮwFcY7Iu֔=OGŵڼ,S7Ԋ9nqظq[7cf5x½ދ6 B)%^5'{ھQŵhc"߅ck*.cG~v6({yQ V;gG֭[p&x@~jjw=!xFyyOG@*Q H/3XT_R6N@I;w45Tn޸VZg}MkY1U;'{pǂjs֭ZB6E9eJ'|6>rPtε3Zu%°g TPA[bbT$" rZ_M躟ٳ*6MHjSO;CS#8MP}bp2aꕨY:>V1Kt\ kr|)yEVKq17i好_0Sml#;y# '!bxO<ņeCpQ4n篻In~!*J]' fЛo3X@ec71f?A7ѵFRyӦML"xLm"f?rbƻCuTy*yE <<ڷoFkjo[o… .=/%u̕0\#аaCVy'b E7%pB_7Ӕ~:VL_lG~}ЬY3&&fݻwc2|n,%G"믿*UW6%~0~x݋X^?*kH3gvk嘙=z4#Gľs2x *ᑚmOxh} s)0d!s Nr{՝ ˖;$Gv^fh.@H܈xb~gVL~݅%->{yxlZ(~|w7yKK`ߓF=N?d)D:uw߹`fbn[%|`ϓbnB=[,z,ȗӦ7'qs/DaUmlTYq.{X(V vڤ/%쥽}v+WŷOPA%J.J2Cc 85gx%b2f¶_CZӎŤI`ǏAbO4ߍXMRH .x.c qI2!!!_ ?!n:]i[∹Պ /_ 5Et)]8r"@<\5kPvm`̞;5UEzkF!G`(eE#{)ǥ!x JZl;_}ʕ+a Ok/[pZ^ #~nS=w $C woC9=YKFL`ҥ٘qTQ.!A(WԂkךEz/bsT0÷I32R7cxz-Oϣ%E/wdɂ%J`̘1Xz5ׯOOn&2z*V-UmT-4ly,ZX"zuV]i"e[l2MSy^.W XzqC@u_#<K &㈨'d̗Id-wc;oW'#~r|KQR~Qsih{^'p5ʓ:w^x!q~-K, zD^{~W`HFٳȖA̳k0TY۰M;vO>7y2`ǘB6TN;tr-OOE`Zr'koSxm _LQȏI[H?9r@&M K@( [B* kh8|pc+R$pypv`M}ͧSֳ67Mϔ_c_~ڥ3jo?.9x@Xn)0w.㾥,iS%Yu.gQm+a'q>@nݼ i/$f7|3c{„ (Y$w'$ Z4H  2O[P_r٭{w`(d͒#`o]vK-~&ڵIN~8<ض}zGugmAy,+]M&T܃sU]qkR<g6YV_/Fah~Zܹs-S7\W_}Cb~Aey^jt>7ԇYx?VdkvҼM"!9nhh_0f,ڄӄi!~jƍiƫJDS>3xo0kAl$;^0 ֫_"QF =fzV, >%ZZM69 |F! Vh ._ 6['[9qM)w.L:}Y;WM6 {F}h%Ƿ# @`hx[H̚ڶmk@ɮ7ŋvyrV)#~o݂~iʡG}1s&FtLro޼ɚ2&וHժUD9F>&_j }1X)ƙS| Sc{<C^^e?-mf}% ,uM6fl#tj.)SaZ?L17*flße=oܤWK,\wDݝ3G`w{U^_AY;xP;U qX7 eH°wj`޼ywMq8;L4I?^|7mޢt{jMHoר9*hNm7ҖMoc{@)0wݎԷ2*NU\oS*~Sȳd+Q0ӹiϳ|x5g(~ +#gXB#0t$dc{,Rƻn7#c>]}^t|\=%i\zTcG`N_Ä!peqt4%!?7YboB0B/_O}uߞZ( ʥ!Ʉ^/ ?5?fϖ!#lE9ݪ`^ŪÁ:}z,2h,fJϙ:B+˦n/%D_ߺF;wֵ9ﭥ-(nÓO>=s7}1Vk)]V)_pyH\8Q'ū%< 9sF-Gq 3O=P˕+7:;x~S-7̾|&e8AGnj-}G[%bA N6mdx\~MD^[+_AĶXT,)o|0"P/ 9=he~jF2k6 4} Kf.`ZZmMz.XЩkwݻfφ,'b["#hN섘kWqmD9]|*C䚳jy"y=Fp dTx7 _ >s/k2eʤcT7CѢE AH}޲enPVۯ^AP= Us1ZȷysK{A< u<-2R! !{{9lߵK/ .S e=PjQeh4Wұ1,>Uo+E/!gͧۛr>$[vX ʤAI|-ne;ѣ"H햸cǎ Yضm Jha>yFlCXbXҷz:ȶysAZ'?*Q8/r^~eK.?IeإzHlǢ6HđOy㫝O u">$w޽qXX)ʟqBy! 9qƄ9ٝOweI_u⯪F .O= ܽ>,k >)u7"إ̝A9oR"~0-Gx'OaS]][)! >׮@tKT*nʕ+:cI%})(@|Q+#}nL2wSO=Ō,Qdk]Y W^dɒȖ-ZnsoMm\&~/Cʜe͕XKYbO߲?89r%YE)*;Q {.z_ U&k"׫WZlBuUڿ$REXF?ˑ2bhܸ1d  ˗Ow6l{dh_`8p6lPɓzk#|gʃ*dtomYORҊ 'uV ""gRy.{1l۾C+̹CP[z~.yX#j࣑Bg5 9>}YIn6!7P?Z:n8o5)逘[Ds|ر裏РAԩS3fs-i/2OXu F){YF1K"k_˄ mț݆C(]jNG,e;opcx`r..X?{{Wo J*ZW^=3fD9pE}?нGy$6M2ePT)ϱ&mޒ]oΝi v((4eOzzGj1w,5WJ)& ?iӦaɭPܧo05tw9c?q}|O QݻwsvP%׬YSu9sLd/)k;$GNW~jEL5(/ܽ r6n(u=+.\ݐ]gѱcGYFC{*h7eWGïj* ߑ;묒O3}eϞ=s^Νu9W\юz ͚5k"/s!QQ9 k3 ISUei^_~}Ů˖ݽu^J]ڔeq ڴiZWŊê5k񤚖}JX}Q4O4~y?*R^=Q0, R/JO|q ٷoرՠxQZl"M@ rGȑ#c[u'&߸ql=7AJ/~bQF!kF+?=%de*Tp2KUkٻ~ )CٍSQ *?\S.OG+@q8MjqĻ{coH޼y3z#s/ԭ[W{3)'./_J-|"'V.ܒyw)_C@X(!޲9;i$ )ٺe˖x`as`}Ț ~_'K/_zHrZjūn؊mˌ!|jJ-=!NGh'<=?TQFHBt$ +sDOv?.S!M[>KdTXP b6BV gDQ:ԾC ³ﮃ *$:}d!CУGOJ|cZZY|ڝjP* Cq{5,JZAD2^r}&N6ۡeHG;͓e~:h'p]Ǡ>hѢd8W7x0TI|v  sC=v3 ^mybF"=j~=v!Iόjl6> +`5U}q.~Nf w7A9eϚ?8~1c`%{+,3x:ߨpxyZ?ET*iSQhw}_wXuvtŽzv_ĒKiؿ]cïo wԚ*w$t4AZ./裏oѽ'nrkhśoc+7ECkj]o[o֍1՝u 伨)ڦ6LEm-G[uhOQ<р3♇~nFܻwod̘sn?S~;︹&̎ Oڽ;BJfkV–3ua>Mjؑ!{oܔuj $(_̔)Z<(͔u^Tƍ!].F8($DWٳɬSnh\{o#دZڪ6[Ure1sLx.s3~H ߲fèIMe_~~u{7U/6UZ<{țJ0T-eukW?-9C 5|\3_FjSm.'O #]'ܒ'3 Suܻ{7~OsyÞFs7o^XrRXh6u",Xnݺ%+x⸡)?kGG>F7~ ft_~1{ّ+g=uC);%N9,2m۶w j0X*3y-8Y~%Sf)Uݩo]~|K45ϲt! Uq+J+'\W7ۂp{7xg_F0ʪi,q֛}Ɏvnf0; sg¦M`+QkuHmAKa5ﮓU?i>Ӡ`(2=|ǚ7o犬S7w:0gOqĞ+@nGu`8zW\ ˹W>X3 +FXΎFѦMhI[!4hXt1 2g=Uuq&dw ԩSFwhlL<*|3X O54 A+S)=i*UOFbhL ?3c#!;!JBJ"%Ï!%Zh YeOLn|̘]{?>}<?d.N{uaXb.R;ZNêkf64lн ڹbBe^t'!~ZVxw<Z靄I{GdɒL)m*U7gjʶ 3Im]Bn?K2x >E\"IWH+ו(3!"b#gdju&Z3+VrX0+sVyYB^]r ?r`ɒ%Zqu?mR>)'/5Ŋغu#R} xBߌԇ *h-_mrwVY5HQ5]駛9ނ堄~[%~Q坲 ?@eo?<,URfP޲I` H_zkZ#m?~x{k!CeD] Da9~RL6Ԅצp8x܊a~H]ƿ{("@cQSUquDFF .kw۶mq TRϏ5a D1eO OY6L0A=3!;+`r3z:C=tG~p/ĩmwNoq?~7!M&lS *KthԨ?l@޾40bͥcAA9˜.!LTPfr *|pvX-ǬYP}'1K 򕫀[cш G<9ĉqaS6zc&YC(]i1: QxG֛ J*SNt 'Gަw$M'OH^$;zND/;֭[Nyիœ9spZ 4+׼feZχeW&k %W!bɜ9.{k׮# a祪W#&!Ao'^骬 |k1v; >^b Uvx#?4Zp53+֛QAw~Ԯ];W옙FܹshIxAC wnUV-?:G[];~ժϱm6e^^Y`"nƻvogs\@[0a љ_kڈ5ǝgF\UlΝh8GӖ]Uczcp4Yǎsu<֭[ɟչjW>`G< scRZ {ŋQhQ;vE Yd(b@[j3 U/8TS}+jQcudrZd#F@Ti<ܢ3fD_22MNOr$g#GѤItG ¿7^ШM~X9XmDW9W}l7xOkK.yKcݺo7hnU9/gUg.ANFU !?@dT:]q>3n8ԮS? bx[)!P|wUշZ7;=S:u ݗp&q&$&rRؼyfz1Ku2B6mB5;Qh Ak6AIa@BAmV'ffbԩ5p1KHҗQh+TFyapD| mڴ1o6DGz&!:4R\[ԩS4x06m܈G^EڈGrLM#_MG~-e~өH$.[KУGg؉L>cÔ7|Ѩzھ3/e20 3>XgEձ䓥hHN ? j>(?~a((9cGPtͮ涐Rml۬$}k?~(X;Pj@=`C߾} []G:7{OZ0wsrc[Qd91,Bp]vf l;cam0BGRV1+*JP:i﯉cʕ]:D;g=j܌?9ܾ fZY;~كM^K Cn:TQ:b߇“f!-= b"(4\ ?jW1@fʹ(|lW&`9BrX6whC c퀖"#͚ sʡ3+Q*"/1Dy+~Iu M|0@bŰe6j2Wwd:sъN#-|z8^HE$~F&y"y_BF}U,&V]3 u~]NA0 _6bk`|}!HGXuTār2D$|Td,NaϟTR<)NsB&DX EeGG# x% M~w1}ӧV^'|uB"%oJ)+^gAjg~TP!w bn  Pۍ΂gΜQpo Sͺ^%N2$ƐAP}[߮}{\|}2`Ͳ%%yQqͰwyV<ɂ:ʉvH"&q Uq'U2ŵX׮[G!ohᬺ{.$W8BDm^ͣW_}mϿPVn7|ڔ}հi+,o޽{gÇZY@.]!/$%%^Ь}Բ}xW!3@ubIX]v G:rF@f?+YtSΕ~R YP R[)9#\$XnQɚܨfF5khׯ_~ [Oׯі-/M_ڗI(dȠ|ER!V;vypc^ثW/Ԃ,λq^ &gA _=R){7C?}U\-ئ5K#r_ŋ+hA3J*+WQNλoQ~S+c/^o7l@țCչ*UUV+bWQI #{Է?hQhذ-7ɇچ/PuZCdoԾ$`T.WY){( ˠŋZϞ=5pȲQPC(ШIJ#M)˗kh3NHӀ+CQ*CO`:F6,Ɔ^zH\]Wf[H#|׶d{@$3&\U jsw@Έx??'+C@q}y8vC:is%p5> \bߝի 3w0jQY'.cw J|p.)*V-[`=J]NE_4cWs.9IN@wK-vq{Ο?hѢE5wНxwT:L0͉ gݟǡSfH[I~ 8(vdp&):uh}Ȑ!8wdVݷo_4iݻww&leQʵ޸m^f0sͨ]vAkc;u=T,& Н4K.?dPw'.mH>W?#Ȗ8@= Ff"ϛ*+:V)5ϘĀ}%#p}2eT\9=m\?gvL/ӂN(|[F RmL'`UKڿz #5Mn;> Oh+rv b!  ?G/>McFFʟCwS/ׯR1l0}͗2g/q,??_no(X3 ܕ][_DU~nDcȪ#iz U6#*T0d5kȃ6l=dA*f𔩇6 $ȹ㐂HXas? iFL4 7vW3<^qk]h tD$?TyS⡇ a XC[PoHx>:?4]Z'W&%zr_70"*< zj F)%%A ϙ*2q)ZL5!% Pq$oĆ U33aZ(ŝEũ`U`gUr ;DhhW&wUGb$R s`S.t7|ux<5!)y$7n7yiON0c 4E`y1118tf&0֭.ZO|h?VZM-Zy``5 [D$?Tڿp74 7_j׬66msU@CWUm= k[L6 ݺu6?3G -q@@}XHwr<`,5pp j?ePqKP(벾:O>_ :4`H٧$s )K4˖ƍ6=k9܉W\ nH78U݅$aгgOȃs WQD VD$@vў]ز.q5hҨ1gNLTx KWDwVvxu(P]=:lD$ =M#PYMөH'D $܇yѡ}{|*zg$@G ߉c.缷nٌ  vx;(Z$0O=$VdHH3|L(-Z vd$uzk !NEѽ(o @3 HA7~-qu_:/( -Bª0`/_ D$@$*©diyWBL</#W_/z=]5>@ UIcV^~+w1;zm1H; qqX~=:t,q Ȏ#/~ؽERv8tB--RĎp*{nH5‰cᦚ1_ŰL2~0 qk.8Ȋ  @ԻEM0evlA;`pΩuYψ=>cѢEMCyDv Ww%L}aÆQ.0G7_fd;/RRSܜ4˕ű~B^{M$@v·5Py=!aJm}hnc Aʶ;v`T1};;Cy$@$T^Tڵ TKJ{޾51qK? Eګ=z4;;H$@K _c۬Y3D8a*k_}H:Ö:I&v@Xء,8| ֭(HNZfGf5Ko#i,K5B윩xnD<ÇsVw@$@@z9={6~:[##ivl67=EKKbwQr`F  p5]E}4:iΠG0_g3gгgϼdY  LPgEJ*E 9f(X[rSr=)~' pSy˻/${)R)Q( x;*|~ڵkQQS6o@!OI2W&ۍX5`ԩqĦM: $ ?, N&L=o}kxrv&nk"Vڹ`S.O3icH<GFn,\Ǖ$ݥ^a5!*B_|oEuN6H<>Z!nlΜn\ƫ@=wÙSеkW  o#@A#.F}֮ʕ+p`$&~Tؤ-Yaaank+& o&@߽{wmf v{]4WY'ָX́N ѣZ[x ϊHH2#(QB'7ol"VEsŹ}ӈUOaժUXlBCC=);A$@F&@oAx Yx_ƾ{QbEAa$@$@y#@7~)_QF!qZ QyM/n܆9sh (W,O$@$`,tL@?^}11>ؒTaSoV;vq4 n{ 9#n جR^){yF*{/$@"@orXk}YRM*&B&GMq% p*|7@K^Z<+~2;/Ա-Z _oXәl|h?6ĉѩSl3 >Pcڊӧ^H,=Yo@aVB2 qi-NJaį?X3 qʩ-^:‡Eoaz%C]_o7&|qD$@$`,T/vĈ= Wg'I9P/ e-e?hʹzͿ_B#'Mߐ fs oT[?"IDATH޻3 A\^xᅴk|C$@$`,Tqqqx*UPHt111"k|6m`qy܋*] +6HH@ ȑXf .\~C֭پk> = 발 bOrB$@$EMqJSzq(VZiW*bEyfm։S$SIXQ|jH f۷oGN9wIMժUCժU39@ٲeQLΞYկ_HHt7ÏFb4{K*+W<sΥe_IHE@w e˖;wN#yyDFFEiƹ-U Gү8fJ' p):uh}Ȑ!իW!{M4Aݝ23!PpajHhh&wyHHhtҥK!1+VҥKl6kyٽ됳& p*IoHl߾}ٽX?}& DPP+f$@$@'KKq>*XN oX3 8.?"jrxD$@$`|{k L$@$@'@o1tZı gg#{A$@$@Yo gqd/HHH KTYM   T1 dI ?K}:_IH [2cǎbr>*|3] ڵ 2_BLۛ3cf+{ H% ^fj8f̘|u2*|'֣-[B޽;yϟGddDv7gϞEz0wۮk֬(}qD$@3g/^dHH}QMW ҜȒ={'>Y8pf߸qc͸?F5=]nw^[eG-}'Ϋ K?Ў* JQ.yĉ}Yhb'/Ԃ6ɃAk"CV OD$x\wwLmv/3x9WdI힄AB /3 p CF' \BOb`mƞ9%~>|f}v8O^>@R…!=.."?*`"p*|pT0eشŜjԨ#GhF{l6fWvm̙31d@V4 ~iKV5kf";00P+X  >(U,_IL @)JG~|޽;v0ѽ?4/yٳzd_˵yشi4ieX⋂߲eV}hڴijU|%p0*|80*ٿ_nd/_ ڴimۢTRi]###b/k֬A͵|_Qb'EXB/en݊D<Z]ׯ  s8sDS* Q |%WjnI Dً̒X'''k~2k$@#@8D$@$@%%} F$@$@#@8D$@$@%@ۡaHHHqǒHHH@u;4l 8XR n #  wKJ"  аa$@$@$88|9dIENDB`ggpubr/tools/README-deviation-graphs-horizontal-1.png0000644000176200001440000017702014334142176022146 0ustar liggesusersPNG  IHDRp@ i[iCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*ip@w@IDATx MeJ^ Ee*c!B) E)CJRQ*S!DoY2+̙#}f͚5Y]=zԬ[/RJ@?Pcqqm޼*5K:;FbW\a)XTo;w9t>` Ý >X@P4B ,>C{*C,Y`}jW >ܜ:u*Y|WCモ}{e>fŊz˖-fΝMRyڵ^KoI"(" ,\ݺuͤ )G1v_CxL>t萹g?b =\ri߷o.$hĈ믗M41-Z0w}[mS釘(YH0۷O,n_/ W_-I?ya*:!Uc"6k\8"("G C %Ncǎ5G6?ٻw?!yF)3foҶtR-[6s13dSpan۶ 6@t K/rڰrJSF yc'Nql2c;v;x ޫV2vw,sgVL6mLɒ%AVWnz)%Խ{w!'΁ O˖-e?w޽_֭[s*U8o0Bcj$KcJ ~/QR\$J2_ ]bo~\Ӆ{AF똡ׯ_?o߾BL#T#g^ƍe_ebO?LDԩQOEPE@P Lq\8$,cNXK^L`}pٔ}a#f.T/jv۟ "vZQ3Ξ;o]|d Dh!;e&Ӆsg¼1p^{mJp|ѽ!S T=b8AIr}XR@냑@mYM;NFf"s}kqR5י+lyhHY,oB\7RpS=E >=yrIJJpA\K(э>zt"("(“("(э@`>n=tB q?%(.º5gke+:_~şD\75͹?Ά`"8`YܽQő(@!VGƍs9YGPT#ÇmۚO?TfQGz9 *L6Mvab )YInȐ!RL~ǎB:y8;^Jơo궆S>3TUpc)"(@g1m~,ړn c|k^ˊ"("8HI&4\w^ӻwoCǏK.#G JQ5cǎlٲ裏 zCv*R*>i &$jtR)u1xTOKN,jqkF\Ic}\<{苮.ዾ<̻/ƒ\d|SR+zLFa!p۶m3Ď_4׋uҾ}{xlذr !nXRo5EwuO˗ڵk'蛺^b2jԨx,X`rӁɒ%Zn:4B)' ^ZreqԨQCb 6>.QΞ qBQħ tX .[0\xxm"3`={v'HzRKX\ѢE}1_ޛ`Kb)۳gRrd )?+URTXQ&L4jHChٛ+ʕ+Aw#,UP.]ڷ/nK]4hKnV/&d?he Xk08/*@$ J 7$+xt_[=׆_3YH2 h->ļ1-V5mԩSGnWȷzYrL6u+!pWbE'-Ƴd2% kNb&N(=!|f*cc|KB-)ÊF< KN|%_ }u] V?k7,7RpLOoM>"("qCG*`F/dG\Oeʔ7*A^e1s yBF_`A5剘0c"("9dq{M#RwrKBrhu&7q.+ ~,`ٚZ!h,d^ױ mrhpSW8[6,˴3Z{t9Il%W\f|׸W}#IpҠ&0!B]\~c/K.:?BtB ZqRM?W…'}&sG_jzkD \%p鋯=ͅ=$%M~'Qn2+ԩ_ě60OǃZɽtYPEo2tIPE@PE (K-"("(aF@]a\s&ո]&L$&("бҖQ_g{\G Y0";vB!"`U%E@EȉP5@5 7U2(^lJO}*TGPE rIG رC*T&͍S&GzQ^ b8`nv}hRbՒO[n]PE@PG z)Ӳχ.k <A9.cU"l,ڒy{d&``=t\>oY̲e˄nڴPuzRuP!ݺum͚5QQE@P)Q:y7koB .,ENӣG)0?tPHVHOΝ+帨ڡCw^ӻwo)[sq)a3rH)F=W,eGI#FH Ul;vrͻyf[oaÆ%@!5^wi9"$/E˗K{M6M3/j^Qz#COF^k>H':/3\;i~"]r儞c$SD{/-M1\XȰQ$o>pQk׮f͚5fܸqrcl߾׋u~׮]kW.Vj -, 2v-6hg׿%/^\֒*ֆ%-[V,pXިO&ȸv XtDZk@R@G:yM$S&H?[G|{+q΀1 %1E2a &|{9xb3e`ٛ `Ղ! 20 EnذL:5jL.}[K~A_%^_zժU3ne~={4m۶;f}gR3wqoΝ;ù+ÉK,vk]k!pԇXcCѢEŪ b}nݻw+_|g+ ݤIa+Qm.G/oLTҥ&uVC^Nd6zj2VJPE@P)RFYK+j׮-XT"UN ąZNmh\_-]ٳd0sLq \6?X !XRJn:Y/e^E@PEbʅia%҆!6 0\Jq*<>|:uJ˔)t&=0v۷LN_ȌϻZܹҢXabCbHER|y!KMk(sd+@ ).BLrYXjTLi/Đ@}g\3DK:ukA4U1D6$wWc஽H4^.!YcJo0EprJ/q"oEaH"o?A8 A R(":1MBI[2&D*&7 6Ez)"(ij:)"("17!,t"(8z13]lٲI&{tV]E@heC5 vNHU%M\Ez"(8i!ƍeIJ+*fV+#2Koʕ[ޙ'W] #a\"\̙?}2z]2~o#)IRE vI sM &;vM6IB܇~W-4E|BncLE' fy뭷oڷo/%Hڋ6mژ 1QեE@PE@HZ ̳>[ ]H]v'W*5Q[jXT)fM6-Sqs%Įdɒϲe O)݅ڵKYɓ' !)RKB2tvZKآ^\9{S+:r@WtfSc(pAO[M7$.ĚΚ5<·}vC\墚5kfVX!ۼy'|"DB-ڵtM=V]/E,X @pb-ZԌ9RC>!kN8Q'̙.ul  Fc -.i5aC\K9tv`HNpAH,RuQ™;k֬[8p1cժU+AKtȐ! Xźt"=޽I2Ov+V>LlrRg1`q?(nsÝ6crΝ;u?ps߂lPNkpOG%pIS&ܹӴm#VSR%0w\7nwp6l0z`Xqˑ#]w%K+VLm̄D ܩ("(, kƤ$kJ^m%gϞ V/b!ժUjs|2_rWF'0&^Uxs+E@4.@!D.V W+uEgSPF@ \F_PE@Pd".isE@PE@P23G Ln4q"2H')Lqe\ |:ݮ(@8Pu@ΚkıA_>::SKP%pG5֭%$-P RPlܸQ!-IqɱRA/f7B}ʕ+ 6"EkSM7ָ4"a{h+"W_:ΐW*yG:dKTv*„ oV*!,Y$ViN>hǴ"("@Yo. FazA-Z0w}/!-p!]"-BBEraMyѼV'Oz C#o޼>ߘ6G+-O,L.b\j"IMS?ٳ'ƾ'Nr^6kz c~r[+"(@#qnʕF>'JM6 9ԩ$Qf:#G47;v0zٷo裏,|g5ӧ)a)Ru]ofp;8PkjJ>o۶MJc:0zh!eǏ[\+O꫶i,XP5;5j$ݽ/03 +{k6/"ݻFs*UՓbo͙3gvirR2?)]I2K ߴ'- /WaE\=],kG FH„U3c ɱϜ9Snn̝;s=BF13fw,Y^Y`M=GR-_jU!SI} 5JKwH$V{mV,m7jbm#O>1M6tUT @~q#pX6q"X `tInx;Okz.k%T(%^8w5ąj;@зRti8)%Tn]_bŊo)%*Vhz!R%mf…<`yDžh"úbF; W&"Xﳂ8H'cB "ۨeӥKlӫ͛ɓ';w ĺL^|EOf\pDK1fj7uK/;n:Zu/HXNsIED!\ 8s挄ޏ#[trAH.8ٲV!/X7e˖X0?vV pfac * uHW*T` IV5Ecۅrӆ Z o`K/d 7I RCKs0Ϥ+~>uܐ 3&S[lM"(@ȬL\ 0=".Y:ݞ`Y&.]"D?QK8u\t"DpG,=vE@p"nj)"("D.U @|j.SU+\\(:"88O*|Kle86a6'ioTE@PBG@ \XiKE a}?/vXbeS*tz""p WZz$UVAKMc"͛%OB]r ! 2"("("pTS;>(u_~eI\L3O>CI+;wnI;vXSbE3GE@PE *ǩ$$w"/{:tHjޛH? m_[-we&dk}}~ .XŨPJx ڱcx:RqVO?IuIf쯇CE@PE]q*eJx"7X>S ݻ9rTcP=!M}1J 6` uJI LΝ;z% ?Hu\郲5$(9RߵkG ѪU+)ؿȑCfٲefĈBwa v>ؿa^Ɂ1Vn:HnJw% s.CzuXmÆ+f%\w <s= ƀH-_őˁJwwK:M3 68>@P8q;w)Uǒ3L,YkBʕ+'_TU={)Sњ6miڴX־}{!oիW7gWL!pl$aꫯ IP=4h p#9sXÎI,)7\_j XXEՇ+'$}9ϕlqu AC{ 'QIிzѣlٲZV5oL<ܹlڴ,@Qz!SR%sw%Jڰa3g=D7i\db 3j(LN{1QՊo+@B5kҥKnԡE1#bؓ*fXF˘|?]))j1{WAb\sSu…/^KYF 믿 jK, ;º뮻V,C^B믳:Y„ =#!b&#YJkcE@PE@Q[J 7*ć0\^ↅ W'): G[`jѢXM# *^Aޱ| 8G}c:uȬm۶a=KNn >br)ΒM*VWYNLu"("8@ZఎhcիW/өS'O<p10G9\%Xvڙ}尀5iDbޘGy >L:U% 7*^K1)kqҥp}=ZܸoE@PE-2Yy.riK\f < 9uPIX1f!bcbjkUVOm.1pwe!zv5.1pxfR{_w@ԺPCXǶ@ycāۘ_.*щm\ GNrB \8&QPF \z+y"X\ "D?J*"(@!.N"(, QqMHRuSA jg)#U# RqLbPQE@%pc-T! Q1U̝=T&s2技"61Il"%.٧XW_}%rm*qRVZvƍ%Q0}Il4-Tӆsi)V!,D1?v6`[X \^PC &cj &);y2d:I/߷æm۶O?~T%q..1Y|OMJ8u䆣"("D71GmJuӧ;Tn zݾׯOPdg2[iݺyWֈ#|9Jl]bȓewxm6vM>B&ٗ`~("(n!s.Yf7cŒu}֨Q,X)RD SmȁĝJ)-P*9 z!U{6dG?~$29ryel"F2Yd^X /_>s1%feRkرRjFW\aqa{׷-= @S_l֥སY|}7 pMpwAFW1EΛ7O R}tRSzuY / 5G|waÆ>Gq'Pa!9eV~}٭}fڵB qlFF\.Rܣ'9s6mڵkaM4ItUA:`& 1},. 7g^)nJG5 Ȼ/kҌ.%p1ܲeJiCef>x믗]vDe,(V(a_TH+X- 1X~'͛WܽX C LҥU-{J|_T>=b= WP&8 \qk@urhc | YfuA] ̙ }s V0"OK\ɨH(tqCC V+xʕ+gƌc/-dQ.\hp}^hQџj]xy饗b + =k{7͞={Lz~<qnM~0pBB 0WFtq&Ρ^'Εk=/:o^|]8RGI !ܡO=i֬7onVj>x(F ^5jgZڵk{_m!}&SG䉰qT''O0A,uNOPE@Pb͞=~?K=.f^KFfδOW+SN ڣ>*OX~!v,?21'YkQ#mSN1ʔ)#nTċ MObp91qBEPE@PbLq wiw>x]z_G0 eۯODvY"Yo\+3gGfnun\7ȕ!!fZ]<jԕb0[]NQ2f,puB%__P3!P_vG&_0 rϝ7.z9ȹP>]"(1=zD8Bu!OM\/q/'NIH  H:"(#3?O"("(>E@PE@P@@]n'2 |!\Rx=5ā29GEPE tTR?o+d(":Qy\dLC9,?$ǽ; %KH+VLޙi&YI0͚52c|*BP!mjݟ;wG5֭dÔ}{xh,|ޑ#{E/V6򻑒#TE q ޽;޹㏥CO~w2.uWm6mHՅ &~EFܹS;cg4~a)Ez*OW^fСv+"(Dsr- "E)",dX̑;(&O{q&j$0*=nZ f֭zʕ+bħ~jڵkA٭zH5P5`{פ*8hP"*"("6QizPWdɒ񲽳R[oƍYfI#G={rWO6+uUh~3f,P@ }'N4X㬕m׮]ZVX޲e|5h"CURZs̑"?`5lmB8c+y"("6Qk+XēAn3|SfM)"oO(}r :wUn̙B x /l9ֹ9sڮ2w5cǎg{VÇǫ:xE~<&K,RؼysCm6ST[Y ԩcp"^+(OP WJ1))5A$5|$xh\-Y MǨ%p> 5jƍcfa9qℐ9ZsΕ@o޼YK.- (fuVqAw<) `}Y_y|X(ՠA)|Q#ՃlKOcǎB .>2D!u֕/e X4:eXS/2yD γJ= &Io={<عRX[3>,-^~ 73g q)qu₎akpXH!c*ְaCsuɹ<(Se-g}An|Ire6ie7}?+,ϟ_n^?8pn6Ë7|c#pLV5/7e˖6=]9F8o.yR邸V̞{ȕ钾&=b.|GǨAQ+X/.DwHkUfHM6tbmj-j_~kժX2gl fVX!ͱ?~\Hg2{lC/_.D k$҂t" dV+}p7oYjZjb6E@PE@pq@%J$8%۷l9r$h1\FL޼y 3f21ױc 5~-҅4kLPB/,nY,<9CZli*T~p%*o:u`b "(",fD^pV4RxP̉L U bӈ._uzꇵ/ Dw%BRw#5ycw-~h]yim"k.T;S(E^]`\8[ѥc[B9]7G<5솔XŔ7"97|ܭ\w= MPQE@ mDX/tE2lUOE@^E#QtIpi$KgLuUH@@ \$APE@Pd 1pK*. @ܣDHە(;zRǤOv`:3$BJ)"C@  ]P‡{}Ӽ7o_Бf)B)XJ`^Z2Xڅ p "V/r7}C,P 6lļE uwm9oMp\̧L/h_E@b2lڵkӎ;DԴi?, 7 Hi!~I5C⨔ID:dƍ8 N)}%m("(_d)N… ؤ䳂4a]OJ 1ʕ+o@^)bjHg*/!kv 3fV\XyW}$ryW)V!~}lirb#c9rDjzb/_>si9>փYzKJoݮ("(@8î^͈qfҥ&[lB b .,;w,ąYl]fPrUݻwRDS\GAN::y睾"|ƍJݾ}yWdE-[~=z`kD?Szѣ p3S RHUHؒ%Kd<>|L ټy,VpK,XxB B6m2%KFgS@:`c{grmƎk s뭷k ֤I!w^>}Lr|{f4&M/Z̪UL*ULom+f l/]eʉq t8J1vZQ_t@W +kj8Kʕ+ܓ5j0X2a5-&J(!>*U23gwue 0@q.Z(â Xgܹ7RŐ/s=g/^l LH7g3w\ +!ǀpfxU!L!cI';fX̞"XK#7+ E,Z|yXr=!3LSQ…@D8\mݻ}8`ƲF̛wn^P)]oתfW-ZT"V=SǺ.n"n>XɈ{GLF|-w |} 6X?BԬX={v!rzR;>H"("D!!b\`BT|BH72|!y`(B~t͛7O ;Wŋ7'N 8sM6fԨQ>K$,1ܱcdLb㰞Y$HpY;* ֞>kܗ_~)X̾ʇz|X)"(d .,LL8,Ts4M6٤7z+7&[Xˈc+Tdfƍe,լYMW#6L##XB=m"("PD"=II6tXʖ-+3;1ȞfnBxnPYd7#տgbpoҿ+#Sńu1be˖Cgݬ9K.qe s9ߴjϗBO.;Jڽgǥ?|isj \bA*eb ^[#׽!PT%NJoOڵS4hvv__ϔԡ ?$#Hu־8<ڤDgS /AGK#Ccu<`rҺOPhD -py+̫PCTݷo\3RC?ک.}D'}GO~ıB6C}IiZO珈~V#j_U*XVIMǪǥ("(YUӵ"("(: \u g> +eo&J ٳ y; :"d4J2 _N^+tʋcp8E@H%pΚ5+ccBJeՒ^eSũ@ Ӕ:ˌ2-QLĚB0oAGF3(@ ,c6&ȉM?ڙwT7 )?#.}˗O:tȼ+fĈ.%ILഖ+VLU%pi("d<8 ]Ν y'D 2MS,ĖvL9BeZjI?׿efΜi:v(H+o޼>˜I],T T+$u$#&!~DT@%"("D=`ghR]bȑ#͎;Lڵ$#Hּ`}$%;?wBЮj*UѣGݻWxw%S)9ׯ}vNFb;y &>}ƍ}f.ZGVHK>=uv%nz37-%}v]җCzz n+eiq.9Ot/U^H f]*@)sQE@(H"q..CΙC'Tu>&&@ jE@PF@ X"gֺ"Z*ʦT˓WE 9k.zˋD^YfJsQ!|sk֬1GwDu۷ {kE:dgǦBY|T}wEPWUEPE@PF ʕ+oZnmڷo;{}yWBzaÆ={ի;cn.RОÇ7o)P!/UX.Z;w=zy뭷$,U%bŊy?"("8@8-b,X}WH"N#)eEm4 d5睄ٲeG6e맴4ܹw}B(g.]j>=ydG^xA,o4x`.={4߲eKYWn]KEPE@P$pIq[޽[HdljժR"ӼvZӯ_?qܹWݲey7ɓ'%\bƌcw.2*7}ꩧ\)<4+8,nl҆R\XJ*+͂ /;wn+xŊlٲRmbɞy[lIiٳgrzcѣG{45%s2Rχ!vׄ Bx킀/rرdQ̨c˕+zf>.tw1iz!{?~ӧ*jwB^9)SHyܖ DKO?/^/Ln݌y7nI{ozeQcסCoX5jv1BHoEرctuwqXjIk8ӧO˵jY3PhZ\&=PidW~Ik{evz79uí},|<#桇24W{1ǰ-s,RWǏIbpٸ4"*\\w_{X7]<IdZ>ZPy\#Stъ~!TE-!;*Kz6lh:#RX $V Qx._|קM& !jSN8ܗȥ^*1 B"`̓'|5j̔\)T8ܹѧ$ۗ+"(t)-ܨX*VkbF*1ZiVYdl)K.g& -ǬTb$nRܹ˗8A1cP1mX6bTE@PE Y 7*b qaE4h(͛77?xu-z)ϿniX,sd`Pt"(I )n U @<9ܦ)A/i%@k+c+;غ53` \:;\|QtNd!kxśA wW$+N o<5g*ti \(3F? B(}jf1K_1u[J Gɏ.HSS@@}q(cb5]2ce_CLUPd#.ِ"("d,BXutE ("$$͊"POI *"(#.t"$6-Yx"V?ULPHD & Ӿ+T@\^ZrժU˻:͗.\(uVK;PѢE}6Jq5W+fH:t˗OJj2eBl"߳؃En"(@LNb8y2d'p/T9Oe*7G7za>3& صmرٳjٲo.("(@!SI)  O?T4D{b!#38DUVZm۶ )JiC[~ sKpw3gQeTRX vK[ٲe%/%9dcǎ2Nz㸼$9KJn5&Pk!K,iqrMpr-<{.ዮ\î\pwa65K.7( ڡC!K}iذA({5uJ7mdJ,)jժfСfƍBަN*?~Y|]vKO>17ܣ۷o+޽{ͨQM bQRTʕ!X yR;?,^XȑÄrǏ\~P:_HsVD_ K9/{S"PEU)DbQ =XpbZ/C  ĝ-ZGv˖-RLZ;Zn- fg6w,C ya]C`3{ժUb;|t?eFBM_qg͚W-S;`.Ѓ4"ͺZiei-ԀJE 1M@7*D  *e̮<̏$UZ<韛|\({vAx6!Ls#p 0P*S3Lɛ7X/n*Wl *$/3fL/MPE@PC &gznTnLkfC4qDuV+uÆ Ȉ# +۷u_~L40zhAdV/͙z2qbŊf鲍v=^L`6eWE@PE y u]'/b1b76dUfMoY*MKrEIa<ҡ<%F|gǁ,Λ7~4%J0.("(d t!9CōI Al,[vc}#(85Hd !6E3g9i \Ϝ3'}GO~7狻v3x=4.}1W{bʩdN(J J#oKUE@K/6& zb<3.X"C cE <0(":JBJ[*"("(ӠJ("("::VR:8!Rcl?+GDz@"J XVpK.d-=hNqk.Wg ׋(8Ϲ{ovsP\y֬Yp’׷! m+<= zW^-nx#Ruڵ`lػ`֭•*U2TiPQ!0hNsm ˺oKNW ("c$\ 2Wn*캴|gz۴i#uM韼p͚535ydSO]~!/${9g}WR[ ֫W/3tPv]PE@PP E)+J_Y)R~w:tHuXiaH*ֽi&0~x郲]5JlQ }u& s<ڼR}ի'_{5!_פIӢE C0*N("((;I!Uw)ES\yw.~M 8PܯorDlԨQfƌ҆/&X9~'rܹ9rDƤI{ڭHb%osUWIW︬?|Y y\ν+:+3eʔ(lG$Kغot};uaT0'uo,8Xau[fX`o4=z/?/cLbra6n(mԩ&K,?4˗/7kJ}SF8Eʖ-+8,o.*yX^}ՆU۶m; q m-[4X|?j$SXbl˞={bM¶>_9ĵ}ucb].:F@ \\`A:t n̺udt…8`yELj V\rz&DP`nZۻwٳĵ13fXވoz|E q5`_.O?-/Ұ+ WmBy4e9KʺCR)gőWt![[b#8xcBf\ F.I7uQ0c֭[- /#pBZҥ}{CHpqZkaznLٝ1 S@+0mժC_jՒ *č`<gjމâ1dps Y|p3ghj;?*Zט`r]W$}Hz(J@\~G 4$݆5Cuۙp{"&՗׷2>6K9܇FL,orp된pJ!!`u&Lk"?Tbi?K,$y`/.vP ?xTE@PBG@ \XiKE@He,3UE@PBC@'1RE@PE bP1BQE@PE 4ԅNJP &\\tWUE@ \ԞZ=0E q97/gLNY/78uE@Pb%p1|)=ߔnXٔy+"h \:U*6PA_!7sD]GTqؽ{J5IJEPE@P%p|IHR[/7|hѢDStղ )%p$"("DJ1%I %RD̹+W]}MrwI5Y^4l/ΔtAw)΅1n=uP4FnQn]Gs1u"E%,y8q=gؿ ,h^z%5ktt|^;_]k5h@jgd}<(5HNN6ǎk`v\)]lloTmHb١_X4yh8t萰to>s7JSSFogϞR l-':)}xJ̙S&%Q,oؒ?[PL(`ScV_}WE@P,mÆ 3!X@"Ҏg^: |v풉%J&nZ~0 ۨ~DWXgzV"4H>bG$V4~㉝kӦ%:uH| ˖-+ŋ+}5H !|.\XH KR"E̶md'dɒB qzꩧݻK]QܢCq.Ifml`_QIرcs!:@󯳝`Nƪ~/˖-26ڻwoy2"= ׯ1.de}Zh!Lb 1cM7n\ KGg#zniNo}+:+n-0߬YUw~xq _ `G_WZ@gWȀ`]|w-Mo=q?Btp.]Z,dP $C]F1|/wρ7?^@wfuL͚5U!fxfm.gn3r2$l+ ?(B! /rn *v ó1#ԬY3ӥK lL!xH%otLQy|!0Tc8_ D\XO?D@&L O8!?sLAl׮71ܵH۶m0rAsq$6w&6.2 !*T"djAQ*)EIsB$ PIJJTdHWWRqν{ι9w޳g?{ߞ~{%{E|@F7oef!.}Z_x8k/l5|u ّ?Vnߝ3= ,_5+Q :8$. +VI1fB&4h »w}=އVoWngzx[~ԅx._m*s\"fc81&E+0ul2ӣGOhX?{29䓅$ X܇sk,Xۺuل}Y7' ]a,a.\,X@׫31)CF!?Y̜*e旋^u'G}f0ۥZ\Ӹ]^$,,Ȯ ++OxqAx&b y^Xzl_uEPtōϋap;AW Nz"_,ҕXmz +W6ӦMn"?* 8 5"n|8^.𠤗<޽ -Ѡm }@q*!%U#һ1te(XQIN-~Yh50f,\\lK[tb߹yJ?^`B/Hb9džn:Iļk1p ᜆ4xet̨Mk~ 4+1p0x&Dʃ7|hw)p09o>CpbXݗ8{p!.H硄.Lm>:47?ӑD Ҿ"-/?7PqU|ddt{m(_-oȊ"p6cՒ+rWx@VH4b2wq5>ӏ'RuR_# Ĺ13TgSbB]E -4G_*iMcrws"(i"#p|4U$#Ya$hKJg2UvyF C҆XnY! MH6ߚRJe(oNzzzE s2$ܪL2PS);eR I,t2GۛO?]$!/BX(&?rH'J2ڵKcdnG}T,h^zQ:4WR%!Ĕ*B( bIg6'O|Y(jOY.tF?Jow7e:u$9p TJsxluE_ +*e|]!>gO{M$QAI7J; EdǍ8.PibyJPx1ƨ!ZBEU7;w¸$&feѢEZt|B v?6r. GF-ywmG_7 lQCnҤI4D⹸!SL1 xG s=bkh̜9SC ,>n)ΓO%wf)Z]́g{|fqA[N.*Jl&RmDDƻOp)ZAg]X!|UA^3uLT^h:)Ē.n8L6Tl_,[ Ǘ١GvEg^\ vLvɌp}R5ΕK8]~]їg?ׄ}?dm 2oQLvf;&MwL6`!>,aWsct-V4^+W/XH tϗU] %o޾fUBXF *\ؾ_~i?4]a*/?f{]("( y' bС ^bW^zԤ" w\L_.} 7`A N:Fe=n٧zʌ5J\jJmJ|#P͛_7(1 d 4A޸=;eǂu/#iKl("bΉvj+m+k%e"%^mˮ_+V,v2J .t~byeqwCuSx^gb\s"lQ.S| Xd㞸I/61[݅&:Fef­H`^ܺ$+ӑ?E m~zIHx͌lmE@E q`j +ˆ{MN-Qay(_d,w})@r!+ӱ56Ύ"}pnMRrذaR Ν+`KaEdq`S!TBp˕+gn6l`V^-nMJRj2җڪ$ uB`yV&MNk֬ rkSϕ8޾-YDSu"QT[AO|Zf ">b\&VLp7Z מ+) }9S]a|qA Tm$P "}5jՒ7|SN9%GWB!Nʕ+?i ,d&LW>[e],x~0+ ڶmkYdibTE@PWȕjP @ԣPCGƍ{O⥐!b~> ZJFR#Q͟?_6'u(y#7j,ycpx)΄7X 0ڵkK;("8‘ÇbwPSx_8bșBfZ feɰ]b:GZ8i׮5JF89o7|S80 O˲] fTw-M Ctwuיh_E@P#ޥf+ZR7Sԧ⯸{HIe8,?$ +V,%.ՓN]bPwu K[zRFgF8w^}iLk8!׹ g9 >JJKbH{\T: Iٟ1pi2r̉lj s޾Y;]QYx!p߯_rHԢE  g!UE@ pbC> tq<&6Ah&j \||(."gRK+ G( VgE@ >yQ#AG*"H?ݻwm"n+rSķo͛oͻ.K=$H,+V l2WJL'83Aذ DtFP2%',WV <8Ձ w'!aE c E )CO&r4#9}Q"sg͜9SzGj֭!qA>(˨6J|r"(ي0 r0`d w-?Qǽf͚nݰa6ƐC"+?M4f9\#,/H*KHr~IKrWӲ-\P_/7ސ tH޵kwgK>}pRg#BUܹ-7K)wEg=pxPr_]v]}]߸BX^~YŪiӦI԰dSxq!o4"L kː7VZ/| ѣ\jw!,A(}ܸqrA,]4h~ҤIRw+BXȠ6l(݌@UV5Ǐ>ٿf$ɓEW^y@ !xлt"zԭ[7y= n\tIv#0tPQn{8qQ''C) ~OJ3X8wfp} '|"mڴ͚533f)_srgG E@P\G`_n/P@%w3#Lco۶xU_m1tAr.I3`̘1bj'ƨԴn0ğƗ$ 2*0.:.5 vѵ z@o$C#nӊ"(@2!x֬YB:, wZ!%$JIkw7_4N| qHܛ6f'S1ԮpH C<_k.V[~:6}u6E H>!{ܕHbN;|hZ|pĂc<59݅zhscv Tf T*7{Bf;'abcp"DuQ \:g0@ŕ@`tUI~rm}Q=JPgE@$Ā/YD \I=EBdpo^&:( 8diЩ1+;RgUIPE@H0 V0ǟALz䈿џYP7WE@PE (MZ"!E !0•e Dw(@($m(C 1Mn}y;ɕ/u__,FESm(P磓(9;>3{5/PAS3Q׆"$s.|O?= gR=VtzSLV,.`U/gϞ-Bϝ;lٲ%yc*W6mEK)LoWPE@Pr#piI {*wIR۹sm*CPyȚnE&P Wh;t`.s=_~ԬYL>]vY,e&L4JkU^=曦H"e 2DS… W_dLݺum!k֬1dVBE@PE@p_5oL4tQ駟Dlp+=TXQJc桇2 X(o땾\⿰yv⊅da%# I/a #Dz-vm#3fqszXؙg)l%ސHٻĕ`q)X:dt,OEPE@PߺP N 9qblېX8܆(Y!&kB`wi}Q*UȺH}m޼9@aXJ.Ǜ7x#P8HU>} /u|…֩SǬ\2 E1AdqKBRq+#[zPt"s}\uȕCQo E@H2RR?,úD6h2bBc2Ww; "_˕+! [.xV$;"XBq%׹S1pJ q͑#N8hA8b]` "k \zffTU~ZAGx;FBtЩ(~C#:| `YV oE@7Nxr52 eRn!EEPE c(^N&?E@PE@H.%ԣQC $vĨŠ"kr@#PP1$#TPYRdF u _>5V>Q/{)pʽQ׆"$91W۠֨Wo9/"uS(PV=KSN9E[H3giѢEPUV6?EG9ou>=PPdD I|"UQq>y׼3=M I&ehcJ-[={$ FR\(ż6H; ("(@r -pBQ~ڵ7H4E ׇ jC[\s$}+ M6k]GmU*=\uURBM*APОz?T\:("(X5kff͚ p, v[Nq&Ir{n)E@ըQCR7,%JLP+/*)'JjZ;De+3bIkO2-ZԔ)S. O?$˨NѥKR-%ᜇ#~<j梫+Y;&s0ZMuś_^s`ήKC3 ;~O \Yj=LǎL+"@Q0UVr(Lߋ w]ݺuŋ*FV_7nĴ@Ú U[5`P:tP3rH8ydGm%B OĮbҮ^\Jizv:_ĕ~xdVT&+}] FCӢ %p'|&o޼S۷o7guV% 2_6#,2V~gӻwo!pX>CqqX5eAa!}1ƌ# {\rXxdwߍ*]JT?3q_ $\9sZxU\zgHu+!g7*)n:< 4@҈9kٲywiw.dJ* qqV˶8[Az! &F}D/~ׯ_oVXax _ SQE@PѣP7*n32Cq+W_^mۚ !%… %k=Dˮuzꁘ;R0駟iiJZʕ+>g̘akLv피EW+"(!i1cnҥ c+bƏ/ԩ#nԩSe2\&J!MX/֥']v57taF2 b}/^\,Yk֬4!~u"("@Jj?npm &.#ѢV9ܨsơe/g2G#.wJ(AJ&WT&V 5.VH815.9եA@-pQʍF '+\?LH;5b~pd8=E@P%f݉"DB ē("DҖ"("%p8 "("(#1pc-E 0@'ё$.R6iqE(QG Wsu|yOhar[-8,(n@}g}Ib_/慳 IKJ*EYϤƪzDikQa)!ՓT]-UTbWC{}ʲ)Ne'@P#?S֫W/c >K5Kr/U[,MO83l!/u>W_}5jY6yd!k]kLF /+V,}fų1ⵏXKւ X|x+}E7>rk,Z|x |x`}`Yo>a _hѢN#%o.\U8FCBW\9YSdIv6[+֬m۶4Dm0 ذad-:޽{uѣG ^c.NyلMBqgA3/.c)܏C@ \Xp﹢/T.u=}/Z>P-8 6贄uM41 .4wիuhB\`$mq5H܌3邏N2O?Ta %oaE"("D'kQQ=D2ȁ6pSb H'pec}ۆ}s=gW/F("(n#0=1$"2m#* bo ~W9X>HkCrg\~y/ː+uSvj!yB%.a:nu>.]\ 9]PW1Bu%jT2 1+F6SE ؈~GEP8?M FFRbӍ(A >>9"("(P]("(PO(; UEPE zET8 /o'kG{Os1)s-`j"k)ӣ)9~dxk_5Kߐ~E@P@RQn믿> k&'Bgۄ4?6_|}Zg9U\=cu"("1-^L0#WZQ+b`РAa w7뭷ӔzwҥKͤI̵^kϟh:AUj("(@C GPeSti'?Ν;%S9 BBoRlٲכ*UHf  L%+W6ݺu 4Z׷o_!v%PBfTRGl,f,GBx=tBPE@PC 8q3E1;v07+V4ÇrzjsE9sO?]$iӦJ-S1`vZf!XSNE@cƌ1:u2C Z ŲuQF]vRJfʕB~i闺4[M~Lɒ%M׮]͡C, R5%$lpBQ\{/륌:& . ĘJ.k?]B1U߇ h!| \=s }vAk.'9jzlpgIC[!`^0/ĔaMIʂqƙǛݻzpĞUPP7;wFZly}SJQPƍM.]E̫[4ժU37n 4mذ6{Qyn&!{X }Xz!=#,J1OWk>W, i.\љ}sj]s Ʈ\V* _~i@urjx._E@PE@pM4X/PEWƍUVUFfӦM3å 9 w}0SN9%]֭[@38#ۣ1 %iX!u<%/3Vv E@PE H \ZH(QBbԮ:C'0ZLk;:m۶8?\/.̻YӸh?|q/gBF.B3tPӡC@sܹs nd<^p: \ǤP8>*:zx;E@!)#>+.*KRef'   [63}coZx>+VXf6͖m@꽓7_:?rVu5N82}g?9ga`a C(y?Q?i<$ycg<[,>E@9".@i"3HEPE zETE@PE(iP%qC;sϿ"d9t+E@'ǥ:ƐoE@P*@H`d\ʘg j7"(FYG:*j|-B̌4ݾ}#Tׯoʕ+K/E )86spKBcҏv(p+hՂm NI^+9%+2ᅲ =Xz9s2da%٣>jj׮ml uE@PE@8aݺuX`޳K,RdΛ~3",) lbJ.->l֯_oH˟ݎd*U,XлK f"Tr馛Lͥ,LGY.?}ܹӐ|sHp$5_m䒄c@OTE@PE]%pAӧ.!h+VTX `SlܸQرc+b(iE;vH=R'O,Ц]v'0X }eAA*-\P,pRf<}`M뮻̕W^in6l ."s7=+WJ TɅ׮]kzi>ln: k.!V>#!~C)5XB]>\љĕjy`x*poZ6rr}}Ƈ7F ;~/i dL2BpTu =sV>}⋅͞=ۼ;&fܸqf{R믿6v$\o?G(p-yҫW/sω[BH-S[KKg {,܈?y) [hVZ7m4pݽ7/Bؖ-[{bϞ=ELr˟+b_*.[X 58`vI\쇈+ݻ UXWĩJWɤ%pXz!:lܸ_r%fƌjժ;h 5Fam WTX}!OK.5*Tx-ZTvei,ly Rq-[|wҌAdE:֭[N:I= + sĈf͚5fG>L&B/⼨yHgl\|C(h-xo|ǿK;Ň.a:п)5H(QBVy0 Yf~An:È~ў<ӦM!s2r nSN5臫cul%cDm{~!ԬYӻZE@PEaaAʆ/9s5jȩ:e`g9I&5 ӦM3իW̺ϰ$^ ,(G\p2,Đ6XӰaC!p?l? ~ֱ/[h!\6("(n". /|2ҨQ#q+DDmLVK/THbz-+W,my{bFZsnħ߆%X:~z)p|ǎ3-$D^c"B|pk \LNJx8 <|W_~YJXI,%o̓B$ZaEZ9آ!o+X?:yHQ=!v.*硭G(ɂ@;wnHR\SQE|_ܗ~dwE@P@#pN E@PE@P\E iGzBToE@PE@PC GZE+@`p1yȒGIiIjNRE (Klݺ՜uYHJ\lѵQ6Q_?dt SQд"$ 'Aڵk;v߿ٲeKX@Ψ@)SH.[[nR2wyg YMٳ ~a)b("8LN;MjM-N~3֭ *EY/jBl .߸qcRWTSJă>hq@Y.2G}Ν;K3gʾ!{:tT"("P3q7on&M$駟n?j^3~)Sٱc0`͆ իE]$(UJm6Czn˚eJ,lrd fvD)-t޾ÒHM` JKVW0|-~ꆮ:?3ó^%9PXB'$Q?7XX&L`k>c!|3xH]yb%XXL81dў>̚5Kܤ\r]d( FUjժ rܮ* Lo޼9 ó;.Y$h}0]>]Ox)`ΦڰdG6ӧO7C 1|A!|QcZ/y<+Qh˖-kgav}]#x]teRO+p1.u㹮I{o"Pgx&Q P9rO4nجZʜ|ɦFfӦM2R4ELesb{y#7 olG 8ťdԩnΝ2vڲN)"(. ~YfP/bk۶uNڵkgz)3j(q89o7|SmDҦMs~2*$ UE@PE}RRw?_,LĞl 1#ܒ{~sL|>FPE qTKE 8b2VcM}*(kv풫wNɒ% U )B~x\t!W(UJ+WJepYAN*;P˕`VAH:J?p( J2kmuWڌ1B BXἂ5\cׯo?|SfMoӴ_CK6Xz"ɓW_iurːXe8<لMX̞ZZ>>dy?\-f_xsbŊ NVb 1 yРAb%#FHze b 6#G nT(A, l`/b4iYyQ^("(( 9X(dŋŅڢE Jp`cu;edW^9 I# aժU:HFԩS%NWW_}%Q2oFPE@PPw>SHqkMZY {W$V2FMyg/ܼ;2hѡ BB7lA 1*~zSbtZ .v_:s)@E@PEYRR/=w2 * Y˟?={"iX%:sľYk9;]#1.sJ2yɝ:Q=lbRrso];!8>m(_% jTrc#olnXYxf ⡢?:`A6~YuSE >E #e"(@(+m("(/PӠJ("("==VRPNӥ75>{^E@H%pc-E 9l^hoz3{e+t6y _ŗʫR"(Ox[;"|aQgMM6IВWeժUUvJ^jVP$ bG֮]hl:Cckhj_tB+IyN… M 5G?Ξ=ۻ8f>6lKA{oy͂ -ZdnVzjY:IYtR3i$IH<:("(n#wiYf:̜9TT)0 {l" rIP0H"$WC@vaF%7u 4$ɝ+g3tP3rHY?Qo{bYDU$Vٸqc'|`]DA 8{8osEꂾŋcvAxH}IJŇ ΪcxYfRֱcG矛K.D ئ6w޲9sLƍMRLɒ%e9"9@[nvq/w.qmՓ/Pj (wGYWbM+/~{W9}zn}u/ǣX ajB̵2zQgH<=i.}E,]cK(D-T%o~20ؕ+WP]bE{D؄5Ϭ0b%IX VVqcXg de,CJci.])CO䑾BO?$лNvatI\.vkWt0~tEN]g/9Q#ns= 5Vd̘1aqsĝ׆0W d0}ꩧ D7c kLv"G|zѲ_|+dn*#k˖-iE@PE@pE8g4)>Bus5W_}O9se˖5*wUW뮻Μ|2 sAmrw3i=HWlV͛g?|Z(TE@PE@HRRG'!`Y8i` nH]/1Tœд(_U!{GAH:W+1piRn6w3&q%'^jr(C@E9_^?"1LN)@R!3C1p Jz}ْ"t;I]KJ pe@9hk([9hMEEc[ͪUի?`' )/ٲey=Tc6mZP'N4={<)@H@᯾L2x㍒ *h:("(N"΢NPk"e]&?)wPp$[BErQ:-ݰa$ JXN:$ͦM-&e_~E~T^ݴmVRrk׮}oi?~Km&ּVZnWPE@PE i\( dO>)+VRhJʕ+MݥtDBGygyF>|Xh綾^X^7o^b]-ٖ}aԩ)Jsꩧŋ+WtiS^=ӲeKqz#xX"ɝw2R^EPE@PG iHHjRhL2B8pXغt")Z,*V5k:,ZXF%nIW_ȑ#ͧ~*nbA#> } [1o IK!o޼YhM6AZn0a0=}%J+f27o6\r]$W\qk%ٻwwt_]WX]QI=LM8ٶm[3ޯ %մ_NJ?E Mx ѣLbmܸ9sxgaZ;sr-Ab1# {ҥKRf]UT1/W-ijѣf͚_6XpiYoݺufԩBm";kb;#6'86c1ǃZVWYw чRtGd/i5=YIJqYרK$ PcǎAs5C Ĉm c|"@b>Xp Vbو+\kg%FPL޽` D2$@dp لMs>;/;qC pV]+f/,_#!as<]k7~4HX͚533f7ڜTe5 nV\]v5˗73qbQ# $Fw KwqX o/!iՃo?X!cG?sie;p[E@PE]\xᅒrQF,bõھ}{1GJRr`4uYFaO1cƈ}c*XH{#Ec%X`$6mژ"("8@JLG Zq}B JKpZn?ViE9+ (VXVHXbqrpɻB=wzh@R $ە!`drAdqT@L1)@7'fǡ#QP$D@1dR~ȑfA3˗/OJ.!%BBGz Ĭl߾t=(%) Gv߼yu] 4 E@PE@pe+Wtvˇr[߲e0j"Y W2]0a+Dz?l}Q/Lvmܸ{dN:IئMʼSE@PwPso ɓѣMŊ2w盇zȼb ݻ۷obPI+Td ύEqI\Lo;wk݃>&W_:bkѢXkڵMeX +5k],fס3/^<ep Wٗ,YRe\k!.(PT\9Xnv%Tڴi]3JҺukqvQH tvW("(#ua}:F!lU7kb>m]18 wqi \yZ<ɝ9b)&%ͺ蛻ɝ1p'x% ѝXԅjo#oƎ] Hz;#'_J)߽yB<#!Ei=(Pjdlt"$]@_uEcWQB@ \rO=E@PE@('YQPE@P KG8@Ǚ/_8 bsg,ݻMѢE Km߬ #Mٺu)SL/֓_5WMKGڪ("(;X+yIwR'tÆ f͚5R;ݜ9s\wurF{m6mj(oO +\fU{M7_]dWg6Ç]V^m."s7J)-of*V(QW\i k׮5/PYny'ڵK)uϞ=2 I^]_Ky% q\)oWY:_o$pv(;RjܸqR{fԩK/5udݻ,XL2EkY8Wa̘1c9rd3C?>+5H".]^2c1=zI& .Z@<[j%vAZ̙3exfɒ%vU}YW\,HbE\QUt *fHD"c>]<8J\8S# ܲeyCڬY3Ӯ];ӵkꈥ(kS~}s盚5kݒ65 Zg]A Cf[1(;47|tvI_gUE M\?@%"2X 2c?%].V~ q±@VȑG]UE@PE@Y(Y[VPE@Pu&ICP\F9$gtuiw 謢(i#.m|t"|y<ob=CۑrtIU :?.r/:BM 8el@@ \6T`6:dl2)yS"0@ȑ&^l I|DžA!h^WF@>7o\$j_88•]Eˬe5ڟs~py{}{ggSFjlE,-TEK02Ѧ6l!Ev" o?{̽wι}9.s|}CaO...k) !PinݪҥKx5߾}>|XCZj8- 4П^z C(uV0$ELСCͯ\r^˶[gڵ9J93x 1,D!#Gfrb2΍H k)}%Ҕ#A &2| L̰jqCUxXgpݼmeСzo׮]UVy^eoŊpc8D޳>IHHC \Z B arA +mڴI^-`qgae˖+um? 5.mڴm6iڴuլY=ԁM^HHI P{bc2o~   {1 ؊-|l547̺BDPOr/g3'4x4Fj@8(\? b0˝"Ʉ'@lH +@+/g.%[OQxS 8[>PѣG5os ~XI&#-oطYf^& GSop޲eFV^ݫ/!;rF.%mӐ8&WRN_}J6ެK>׿;w^᱗ڵkӸi-l^A2 &SzadٲgݻfmyMԣGټy`ͩ  GH5|T-B=b;e˪5ٳzj`?fILLt:},\P#W\\ԭ[WV\)BA䥗̫q!  - <iӦ cbb4M̙# ,DHDžQM|XEz, u^pAߖ)SF' wSb:rG,f? Aꤍ[1_l1cHΈy$`+r~o{nN EmkP޽[n1::Z~۷kRk2zI]l =7رiMb:uJ-q#FzkV ,o(RȻ+VSҥK=F~Y'm'gRXQ $L|~qT W—u CPwp~%?ETX;wM6ܹsǎ˶0UoȑҧOa_ |Zp\rҸqc q0 5>o޼O_Lj5Sslr@޼ VAXH (H4+Wn3gΔJvtItƌ"~/ :+u۶m$xjJ<\Fm: = 0 5ۉt]ڴi_UJM,}9sF-~cǎoRÆ %>>^g[sA2#  3Z 4z)o ~2*kժ%:uX)VXFMɒ%K [O?T:t [ԩSGׯa@$@$@$`h5Z#D")jb"͟?zgZG8Lݖ}K? d>W Z CǛPui$b}$h0툟xHl%0@ex銸A"";b{(=ppƌF0-> '} %!XwJ ^{N)="R 61f|;Bgp,9   0!@&$   gə# *TH3i8#{DD\rYnjP|R@cƛ[\1;/"D/j\W.`؜;ظHr@c Wq&'>/LsfQ_Yrԩ`u~ /.zŋ].ON'pbad8i*U*ߤl5țs@H Y4hNOռyscкTp 8P􊀇#GHDDq@Aۺu :) uk֬Qo>uX4¢W`A],Qv\qyܹlڴIΝرcj3zh0`¸eZ:8N)T Ӝjb1\PN,$@ ՘-R%ďg0 6رCVZ%X^D^?.E!A|~aÆR^= JڵkG^JT~srJO?t(PfzsqW8+,xڵS:c W4i\0N@`x-}f8D5;e 䒼r!;@ȝ;{{`BMo~M6͛7kv뭷9ap^ذa6 WժU_:XְZ~}r%Cz1cƸ-qMpO'xT]vj6mT|`9w|= 3 ݻ |l hB^{5yS(yIrr7N*ԪUK:u>u^ 6t˔y0GGG B$@$@$| ˞ zbhF] ,IIIQhz~cUI?ߺiŷC0,> 9Db=|ΰ%Կv#8I  D 뮿B gACg>!c|r  )PY) mj.uKO@0 n}89 ؜@[l5i?GCaFK2mX᝴M u ڕ7|uӋ޷۸Y@x04Є~XX yc!y*в@Xl='.'`O    8PdY"48I\`j>;`j' _$DS 2Ƽ{N~v͍ԝ0ݻwVQ!I9I} Pph$@$@$@$`E ,68ϑ@f `l 2HLLMF9OK.(`&@lHHHIKIHHH (M @6 8glN ؇o&-_~EW@)Sԭ[Wz}C# 'NŋeΝҴiSyGܟ٩SJ aÆ S iM`ӦMf8+3[x2pׯC;_tI799YLa;`M VgHŊZjtRyҤI*ƎYf8"L.X-|8p@z-뮻T\μFpP>>>^-ݻw\rRzuf;wQ{Mo/_.{I TB k|N)))ray饗zĉe2zkl@ Peqz"EC|M7$Ⱦpj9,M/_><9s 4H\֭p7fD ""B,#kċ/(#FYfet;0o(P(u%$$Ҵl1U ݺuqɌ3fGcȐ!7o^[թ@QFS`qwQ}Q >Kߺu3rQ.bK,O$HղM6ڮu7 '@ (]4i-N cuD)_.FEEiu$OkdɒqX|y˦F5UfM9}@߂ j*iٲcO?~wwu 2Dx 矫?k׮*'rݻWf̘!5=՗vڲb MQbD %u_"|O$7>ӧO'jXhϟ?UQ?ƍV~ |ۼ2ŋ[xw-[E7ߔ { ̴A-[L`zĈ{YC$(s$X> X-!? H˲hO "@^ϛ% bEyT@4~yhѢRzuZ-3ݻCVWe5Jܹsݷ`9V;v/l}k0 XZΞ=`>/_v|]Y0 zhg=> 7{7ΞH @/1!䮵' [l۶-Uؖ3BJJ}簴1|pٳgkJ'Mx yX!԰ jX!_}yI>OE ,}hͰ ajդDH P'@pޟ5k.Kf?֭[k / \llԩSG-cDo/ wV0Eɓ'U B5h@mB [`L!@=yR02,z%˗/WA[Iœ񋉅HJXt4,g.c9elЫ .W,~ȑ[n]?#`e 2yNb\[;wNOߗTay!\x.#Re3̙3u 2\u$'' _7ǝpkH~o.=Eq.C8H!sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i@6G:@IDATxEO' 4 BIMN@0# A(HQ@A 邀A@H"HoIhIH{t=y|_yrw;3w3QrbG*" " " " HREw"WE@D@D@;R]+" " " RTD@D@D@)@ȕa)@" " " ~Wʰ ~G@ P+reXD@D@D@ @# 2," " " Hu@D@D@D\hnx2;;;l@GG'R,TOa;:CJ0:ҟ Hϥ@ xk 5iˎjKloyAOjX|Hڅv)ICڜS~h_za6(נ,a4Q;MJSyD@ P&LHD@D@DHjT^ږ3_Rs;cn2RD@D )@yhZpyHdrg'N,_o?`9rvy畯 _Pz;0[{m6~x6lm&χR?x u]m饗ѣGۨQl}{FגW&i^{mbPо/KBE-sj̙SOUM /`~ay"Lm}jW ,*l=coPzƍ畔.{),@¥PPPP}.p.*|-^1:s߹fUWXj-?-۶)G=?Xl`W8ő:uj={_|} Y6|_պ+y(֟|Iⵟgc/}KVZɎ?xj!}@SH2J4mu]=tuj槬z򃩰W\ў}Y _l{W;lҤ{&OZ[la?яl/G{?冂u7sŽPЖZj);C kA许~ު.XC袋i}ne$6)@MPJBkXdEl5ְkG~{K۟'\p-XpP,Ɏ;h_תz+P9[eUʧz!{ス5keB[ w];s_r9܃>hXtO?]>nfLg6o}[v7i/XP:f첋=#>[ӧOX|6r-[;`wqG9guVy M7~_ڏc,_GY@3FX*JSn?sfVY1ŅAQf|M~:$La+b}Q`XdVo.0=d0aB;JaBP~26b鷿cYCa|oae.|s_gzRWզλTr, ` ӯ}H'$'O\>׿6:HPN EeW&*( /p堃J{)gj*(?E p!VQXEa W6_)C9'Xpqy[b„:.[A(ZO{b"ɔnnf͚e~?袋g"(8N"wApƏ Uu(XC0 ,N+d(`Jt#>Sh6RD#4 IL E?V%M_a h<(FLI4Ka˗ѡ|3|.| ,4qy*:Esw\DµB]* b18Q)/Cg}wD[ߚ1Ռ҇|%c.F@ PrcT̔#(83R$e5aE.fauY4FzPw5F~{sX9HPf鷤}sSm\wweIQXڍO?4a/ `l`bZ?>"YŔDZV+10U_i o&sO~7t:NI`#? ¢irv{b03NV6h_+Œ/Ǡ,1HZIp|RmP&C ,]((vLua4hP+*&'hUh@'t}+_i@l;T?OVZNA B1c>‡E(کh0pje t~b " !N7_tׄ,Jb|*0kO>;γA0 ,{ge"VQ먜|џ.MC@;A7MQ(!"P>6 Ng`ʼn;#W^YyN?:ŅGy_^M>HC^? :W;Ag{1#>S^x gfG׉@_X_/05-VQ~BWMV%)? SGyhx}[a dð oS@>KW@' +hekSEE<~ѣ i3W./ |j+uϴoT4xEs-bGFSRi+"jfwu8oxuDX*D(T#i *mE@ P[2#" " "P5" " " mE@ P[2#" " ",t@[Vũ̈d! ( %]#" " "VUq*3" " " YHBI׈)@mUʌ@RP5" " " mE@ P[2#" " ",t@[Vũ̈d! ( %]#" " "VUq*3" " " YHBI׈)@mUʌ@RP5" " " mE@ P[2#" " ",t@[Vũ̈d! ( %]#" " "VUq*3" " " Y4m4{7S׈@@K+@d! P '" " " mO@ P2(" " "' (NDE@D@D@ڞ/bePD@D@D N@ P~=)@m_ʠ@8h{RھA8)@q"-" " ">ʠ@(J.e|6)@ٸ*9HfM{fbͻwu SR4]D@D@Di|/m+Lψ5A7y]|hH}% E N(N@ Pqv )" " "Тh)" " "  H*N!E@D@D@Z-8%[D@D@D8)@)@Ԣd' 8;hQMuww(J%[D@D@DU4Glƍ.?~6k֬Vtx^{e7xr! 7`G}M>ݎ=©>WNjo?gkړO>iwVEJ>={}ن(*-}&(}h>7|{ J_nX sGCD@D@D ibO͋G7k\yA+@Ih]yQ}Y瞓t! =mjĔf׾W4t) 'WM8"LM2I4M5凕`s~_6x@McBaN;*a@S(@~W~.mϕb}vGꫯnK/GrwaMs " " " s^~N;Ug-ÇW(Jϝo?+JU-ZFj q-RzhZRh0" *^% iF -RzhZRh0" *^% iF -RzhZ}.%@ (s:::z\k&eS\uoX3]CmШ +C!_4s=ݪǡV!JIiJlڃkgIoң}=sу78%%*" " " N@ P'" " "pRT4;)@^BJ@ Hj8RE(" " "5{ )}" " "  ' H@%4#U" " " N@ P'" " "pRT4;)@^BJ@ Hj8RE(" " "5{ )}" " "  ' H@%4#U" " " N@ P'" " "pRT4;)@^BJ@ Hj8RE(" " "5{ )}" " "  ' H@%4#U" " " N@ P'" " "pRT4;)@^BJ@ Hj8RE(" " "=JGO]KٲiOt1W/y!l-j^ zԓ~@S}keMդTy|*@쉀TTDGD@D@D@ڜ@S*@|IcWD@D@D@@)@\p5/" " " mN*ٳgۋ/h]]] uklNeP7LE " " "P@.  '`#G%\8 {m׷~Mj:uNvb-VrR;8;Sl=6x:c(HEˮZw#IEҡ0" " " @fT*OS >c7k֬޾hC-@Lq}ߴ?ܰ;~os_&:K.|C=.o}f P*ud7ΰ݀AfYM yo4dV':('9lʯs3߼Ѧ=cM C&c,w]Լ.(ȥp JG}~WA+ YzwN:8$$=x`>|M2%9&!R#<;0{mWy睷G6j+`x'"Y"{ןg/.h43\ K%" " " "r)@!KWZi%{)}@MN>S;C'N^ۆ _o6}f@@.c3<ӾٕW^i=>6`1c@<?{%k-vڤI)}@Slzk0vu׊,z}WqND@D@D@DdVƌc]]]v7V᭷B -TqND@D@D@DdVߟO<Ѯ:c%̙3o:tm͖?GD@D@D@*d"䩧ꕝmG/"vWѣ+n" " " "lr)@7]{U?/ؒK.P#" "P@|y]_4] 8 n˔ /`;OgaP㒦D@D@Dfwno\W3}λYf R9g}젃*+<4yd⭷jdט{=w$0kc6 kWf"K[AO~b'|r9z=vw__>/" " " "Ь2+@=#~%X<3Ǐu]מ|)#YU^W_}uE&PEH"" " " N K޷~{;/@e?⥨niWˬuww ]vY<~)" " " MK i8B?X|mWh\*a" " " "!(O-yG]D@D@D@@.+l~ ChMQ%ND@D@D@\ ? 2um_;/B{B%]Yn^~: " " " F DGi묳_lQzD@D@D@D E]d;찃mfƔDD@D@D@Z@!'s=[l1c=g'Y UPzE@D@D@B h~؄ ^|E*U \4 ɓ'B -dl{M)%DD@D@D@:lzgw}3<ʐDD@D@D@@. ׿,2vW&Ah6fK#" "мs{Nz[]ktVz^(E@D %=j&ck<]q]{MV YԆYϕ:H"}A@ P_P=E@D flwgͻtt Oԝ)|<$Qhro&voAQE@j6j^8pŮL ?(~HvwwGarr)6vrd(As=;駟G}|,NM г>k}WZ"Zk-oyG.K=w5\nuRD@D@D@HUxyiTj+;ˇp3fcyq;찃\kxz<׵" " " @*?m|YvLs"%X+&Ol+je]{.|5n!]֒&wlVw: g߷iJ;zprJ#ܿ^foLhH1hF_~{{OBlA6@w>iz僤 =M=-6fnt,BaPKƎl+.:َm jйlRe'ޱOg!ޠJ񧵒`we8( e>vH9O2ԕ+p1Z{gL{̥=3OE~ e8f`[i|2gptru{g:iB3ɍ?]NP-; @^{vÿb#lޡBgƦ_s8kIW`0+jU ?Ҥ([o٨QlF#\s~36lX~_c첞}4cmsk}k~캉]Ù 8o߿ {_> 6_By+?.&mk%(pmOhoh?PYxy#վ헮8›e*mX.wՊVYd{z9ٻ+0C 41})qSEpF6)q9첿?\GL-S\yvOW\?p]a4w>z='8`8g*íVkZEvg Sq+s`׳"&(* IJR\ϝ9Wũo~.+a+NFtZ^_48 O\ơ=w^~*pZ9eVQ7|Go : T0'7xï:餓lcLgmfڹ_q%)" s?Ӓ|X"t#^%U^xOV\qE袋Fn= 6lW~a:sljDCD@r``ID@ژ@u٥9J >sPݟ]]]visE]8T#%Qa_-SLO*>8T Pd0\pGV 2$ԧ@?%ّɇgܼȔm9L UB?~|$AB"KJm'eFD*@m|v_ĉ h /l>]qvW_l&;[om3OCRw&%X?pr҇~VYe;m̘16ydmƌo E@D@D@D T \~?=vw",b￿-ۋ/\E@D@D@D) NxVeY"7l30aBZ0hsY3K/85@D@@n?oXu7[np 7c&;ur" ":2)@A+S*碋.ʏ[RThڴi޷禛nx+ &~" MJ`\]kn԰A5" "ЎR)SW_ml6/Deڋ$olJ:c" s{m΢+F U4hʞ믿n #@Ct>GԺTD@@zi@*rf# JDuS`~w@D>9n8p`:$" "F@4::'}@3sW>(&RD lTE@D@D@B8)@-^J@~R3S'  PO@ P~f !" " "x*" " "  h#BjVK._uYdXkt@ HjģOF@ P52k-XM5!$ )5-^{_TtJY.5" " "T3 ~y*" " "`& Pւ ؤ毙GU] " " H)O>Ć "]e @#tS`\p5CO{}u4+R{ュ$f/J:uW|.R[fe_n E31v`[b55ך" " ",Bzk^x;#O3$" " " C)L=Ӷ6N.D4hĈwBEYo|+Kx饗ED@D@D@ omf*mذa6t,_ `!nɷP5" " " Qst l 7qƕ~EӒ^h׿uꚣ:\4"&0G#8}25\]_D@D@D@D`N ɓTtJ`NUMN$ h֭D@D@D@@)@x}GAGhKs- &dwn3gw'yh{/9B@ P/`]^%tS`͋J)hRڥ$eF E@D@D@څv)ICD@D@D 3)@QBv! ]JRL@ PfTPD@D@D]HjT>D@D@D@2.hRڥ$eF E@D@D@څv)ICD@D@D 3)@QBv! ]JRL@ PfTPD@D@D]HjT>D@D@D@2.hRڥ$eF E@D@D@څv)ICD@D@D 3)@QBv! ]JRL@ PfTPD@D@D]HjT>D@D@D@2.hRڥ$eF E@D@D@څ@Wd$kui ivG>]#hMm{{usب ," " "jJ;J& (72huRZ~F" " " N@ P/" " "@D@D@D HjTE@D@D@r:)@^J@nRr#SV' KPMbه~hÇOٳ (,n+Ju'O> a Oa" O~{E@20A!cѶҾ.CϚ5p[Lzˠs?|wlРAd;QZZwc]]]o'f.6pC;<Nw} kGQNsS" w?Arwi+ J+RnW2dH? />B S wsiV(~})9LnK \:)" " " Mu[n^^qSa޳d.{L)|A ~ T$8fH3UTYg[~SwӧO/2\T]tQ m>:-ѣGE˴ePo1|FgϕW^,LCp0j(_"gy|x/_:Po±|)S nK/9kn2wy ?nܸB%K,Q(<&NXW 4lQqd`*E9\/}~@`@?ȣ(" " " =HC?D@D@D@)@sYs}>0'\o_-߭|3zC^;Kz_ycޖ_~jeY9$IቛzKƬ`ζ,y.*/V24-iD˶4iӪ>cc[Ne$,Aa{pg2[?m+ 8>1kwrKƍ=S\I{1g N:$߈o,76+{װf 8A30$9%~%Y~_346 |=6cƌb/}K6qK鍽8>`X>Q '`>gFmT%6hvm}Pgž?nJN aO~8N_תvb4\AQa[i_)7D'v9昊{DW4.+l?aNWxvNnKy O[<y뭷B|iSMa]=6=', ~{߳_"w#FH7{6D%V[-/~_OS==92E%sD<Ӗ>rrۑC?{9W:0ud-0X!'{ѶG?ZiC|s/σ:quE&P!LhFPO'|oU`رcCތM\rIc%&Rhx'`86i"n? ^c5el&~tW^yЬW\*CXBB@46hDnni ]V ! hQ-R3c@IDATD.IQenc*2󢡮)V}?ig}v ) '6t{yE;ʍMQ jH Ξow7J8?QRoxɺM%}_x~?cU1҉:馛lsN.ē76Cq`=:1% +脢B;SmdM:_4AIy#"u VQA9Ӽn"Bx1|vr? ST9d@:p:dp]Uæ>QȢP$6իۖ7iO)+(+(4ۏ?pJ<З 8y&&|&)Hc!6,dD6W4ALX]&Eʰ0ϢQ4λvM-GRTr Eu=7KnoXrUv%gmok|\q}{ KnipCKnh5%܃ᅮ/7-Qv7.t{yg!񛡹F{5%hT풚ݨkxKɍBKa/YQa319WlkyYJnjZr>3ѳ!MIWa[oow65t8 Or PY=QZ 6bPrCu|acQ=A F|9927.j\ 7TM\gW rsEX<|7uu%gq JN)9KC &wy^)klI)3%g5Nitp:,';E/csN.m26sʶ:Ј_ϟ۵F_7Wup)iRr?8fpC7-qPnPZrVy nMEG/k)'چ$qp7Maa4=Eh[xLMm 7ILӨK4Vw߹nt+^\կ~#*1M-Aq@9**IƅA,ac7O򨸑/KИ:+DB:skjp=%7¬WͪiT<(?aSb ᦅ3.׳La*f370}+DAk i?xJ&OIZ1kϽV\qŚrl -xWLQ0VM`鲢tIj7 ()h^1%&ƣIi&+􇺖g8O0MZ3m >.LG&Agz);1yʄg0eY#:a5^҈#3BT7:zo[㇒&ΊA:\?G8h'7>Ua<~,,6 tbAA}׈NF<s eeFGȳAyky;^4w&iς6Bh_j4 ?-' i`z@m)Pk҆5.ͼ?!U^|(?-j~)Y2˥ZNdz_4kaaH#EhIfv9 .=CXrf6 :o͵&1ߺ+C%B1g>R'YݹGC>\Ƶ.1gJ^f S.HkTKI/7/t#&{pzƿ?>ǟ'on&K 1jB/] >ʱ^ 7B|ͳ&Nu4a^ 5x)Qe&/9G/t~O>zIS;ć ԵPX?,✌igS^"I4D`Z)z6qҖ&L[v(hS@Gډ˭L_iia5̖2MKXrhrIq9a/#InSB?"#Șj| SI䬮:2 k_q,󮸹; 8#:P-me,I(C(ʶR3хYj9^ y.鳭rbO|Mi@ &X0݃M{p Uj\x>V3'rOGA51S3>0%A~q0tfjE0fny>f?؟)<~_ LLi0VI9n@X"?m1}<LG6RߣRF yd,a+blgH]Gݟ)K7Zp sͥb7͍r蹤a#LN,+*,m| {?9˦n&E2]cVfO#cڊi !S/i++f]7l)LUTnVw_,juH垵i[ 2Na3oVq7Qc>'`4$~2nٻ!zPs(W8СHŅ0ltT"͜~;gr%9lW3mt(?B'÷ -((ƥ4!{p9Ne:tftW^ays,9ޒS>^Ꮹ4a%?|s~{C^Y~6N1eGx4Wɭz1]v}tS2ʾOϸ^cLL?:%|ANtb*Yq}FfV80PK7qQqΩǴT8 >%b(;E7( V ::%O4"axaIfuO:/~[Ap?,.q?t |g߿oFm)<4I9yp埩yg 9OHc_*HҁӒaFc}La} 2P>ELFr+|V7ĿZNExhٌ%ح?$(Fpg#pja;KIY' Nԏ\@z Yč}'FY.qM_*NoP_褊n( s=aLFNE?B/߃ɀUoRM,E("?(zᕻT {6KZi^LyFG9Vgqid%I%_e\5wNa~v7JC?asbX~weA0D9x=&BLܘQǬS ?ި0c'K{$aY& ̏i)$,/"d Aؚ5TgO~j{,E8/gۑZкcTa c./)c`~,GByQ`֎o/izO ty5˱1_#ü%4x~'ʙJBB3uť)LVDPˋyYS-R&2 euZv=# & <&퓸F7S*x;0:P?wG&1swhxv,|69N3 $>ǥPS`U>yuI;_zΗrnFwd+#XCQ:ve|`e*jS`VHSFSBX0[ճ*QT#6,L$ME%sNd# qkAﴝp_(.VEæ}O kqT,Owh=H#\Gc=’ySͽ%i4LGeXdjY,X}0WGmXߛNg` J2*0km;A8Vqo,zXFX@JgtqAhXQ'߄}ej Z,/1X)|"NX}yXy˯W0X轳|gж´[c~A` C60JV4,%\ ^{UrNPLP07BT :`t?}1Lav~:iz/_~aۈ%tm_#g 3/2^8MI*CQŀ7Y (o7y:0esL%Ita )j0 J00͚$_ g:j,>>oL'28AxX:oT4)Krg6Igha͞/(E<¢Pß) UզS=P` _Ea&h\|Ww[T>棚ස;CޭhK&ܜy晾ťQ<~aq+~Mo]2 ?u ҷ ")Oac\óWoo|okD ?j jܓ`ڙ+N̈>I'8݊#ICLJ%N qxpY2zpFST*@t$]PJÕ(00gDy2کSFC'|qhA|]iҤI" IGOF5gUj }DžSO^(~ڪˈ67/0V2 {*hF}wmp2a 9Y-{W' H(ĉ9;muh-#Z2<4?Q4PmP1G3XQɪ1beH^X &/i ӄiiəb}f SUt~oI^\Bdyu,&t(t䤝iɡt1F\R3M7P6uEQw1BW_],SewPwz߁oumbxS߂XV)tOq#}.{NURYI!;"(gIwAUgE{<6\8K\v,}`?<>}gHyg] q;ˮ߃)=99E׿qsvwp3~c[Aذ4*ΗЗ{Xw7Hծ-rjh}("B2 iZY7_-qCJ73V4m+E|0]Q54M#+at+PO%y0_2vHѤŭq9qhdzFaoŲSlTP5_)S_ V%FAB{%y[c}IS{ ` v#FOQ2+Epaw1:))Ӟ(./ʐ?|r?F 1EP8߱R~ Vb~X bIǶY<:ihG,($4Yx&*29VOHX"ev( ˤ8waƩ6~Ғ$>G{۪ZS`#,дZӠI Ǵ$+(<뀋]nTxl8HPvJ87Ӻq)Ӧi?as;ixQֳ(N0iqu;1g!n be,SIt(@`pg GNF]N)@AL6poA"e׺*@Tz}xPa-< "Ej$j ΄Çph= aiOKEc1R4*8Im$i0zI'i>"~ LQ3 Y6N~I GS2&e+Y,8+H,L䙕<,/eIk#PGE#0gCh& YANR<ՎQOmIEݦeXN>dcEf"^xIw:6xFϡVϱ(DyG[dQGUc- V iYy e2ˤOH"eXfƀm y:MJWzPdqFg7Mx5{"Uժ!vue!jVpmq:@1"  G[`y5:0g?Յ)FtmS4aBO}ib 0Sq>ލF ,P?$KT P:Y݊RʁR\>Eʍ*RM ' H% Xb KP]c-Y '\y{DDAW8OcOARWShټ+ M:A`6C#OBx²,3 }!30bD 21gYcE XҗUtƣlEj-g ~3Zpt a/uKbT* -9pNO$2Xjt8bHy30B@K=3 qL8')f ` 4VVZS8rxćg(z}_"o<=|y')3(KzJL&G5VC<64+'aa<|zڧsyÐeѩ@3¢Uq*RVx.<|ąkX/aI`Q6:{/geD-eg[+@!y|B'H:M"Dū{'"1{cUL!#\3DtŅ2 cagp| ױtt/8:q`%6j8t\)䝺 Uht8NŗΔ<xR%4Ҭ` u%<͑udPZش(Իڵttq!(QAgu|G)M8a9 .ou?:s,i %!ά 򢖸x8,]PO$m"EVϬIV8VRYMgt`cũ6`XR䃩8f`GHFvbkd0E0x:l S܈H`|o #0r*@W L5i0xrF(qZx`iؓv2Y P^ +#GL0fK##,/d9++:%|%<SDp,#sJd;8TS(U?(Sx2NJ5Ztη |O"Qԗ.z4oaJܪM#]aA -㣕d i@Q0&PHӤː8Fn Q2s蒜 6 MA(iq9FUe:-'H$&|#`H"*ă*܉xQ SSY6P P,yXii ^F0iBGƴ]-4-p.kXp-J _+V+.$mр_eVÉ%$iE,Fy2t2I ~<]h)@>>FL-g2M{T Dldq籈/]>GacLk,WiBDk]ǠŚ:&}]䣞} b+Ӏ9ə%Rp)!6ێQrj܈\gonǿҀ{.Qi8k[EU޲M$9sQ9Ţagrtʏ8zw ^Yvl]ſ88??,sk˯MU=er=.p?\Cb0gptsSI_?u0Y*qMyN?UMQW}uhUù̙{wVG_׈8 ϹG?ퟑ2s! qb0SY%ͽ͜o6U"oo<Ǽ-.')z '5Y<}7 I\x_[6gy3ݜWR:GܠŇq:Mh2g_\묦|YY9I|itSWp+MJ6}}S{܋N21Np N5 m9yK.Cۇ'  \1̷ḥb94aV!``@+#GE!Xä"9\@*qoO5lBmsV/h^'7iOwao |Zf33o8iC7?j \{jˎC\4Y 1|V[:~3BOH[L<~~.t"gPDq^dcaiDÄ+gb*U+9w E9Ӿbڌ?:`:X"E=IvmE20fEV-~:^ +4y£i&-ɘ{D){#,QJ݋}9 >*kij"6`O.gD ,C +M@͞2Y,}= iI;Ai((P~+ZT4KkIZ7zF`-g?/h;qaԧ49bꉸ -%*y "nXHÿsSXeV1(qw3(l|%.ڢ(+ Pį7#xi {pº/P٨L4C7)'݃=`jY.־rE JF$J 'ix)BK#DFHB7*ZR*u%D$MggH9{^k9w|gQ` goH1XVbn +QwkZE&.Gڎ٪@%vW1 Ę k_oE2I m1סenc!h  kOX(֒G?biqz\ZqV0J+5cF5炫_:>[7;\{& >WBD:'749 e@{k>r-ڥPuMcb2S=ށwHZ H<{EYkQVfmfeA"$e6)~ߒ)oR)_bI6BuVʅY~j$~2ziY=$K~[ :nbɅrsGr["2`ny?؞LS@} CԽoZ#h&[)Jk~gJ Ka`+ s͗&h`=\=zgʤMCxy7%7\Uaf1փ5ւS߿\@LDt}5R}_J/eK/eүX:[(6Dpij}iB>sA_4Pl5M_u: fM01cDV0kX'[JmNX8eA+ߵ EqQ:{RCFvqU>䠈xJe,5( [WFYDTmJ[YLi4wOؔgBozˌ2d~#u L2gOrbtQ9dL{gAF^'YĠjm R9A bm)ɪ6g0^ ]~  PmZS~|fW]X">dm"CaŠ}<lX?ai3z&e5}4i_oN2ii&ζ6Ub L$p礪~:햕k ]Ai}<,dF8[WVU{*Y\+c@9t)Cr#-+13!$M'p_PprRHv o'8O`01#wq-(sFE7}.S$zk#ELyK08X8&kMfEwct3_&K˚蓶L}57 nQ4 sEt N Mu2b貾ɫVJgxu9DgU(Fs pAK rK,AS>LBaM΄_"ޏ^P)l 1D [}S2[hzlc6(E}]}גJTƄ;Wm;vLdWy. FM:y4U.O!Ȳrc"̹X$)_|{k/U:b5mؾ _4;y}2݉XeiP  _+{2Ж -  x NL-nO|q eJFbQ\Zj~,w{%ӷiB۾+kj(O}}H,sEC|VlWQE wZ,Hō=D)] k3%S[dح4˂Smm?{֘ ˑ5IJl /,(7c7׏Χxx[;ߑcr.U8.R+@3guZqn;oLwNL.rMqO5ʱku$W̙MS g^+_بKVںlk5>>7P J +SXrQajבU w (%0+c{oek && N؏Je+yk D7poQ%u mWY,[awYQ>ƹ@8ES|R Q{c!eآbBs#g0ye9$,#ʮgLP', gS!Yӏk) 93,|ER OߵGK ذc46j!_3 f /b%+€nH)@Ln3=G}aݣmi+ZT)p.вWP" LBOrV ?{&SEM6-Mh7pU[qo5z'}9ac#Lm1ޗ o|c*mdnXC|ȝAea$ kqOΑ)`('S i +R+@2da(lGʽQRV|ֹ.Xy_GY`؜w)}Q`}p+ڢC>(D,%-7 I^.`_"DO$l$I?b@;=рX-"b ^ ow:xgOPP$ PfA @[K\{+# Uxd-nu.unx;'>)4!>52ʇ@[k3,B]o1fwQKcb@%(77xbƑ2WDc!ETעzUgQQ\@ J(\3XyHɮI{c Qڃ}+hԢ Ť>Jи{n7x/k87@4K)9/A%E.̡v繀ZB騿g]Ⱥo..@8y>ђ14{|s]3[: Ys FBooD-9&x+m|:M33ɶfG.ZaIX55X<>. c6C.+E(mfful6Ax^!KO[-#yRso.bgٴqVN8QX 奈pV,nRú?ūϙy~8KiXf)꾜?=^L#B#:21afnCo禃{0_R`3L6EDt!6#q Pk6f*/ڢi +ceX.[Эn=j $~[a L{XLS*I=4x*M_)Fٹs<;&>S~8ryyEo9Ot^X%.Y?r_}:OD OR5'* %XL(NN=H3#l(pGϽq׮ݴ &"ie~cH&^DgfGwf7׫/ B%s/>@.qNc%gf!q^ PY32nXy?'ğnL׉!$r{Ge#L8{Q#g_!IGinB[6w=fM?hE D݀i,)2WUXp #.L}n[s㍑J[.pW6\rs$9;F-+~o$4.;T㖛=RHU,9=U'`!Z797yHs[PmR #/+htChip9nV Ъ=cPql*+yoՂz[,8[GIYƶCF[>gCWqi<>tz,&|rf "]|.V)n1V6V]D>#%X VSiϯُB2ACˋ ߼5fl~v ͺ 6[Qplu)^!ǀ Sgown,}&e[o[s9">/}ou[ЭnL~u¾2SL EWJ+C<>qĭ}1\%~fKlM= _$Z1)Bh v:,P$޴:&ї"w%Z{YQ|<# 1#Yø[ֽ3;({qR=nq^{ovPͺ@G#lwȞ]DtGLlipֲPd f. a([a$^gv_t/ap,w]%Z;&;1sU3pyX!dZnQfD[ݘna<,P](7Wn3i]'52EcB{#1.N0cLjp}$R^_δjJXo׽Dlz0}eI#Sńrs^tP~(KYۗiRん{ӷ9$k-H-D%AξhF{g(kz kZ|J]FB#_%b <[.,? 03#^+s}{90v=]ѮLHXl;qeT5l!Bܚ*y6^F6gj8^|}{kog$ax\r-=,8[GԁÒYڡD?}+KU>>HK%в\H\VC%:$pqY$u^p."J-8.B͸uةջXKkU;rle~$4%XvޫE{Q@E$ض >)_?#+f!WBb4KI pkj/8pGI@Ɛ̅75[gZx8X=/J-+r +v R$cy(-U*%各{9&8H18^K{-K8d{-7XB^yk?0@Ә]Sp ڏdVحHZ,ک6FXJ҆c5aE` gEqÒWwP8pI ڴKWk}P{c"C>~/c681+|~d`|#d  t ^kuo}[;Ӷ9CȐXge4' ^pw\vxɧhlgȨVcBJ>q KFd;d7~4m7(B[)zpDgܮ/-[,8[Gbݔ`Ϻ@£Lc2<lVv)2^eYQQ:4M~|E;?l?/KYkHɢGf@ש>5vI__z)=H%"L#8P0'Se$#\iU[ rM%Xރ~qf1@1h$ rG0V%cYp21>rO/7Xbuk{ E((5$ꀥJh;6\]IgAcEA.*칂 VuѠv6X=~sȌ 𾭖-g |7c׬0 :=Yrye؜yk?iɅ\!x,`(,_ke+s Ex`{ZOy!帱7Z62iK^qFK`b*k'0wH{Ąb d"}u^ +_o\Eh#$y}Dž@I.cP˹\N`%T.݈ h枡QLԂD& ōbV{L1J0" -Dd"ڱ=}f~bmńk L6P7?&.OY‰f0~}vLBXt"zh+;K0k6)`M? h{jt6:bJPl LhйBCksmuluVPr6]c<1{@PT+9劌躹8@}p3) kXuCܸY}"'۽+h΅ѷ= Aρ{`{UT[a{{]2VsM}٧.BԼ[t}IYFڕDV !3|qZ+B+/TReY19tݱpñXa2ee)@$}ZX ֻ> ;ke1ZvZp! L怗@Eh¨/)液z/D'U:Rf5*LQCfw}e݃%`kV5D@?M]l"g+)1` vMքT=v.K KJLKV1\ gibqA;kػ"HFmeȊ34A}"ھ) r{cnܫ@kƆ)#,:Kx 8y[?9:\4kY#&HzT E4 qHFpC4 Mc r4oj.K4YbEyē xcd"^p0s[.~>s[Q^{VX+G_yϢϦԸ7T';&s5u[)RT9Z|)cX!|P$AJ l)Gِ2[!'%2y=/Žl Re~X Pra `S+bcOJL{E(cY(@J yߜVNP~2ڌ43>NE훡ğ?S\qE$Q`LoE;~1{ǛPWi.6bQ.e>ڦ"uM)KUD\D7e*x"t4\[ҊR$ː,̎LV a1>zIJ*1`Ʋd%@IjYlork,8ܐDVsy|br͈c"ΝʳZi}ŔI0಄,5KŃKp=0k\ XY80>Z"bYDǬBZNp~TmZIwTLwT0Nv:{I:Gc)K:^wM рoOٻqr?Jn!+֘%>gnLV8TE #kOa ; & vkSnY1D[q`{3n"V”q͌w* Y07?E5@ !38q1k!2b0ק` Bh"M,./M)uR wh1)p:bkqߨ↌UV̭f24ԝ.dkIኽQߢolǘRC ߥmM_/|opi_Ԟ;shc  [ 9: dg+Q=N V(W V7&c#.go,_\;ا88,4RKE * %VʁtϏA}˪p[5<ꋟn7Xاqb7 Jh @Z'xǔ"97JlS8%<>e2t.hzׄZQ% k9є0.d,)?}kM,F,[A=~޳Y -Xh-\-P"kR,B)BsZglcⷛĄ~3R5(:$VeB8 ${yCb{ 4CM6ݰ>sx0ɪ/&SxOH|$3xA>|sLh| C\ e$qEV])V'-P:׎eW]+StؼOL2ϻ~ AjU?RdHPN1!011÷y_1ilSx]椊0{wZ{{ϰ?aec ",>h؝,'z V}ޒzSGhbu"0uzH7cg73JxN=}ypj ;Ţq3kG-aK}с;QTk 8ipsEePSbt'\;ćbL]Ýq Ӊ1G/@F h*2F1RqL(f%e+| H< D&gv +l0>DQᰬo@[g;,ע4hwRESP" XI-\ )\>MeA=YD{ޭb ,֋qhbpM91{oa}=$ܗ? 6Fz@r/s|{O֬|qK=u(@M>Yr*j^,ip\"; hC\0!B,Jkq[( m+|\t0̦pD=C ^8yң]ܙl*n Vj2>11É]Z.ya02ک-: },:u+4ćA DzYrI ˋvB-nW? VyG,KBqqkݘ,H,-}L >m\=ζ2vtmOɚ Wd_ @䘜)=A=~.JE}d\0$c74`,VWb+Πȁ O$CRU>Y`B(\[ %mwn/ LZ&\d2S|ZmQC.`zXYhHta. )3ޝ2Fuw5{]>}oٳZYpQ )OZh]P"JZ%ʪzI1XDi8H( R9xׂ.|IPW?G%'"V1UOr_v - (b=rI~[3X;'ϗt%s݃"T%"yib@wz(09?'\hy{' <a! K‰K!ŋVf{PENJ*C1<W>("B(Ly|0)5'Ry9cN&w=@y:'dH 24k=arsن$&pu/Ρx'lO';]9bL3;"npqȡ'$ʘ2VrnZ\u>O2C6&dK[ )gUyƌ>"DC+HK)ܹ5|߳;!2&wY\SV"g_,Ƹ{Dq7%E YirE PSe&ZDKSP 浄&/;\@91տ}F.3qmUaW)8Mc$k1(E>vwcf$b4D60ڷT p%tmZ((,i [(N'BI|Cަbʁd(NHakeTLaR>ű.b2c;\^I$ p~ӦgM)XayI"LH0 GNEĸVk~\"⤌)@&p pc- !xvsc6ʚ6жZ .eէ,M޲g?s=_z"EhOn\X*Ʋp\Vڜ=w[r!"p DT3v . MqIaO F={O]31%ˢq C|J+}hdoC#sr9(+kH5Epł(]sEJ UW!lR_R{T;q= kgjk9 .!b|/r/2sݩc+`CaX5~6 k/Yz0lGM8>)zQ^=vtn5ж︭•:&) g~(}DQ'#9jH)#}QT}kk(]Ǒ:!qG&y`RxJDY5Tk՞gޅEQ*mV Z s|yšr`KS'@q.͉:\&gh{d@Z L@7 ` iIDjw`cZA83TK{&Ej6Qn/%<>Kڏ_U6k{) ǢJ^T./pqLQ',P\_襵"ALXB-lp|>o+eܢ ,1̥2أ5yt @¨al^*7ZPXs#4u9oarjd|P!E2)P8`Hqu)jK1!3Vdj2(\kd㜇YLv蕭 d(c+V T r]G#v,Xؠ57o\%ä́tg]c(@\K .}=u CWt`sfA"H@Q6w~X6VgWI>hPE e0qbrHcf &@>C7wNƠ{ :&εDuxPu`djo/K+g(S $ToA>=VYMK)q}yaΈ&XJw ],sЁC:ЦrSwkɪ>sG|$|8Rߢ a \l|r"n\D]/]d,}Bs7 |ҷB<f]`QX/*®p”s-xW;5N']Hx!pOt I:$8q0_.[/)Ą\\[E~ q1+AhmTW!nA$lH^$Χ~f0&l%P.?sDnDYg?R KGJ饋BjxxI1sD"+1iuO"E} 2+aK︘v1f?ӻPcVET$Snm=h'ƒZ|Ǜ'P}w8Kq38 vxIQO}ڱy#zw) ~g! 2ZϹ^a7 `>ݓX@?#5}X}R,8SV J(wZ+meQ2 A5"E6VXpco L6\Ksk{D ޸bY_p#:_I vIab:o֤0'5Q`?Sr +?*>*wy*uՖSӈ|L\< WIJ4$.+jZKyL,p|fP/y31dW 2P ͊ ص OU0gJA1РDoEӷM AT/nkŀ}GƋgrʜqDYc>k;.86/]Ʃ ۰&}lJ,j"(};| AԽ~=>n#k( ًIas VruX{BLkaTnVY%HX8Q&B*;{c-aO?gb hA$!Ġg c d;G{NM}7uk,z+Z^1  V/ \@ '4h'.-SDwm-V\{}HT3>1)}w  ){qA2Wc`:Lk`N/Ec`: рBַ&ro>Wq~zW v܈KʃX?)gȺ~<\ *}oCKvxr-?\%\H$J~‹P8~`^BS"HTSYH$~pXP&p Q>u H7Z+@(u."(~"|\D>t 5 Qj}[<7ERػp)&]:CRiV.CY>#Er um,ɠ$ZDG5'z> `ҥuE,R$Eȱ|#h'.+&:.*Mයp'WW_ hkRX-cX:n՟(`S;Y~֔tKqlɠb/L88EǤt K@!;,Sm~ {#j+~ږ)~L. .-OȮ?-;L]Jރ\"L>,uN#Hh{>uKD>ϬN固XOn&BwokymE(oLD oϔ:KUZ%I $]MX%yZbM)yX"Nn3Ѩdm¿LsLysQ^֪V$e@;q%_+:W7^ϳ=B;0 2`}{_{W,VڬE,{(/0~*pXyUZXXZt{8BHxA%M ~uV/.c"K0"+)?aDeE&YkV4d{XHɤ$50yL Š` ?lcb|`d6 ʏ#zL}6/˚5qz.=T %t2lf(ͺ#DF~ȭD[᲎;ym9h/q!KQYx^c {*ŇKPH5ppA<|Hj}|Z xuՀi~oU, D}HnJZR}/"$')h-tqZ)v}{ pwY?x@7Y%.*}q-oIXMA& ?5)s.R7kg;9Ȅm<25V_$ez7`7IDATO2iʂ%ba9\ sV*,ǵ {j? ^Y|S [ObҠ"DimA\?鲴_eb95?IDDSHw-rZV- eyj#:SD'Lˮ@h"Qa w1osE;Xq"bj)"~M)@P&{.++$C<6>u$ \[[Ba{^Le?%79D5kmo{[*B/u!W[4,.9)~Hx:xFx|@h؟EqʏzPHBwp)L,Ez=A2&<5h]أX;/ltS !sEHqC:x/x\rG?ްv~xֿZwW+w M yPms,&;gm[G^x:$5p5L@D`")xbN$Svl?^~yJsOqSX sLqfNȄU/NaٻsOm!v'Ř,5|(cH+BbPXe_$h̅lr1Vvp`E\/{k=s},K520"4R`fW {K, 9ek5pm5pS ȇ:UYJ<8H} 9T2:ft}~Y2ʯJ 5}^2o]R0@!oy$'l#gUڱcs P41Mo-nrqaC.r̳_ 1)i|{˹vQG ̯/Z'a)ylOO|wBwJI}h5TәF2fOAzd>䨁Z0~~-"R?U~vlop pt}jꭱ&__UO',܊ {w~wE[ o֎e[XO==8Sߝ  Zӫ_S?N1 ^+S~Sa.=1~ S>SN{Eӧ}ڧ{ﷶ#NApUGط9}(C)t ~}ovW <)Na]=tI__ r3 7LpʟH77W Q{_TKz TxY<̅G*A$C_>5p L&s|cKRà%$vL01%_%9idz\$J]&HcF(" T)vC.[/bf,.E}6/rx瞻l!X|{Zx__9V'GxY +VykrPyސ̴c~ )Ikk3DDeBTfKGVAw nlKjNEǕ_ \c#3i ֪X(D2_5_7xv!BJDLa#Y_7kb^";A _xz  H3.1LLR? ȑ_ !U럍Vzk|RDeɃ[\ h73[ѹG$6^z)CYZd .CX$=蓿IN jo^[SqG 5g ܴd $׳(8c8HP7ṯkr?ћCt*??;zqwNa]ӊEyQG 55p PH|?ap0?!Y}}q'oLVU//%<|5pQP7 +-_fn3 ~O!G 5pQ^ ܬ795nGH~~u|>jਁ8jਁ'P7=wp񨁣8jਁnw8jਁ`  |iG8jਁ8j`[  ж;>jਁ8jਁ'X_Q8jਁV8jਁ8j =v8jਁm8jਁx5u,eIENDB`ggpubr/tools/README-ggpubr-2.png0000644000176200001440000006241414334142166016001 0ustar liggesusersPNG  IHDR@FiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i'֒f@IDATx?^oq K4Flcbhbf$؉-*VJ@Pzzo[r}gvgw>ݙyyrߝg(@ZЭC @PA @&B @&B @&B @&B @&B @&B @&B@@KSOUG!5 ;.yY%ݱz=)9B-dj x4_^ȴ& yDSvBdjb~3> OH@ODS ^]46;OhR利5uewa9&܍Ŗ2${jXkz*D~;B|q:tu˭|] Qb‹BҾSxמ)!0Of! s z@0I:̈́@(';:C jQƎ `lӻ]ԮaXVD9zMرcTSSӡ\ׯ_FY;vE4lذڹs';l Uߨ=zA ~_/OZ2릦&:餓(--(555X۷K/wy'/ `t7z~q-PWWG7tΜ9>6mںu+QFѽKGMSQQAg}6u]<---tЏ~:#͏}k˜ZxqU+P> ą㢛PxL}w}GO<͘1= 95|Ӹq$ErT|Az饗<\r%.:K-O?G6 jjil 2o~=&S*n T;϶ww|m*z+ |W+:@< C/q+b ?چs95XQ|HII>L^,I/~ 4iyoe>B0}tڶm[p]߾}ZJ III3Д)ShΜ9e`/dyݦ[|={ zrCbMKN{Vɝ9u=t(RɓSk5G"IH$oVOPOKoKr-^mOi2at~;Y0,VN8ZtyW_^Rvgi,3_zbH_uiYz,V~!E*| |Mu:3z*_n~F~Zl~-B/~Yа{$A@/Y-[F#F0:4E$~w.[9k[d_ÇڵkգcǪGr}8#͛G6lP |&SQQ7mLw1uTu x@מC / G2@Mi58p@/ [$i}wkDz>SOܶ'z!Zf}9/}0w^(R(8tz~sr/V ?NկZ=?k,O2O(@?9/_d9'G7n W7t#B>rO$n>s&Ȑ!@hmFz+>|X%On ,ӦM#zQ^JZ.7yՑ]a[:T<l|[\gs @%k%r!@:U@o |xpd)x3rw|}6ń9acB 'tqfqkx,*ZxzÛ P2]OR3,."bocYmidsv?x =B .0J?.  '9Bj@ *oЎA @z 멉 @@7hǠZ =DY  cP-@zj,@A 1 @@O|=5Q @T  (  `P|v @S_OM@0A;Ղ )&ʂ TߠjA@SeA *oЎA @z 멉 @@7hǠZ =DY  cP-@ AOnE!?`V(_krn GAOd6@qc}T\jv? ONjXF$>8 ,=RB3̴gu{EUIV@{ć @~B-!@=@2CC?>  H3.0_D̺f$hooQr]f{jy]Oۻ`gfNh}fg`VQe\kqm_J{nux~@!@@!l)ȑ;Usmo=.Ӝ )o~G! ȩyGx5*5{5!홵n@0  n]^wNy}1EPH ToJWI@7\B$RIs !SŶ~w5\enJ|Sv; @f@7[ `J|Sv; @f}fqWW>MŢHJL~OMM3Q{ K $YcҚ Nʉ @@7fV ]uDa c ,+g*њΘ @Q履4x`*((njkkh444wMF\;w.UVVI70*<5BCߣCUQz馛hժUOO6 ʢ3<֬Y{+**x~ߦ @ @T>K{z_}f2NÇWW͜9S'i۶m4cƌ: @@@T^KNSiOFoٲnx<ӟT ~wЁn66mz!% @|*"]/Kp_z:ԩSu^x|ozI=,0@Y=Xh*.*|DQ d]*WhAupy勀˨}O (t1R߈d:l-*WQ X;T)Sԇ U&@@zJE  D"@L?: Յ D"kTy `D9Yq# 3wY~3))}1+Z%~Bw/<Z^5)A@WוA)o~A @ ʉ @@7fV ]uDafXr.[b 'U%#CNбZUZA0h&wZ#t@׍A+oܾA @ F @@7nߠfq `Z)ݞď|ʢRȒaԺoVgG %К uDa c _P+@r0@1/ @@W|]9QӫL{Zl}i{]SSfG>D,12B蓒rgx.}h@@@ÁPhKTQ鈉b/ ԹíFhzfEz@q!݄JjYSG[jhPZ,{ť9B7x17@~.:0d@fmO-~CHH\OnE @mp ~3fda8q)u\ @<C2H~@@#g֤H]pJ_WN@01 *+'  SߘZAt@וMԺ[l}i{+NL4;A bΡ/#ӠY@Ƨ99B@/|$Q @T  ^( ``̴gAՌ/0wހ`f]wAjh:b3HmP 3 VX@Z2Gު5)A@WוA)o~A @ ʉ @@7fV ]0hOWN.Y~zp󎰚 376m2PLmOmR4;V8/fW|6L'#|u9 @f@7c `:|u9 @f5|3:ڬGo"Y1B_7/(g_H{h+Sȭxyθ/*{kRz+RMh4 Ml=B)pJߔݎFC/Ӱ';s=sMUZs@B7t@׍Q@uזUԾ}ksÁ穡虈3S˒Q>d@w`B8_d\9Fꇰ2f/aUnCao8cd:K'_QJvSp]u{n!n( bޝ[2|{b?i: ^*A{r0@1/ @@W|]9Q @o~ADb|af80T3)s,R PTlfqWW l]wR><.JǿN ! ߇h @ ~H"$ Ŀ~!ZCOg>y],"R%)@@W|]9Q$k {|U TG^rB B  O[+ @ B  O[A#2iX INV{H=0(t6||ӵ \ 3#'z #!+ @ ^p/=z&+{RQ{6rE&@>nA(r|v D@O^DJ@y94{@znhWҜ !5"x0dJG0nlNiOꍦ6@c#w5A$<~4uoNrU} ^CP?;M @o/ @ONE @p[^{@6D ]aIJ7SMhL| G?p?o2ՑcjN&@7A'#pgkŷځ|X DS?WB /?v8V!XDŽ(S<>@(hc '&\РPnR|ͽ .b~:s+c mNNN~?LQAx,:v3pOto3D 8O1o ,HK/G19NfJYv`;vx:-ㅡ7ЃwRJ8~n/}N[ϏA@L~mm-]pk.u ީxrTiŊ.VYgK@JJJx#Rӡ%mM^ !DP?|G}DӦMk]PP@h]:MZ @@@T̚w%Б#GO>I&u̙3INrAڶm͘1# !@C ^{ ?iڵO2 sϥ &;7xnS̛7/!`\8w@q&X JU%]sv}y<OEK^ Fv]]?|AUu? k Ih=c[(l jOQ Ow4x`Zz:ڗ@ @T~Ք x@ syuQ @?!x2pooԆ(q㵩}pHOM~o}Ӫ;P(fXj&E?;͛p)t/D^jIclqj'E{b0Z?<"mChE;· '}w5sg uw,05S4W]|Q9#4St=rH(3d'S.unV,5)5t8ߖ\V}|6!a| `^|j@$ @-@`wmj*ċ ER]33єs(ý06U^ ZOͥ&h/ RߔݎFCh/ RߔݎFC0z]AIߙu" 4={%e4PPu!P:[6mDŝm:$#.PJJG)VUUQii) 2$!@T dK> fp8T+(  @njCoZ.z)ׯZA Х@Xy.)oE 5k蹰!z*O_:i٭5^­ĭy 4!ҧ,0 ]w\R #Gp+RVVVFR@%9Ӈ~H ,:Z~ tPnvXjH|x*C !4|F)#'Lh ?-T*lE ~ff&}+8o6~awY}4i>_PkS|Q4ʄ@"i񔚚ڦpmOn3 \3NŪm))uݷ.yw9Cs}z >uҝ2zh(x@0@X_@@ 5N55 @@:Ÿ3gt)'f̘vl @ 6aQCCZC &hiY'fj Wj: uwe˖ѷmt;VB UTѹ}qk^"wm609X*@h*N/((%Kt!@@XG]Sf+++ʮ`= L ?1욥 R|#|;?NMm9rfΜf@q~< oL92O"B7nvR=Cm4p@?>M46  X)} ; +=C _SScZ0Ǝ +?X 8KNū%)@@W~`ϵsNV$yz^9fv:LQ'kRgT,@HFK3ϤiӦQFF}k_#L @1+Lz>(]{ӆ 襗^FuYCc@|J_n{;$ EM:Iyk֬Ժ H@~qq:̨~1bs9矷߄Hx殟/G{ ;2@~߾})))}Iw$06@ <| ?#kI4U@sgzIFnڲe }ߥt:u  @@ew~嗫{rmРAꫯ9 J .Vͥz6nH۶m#gȑ{܋{ߠ@@na|٫/**뮻NĿ/jjjQn5CA &'ɓ'' ϛ7OV1x8oĺ[gRHr;/AロvMVwy'/ `s%ςZə;UKR<~ӦMH52d}ٴcǎ h2`/??|Ֆ/2˞~, O@=9eyWsdd{!:s1^ Q#@HsGyd`wرcX H@)}fSG+W7x֯_ު'3 STX EbOPKRaNx0@)?E,pAdQnv>S{A(k 0хU0'͙B/S# c@G! @=&Df}f~E`@-%߷"$\Рh9Q*@ @"(=v@@ @"(=v@L{` ~ h'94E")&2ChtdɑeD.P{ x@^B!@=@! CA?z u PEZm\L[b:b(s 쬩#{s}$5ao$Y=@2CC V JF@&|O7[nPцiԨQKsΥ m1 .nVi-^Zp!=䓴h"***ٳgc`TZX @-u׭[G7p;vۡ7oG}T fR/XƍGK.9stȃOOCV fӏeӾ_@|OUF]D Gϧi-[F.නcѣiuxحQgdX,6X~AM%~GqϞ=։ * @@@M Rzu^tk֬Q> 5}x@0@ԏCl6vrHt ]vY_|1/ @8!`߿Zbʼn~233۬>lp+|a?q.sUkԁqT?~J?PAAUTTܧzCm !`&?F]//{PU1 gΜI2'|>x m۶f̘\ h0\0a:pmFӦMyioRB 0\ diذa=^} b:ho՝x$^Fh|, D.Ӏ2]`~sOF%Ϟ5liCS!444N(W> >]@? @ve?:}*ЈLsxuU|=32CLfm(iI9Ŧ !ʱs BSߜVC~>alXeX,iu|-Ԃk4{!!D@@W[*GybGBBjb}&uO{1-˩K N;eJhhxIў)M. Q0䟂4?6+ @ Q @@; @FG;KD)ɘZ7;dqdKXt-ߵ @@iJD伳 DŽ; `.P[ӒB?ysBk{EB@[gvc7<59_c7)IV)  8A֤4iN `~> @HF4"8L}{w4j эhD,VVD0 )5ƾc)KumR|v< @@7W `R|v< @@7W `R܇oҎGu~pM&K-Y3kMVް6a/| |8u\;_f@OԞE& V{֤Ml9T|_}Qny8'j1|<}/Ǟy~+5Vx @lC(}uscz2ŖFc~XSK{2h?c6 @ ԙh  @+dj]X,%D~.@8pOG~%g|'IU15zYSZ$zj,@A 1 @@O|=5Q @ߠjA #h]N+@@7fVq$pj^YfZz#u9J*ךŔy*fG)ێFV?{P؄"e0ص-SLC-G:5mڼDK?ZLZ@Ik]] f0$@0h/ @ P>!@Q@28v@~,ԱτxeAR0nBio6U95]ԛ@TSvÍM{=UIb31@:v @~ű?@@ p~ uˏҊceaW62@Q_GD/Jz|rjjGuqX 5nae0LuP uiiZR}oȰzpӎ[⟜2&ުP 6᛹v@0i  3 v@0i  3 v]Ubj]]$Q(ywh L< ,>\ubTgO&j)(F{n,oG!@44]}~~[u35y|$Ĝīůu[J> zxR'..~|~R!] '`jRqc3M^$T2l@X}BMai |as9Ѯ{4V2-Ҫ J?3Lϥ͙>+- h&~a1 M L*oҎfLKYX"r_:dY-$ZKM7F>-%Fyrm1BwJIcU (ʜc;mN%: `K) [ ~C El  +Xc ( G J?V/ @ QƮSM;0~bvmtB!Н~w: 2 r$ JDSESض=.=ǧ"u{ʇ$6BujcWkFҚ q84?~t!scEu2&ݏS+͐qP%G5GBS8OX .NPiBB>>ty h&$ OiB"]uDafb+fA 8s]wfF  R?7 @ JQn @@> @~XzMսeڭRRrQ B `~(!l@U5t^5/Iq`1)ݝF'6bjyzZ\aȑ_ }|U$.Lߣ=Ȟ><+SuJ-oUZ/iziLcX#?C-u48n)W9Vk n9:J^Krcܫ)_F_$_\tLQMb-DT>l}#n&nvGJh@Zj7:n:B.U֥zUגݪKQHI\瓬{t&RʰP&K?,}l"_`~iLHKy_ZMV-n WMl|-9\Uk4m _|Tzr;6W`tOk;q/ANgeuZiKU ٳSr_>M_jJFZ @z 멉 @0)}eYZ]2#eR}tNA>fN3iG:PjN>84} :0~CC}4j(ͥsReeeg:T`/_Jc  vJ !`Ȁ… 'EQQQ͞ՄС }Ý߼y3=j5k*`7n-]̙}% ;_l9 cǎѣGŋ ;߳gAu3 tմf͉{<х~W7~$K%qn\uO>O|o~;z7_nIC*fo+$MmU,d Щ')0kqXu< :U&g;^KFvK^ʟ J  +-̩CLF pgȜ ^IDAT'% $kyJ]tdl6InȭynSN9>຋.(ZI}_z#e#x>KKդ&-K[#a3!&7&'Qj@ h>M;k_FNG9MT'%ٴ?[ԏ.>*SF`JMr5.u3$;B^>y_S\>vF>Z{ȑ1Oc;||q#XɑiTJj%rzٱ2znTTD)R4٧GOS79F:J])WիzXN8`S/%eEDoTny$ {&#جt'+1a eq;cn3\i˾%4;(i+yixKRC4ݻ[h?DE'*I[]ZAskjI.TH^E;e}IÚB3}C] =N:>ut=gs@fc/}48;\WMvQ(Y-K3O¦/ԡKDoJe\|f yԶ{5G3ZĴ|z*'I>K9wߏgJJrnnBKdq 9TR-#Lqs5j]}rx*9 יs}㠥}ޗmmu\*vyjSy _ ߚ9dN$5/_T$_+y_%vA=UMc?oS)s{.u];oq2ޖu,s]Ԁh/F?.bq*N_>5oɢ_->F >?FI~qZ, a AYL>xxjߨ}_ҤaE52$Ky6p,:)$6ߗұR/wI zš>RX&tm^'yvTRMdr:U,_2uLXSgE>~egOҬQ2XUD;jj(Yw,2{a y¢F.g;Y@3N+/3c[O'(R=3嫟OϥOP'IYKi=SZ'|~(l*ҬL>O, {>}j^+ gu#g߿Jq7^g>j6)B۾FɈxR=3S'g{xr<ȖrPԦ=R נϒε\ğ ['l>yOD&rƳ5z_-w9\uG /<fp-tWe|i#=ub2iNۉsd&BW%>x#g޿}"mDF_W돧>~k~޷/#x$ֱ;+Ik=)IS3-{쵬rի\?'N+y[,YZ|MWoגF['jڗ(/;^@mYcY:+'P4t :jqњ5khB.[N;233飏>ұT^`4vX^G<_ֱT^ ##Zz'o{$ʃ|AKMzP8q@@ }  5h/ts{Wy$Н믿aDw-2ŋ"ˍ\Z`>_5҅/ ׯ2p s $NН>^*&hzv8Z|VѺxOI666 [qtECSSSiʔ)x F']:+[V\z5^x7|iYXK~;1bɈy،8=z 8---]@gn5jܹsRN4%wұ[l;wwA9RM]UUEwSO=EyyyS א=,B9.A|;QQkWZEr^|{OyGՠM L@(g97I3Ϩ w]pm6 -{wA?iٴaÆ|?X Sd-/"N(/:~e;ބ!(Re'8R}`Ѿ_{P{U?*uݢEk-M6)SPqqq ~,l{=uɟ%iӦ6Ϫ|eNpK'V~'.OӀ+/~ ӟIj~ __;M8y؉~ b, ՁL2psU6 r]yƌSN9E="_ d=Z#r0qe Np{2w -U9Hzq7{APXZ x<Z&Z(ӧOWHᇺY."Wnݺ6k-:.bjAkrro]R˕_}Ր@R?2ȴ{OH/2HƗG@~uxѵ,cdЙ $_d dXB heXd> ;"TLtʽ|%K(eee)WhCdK/懏i8G5"ߋYrr·)r*Y.I=BQ:}`|8*7t3IH8quϴpWO~o{ױPT@g7oS3/I?FIO(]&ᑠgplockDpv*sEwa"%*Z\ϗIw>IIk-8۪8zLEϪ|i[տV$hJ<-u$:r-H \*-G._%(_Bqv-M21Jhu>vzj_IpDlJ@gU栐*ݦU?{m |%A{(@L oNF!@ @L oNF!@ @L oNF!rpEN\(8묳K/׾6 $h. HRKIl  qD)?+ʑ^'ӑu+VPR~~>}T(Dp x:jRo~i꫃iEKK G?R?T 4EUMϰBѦ"x DׯU}]^{ຏ?6l@'NT׿uz뮣*++2EcYid`~?zzGhݺu|oFK:~ ɗyO?09 ={6ɗ,@@Dd6CHdկ~sՇTUUI1YQjzy8L`#~uy,lp;^@ _& OIIQw/uG::r/ҥK/V_HF˩|9R;vW~?~/|>WG^L>dsΡ7 鈉 =\Z|tO>IIp?Sht%͑,O;3:4 tXsN2"/mV%''/)J."?;jW4rHƍSۑMطnQ=5//O'/ Zȣ/o!}pJ_Go>z饗HNKSr~…(2 G2(ONˏ%O~op9,Y$?{-/_~H@HDÇӘ1crz_%σ\#u r@F˭r<:1i=Zn_[o_* A|_'%%$c`ӦM7= ~`HD|^r\}OKK Gr\[h=c4eʔN9{9_|nV~kF=3i.Vʗ yE  XdH[@w\TPP%\{&Mj3_ޕS|[`y; _4䴾|D.#Ax{.g ~ߩe'>pӺx{ZHpߵ @ ly\*(//WaTt* ׯ_N+#?,@cg=C&۳ca]bZ ^d?"@?W&@Ϩ @O  @@&0}AIENDB`ggpubr/tools/README-ordered-bar-plots-by-groups-1.png0000644000176200001440000015500214334142173021756 0ustar liggesusersPNG  IHDR@@e6iCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i@@-@IDATx ,E}.˾ Ȫ& h4h4JDcL|-/(O%EE".";,Ϋ陞s~sꪯUkEt$  H`̟U H@$(Y$  H@8 @WfX$  $  H@G@h K@$d$  H`(M\a H@$  L+r3, H@u@$ #4qEn%  H@PH@$0q&Ͱ$  H@ @ H@&$  H`$  @`VXϟĿtֲZˇyam/_Z‚ $0f OfJcIAyౡoUWPɼy ÿVX-ݼqoAXeῙ7;hAEg<W$ TP5 L(o5`(tUfE"^??tfE"?å^:tXvi'5@CiDN@q/a' H@4 @ӐxA$ q'4%l$  H@F@h/H`<| 2,b.$  @@z  { m~PWsV<#l=H`(Tq L6e˖8  i+^~xNoo[o᷿H( H`w}o{nRguGn)nX<<G< {G79\9?.첹_}ã>>ό|_O}St@ qI`r9,|HB??:SN9%lfᓟdx;~g.$i>կ~5o rs{OljߗTN_ OxBXkRR;: L5@TuN@sꩧ_ׇ??w\wW:\wu?i;_o뷯ͅ?N\Hr{mݖv}[ kȧ oy8蠃Sah.$0I&"t;s;Odm {gx򕯤vZ̑#8"{]v#)oNZcX'>N<9I-^8xk =XJ'I"4Im^_Waɒ%vS.8Gc=rc 3L\lnp%t6\s4uQG<9MozSF:1q؎ԟ'!+_d4i7}a4 , /;]W_פi0~yK^V_}r>gz뭗ַ|; D{ғ(lA;묳Nk_у.(MMʗP"6sn:¯@Nj;>_z8묳כpwz^?s ^]wݕ?,)u_bxS1FeU'I!4)%m>7 aV zիSC,fe]w ;?hXi\o{`|CJ6(lVaҥ]z׌=oX]dM†n~9}-i pXL}[Jg%l\Ƚb%a⽹xP1Wܺ뮛3Up$΅N γl.4J` @3fnسaW6Ώfk}kҗm+4'C'z3!FtD @XyׇY7e-ќ˜ $(>R ~6mo +r8sqH@515#|?a` ca^v[lafgGG$  H@3Ƭ@͎$  H@C$ 1#4fjv$  H@'TH$  1+P# H@@=zF$  H`(Y H@ (3҇$  H@cF@h H@$PO@>$  H@3 @cVfG$ z @! H@P5;$  Pg H@ƌИّ$  HP=#}H@$0fƬ@͎$  H@C$ 1#4fjv$  H@'TH$  1+P# H@@=zF$  H`.w}cVDfG$ a+h- {$  H@cF`1+# H@ P!F+ H@Pݲ1e$  k$  .-S& H@ P!F+ H@Pݲ1e$  k$  .-S& H@ P!F+ H@Pݲ1e$  k$  .-S& H@ P!F+ H@Pݲ1e$  3J@շ^{jYd Q/ݪ֟$  H`8X$PIGK^NUJ$ 4`*$  H@E @GI@$0FL$  H@H@ha( H@Fh$  H` ("l% H@hPr0$  "Y$  H@ +LjZ=_OI$  D.]s5&l6`p衇{Jaw}ᨣ [ouXwuA)~<$  H@M ̺׿>ӟt8cE]^LIGN>pqDžSO=5\{a} j`D`yZR H@cO`l;N~~ӟ]w5=|p+. sLg礓N m]83?IY+/~{o8צ^ayS^'}kU'=m]JzMƀ @_` l7o[J+~>hѢplaҥ3PjSx0|쒵')ګrx%  H`< ̪4o޼s=$G?8lf0_? AEna[7N9e˖=$  H@̪TL6=^xa2r{7]k_uYgtUW-mϺISH@$0w0~zqӟd  *A#<2n_F H@$P"4@==N/]v%,Y$s9dp]w5\sW^9lkI: H@$PG`V5@7pC8i {я~7/_>?Nh O$  H@@fU:^{da-H{F{np嗇=ܳ} H@$Д @rHXxq ^?a}pG<I9#u]npᇇ=#4$  H@ @|_z~Aع Ҧ4gw' /h6 =XhZL_ H@!0F|O[`j7xZNV=0$  H@YH8M7ݴ6l$  H@&0S`NI@$ &P3$  H@sМ.>/ H@@ @MF$ 9M@hN$  H & # H@&4K@$ЄPj$  H`NPg%  H@hB@ 5H@$0 (3$  4!Ԅa$  H@tx H@PjB0$  i @sL$  H@M(5f H@4s:&~ ,_ ſ^VUV.kaA&40B#DovN^?m߼}$  H`& 8ܞI- H@HPb1Q$  $k$  $,% H@LPI- H@HPb1Q$  $k$  $,% H@LPI- H@HPb1Q$  $?1tx܏-[] whmN\uaXp~Xoyղ҃$  x @+ F:O]Zz}7 H@(p lJ4H@$0f$  H`(B) H@fЬa$  Q(  H@PU>L$ Q 4 `$  H@U @ۇI@$0 FL$  H@J@hVq0 H@F(i$  H`V (*n& H@(cP 3V_s-\0/̛7W$  Y @ss^qggonI*҃$  y @sg_t럚Zz$  mƠ͂$  H@Pꏗ%  H@ @cPfA$ (K$  1(D  H@@o H@ƀY$  H? @ҷ$  H@c@@h ,H@$x[$ 1 4h$  H@菀P- H@PB\WT_ӳ$  H`5,eQ:[×λ)GhۖkX ?/v8z 7 {,]':$  H` (p TW>kJ/¿t *{Q$ +$  91/`' H@t @әxE$ 1'4l$  H@N@h:H@$0Ƽ͞$  H@ (Mg H@ƜИٓ$  H`:L" H@PR~[ oI@0q_I?{^4ZaϛȤK@'Ϻ.|vbiwͭӮ/ߦKK@c@GdvRW?ޔFX @K>VGxˢP׌/X`ޔF6@W&H$ &0g Xj0o0zz ?o0( ',Ws% Њ7wVyY3:^¯s. E H`< 86j$  H@B` @˗/b)N$  @/Á\sͰꪫ]w5uYSt}:*lau tP;D$  4%0НwopmO}SN na.v>p';.zk oPF$  H@U#SN9%w n)|3}... sLg礓N m]83?@v * H@BU N;>O `5뭷^뮻Ry}aѢEh϶n.]85$  H@@SB?puׅwW^_$1Uv뭷/o9ie˖C%  H@@G*Sqo|c}&uYgtUW-mϪB\$  H@[VJ%ꫯŋ *A?bGo$  H@ /| W\ wyv,Y9y>FE+-ܲ} !I' H@̺t=Ž;8%lA$5A<9ϙ H` ZòMlTOE`V y_np&۟rF{sta/~=F@kP•WX H`hfUbm?i9a^{va$y_jXmcpgJ@$ fUg?O|"Wt!NڎO~Y#[}6+ܰYO$§zcvm~CȭF6o~  H@yAب@/_p>G$  H` :#@tPx ^ ⊴г ͐N$  2 /|#ki=7<'~$  M<=}ʂEPxgO[WzZXK.Dh/H@&AQַ7߼H_ 0 v>yA$  5@$<t1DŽ? D\sM?:sg=YHO$ Q#З}, {씼w}`;N6 $  H@%} @z(ݴH@$ Fx²eҗ{.`K@$ Q"ЗO}*};@}+^Qyϋ$  H`T,>𲗽,_UXguauםv $  H`,1;[Z>L$  H@%g}vJW7Jڝw9qo:33k$ 9A஻ 7tSmZyZ?gk_KuY[` rJ<$  H`"%p oL~4@Aϵe $  =?o~s|쁙A H@>5@#8"ls?@$0npwצr-- ,/[Jz< $  H@ |_ /]zĭ⪅Rgx^צ`vm7m/ G5- H@A߳͟UJQ }aW_9ޥK*x. H@I`޼yK. Lcչ;*u޼?D} @~ uJƞ/~p饗s=P4\ۆ$  H@́D H@@7p 7;Mo /v=﮽i7e?*S# H@C$p-\|yL?s˖-#4bbr$  Hqg_G}{…vix$  H`4>]Vuя~4oNEeEH@$02LQ H@EQ֠SU~;|+ H`b G? {oW ,OW?ޔP1=FyKSF{J@Q-% H@P1F, H@PՒ1]$  Ck$  *Q-% H@P1F, H@PՒ1]$  1F, H`k?FʆK.]5E @GI@m_Ww+r~)q#ظ$  HP-"=H@$0nƭD͏$  H@jA$ q#4n%j~$  H@%TH$  q+Q# H@@-ZDz$  H`([ H@j ("҃$  H@F@hJH@$PK@$  H@7 @VG$ Z @  H@P5?$  PE H@ƍи$  HP-"=H@$0nƭD͏$  H@jA$ q#4n%j~$  H@%TH$  *-[,<#]Z) H@%˗?? vش4w}ᨣ [ouXwuAi  H@X!?7o}[i>';pꩧk6AmP%./J@$'}E]=p7'>1}'?餓vm<̰O  H@JFTj<,vi/I ̺tLJ6(~C³>;,Z(p{nmXti83T< /VYgu: @_|q{fu5PJțN`IOzϕ+2I*zp íZHrJF: H@$PG`n{s9ጐUW]򖷴ΟBL@$ A`:, ,U̼yͣn!(>+ H@:9hɒ%sΙ+Sc[!$$  H@@3` 'l͊<$  H@{6B;,Z(pvmҥKgѾ$  H@hJ`4@W^yeXTԆnnp7SN9}mٲe|M }I>ĵW~5z d+o= T__~'W刷~ʑ^émrrO\sqOwtͪ k,)U~UW)[Tpx+*.^\igOSk3`¯`d޼z ` S--j[O W8U7-zxBXԋ+oXӞ#ïzu'>x<ŠUV~<%{Ġct/Xm&ztߏb[neXuSbiQ1\>^i6,̛7oʵNe&{*ȔkWaoqx:Ĉwb%  H+M9 Rx$ SEn᪫j׏߾} ~R>ۏT)Wi7hyr _s H@+mly#'-Y$s9 k9ubW779$  LIȀo=,_|J*,Υ$  H@FN{!bߓ_.{KJ@$ FNasG뮻.vm{G8gԀ$  H 9x≁%oyh?~p΄$  H#gM .HV=0$  H@rQ' H@M`$I㓀$  H@E @EK@$0&ͤ$  H@E @EK@$0&ͤ$  H@E @EK@$0Ƿ%kV`Y"|g/7x7Hb.[q᩻&Or i\h#&9|ÚBzYgM;ՓS;]?N:g? X}ջ9.°~~o8>6x馛&|>IrK8sgu||]uwygg>3lw}wR뮍>wov)l}? ~z-K.;#<o>lv})vԧ>4^_RCw']ađ~)awꩧ'>5 g^;OjBlN8!QHK(| C9q6۬;:y[{WQpkDoOz/~[Qo/y+8ڊ7qj-\q:*>h8sOo__R(4 qǥQl>~*+h@tI@$ J`z)E5\s|>@z4?'M8yᛨI/*Y?hW^IoUVYy{N:g #,v\Mz衦Sޛ®GO4O43urq)QVİZ\Ÿ+^s {RK*o|+غ}c@MߛV܀lʵ/}Ki_)+N|X[qV0=h Z2"D;֧>VW_jUPڪ7jN2, ;V:>*(v7J%lM7Ml?3?; X+n8%N'q-nĖ {Ƹ}=;,ˏT~-ƺx@>Gb8ZIV\y^ܴ3=ϞߧqEG+n.9^>G>aߚ# G`S~rQ.;/L鄺w3!M7ix{uK*+ʫ;&6V+~CqņiO({:~SB]\`(ض^׷'?C>{trw]((M);]`[݊HvpvzCmVe_ځ+m [QN ؛avf.`̔(|Ǧ]Uٝ&ϧNwy߸b5mo qspUWM+c"#`W8 [[/EG;? V=/cESB@IDAT Ovb/Gl͊ާoL(4"i'ѮM&XGPiј27Qh<@3 z;HطEJ~)"9tFzX]Uh O,?O] ϨvlQo6i߾?Hߌ#bFHQid:IquEw'-S>4꫺wWw?}EqQi,#5Fy)OyJ1˔S7r8q%=볟lP|[#/mW?9BQϨE&eC|;T6kR%iZѶ?43nn;FTqPB;bRRo|:6j)a'hʢӊҔ[䓝awi,iJ`&4SW00oAnOOhx}ʷݥʶ{wn7?;R]Ij?$u@S@ЦiO:5iuS<>[:=&[qVqQLZƙ[}KL-_Ѡ 2`tmQѡ%`dƨcdMFE7hx~"r1|FUzUk;FEiw={IQU<>'{Jy36J2'! 4qewiwo1 fo0QEU.(M)SFČM'Nq{J?n.vSFSr:Oc+#WڍNk4g6 d{sާM!Bp:^s4W7|6BKƪ e-)ShQ@QbHxnѤ@{IZ4PM\Q'9| @_7GnaR/GǔE4LTMe6z5z14 2n4;;9. 8S% FLѠw۝k.bLr5x^vөWLC7y~6Vf#t.c7GwxaA_lbOȪG!tlh qsfs?M_Nf I_VcEHYcPZLELbcЊ/XexVa%LsMse snq؊V+AǟG'~rb9%g" ;4ߎToFG}5׋ccӊblb%X|?Gb` 7W+RZ)\Ž5y>sQq!-qusIXQ^4pNu +(: (s(cvL8(Q.Wtؐr L:%,lb؏Q{qoڤbx(lZ\[ ⰧhN6,[GA\+vxoaJNۺ(`%;bq:B,48(oU\۫ҰSE+ عV)Q0]]dR8U-xZ)do[QJY (M Omz-G0h8:dkJ::\/+x?ucJF::(hqUޗSX0i#?F1sUR@3P帘bĊCϨr\>Kct蕑M#mFh*.Fi69l~P=u#88ÿUlbph%mυ&Ǫ2~;=>hQt9bͨm@2+<}HZ:97qA *i+>Pʦ),9h((\bݪJqbQ;˾N0#eO)ʖgk=4&āmB-ϿhcҊZb)5Vur#\4A;1^vAӟ{GAd4zLqV9h05 *"nh/8%. A=axhh[c@3UW7___ ]!i2*{/oh)l>& FUX [q꧟ S.#aD:ߔT0`OFp/6iDv1Bd3İR# SRFE9q22*64SDB[ .N3؋c&+uc$1'њQ`09 Z&@x4vTQ):T|ڛ("bGA{>(hR\ܓZ4}74smUmk~Ga{v%N+5MC[Luݏ[eYW/v7Nvl8b!.GX!mw )5T.q*K/掑nnXuZXvT ^AÛ)t>~Qi!`.jo:øE'4 G^b4|/(aCH8”N=hQ-3U%DKʚ:K\yԎDn;Y,;,A4BMӎˠTYvT$;hGfx6q\hz+ڎM{"{Mt g^~^5iz S'2AH,;҃@4|7_A?EMP7Ufiʆt G bډĥi~j͔f4_Jˉ$17jӔB m-^~ӟ/ w )xq+',1HEGI(N326,lR Sa5Sr2~ad'cS <ڼgK1s4Vq$ ^4EGBSw [?ox)^3^o4N<8,XQ'״!MeN6 , 0A`kļ>;Svt\G3R4Mz*8ml["?3'U|⢃ݭK* g!yd=u*vvEBm/CȚO2 lh_&83l$Qhs(A_y ,:`LH7d`Q7MƩ㴏o rnϯ7#RFl2maq#FpftH8 })\Yr!u-( ŢFzN4_N* ,2k8q`a97< ʏ,`F,aD) #FE`+^^aɈx Ftd[S'ci䘑r98Vx6q77IZP|J3T?jsmmFLmf )K_j R.h$c [cZwwTE۪iaQ$ݻ2e{ٱq$L:$No_pL_Sn{:orw hOFSQhO~IZ?>׉n2x 1r//Yx,e~{qQIK/1030'F_#|5J)Z id>Ч8q1xGcC#d0E 82Ic 0ƒ] CJFx9-q G2f{v7 ˃U. J=-aa10~ƀ3E1qЧ} 6 C>H=vrLG!#m;~]Ԟ% w1'8E6bg-#}d/V*%ذW6^>?Sv\gAD7džq4&E3)o,mb'1lw^{68ʸB!-]aN2HiAK?Z:F 1Z@759Ѷ-- gaC6BFQ⍶-Nݥg9$*[ D%HlZt߾5Y! SSrN/}x/`@,v:rP%5F[U'RY׋( QIh귢DF]yIzju3sj}FgR/;2R3eAe LJÈ{|-6+c-h5?k2@W 0~8w6@L[ S[FLkFh0FcXi DYSVdq1%︪Wd/1}Q/uv/68r!<& #Rҍ!>ƞL1a1AU!CL͠]zH2tsʎ)GFhXB\th.)K*#hy3B |biln649nLEF3rN Y5mSuhSf%_;FTvjpeG{_;ui'蓺9>gENb}Cl m7#tz Ujc|,Ƚ@`u׻gl7{OƏ/c*ei ԨHVgK10Fg1ez&#y:KtrΨhT_^V9#Ƒ]mP:5: d?F aTǿlDiP%S,qXбSN$">PaN`>~ KtZTS?* t9.!>0HrQ3d $Q%:NN{qYw9i <dݴ.t ^>DbVpTGLI2(L0(;IE72=2EMzϡO0;ky'qd4Oʎ9:cT4],K hXN 7p:H!0Mˈ`䭗mIyBG T LZ]4Yſ4#z:G{FЏCoK9A# TC޷1Nb>h3yרoyj6sV"H kL0{Aay@H &hXYkMX\X\h:.μ..  |{L0Q\HP˕YZ )H^4z[Ή<^N_ l'z-WD5aaJeUЀbi$9OQH@2auʎUsM7Te/S#m i#6X)9B#ZƼ'uSsLᰚwp@Qޣڷn4GkhFM/DCGz֑ڱ/ʇqXs~NE"lUp\DAh¸geacu p-ٓ?/Ƙ2-:lmIC_8¼LM@vf/@0#nZ&QwSd ,ڏZS>`F̪ Z`O~cO1q.{n#Ҿ"xWƧ,xa/<}'XO?A['~PT%Pװ Y?O``SY1l| '**&L]4o˲c BH{es.njN.ǽ.eDAA@o#>U1N|_:תMQ?|kP4/4e5=  *i줁!,{ aK7KiM.i\0zD& LZ*:o4|ԭB/W:Ͳ \^B\NϠS8khv!1@*U* @Vla谘FȮĞGn<RsyvhQv Aia98n:Na{OYP3ũ[.T9H~CT3S{51bF3cvjڰ|>Ĉe'(H d0rz9Xc$&={SqtYQ_>o"(>o"򤣡/1lҤ!鷸a &Af&LpgQWs/0r8`=6u  Fsw%VŸ()Nݦ@g)E{UeW0Qth(#lUƫ1gQ*AdlBؤmAx(Dp?;| ^!ho48gXRE$ :ZG~bWhp\FL& MC XQ^ FE_ @Ÿ;# X`uβN:<T\c/^ʨ1:h'UQدR )80O4j8zQ,Z>$oX79O^uQeèFػ4ņN !*FMXTmʑ<3Df0좌 ҏvr~Mpz^%,= ڴNXR窄t w1yi*S򆆵РёK~zE[pB[Kt6xxcjpK~~W|^/!eMxsx~eit[1 Kbt[:,0?_Fm5ѐfǴ #NSW^yeE]/z@zMh/NAaGB_4dE@KECt/bzfˆԈF_+&2Sa!B#?^~F9ưs'>7t!S<3ya ⢡J v5u7ΰԇY92H:=mzNVmjTt?ڂb|ܯ K \gz1BّVJY-ZNǝfG3RtLo-FcF;8^g4Ơ048 ^Ѹ63>0O8JDЋo55@+1 Ȑ*<W5Vw>ď|ց7tz^Mh564ؽ {'Ć׊8=׈VA!la:B\١B;I>tz.:^@%Y!i׺islcÖAk36gLkÞ?Mc ;\'Rʙ緉Z?Ϧ~@z!T4>M0#f3 *ۼF8YŶumFpU69lS L?Ahioqy`$:јWLaLki!}B ~r~BBЕBaEv]LԹ64u~hGN(Mv2 v#Nnwh~.aSVV ,ՄG(I1&sDlӈ2d5CxG`-BXh!j$Bov!6SBSG$V#R˚_%9NA8gBTcOB0q{SU!.LURqځE 3Cլ Q8 qk ]47 H!v4! qO/QvISE5x*)׆yEW,C"A;8b(&.6hĕUMHh봸z݋UN&v! EGц)Dڷ&#Օ8Ѡ=iЍωWS!Džhbg!D'R:S߿hW;R;†8GIlNl~f9=+jCHBJC*(DQ(PVqZ/՛8 QCU4gq: !lǭ\hJNќ Un@[3uzwZW!jg#.ڵJ<8Sd!jЦCqDBbїU]ۺ2=Ok+NKЙNJL꿉(bQ=Qzbj Vm!*o.}ڣ?;&aÑw.'ڟM@j`Htf)u#HV5xFWMUfi(X'eTʝ 9NF,e4C< 4O0Rփ0*c˂Y]EYكFkbC-~yby~>n 2GV7#g nxǙdwl 5sM1(T-8l7f׫'o݀ w‚(ob;bXZ &,ɮ8S?Ôzes|XFm*7]?iԋcJַĊzLCnD "hԪ  |80c4#N/v%erzH#ƄvxG^ʡ|J%}ó0ήRi<)LB %4lX~.׿^m Sʢ ,aL1\DkTNha47,G.v.Cy `h+r"bmt7W N!\Vm.M48hUW-|7.n Oq_7gNvrhx v>1P'^gΚFсuJNP?I3bJG&`cZr|eΏ--ew;1sArQ**4PL7И0BX5Aŕ/ <7pS/;h9lx0FVL0moPCNNQT 0ҙi^A?Iˇ6SVQG\6{3ÕI| C2i}|+ROg_k%`*I=w9Pt~}Fǧ _'5YEeV]ޛAo @]隷+ǭ KU=yn-Rطz`?I;(a1sK[(Fp_2Nijݘ*ÜdXcv$hwGB@Z ܐQ%" 0*)gN\ c@ q=?p N͋[e!\}HW3!±1iѾJrdg0 L`f g+.! +.쑣qsQh pT"\ MKӅ_eGgBeŊ m+ĊUPy^Y ô@c7 bWja<0~:~@a\q@i:B=X$W jR{E[.?cDti;@fK;WȂ?0}uZE@&A TΟ *VLx\*-PzC T.+/"n@ ֱ{ \ٿ[ Mb{#0";S~i8& .G]6 D 7ZMU_R:YpPBcXC<9fslPA0]8s߽}#\# v‰L⡅:sol e'L//;^!gcD's_ɱk~uQ УЌvƖЎ%s9w>dmއTu[a=^IޣvLƯ]/!"܄~P&ln@{-ۂ?€,Oh@][]h{ٶ7\Ҫxp Q!96Aª" ZP"T +D!Q 5j~Oq&·|9nE2E:۾dVwfڣ%#)MUK>9r6Ӥͭ@e^GE̕жSL0]5u^}L;z#MP,s~;|dN}hi)whLbU~DLޞsT 4yVhm*c x2DOWMF̳%|q3"5!,Րka=1vn*O3!дK*H;O)#AKփTzfc1\ ҲQ lY{g,I+dWgN7RDTMs)ފ&f!Yd_H꿱{c1 9W ' Vԣ5xX~LHKRywq )E80r;. +kɎ9]h PC_jF SfRoCcd%Lɛ4} Pgzk_;Z4[886r RMc>Gx,<S|Mxn(Z8,h\ʂI^G(D EŚKhקȻS :wҁƫ)j8Op2zSn&x17uus &m2I5v[ZPD%\| K+D*("3 Ph*F9"ݟǥFΚ,˳ uxlЏ]B[@R'Yy 88b,!DkEel/#Dk/>@Q ;/F}i!H9=$ov.CSRqՎa*'s n(9 <^H_TWu"Wd$Gi}-Jml9̊޿xn8YO ]tC`H 쯲ó}cMFpG-^9gbᕿ/[ن>\Ì{j_?@] M!$jOu/@J(2޿DosM.C(Vr;cHZ*+cQT!kDW K|WLEA07I8 K y6{| -,xVJ`!`V&r/hM\s"9+ [L{)x!_BfEn#[_C˚QB9&>z]3iO! V$1) BFwoS?4D.0-gI%N}(Tv2@x$w?&p}R:sB:ic2> 7q![ h VO &)CXT=camsy) `=4ф/G) L\BSS( .e|iDV 9]*_$U_0nL RAu9!S DeϨGD%Υڷ~뷦9DaVbBH+Cm..ħ#4/Iu2DAګ nz(>DAS{7Axql@QP]KKaIH77R~~BαHˇJ/>;w@vO6ߣ  [?؇3'g'k]y="̓"pA #xs\%40[a&TNsev.NcD8 U EɃ:7NB. BYkɺ Ce(CO_k0N"bW8Γ&.\!)@KX%48=$s CeOM"D/E޴0nc9:ťp") y_',<8IdmjaC$ ԧ: #84''al?XpQGz= njM]6‘XkLb*{꾜-O"ww!c ע[ G aL幞Fؗ+m)Xs}Xh_<Y6Op;|;Vo[*o~0TLGQ+D`ٟ mwDKz_7Tc?f:Eg>~F1& B4EP#FI%U35$&Ts>HLT*= ]4hPyAuN5kM`L;Mbr7ntlGh9LDTL a%(&ִaý|JSx&O4%w@1UD5Db r}P|y|>|O|v!ߓBx>$lSĜp]vzuSa  >=f .}ۗxȵŗx9W~\slgw6cܟږY%,VO dƮBHEĮ[aFG7!{mDW; $&(Zlp\voBDcu,!.߄(D,Vby9?%ߧwOlEp+6xC9~E["o}kN&M~<Ɩ(NuUޡv RfK }>>;0B+OJ]':?7]s-m놣*#Ȑ9 !u* vlpD Tǁ8$XԎSHML(ΏA.A}0OƖ҈!zo~"DŽMvKDeRS~#>KcZ7u1IʵR OKŲ$礚?yeX3SŤjT"Cm}TbȞ:]30[?DŽ,M@:(\_>ۘԇ_4sAfE!8}SHSѧV;dN{MQ1Acӳy?S f`a^"c]4L\Y_>ڌ \!!e:|lB0;>W~AVR4Wv%+i+^eM~3R RG犌 zpD^QW3[QNe΍M]@Mn e39y7F:գxֱ;T 7tiL:0GIحI$0wI@fC'*YeuM6tϲ mH b|_%G`%U?9_` lKdD"$ipʠ:W_Vsӱ&,}sz *P!"i-"r&s1`XG"634V☴OFp/dL6^F+~}}58 ,bŒG̈́ٴ_\Sisod_?F @53&8dh#>|ߤ2@$4i<Qfܾ _MKJ[ 5 a){0x5(>P)PG K۞wߝU-f=9 Ց`Ǚv>F8cn[T sL/,rMX3v?M dʱƒ"L0y3~\oLRstbqox )' ah>p%_޾f.ZGU?1Z ^,- )ZѾ!bԎ ́\8FZpc /L$;pQ C Tۅh@p=`ŇL8m NwʀKl0O~(wmRԬ%PPW琀jƶ]ԥ<7!T|@ LS_K՟h%iP5?ƴMY"妈[oSa̸ŷf Ok_9r,wƩ L}y# }".m?s}m3|ン V&插>6{ V]Z(\'`hj]O;w}bhXC 苰'VtǣP1gh ڑ&^'cİxƇ:DBه&#\-5T]@ / %#CS"zƠf@ͦ`[S].6Dfڽh_V闵i[@m!^ pbd% `;v}.VeaDňuGv 6Q^eg#QJk40}cgٮ@‡kByLnZ{^Of"90e_سb!1y@QY!% $h#cYBE~SpF%(iF ШoL0v mh@C>sI6[~(ǜ 14 .9S3~HVm&4 H9O]?śBeX9[ AiECl"1fhDml?/Nx3pn_^ogEñ˱oG%C4'ֿvȃ߳׎W_V bVRᝲh/<;sGg$hw:T^P3;~ t^d*,=S Cua+4RǹȤr="[vh^l||{1FrBdRm4.C45:i`ӘTVc}h4uo&!DOV UC bʥ\Bjmc 5oN{&-yOc%esE7vhN3oX G%N Nzd"G({FXr+Bp˔C b`Iy0DV"~G# vnjVg\b1~BD1ڒsĄZ<B_UdH bP A ˉ6;sBYS ?\1֬cv5V1fiYC)OQwd"Ԥ(wmǵV/x R{id ϋ*O`4%I= bE(3Kf\Ҧbj/i?TӾ_՘0qs8:48ơ@JL+[}I9v_=i$>(9Jy%L#u 3o=M;iLI#c_e".r!XL^_4} 6n~J^ aΪh\9 !V{tuMę0 P2Q1i! rT"!ihyu}˽k}h3%pƠ}[3FFvh vT|GA77 נsr?6Œ&uBHc8D{4ZXS7H&OǝR~p= :dO)Q4S*)9ScwpAcEq@:PG# 9\.?RP !k!gq/ƱxEpz%||3Ŋ=#KK)^P6ͱC.`Ƣx)٨l`"j9"Hk>D{_H R-YyKN},-8YxŢY6tYskS.ݦmm"mKdŢcj~ vGV!+HuB:A&`'j_H_K}g,XK4B4t&cIS;,4 1*_k]x ="i`cM1h dnGTkWO,vC -@ÜC(K</GBTiKPH&uZz[ҿIM-Q\} .HXv znBh_R+`]4ޟ觉7rF {om}4"H; dրlO* %TcxHg2۷ᓕ V~Cc @/$)s]  am>&]{MUstWe$R 1}g(`.riR%Nc( ?E4R7@[ iN~jE]SKRO`.Vџ`vC, C=Z2oT|4P휈mmsʼn0ta0*s8?$܅ 5IpRh?Xu5$ 94gED'pz_9M'*t,k«1,)t|L*CbhKGƱ?:p:ق`xr"F*9Г!#q.D "ÅcbNgNb"K]A,'hΓ8As|_% t_LY;As8?Fiv),),!lh1[ptaJ=Wd,"2LΑ?B<0r8{>Ӫ k Diur;A3_1Ehh-uvəP8!& 9|w Mo&< O9KZR񆃺J8ۂ@"f0"j C-A zO;t7nD/$`;߁cvN3t?x0F1g y?`ށ>>?B7BPu>!U!T]8eIr4rEkbEI'3{i*t2x^ E'0DK}fώцtzy@0 &XoXׁK!QU~hr۱C96G:&;96uІ䠆ڒoh+LL)F3$(|],D sƹQ\?(S C;h m[}sSS$qA6z,Z 0lCqgfВ\ lnLk7s/9os]傡B}^Qlg@z#(:jO&?reRu;;H+c'j lncS1IK.1eM|* 2R>]ô9yX߅ S]A;P1mB !!slqwԓ󘟘^s* e}(@[)4BVsQ\#6b $A{ommد&o8uCr#` <}u]aK.̈́0>Ss>H>ş.P,jl|HƞhM#9 Im YZ=8FIFY Y=X5ax#jCK%wS= j~ <{'ctOx5Vcd%7ǮOCP4VV!$:n2k\+;w R/rԟF_7qjo}9z55  "*ro}J?|ʩVת۷U}͋:XI*&R0M1BC}mQ9>E'3EpO퐶6{ `ʹ}P?^_dps/>{׎\od6haB2}伳]4Vp4r/Ql6k JG2\Ʌd-r*Ϸ$M9Q]sS"&f9~kгdjCgw{(9+EU-~r0C#<[j,yC=]LL p%5tO#0˧?M tDkeۡyri Pš\b-}}NZF(L0hȸd#js~vk lQAGO?Psf(}pA!! tXenss,X9d"*mE~{Ly&۰d'\]ƒeP.⹦oa-#>5w"67ۄvF{j4+Q_%U|b O>P (Ba0Ceg a-3. (OM9K`I'賺vfbBj!3? mC8T!pf=C}P$!p& 8t+e1GBk^]9|EH>L;L71L$CcՒ )rf̡ u0$VIC B eX\ܡ8N9|cs s@fs&VPPC(9~` ohvDZ0HŊ;oa q'."4zobUpʄZlnm}"5b;E2.chehs98?#յI{B˺ Xr i$@,| Ih@;iHS_c`|kKUb<Ǩ8A lΙb骓!RC6w>oVBK+z}>iB>;.L$+^"Ht"CtB1)l)du?j.>/~b@tZa9 ᫒(B\  )W™lӎi}~ o"n 5&-D.!jv98gA4 \l=P2Κ8FqY<d <6&SQa~M ,vjBxCxg|3?Vߚ(dZ4LsBx|DԷRxkH;[t׫ea3-eL_Y,%VW?' wlׄY׋K'7.)275z`?4_{&@DHtw$6g2b ç\ >,>,=@ ߵE4>VDtb"}~J?xcA5GYH>°O!$͑krP_$ ,6;tuSDXJbM?u ?+ 3hm)2*X)s}➩~u-!Ast!\)11Dw`L@X|LK>t]qhY?BE"Mk C%Bհ[K}I;^٬@+>֘0քjBph:w}613ߪ%&"irqSC_?2$d !ߋfv_2)փtzX^$҇h#h eAC3:d5fΑ1V)"`+h L~?#Vyl 7O0Lȴ el^vCL2c)f&xuU7m.,9쪯D>@gHܿvI @Ct:8Fft9i)c'\΃͈~)l}Si IuP;"bu.1BP(ld= %4\;/֘0`8ͱ{?>Ѥf=krq {Y@t'P:E4Qfa+Z9 |<;@g,D=44C@\'f!.!C1AullQG4Ek]c^(0'Z]B!r.ERgaCfTGd40p}p'tu?VA=Фԁӟ4,[룁Ro2AL`ABjd`h#]"\ŲeM1l Jk2I vΓ}JSQ_ٿM}P:3_cC+b%\Ιr#;UV4vV|Cyd拈"DAӡ kf_LNLKZPD{ԣBȒrv=G;q*BHh,~ďy b"wt*c;F♗l{X\gC/k6ŌK1 }cpg:9ŋH s?t/6Eљ$k}h Y.Pc j*09I W4>&L91zB>"엵~gm.L0\[Eb>am@ Q Г9и$KLɽB |Rr0cK@@1 vaJP;:&‰ e% { 9*2ta6mird!!= ݫ{KH;"XW"h8 g ! ^<6 ;yIzB=a*g,1 yy4l@B`IǖɘdU7Zg6*`0K̘0`"fSg[>;j)jEcU}8 ߰_H&t,>:haD ࣡y\r97R‰?:5E&PZp&~R(hR?WKoʹkDŽ9(UkHBójġ-Vj5sX!ք//@9K6$&CsQyW!$;ıdT >wqnlj]DB=e"7a^f6{jۺ̎?<0Ce((DسH.N ?Զ۰Fzh΅/ ArQ+ g}p{D̄86P}}(=k9Ɋ+ π>V!7B)5>$>*e]ַwk)c]C1eTw_{o= _A5!kjk~Œ*{gssJW{iz狪Hjj]~/P¥Khmiq^#e@ ` ?MViKAe\V:MAp1T§T/;n SKKlr"Q)%P!&MXq0֪e\#4T>Wi_=r,^ Xw%p/8Kewg!y `UvŒs, "tiTw) v>ty]uԢ1iQvv)ﺝKM L @C}^r)lQ"&VY=Ae^V*׋ ę53-EK* &m u\-/FT & f%tH%:sAr& Xg-c)|"K.-c",VM47O_3U5Bב}4tw4~[4u:ñ1l:j!qVU$.kivryW F"%SCa?L3 Lrwƞu-Z{/t ' |bQNh_XUUn $ឱb>wKBQ  V;KCBHZi/[Hm;"BYA+O}-ǤaUy5~ C%V]h gmxN!!Yt}r‰;`hM_^+XI8%4#s_ K Z,5 C\M I? ']Btzp:0~‡}R>{¥+?a<j' aBa4X8CXfLm$x|@/}{V!` B{_RKN8{tC}́ "xOCRv&`@L7 :YF1pFD áb>6{W ¹v=NA0S׵c9Z.v#uc20!OG‹I )T-V I]&ƌCI GhM` C|[ BkEUh!ASt6΂fjC`P?>fſ#G3&m#5KLhJ*uTFC s5cu{m@a<}̩<~De}h7DpiBu|H: 92?kI`+ȚhI hVUCEb.lgbЈ` d58;X Dxtx]"{zܤri V&>LB?+srO B TS@ޫ  h}Ro&bB&yHtK먍)4 㦲OO 45?32/p;^Sg&bDv.ls:7yÜymͱCe[x}8B'0̓Ck(k0!YZLi! nxs_m+< .`E7BlӬsd&7c5l׼Y+QFɫ&3 3UE5Ms+`H΄BtiOP|i!-#v 14rHp̻S*=HgjL3t! NwC#&@Q8Ԅ,Ѥ0Ѭħ;<Ҩ!UZ)3(}@Fh1EQ/n" 4|fco#b8=7)u%a9"yƫCZ@"`Ob ZCct'@~p̴S81f4̲p4V|fQ`v){n uV-%r)jI,6א`N& mx 4EF!EMgEQPͣ HHŪ&y"b:E@BEcyы^Ţ'*(ڎE0’߄"(LEh.4>&QsZ ?'R]W}}OmBÕ|$XNQhe}*Po.H!"mTHc96;l2<۠9D.t]t"DO $ gEIA]8`),`V5VOK0rOp (q˸!]5e}{&PG/!(-JdD8G5@~b=wzjihd&@Ct, )IƵ0&PB%Y ȥtP35=CRygIEPoKXkP)f=3_S1iaiiR+]tuUw8ji"Ik˰L8r-ϿȏɅ T>"=Ix8)ڵ³ZY9C&/͡\%(S>)PE¢k6eBMZȭS6-dAj oY8Kq]֚P.7tOs]zc<&* ?ĻM8[[Z?fZ6!$Bsa)>r_f{ǘ&-W -sVDD཮" 撋v85h4A§B ҅ jx$JJo~yC2TPrC CH{|CܿeH,"oHĒϥ$| POkD?AT.LKWC$P Dr<xh'XZ1UI>cB{ EQ?│09&'&P} 6O0 ##_ ?:u"E/=]4N41X,PUR. eZ'Lb4@r,Dx[Az^'!ЛXX`_xC$G!sȮ_1}EGs S?vԈьOS `)=cdQ|pvIRV.aEӗjw(ʞ J -LsW.bLڃP_ۭ8Nt5}H=/Cu {M!$^o`,v򣵈D[ sWX4cԨ1&&A s97LcS:FHcyP%rC3yܤil礍r LAv h%mU,UӼXt6]7PVzG=)5jW]S[Q􍸔4j;3 xDtn `wbXB@/΁~mAT3E~ J (!x3{9yc,|NK/Ld%U0C@-&|f$Y0 ›95v\e򖷤 3jm4ke\}z`jQyP!`ОyTO%:E~c@5h!oi- |u:@@t[}5%Yyў!Db9ʈ~]/d1[@r5,t48uMsEa|K^Hi$ٕK*&" ֥ZFھLC"5躵 /svk8/!Oy`` =9t0Dy׉BsՉ3sbtS앮:(6>E-*ip翤h4䗋qpOZ[K4)2qF)4YLzГGE}U@]4.~b?%b%ri2O]aS۱^yi|Dd(hv^y|眘M?($dƓ~*!gM4pN7BO-v-=^וjP7us$m9v7s~cv19_7,+X,"xw} l)cߍ>vZL$H*WYnm5>Oɡ}T8;s#M5[IO9D2s۟ƁZf&T"z<9[^~X݇hlqH &nS!+hHi}{k&δqJd:q'ꋀ~dA I)k_:d R} 7:NgPuؚJ>nJ|E[`8`^ B?&5Z FכNap%e3)D 1]u!/| ;N`qa*1Q<\ BD'Gx$ɴ 7骒 U} Vt6E'a3544<\ g <_sIZ 1H\ׁ^WnaIfCu^!nKDh&sD W@yBg^Z/r§}4188p9 \`O 8'KFg?YENH<=TVSGg%̒W=p'T])$/,`(_! YBƢkВih8"ALrOJ>]H J\&|~HHՐS@Lh i4}ٚ_ O2ܧCb5qq$8 JR+\هBT?J"rI36:~MRd` Q_:tHn ?韾>Pi7 <DZ*9ACrp:2YEGvcb5h׷oh(rOoov`S?S8/p>7|G}//0˥F軭 AҎʐg.AL H~6y^  1FF7P9 "#ȣ3OÚ( 9$R"|`NڜˁLgui>)~ik緽m[?F$u JG^쓞ٞqqq`},5Ql 5Vk? 9zӟFy~ZΘ! fL7Ȩ0 'yǮƹʛnȁɜ\"s_3O1'LU[򖌆8Ait$|=;hɈ%zs4j-OO]rڵ={{Υ2}8L`p+qqR9P.BnԄAg<-rD'In*=i~6!"e=0;HOx~|b;Tg_r1y@M/"MV.C{sqqqD8ZMopBF5@|)O~F{sz"<|o}k-gU ^}mFBny) R݃}o&ݕWSQqဟd] (r?OȆ89Nh587C~.!co-NW @54\.*TVp@w݋*D0{{]Nٟ-h@I@ ER3]$۽n"0&ɭC&h&q^Hd 'ǚc @vƁƁÁ Ƽ ۮ*}UXW@@u@?o8Q@q @vƁƁƁa?"A?ĭmG@8L`m+qqs?GPiydʆ.'\`.M8^;54@ɆݣٴkVջƁƁ4hAp@@Z|}]fW.ЇIEfx54,@ZΫvf@@@@@p9Aȋl888888MZΫvf@@@@@p @'"c444444,@888888p"hЉ9jg644444t"/=FuLyc??'u{ú[n_s%e䊒>Gw??vr˿{׻}|M?گL5qgG<ݳή//r˾{px88pZhi4גܽL>Cv=__RE/zQ?݇}؇uzkyN]!;o,닿}h^CYO{Ӻ^Ww}c;yG@@d"n888pMegxߟ7q__7yի^J9s9N"yK_z}&ro|Gn;;77o>s>ܾqqt8Ra\=Ap૾ΞEjZ}Imtg1y}ȇ|Hg_g 0?O>ɟOCDs_G=ﻏ;~44t=EIp?= mPW{{}~h -l5p 9*T}ww&7\44 >k^oOΛ7y~_z>c>&x}8F7jh8=4i{Ɓ^ 'vqjj-Ѯyɯfʵ/r \kƁƁk&]Ԫ88u__хswFw=OM}vW8:waYS>Sߥvn@5r=5yVƁƁwT__"j,qwz"gg>O[[kUƁƁˁ hk5khh8ڞH#}LDSHJhhl4@@@@@@s]8 .M7888888phЅݰqqqqqq9~΁&]8 .M7888888phЅݰqqqqqq9~΁&]8 .?vsIENDB`ggpubr/tools/README-lollipop-chart-1.png0000644000176200001440000016667514334142177017463 0ustar liggesusersPNG  IHDRZiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*iРv@IDATxU϶BBBi@BBJB $*A("EA_?5H*5 @@"!!$!m2fwܙs;3w=sN  @B(;A @h@ D B @g @@GŮ @@ @@(`+ @Py @  tX @ h@ D B @g @@GŮ @@ @@(`+ @Py @  tX @ h@ D B @g @@GŮ @@ c=fEEEx₼~.'=; ֬Y˗ۊ+U',//K C- t \ 4].>^&BTUUٸq/57ϵe6-}!׭[g_Wmذa裏-[ĖbgVqg_Ė2n >؎hۀoeozJt 9l?Z\~[Vz6 >;<4.w}V76/IgpM7~ݏ2SN6Ǖ;ά•*^mVYl}vms^jfq@ $o*B +IL:,wc7|=gaͳ7x#?ܺwLcAJrVe*r)k5Wٰawwqm6j_TܺƺVXզkGIXv-[s}1bv6l%ݲ6۲ܭGu 8Ər O'@Yxw=lJ{&۝wFeo=v)O/v(*u(i%swEK4 w)(ֲos^'t_ZqA2g/Η{k!O|9M@P@hv:kVmW tS{,;:t ׺vڌc?q`_۩sǜϥ ,ZȳʷX>߹JY!96bdlg=<+nϞ=YtsH&P]okV?_k%m!ǭ[5|՛[d (T(Ѕzn4sC 񬙊/_9sxr;vn# @͗{(9 P˗+Ck0@ t\$ @ Ʈ n3 @ H @@A@.EB E:.@ PP 6s @q@$@ 肸\$ @@\P"I> @A n3 @ H @@A@.EB E:.@ PP 6s @q@$@ 肸\$ @@\P"I> @A n3 @ H @@A@.EB E:.@ PP 6s @q@$@ 肸\$ @@\Zh"[~}\l @(zwnE@ (:.(@ @Et@ ! I @ t]dH @@(i@ @Et@ ! I @@i]H @@s%zK}g6}rNmk>A#@  jt&W/ ?/imJJȾr.&.9#$@ |"g[Ҥ򬲕;wfRLX0  @@RUmEVZ6 (P@ %0vFڔ F@ N[чzYIy& 5Kca, @ ҥ=8{6h>;V<P @@>PVjC۶~Z,\8bIf @- tK\ @h&6WU٦Xt\8P&@ P`<#YA7c:/o  @Cஏ>߹IN69 te"a.ᓟ#|+  f~h싖Vn)KIy:n @G ͤV,ѕJu>QAΧAY @@zMyѭVz>$@]  @ \;_o@{gСsXkW.Tq @ ~'6R;zľVVv^B|Bf@ zimey< [yxS) @Py @  tX @ h@ D d t#a @ @ W@'g={3<֬YS:֯_o\r 4ȺvjǏ+V؇@ p\=3g;*7߳}ڎr.ڰ[ަFcwYgٖ-[[o͛7ۄ #_=IWiO>|֪U+ l̘1o[QQQr? @'UvS/itϪ#?{>ܼ*s[Ѷ{m9ljT駟_|x {=RO=T3ggq9sM8~a=zϽkC)Sرc[} 40ӦTuUʒe6}~E)ϾB<'mOuV[4 nrg]x?uTݻZyB6M=Ƕ[ZR*Ai>mӦM%iݺud— ]t@'z=L***Rc 4nBKm[\)?tj6+.dW﷧wlw(-;w?4tmf .뮻ξ򕯘n%KTf׀>u떺+ @_PVjK}7i>.AӧUVV2 a  @MDjnpZ6[)ֲ>+*G׮]kC @@+кHYz5 @ |"Ш.t @@Ά@ ,肽\8 @@6P1 @K`o=@ lq  @@@.[υC Vm)/٫k \Ms @3ӟ{ժ [U^acPljlX8 @uXq YmUnthm°] Kv\8Z-!@h(Lf՞>VW @%A 8ʫ4IMiU\l6lZ"ݢn'@@cةSZtpؾ1 t#t 7%h_.s;v`a \ @Cwv6W߰7]㜜4&Cω!@h :O߱-]Byn 45‘;@ @`+,X @@FpdD $ 7YҦ%]HP 4 @ ,޸N}vmq1p;mM_0JЬ@7Ea!@Ȗ*O8޶[ّ}{Hg>:l @"PZviއ-!89  @ML)ˁN\U\fa@> 4{{ 5DxkLP3b; @-@mlqyҾ9Cw3 hE4@w^@m:٧nɯnCm2pO t\ @--~l6#ŮJz+ @ tFD@ ʂ%@r$UƲ嘛Blce)N;'@ W(йx@<~#V-W&'cr*ɮ[JGuVHإo̴oc8@vOtC o]~5}~ո:ᖫfuQ=-ݴ)Еd'}߶x㦬@A:@(p3F;"(R_4iyΒqL55X@c@nl  tnUf)dCk[ܺIoH<&7A lo;v`mw,}Qe} / **>vg.YɁ@#? @ 9٣Gwh$%#^=뚃tڴ_쵛=p؁HK7Dȷ;By @͘evUlH*:[ ˗۰]C XcH& @B ti@,QJ;kFȦ0\(7l6,j3E[3m 7oo}@ =\H dM Bxl۸17lc?ݲs v곯x3.;w_=^^N{/^2Olv!#Γ!P(p(;uB@XwlÂGy<ċeʰb;dT[&,9vǟfs&goi/Wj!]6A@~*_ek>VϾWό?mg]akKis09[^u۲ͬ}ϭ}iN;?U~:HQ3RԥRAO: @q6 @yGjR[Κ,r[3 6>k˺bl,e[VZqIv~E풖gP-Λ__k˘ˑ2rzt.LGmɎc PP@b!4Or* oʻo~Ϫ6/6/}rSݴRZꙗfVT&p[.{/կi 렴r xޞi#msۜmY8͍@ͷK_]L1@Ob[m(**uD_v:]e_-^OpC.;|KJ8evKӺMksVcLF2}I]ߞvuHeeC}ٛ㏴zd?1 -@+гg϶::udڵ۞yHׯ_o\r 4ȺvjǏ+V؇@(L%u+MZaJlW۵…+m/u+5{8x Xa6(lӏnj sX;א1ݻ]:Z{26BhTzʕv۲e[n'xz)oV o&Mdsε1cƸA5-X !mk]kϳ;J~}.^S@ZvEŭub)rhsLE!4FD裏ڢELg~)wy >fΜi'NѣG{{6tP2e;o@ v?sԇpVe{־ߩ9a}?ڲ>j`֊K'C-@*Æ o1< kǎ[nzjԩS7n\!Cl6yd$ .Ͻb?h+4G6gu;@%P!ΫW_yو_|4g޽Dwǒ%KI,C @ 4:6l`7X6[8o.]j)П|OJZYY\f&=Ѵ[V|K݀'U]p@LV;>c{u/YS{m=kZ zi˗/7MDY 3@5 ۲U7u38=dU٦ VrV5Oa-Q1mraW@EQ-Њ|1؂ 쥗^< ͡jrv_lϚ5F'%/m+:pGX5ĢOk{Z}7Ziu~mz)9{ZJ FUY'hos=ɟ%{챇(_tE^tM#GSO-Χw@h!6.z6/})"7iW[PQ:( XyVyj`}.r3t}NNU~@  n٣9#=Cyv!x9u]v)KL @͝@{mbEcEmTnfsc?]2Q[jw'εjo ҾIVe_[[~v;(v "){キm#嚤n6Xϗ^zm){X Z ӧ{S~+*G׮][Y < $*+⼣,1CsfV[f[QϾY]&)r t"@):*?Tc{KWXQ~5"cN;Dvw{~+W>@D1c)Ɛ!ClѦpsM7?hNN:Ȓi9%}+.c\T *pP{Z~P(< DRu>Mf"Y.1tФ(Ϣ@M Uyep/rq: o]eb΅^@J $\_vyUk_[@r@6Ϸoh[f[h3^&1ťBuJ+*F_,}P.dv_vEZ H ^h_?{W/}vXyyͮȋKb ذʿ%>tQ}ʿ:z֛Ynv[ZNCinC_eO#Y{Gˀ!@E¡Rj;眭hFip^;E TM}¹gsTq_{V'wM~[͎ߴmv"8 Ph 3ΨB؍1 iWk# R T*(OĖMI;?lϗmNOY=~l"!@ h]w"&stA@ @ͤDHSRX .*zĉD)R?[XӦM3$?=@!R-*ss~G_Jz\r( @qDRZС͛7ϛ0XەW^LO~??ªYݠ}oyF]cɈ1V9cm.;3u4 @ME dɒ*'@?':oBp_96`KtS> @hLh^{5[jUr>zU+@y~of.JFRr⣙V=C+s2@@!@r-6a[bEZ6mX;Dζ +9Zi$@ @h D*{ ׾%⚋[4/8=bΰ'yQ$֮rOMrĊVq#^$~΀EVplj[f|fs^z/Ȑ@B[nĈO&fկ=k玵ojO?nbKy)VRj}\5›(/wyOoECrY|wZM]1ڻ7\39 @7? 6tZ?xygf%wNUu~AԢ%/*)Vw`~6_gC @G _ڴic?K@BɳMf.NulE;f]D[5߲ Vs{)݋ϪJ~cK/U|<˪/nkCYF;eCL%.ҋj]&ZUY9'@ @$zɒ%yC׭⧧a]J~W+{r+snEMeWn^6 tɁcz)V]VʬNVuټwg mg_YpϿ/ۀ].9O2 @@7ˢKXهHwNWZq Y#Og@ʹkeN͇`^j݇nu  RJnk]3WQ %zaMyV=zGjRuM\vIuvVd" u9N,b{h+F`,@Ƥݔr i]e߆*Z{Uy۟+օC @@ &ԂK+&qR$bU®mu=xTC " @Z\v3[$\ҫAޙ@ : Q'ߠi}Wa%cN}s*T=-[vl38 "VTVwž#|K,lVp @h2 tuu{v9µ~zKlРAֵkW?~X~&$6mohbbnk˲;rVVq7VKrʏ!@@([ls=מ|ɴT&L`?|6i$;w3dCʏ`OfqJ5^s*T;ݪ8ˢj#d1 @yLzˆ f>mv̜9&Nh^{=<@{wߵ)S?jBbFQa,AI,[dsI^lϤSF @@& mf}3f;PԩS=q% 2l';E5gqniY\m!Rڶ3KBݾc @9hA_~ѣNFs̱ݻXػwo[dIV\iJ2M~ՙM[+9GVߛmٜܽh#{zαhr+L_% @h]OyuySuҥ=k,;㒻3~wYIK-)'e%2OԅZgږʵ;h.*Qf@ " t/qm:EXk{ /L;#˙J};D/]v%un޴Yg;S91@ ݫW/6mZ-WN:HQF%)ɍ,@ @ |b8Q,zi˗/wA2j3yaa?@ 4S=PD*/R?Ssڜ @@)k|Eټylٲevyȑ#SOmD4  @ "u]VVVfbFWVVGk !@ $ФOg&볢rt5~$B @ 4b5 @ |".@ @ H:He@ d !@ $2 @2@ @@` @@gf@  @i @ P3b3 @P4X @@( @A(A,C @  @  !@ t@l @@ t @@: 6C @ H:He@ d !@ $2 @2@ @@` @@gf@  @i @ P3b3 @P4X @@( @A(A,C @  @  !@ t@l @@ t @@: 6C @ H:He@ d !@ $2 @2@ @@` @@gf@  @i @ P3b3 @P4X @@( @A(A,C @  @  !@ t@l @@ t @@: 6C @ H:He@ d !@ $ t"e@ 4)Tׯ_o\r 4ȺvjǏ+V4)(N@ Kz„ 7l&Msژ1c k4- @@S(m̙6qDO=z{ﵡCڔ)Slر@ F#wSZVlܸqIC ɓi,@ @)zΜ9ֽ{wOݻ-Y$dնqd.I,@ 4S׭[ L.]R_y;G3m۶,SNVZvYYYYIHC1kn2^G}>"/c&2s{WiϷo=⋓i,@ @ NJc*U^lڴir[zu]~/O. @@4(AJ={˗{M0`@0e@ 4:S=PD*/RƧ~jfͲQFo+%@IDAT%X @@S;z=.͛g˖-;FizjS0 @H;Z%뮻>}Xeevm(dY @@ȻAbӧO%%%i5+N @ Kڿ/P @@>K|DY @ $2 @2Ȼ3͚Qno}tY:*O)8l#x QjGBsLϣRUU2r8(3<z^@U5wpfº_|Eۼyq~RNWXasĈL'T<7ڑGiPW\i=~ַoPd_bw;6ӮZʦNj74AvzWlڵ6nܸ {۬1}Yg}ʰ_{QGe35k֘*;I4WG=ymᦨ;qkMt1đ[ΦLb{ҥKc%?ꩧlذa;ƒo[xwqa{'m=v);K3fBێ?>lb&Mv͆ Ko}'v'ƒ_yy=뮻СCcwޱ}-***]vőks̉裏z 2d4]p/Ol1|0+7[~zͺ[~co-3<3zb)^?Ŗ緾D׮]cMCly~;IsʸW믿><9Db?x5Ė"Ѷms Xoc~UVr^~p=_>^_ǖ~#/ϸ2tF/_qeOgXu @ ݾ}{snaiiuԩ^'򹌻ڵcCcǎQ׹_Fgmsđ2FV{B(>q>Peu%~[nW&1wQ.zv|۴i؜ʨkSZ 8 @(h t: A @>(a @R@aM@aCB{)R:Q%P"˗/);E.0@@:{xV\蘰OΝ`lE1m3G{ذz}G5:CwҥS6sLR-N3ݏb8i+gb?{ނ1v.\h(8?陼c)d=9\8Py6ԽրYfQٯ~+?ic.1Cv!,2Nibޤc,qbL+>y\(S0ߪ_Z S\+\xd,wdoRMZX.lSO:AϷoE\]M㏽o+v љU*_]1[AQD1-[m]޿;~zEQowab0L*z.{s`vzh(f$1/wP^ANuY^xKkx!buFG*-ܒpi$\D/)++"+>S/qfUl P&m+xW^޳yw*wzbC?O,w M]rn?7(>SBMptx&\s P϶vRɪcM28ƾDygc)w ͉{M}/R齎yT54|n\T{B} ׻NDH-1`(n~t{U.^l䣏> [nOd!:^nt:yc:\'[ ^@\e /gotw9,yJWKLZm6o|߭j؛Nmn/SO=ƌcns=X&KZogqlbnxlu+a)u,hYGUNX5[%R@u]_u/\Z5 ss/ѣGاQόz3dArgE Z34X\wmq[Ck=NFObOY?݇ePV4A%V/~`rˮ!dnoSCNKX~'˸,?p|ԻWG3}UW3lxz&3$x3y&+,d\ֻ:FWG: q72ZB5[]f?A3՞|ɞ52!wP I˸mY=3y:}ϣk83xV]8fYXYk̾}$K;H'=@;7MVl(5{}{l9 /#dVkfӬbQVF~U\t?WmQ*`n{-HꡉBWoRXLzve)OR=<j;8H=U5fD$Έ=Nz4%Q:]ɨf57(Εɳ:= Yf]-Ke͒:]Yw;/kg&ih f?u.Z^14Se$o?GtSy~j8R*AJ m+ossz\_S=M"-%ՂzQ)x325˴ Efؼ馛e"Ε{wŸ) ™;I{狫N P\"^(wwZP=:S~Do~*~X?r쯇ϩ9`&LtW(_`Y3%̠_Ӊ`/G}#Mϒo׷J0T/Kb4(q}3'˨ӹ,`E${Rϧ! z*vPCos=%)Ie\vc^ԝe:H:@i#ٟab]?^ S}SEϻ0e\T_uG8D 2\^0O54&Kz&4uɧuw."M-sՅ/Q}z\aa 5 <V eaIIQIRr˥ ]Šd=.W֨ΊpR-hdM_s%XF}Uu{Rv}huY䣎ޗ?X>M*(g5;HW"(/kIu,SLILֵ_jّB%:5dJ Rxêe]b)Kig"L$]Hjބ*2ە)(R6߳k"˩]vTYV/`X- A+Y~1QF32$*WʨeSՋV4V`ƌEP)_z饞, >R^@%k?nFItTgˢ!onE f:_6])U9CF׭_=\q?z^D뻬wP=Ru~T,a,1BD )Io(47לH2oSP哟INYh!\,^?4ݽ݇NN?-aEhp o]~Qu) "zb*΄S3q*}JָYR7׻._FWoi6:+ȧu'}%5Y)i$;3G_B%\azfiI CBNR^R 0Ep'pN!M^˗^5*t~ƗԯwL嗏gX9 2Ѳ8KWD=MW}O~ySX^+vnxwNGQCPҲW"K"B!<:vde%2T|d3w0 G}4n58xv /0ؚ{ٞ6myELtu5yv EN9qճ~/ XW3 [ 42 :,?jAjjME(릓!%CiD{F!*xYmU(@@°"}~%zJ{T1yK:ѳ(KZ>U/zVԃ+f!z=FnJ]t Ewa=Ɍ܂npWOdS`ʤ %܋l-9(^ mhZ\D2+vY5!kDűUu֊!6@F>dk5 d-ƑךUּFcҭ˺QЊ~/uU&nFo-KSKfp I^;X(z9g׽g)]{ճ*L ⪨!ҳ.z7Q&Y#$g:{KφDЅRGL[?OE}>NGUx؟z:ThjJJ #nrgc<!t~S )$B'BFQW>RrUNPrM)~QsJy;_"Y/aBIUbT몀N0IJS&-EtUŻϾ#P:ꖕJ.:H7 +&LD9?JHaˆ:1TC]!}6)ElBݢN6UO[]Ϊp:Gz2^\T?%Nʵ+n*p\rP|;(@Jl 粑pN{Y`Q˗\qfu9h]bjDTQ-cJ%6RBˤ#P~j:Z=A+;jO9t/.\>] 5pk+|U22M5<Ì߉[I-KCLVt"w)QDx] m!輩f.7Ŧ/j!*\r{BSqgru`%]M{6(K1k>YϭL)=sJsq$ϊ&%{MշF>o}kmRL N_tDԉRI]5wP \Q"46y JT׶[k0ty}CL&'ukU.g]zTްRNeTpє":dqrQ`".ѪFIll[?D>~}P83x$MO;zqFws=Ǿ# ,aƭ!{'5hNpcJW2Bq ]h?ewJ9KDƩ_U.: iJjCXq$~MA@1 *d6*hs#̓iu-4MA&aE袊8z7FQΧI!48.7SI4*s)s4}  EdBLa!3fYvAoЏ:os]QE{4hb]ATNi \CثDOB8 ]lLs]^X:wAt4S1gs0{]soqPxem`L Ӏ*%wH,h9{^uLu{!TGHhwFq} NO= *\Fx 8T@ dڳַ,k&}vjXVzP*19<"KhCHX 7DY橮3],BnoKaD."J]5լ?(ߠ.0~ھe&Kʚ|?$  1odq,Sq `+0krP ˝|XDERz$mEӗ\T˧Z>r -ۊ gP =VF*ʩ:Բ+\ǥC+L^h˂Z|-UXQ=zFV?.BKgh0ӪxciA}"u&lr׵Sg#,x=x =?G1s|*xhr9n$چ[P&@UN)aIL/>ZR(r'Fݝa+;m(_%]cO]YFId>{``9՝8A% t.s1MS\4p&lOU C,5IGdSaD>nBPT+(%#{]\:k:(0]3UXf5!EY2X^代w[0 c=2$ +N2)9{ʤ-qNjշDqE4">$T= :W=w;'T'J׸(gPlA\z&.c(n~shlR&Q A}^_> Qʜ>[ŭD\-HhjakTFbFdD*i]tS/&P+Q-Mp`KScAD  (,訲3`@ E֠0*eIYU> kkYadR&ܗ>j\ 'K3 YEo//G(է_E#X(=7f $T'twE8$ FD(WX{) ݵ'+콩:{%C-IQ,A'vڮ0՟-u8y#l)R~~ &]B:8VVD*䜮=MzꊨX '/Czl=s~&zJzs<B {+IF\I?߂V Ib2ޓ[XZ#R$R? SyhM*OW9DC)FH=e+H0"*Pײ>z|Q#J ("K,Dn5ˆz?ԛ!f: \ rfzu/]~Ծۑ\+O;Oaez|4 ٸ{tQWՅVNI7@IqJ irL#bCԦz_PơBߗ0ji68 jY ? g{9g{͜gu됎 1UZӰ~ -|洄Y`- ?g.t_t em~@8)}[M4!ZYDeS8>go048+* mcZQ-yE Эp<+Jr|]Lλ>A$H7t(r&sŖLS% dv@sAnō`H@xZCnx웎I9۷;D)t h6ɩcifL8~XaO!'КD$b*08-x7>ڱ:3؂-. ,9p~Ĺ %X!Ь<ڲV[[2hm}-ʩP,aS:j.$@є7kurq],sѥs recCKRGB6֑w16ZL)ss-z]h%%4(ͦ'=iRW+@WoR2a5yJ2@#kh g{w0Yh(@sPnߞ2Xq #<Z5=c Y%\)c-i D,V2H[;Zf [f(eQ웗42!3E84$~{֔1(j8M2{X]8yY|%>"S@6إj.$@IcœZ&;T 4Ļ?h㖾"1 ESW0i2훓ͩs_H׮fZZZR!xբM16Yѣ]~n1R1Ïo*oAIe(@ OYa pw%[9T0\R=!90#T/Wak4^>(ep4@!幇06E@HX8Ԟ*o|`cY)ԁx=L*JM͚l  n.C}۹%;Yx0k#b-|G8M `E8iˮ}Оcɏ6q.J9N7\cB{P>я^x )j%ZcW`+,s(̯c"Ist+b U$aPV6 45H*qEcOL&%S 4>h)VhM"Q[QZd>B7R :0 4,@dfƹZ\};3Z2HEW C>lr!9X A],d M$0ovm;LR=W˩H-BW:2>YT߫s? |6dcu rej G0 INMtq,L`m"P(Qd%Z]hOtJF#Il=_2 ^q}LB,]%2kjT1? n\Vmk.!k`Xqp\8%@~QhX@`Qk|&Z'8B뚽R=GN1g.4WRKՐc]|{ckeۼƚ.Rư85Lu]NbP׬YcbרK(LI*d09֐.8̧r $I9*ZfЛzI$ga[_j0s_p??? . `cٻ~3 )f)'r &}DK@КҰ'U*dЎƋLSS =@k21E,hkHdu=(,d!0j9ib%81 Yk`,ӂȢ1P82Z̅hXBʅC18ȳD1"5?tşNHc2+;CdqHyd:ʃ8Zsܖ©ql%YSRQPW ,oͳ.V4L]CtIY{1u>9SRrJX͌^yW'JJ/HjjS )J{dq\ #<.2^^91.zʺ6qCG l.^B2S'iKiT뚲i"i-Ec✲o"ޜԵ-"nja^Ta!bhJ3gE>V̉\S+8gt̀6ܔ]CVz Ġ2%|-{k pއWn:O G+߸&%ĸ?$pcxp(KaK!(p)/>D[wH9'm%0):lJ&0vؾ1)~&+^!]+b{.);[8]?B "L{. O\6whfs y[Dlϯ0vqoQL0rMhoR?6<SX_n118)Bc -{Ǿvz<6W/㗒 mꕔBXR`V\aNs? u;E+?ș1IS(ghxh8VsjAyG?=_G bؽ'ВyZNyiy۲o\4kYC>%pbi3M6Zm[=USGٌkVq 9Lc`ɟ!gOhxjj6k^{e _%07Rkzd1gɾ WC4Pyr}J(XbF:VrV,4AZ`uA F:"8BMOH{ZϮMh6P t>fccG>'jniHپMv)c(@WLڐEBb)FQz[*@K(B0ad'x -ɢ~ ;4Ezs$XuŁϭ 7M(vi)UNs%|$83o~>O12W F%|[)j8Z"@{-:}0(@OZ q),ڴoN(kZ,ڕAoԡ ^k!)@s"HGxZzm)MKwoKI uc]ZVfF$\o޼i; F&ⴤѠZڨg" 巅SC&x,|\s{HXYK\&Ze@L|!߀<8*S66rz9k5崫hKkg]BPu=gZRqwZ'KE/V¥ttXi)? 4EaTן)[jqa?UJ ߮X@"q{% Vse3 PD_ 1d:zqLBaiK@2DeL'&-!0bp;msn0SD1A0g@q3UUWP۷m :koa VS1 {5wD`$8-jS>""D*pX"@|9DH*{27k{u5! 啌&C&BܕI1N>R[>e* /:c-.932,`EdhI r[6<\tfS`X۾O5|mKʡ-he #nwe3&6` kyY`07;˸hjTH3f"˂ṥ[3/it,@kï,n[cm$Vo26 X &Q\Ssx] êz=_)NVKE дc\i%9$h0&项qVF襴&ai 8,%!lX1~+0Ӑ`h2h,Y9Kj>شB)Rrnsda2`%f.*#Y=Ґ_Ts}ٗ] <,ieTx/L)sYleDPN6dZү  M1 &s͵Cs&|7ĒnǘgS&Z0u6V%}VOspc';_\8r5ZøNc. :F&X*Qz}[|#i 18?97T6jhꃔc[y窛ַ5{UF6794¯ YdAA`,W  1&w=}2%oٳ|fxmKۤ`b TY\Af\Y>F6SI'5"'{GLX%&kvI1>ٮKf/>h"B)VJ)0X!d/8'ǎ=L)\~tϬ..S%S>SSg{o5&BE mkN0'4)pk)Ϗf9IaIvyI3<0UA$E\5Ţ06'''c,s"Xe^ϩ㰠drXlfކexzo_¢,.d卡NHHZY1Nxɇ$Oj™4'ژs `K9Kh8=rb0_Nߴh,612)lk:c{-4u)O lx <_LI W'g`f} C{\S{[3VdeOs,#U[m {  T^5dG6Й7aLj|[ )2[#SZCD;: prn&sZ%,mK|\KǴ~1-k}.B]S[}O}@,%q}yfQ8,h&ͮO(0@buqVHS=M)|vhEFv~VqRTʺM{p@px-\Ū]t7~yC Qb@n!?5 +_ʬ?L9 30Kx~4lxڑUr!45ITtڼ_W\B-&4׹s"oͷO֣颳p"\p+cYXr%.`Dw0a{IQQFH-b9:E9'\jX_T4 j(›mhRYΧWƺrf>ۓh+Ơ kaa,B4-.QN1E5`z3b_)Xb0r'8F[Nޘ80tM)1,=;ΐG  zx q?YRSLZ^&Cn;D1@eHȡ򖞏 9g1hd' < &g8wj  Ă,#DU95{LT2,s>951zWm # {N.Vۘ>c? d|Q!0Yv85sRtB&-Kq&;ٹ<,O[CmcN_hXTfG"Y蚟E Kr2 m ߀\hM(?—>]mh\hA xFi~k ]pW?' 5O[[7O~r*QKpw9x  $Z9Y0d d:|_3cqY@p-!P%X6΍&xKΉp ks"W-(4nĠQ)8߈_f"r@mA2N&XOJ/uT=ǡ;֮%mvgfsim{D VyRoWH7 4.!, =YqmxqfZJ;K]p>c9W)9=L5&eLt !ߊ6cdx qvY4/a  觠ūWO6V,r 4EK!!+}oʛ{& GX,OA͠#uƒSbך4DQ_mK==Y^h Ț}G'aZaf ƸR}hG"s0m4nL@4Ւ6º@Vk!%`s^G`ˁYfE$5,YYS !9cl)!@]kᇈIZ8;C'5~h?||oit4[umENBjj(L{7ABɒyMzt,STsdzs"m sSz\3.ě6wj,C̻~8 "jLﭹ53,Uy<PG+oxNR}٘S8Ni|po KydiWINXV6&-'YR&" m쵎dVa2:05{~U^C,k@ `jICyχ8.C=G{ :^a$(Va95ɗ 8mqZSKolB3׬(4-9FLp6ZC:Uh㳇9y1(j(N6ohIIt}#,LCܚth@!rDM`38s"}E蜲<4XXt!Z<F@`mfa_pm-C&C4#|̭- ? k6CӜ+{ބuc;[Fzv=PfFNmPی'xZ85hwu_U]JHQD"WfEB8N481 ajLv~ >cw\aKZ94#lMDpMO+\ 1mpT\XKV0zLlOIN̟&9Tf]Xǥ\Ps8k0Uʹ?'/svl ^Qx<>DCdeb=%Z9?w%p2AFC+ء[C1װ<{-[C0k#5OE7brARk8)S9%0&X 7 eY3`;* 'B4`4UvsT^0mA~M&a&h^h=d!bgaDB,¬*{+DXhm?X dn 7Lg]&f8Վ-~v;Rg3m-Yl̥c99{٣}%Ɉi<䄴%u'`9aeE^4:uP6OYkCT|c #KKZ+S*Y`k8hk]˩3lcMi9,j8L'_BA3"fJEN1+s]9P0Q!EX h:̩C͵ 0úG9MQ27s#o}$b‹8Oե1Q,k,K4yjls-ߩ,u5Q~W}U"Z\C* дj-2@J}4fxM)4?:i"ISkQ,oI}Ce+3!I,V8Z][= _o߁sD8u\_E[|h C's y6l2T^fpQ^&C{9I{^w9EmſVkLG(~5/fXg,X ]9dqcF $͡!֪ʹ(=fMR'`sb o|sċ9aED ARN0^tڬ<%.5m91RķIb=;Զd xw xD} aI.O˜Jkax?H9TI_duI֪:Tk̹ٞײtI /9ކS}\#K>|4%ߴ"VnqpwaeuzWYZ)-{oW~sӜhiTP.wShy&(M-@,J4"Jp> [ 2 MOSSh8B|$84)}qVGXhC1<7Ƹ~FUV1Ef)Pdm_iKD~|vdiǛKYb͵L,fZI9$OkhJYMCϦWfZ4܄KY8gUY? M,n䓕.:J.~+ mȕ cLN&N004WQ̍nsXK̤Bo1 _ׂ 6K,p ]7|j5pYxRZBd!❟q}B Sm [C1Wkq;^,h3ε4aB&!b |e]QBK!E ¾nsbЃqXj/  A oY7so_" Ȣs\gL>H8m!#F+94v#da:oh#Ak /&q*_a04t-)>X LU6 0tؑʭ1O:\hԟX)@{\b^BpR`NiS8Dz|cLȞbSA8 ShlRx):˴Md!35ZὭe >EvB+|%ΚK3tոY-gJv~AL6nc'Yy8+g5W. ]-5SS"H蕹]{y@>wP P&)k¨̫3X\o$$U|ØMr\&"q.+KT1de)МPyJ'g=qVdXS(jczL!mʵn(fB#DKP^:kk}u_zc+SInTS~4?Yʎt]i0k>OX!|cxNGsP&ְ1tx2:&єk6@ZǠ?/Z)Pr{.HKD[x*=jAD!2lck3,]޿>kC˾2Xw9%B:a4%[b4ЁJa">xi r//=NdS8)X[ ԩk8Up,kub^wsHS—[8 8-qJ^aM!hhׄsh%||M: ^8pB VX]6, WDO3"uvH#űUȪB-soҗ4AKgGD4^5?oZL>5yA@X~+D~AWӞeMM+ex -\gG/xA( Yӹ։з]jC'ams#ِO~seׅ(SW*k8kKȘ\A_BڎЂZdӴ1K[g9eǂ=mm2ti͗8r~8H%sU6ZH;}l^ w) ֚=C!0~DcI8\-E/7>aZd>_b+u(:3nk&2B3t(CsH`7 WC"px' !Š -*|d.52VLe@ n< [6BxĤ.Vk yX,8Ǫ7Q' ,S/`| 1)@QL}yc} };-h𷳀F'D3a㷐Ɉʡ18񲷀/:#fo}0h,TqPRz2Dq1))L2,)[Ć)مƛPcOZxoqE @Ng+30ײcq}N[ L)c\ rƤ>ե3 p [g+u Ìu?^Wnxơ윉YE, x ;B̅o v!7m0<,A# KT [! `Ѯ=wν}k9:w3x78FYt8ZOmԔNDѾ̭[ UAXFx,8%\Zr2uA}"??[a MPH a'-)f0[4h%x9_' ,7!|vPN5e6\"2Z꿫"`ZtpEcЮ.Z1[,ep~֊sLҷi[BLV%לgǢUtH~HF!MCɔƴSd-{ ؉nȷe-57󽅖ye ?S|s+ؒ|*(ֽcU>3&) th;3ְl E_ԪkԄir>(\F0ِ47 X̱43'[Z z敐71(l¼ u45H9t` d &&sc0ws[$) P~X2C&3p@"8C$$RB!+(6n1] /97ªNWu eSTwL93qM9ӻH!oia+X0ĢJDž E>Bۯ T8u |(Ԃw }ed`I&,xOM-j4,NkJy1 7繤0%)̞ dxn:ocT>zwaNIN*VQs6RJD7 9G_%"Tk熋MR&a( l@]3&X R[^H" %̧k{+R|T|6m6mMqVChSZ&{ f KzP9$t5/F^d $"2hDDXJ"U#X8ìS5/-o}KrPmb 3&| P/m-2mVQIfIZ%q#Rĵˬiq|0B̻X'zt,5c;F`( yE`,wB8W+I҂h2 n,d1pʱEg_Yr7LZLHKN oh`Dar.Dydf])x,gSE&oL|P腜00殮5YNi@-MaP5L&X [B3 <))[f'44Dd2Թix@i"`l p5dEjl}Z_jpyˤЀG1s8!H^Hۢal,eqsr Q}6u5ב-oyKz@0Y^6BRbMQ zRf YM-(,/#3:ծCi)1HhJyayIhbhWnq#g-<`. |hfWzKHp8xk0>g a B3sF\'DCNX3 ;&ry]C1еY1Xtइ?9d*⊮^9b!*x1,}%^QT.K,tsq] ?Ǹ.Ìlx)ф攤DVDBCA CY|;ϕ{.s"ᱛ١< 3y Y #'\UߛgZӕeeՎCH͗p3ȕʚ:ھ+qmQam+,;9^ԽSb1sċTBC}E%^h2wE[dMOsd|<$ćfzVe;aӃ>JUhc*YLHm"L{ŏڥsbH濱,Xݒw0ʡUN5`1Voʺs?1`%iXԙ]=xS40,|--pBz]evwp[5NH!>?q[Ch /gk0>h O`mZDzo=UP߿5u9Ӈ=~CpD$*HdĺVG߼+{Rldi]7&@< wixBS{³–i&Ә؞CT,[ 2 53F _e23%} z#)ǩe@_&crS/9XkIhgCp[u.PSorkºAg}XIJ֭9bc'[JVt:Ћ-5|NapxӞՉv?]ViQZj0ő9,I;:D)RJO/x f;V)VKI ڍ]cX1|WZBYxXk ~_SʔC{,+^ =~{޳x)䋕yJ@S%i[km2pzbTBoB*4%(IDATsu|X{_B$}9zޖ"=ymͩU"4:W9zQM,befQ:p!@D*ZD>XJe^0IA"& l*'+ȁs$Uk1w[YͿq$% )nJ/r̥!&׋"^B9 =s}X"p,qЏ#p@A}C",Nђ< LR2U%r gWis"1ЅAέh""TZTK3G h2yLl/hf FS)ɂ# 0p֠^+:x<l cM$[YmŜ:&u7'ސ̥, ddbТav>,w]s50gП ]"gc+☴o}\K,V! oizJ2YOIi.9=6YZ(IJW2]zWVJ.sC lA([ԭ1 @2Kq<% d!pwDKaNtk뚁k2@CCB"Z U߁iWJaP?M0-h·ڇ!N[84|b̎4JL.rlY/ƌ!@ǜ,i:"JZ>%y'xYǎz>(5Xi;]kkJ{.ֆ5?Ss27cp{yX ,,LCWv4P8d/Lm\^N`My/k0SU-1T6)h#Nђ6AD!PDw:t16bوCyLۄUxF0 դow2y܂YUɇgP ehk%KY,:>wp3?(~F|ha{}~l*gXGRl3r)nC@mdN"6pk &psmR^b)τ5yF]܊Du,K,V1_ /ZM`WnI?{K-;7D)reĕ5DҎ/H@$ye>9\^WX9Pp1ȣ\Z#+-"A(rX]P|5ى4y ,ڸQnjUMwqd<\"CB ߜC\,8y9^+TZzsXqLeJQC&̋aJYpiK}[%iYRVཱིkA&{:ʩ{ }*B=r:s".t7HcފbY)w,F؄#ІL\7M9C"΍uysae NERK61OYlY?s.R8OLi-y@IܢB K㹐72.m68ر/R'  ,HGM l3- ~.}/~q̈́ &>7rQ-oz _- #n% ВT?$ 'M X bX;`-s6jM\hojD``py ~.2__P\5%4#t^P$MybO]wێ+(P?ofCa8P]C!%yޚk8 _JkͩU 8+̱8> 5&,Bc҆$q9 J o! 5YŴ FxBe@rMGT +jTȸ{[] ~Hvh'""Lb2~^/t%˾Ǫƴ d)U;-1iI"f!X҄MeПb=oD5FWBs1ume,(فZ8N',,ǤpJL} 5I?}eI^L-EZGlGc"U @iuq£d6Ngd{L<&Fib L))I9gq %- GEI;8XӇ7\ikڎ>/3]&c Oaѩz]!1y#%:g""o\|-"lb2v: @!)((DOemL2XExj / Bٛ%ME,Cye?ʯD%xM \o"\J.Y-iY} W=Apxog ŢhyANIXfG= Y¾/f+"^xw7cx4p>)'bff(Xn/?- &czֳuPgdt{SO4&r"Z~j`$ լ} "NVyGk߳eoLl$YR8e?e}S I>3: `mǩ) <+<8}$+JB`)"7.I5!3me<3񌌙%:Za}[hK*X۱ɹNTPl_FcX׷zI#پ؁QpeG!{DI,wſWUXqP]6ƊǏJ4Kb!ÿ;MaNw >:]4&"XD+8 o&sX;Ph1FG=^rLۂ[M+m4ڢ ->B>ܭsBx#Kt8pQ8hB-]Dx#@ ]c"T8qBD]#c\,H:-w`,~35qi?"qϵRˡsݿ3&)KiKKLbI-d0kGNB}HJ5OQDؒD , ѐx`lkSe4%#aҷ_+K{"D׽urftХ^Ǫw|w>Øv4@''2Ǡ7 ? OH&bhBq*];v]nYa.)qe&b`vZKĄ6aKF_ơs 3D@ }7~c-^!Ȇ#X~Rҟ;nS΁s@8fVQ9з~nyw,OMs( _kw%tVyK޷y )}|Lmg ƹ>`{/sssbcG=gq3 Jȋ.)"D le x*U 8¯^ut\:.F>f@EA_AaiQ*nc8`L> aIKm/p.Rs-c߯ʁ@ø IO@1hjI\WCm"}=ٯ0hs \bv8&'ear8Fw3>D.Ĵy~=|ep,';.~UM S$;u/}q9%zߞ~~*z{ߛDr???blӢ[XTscm;f%ƴ-Rr|nSu;:N^EM@,6mDMdڄگ|<4 x򑹟+6l"}[Z7տW78%iMDڼ}ﻥoԫ99pSv!Y&0{Ba$:Xď0AxXw0EeMW|p#lߵ*aibP`10BoSWjNw m!!Zon~p]]xPݍowc)7A5+"&U__oӫ99pl\$:LBz\f9|~ǖ݉Ĝi$EsBÖ͢bw YpqKgofcCҷ`WtZU.l/zыcV?ssl8p}x7=1>g~& {ʑlw0}=x’umd G qzK^J׿>q^t78#?#go 6\:knۼ &d"oaDHK_YC*~3mL2J2 >NA@k"j@ oV[Zbώp0կ8Kǚwp!S<"4TbAGX5E{Ϙ2uki?PIO8vE|{N:::p"!"c0#IPwm؏X>W'BR,r?@ U雾)$^2 \@q"5аmp@? &1ʗ}ٗ//IOxC`m[++r(444<ODYnBcYșF 9>Ț}vZK0:ׁ~M@@@@[\{ޖ^ץHxp|x_'\as?s^N`9P85_5y7)k3YcL*xٟ)E^$9W^Jr9999pVXWLz9~{]Hcr -sE}D~q#>#Rd L[T^΁΁΁΁@A,$hSMpjM{^1ңD3::::::*9pq4-3gڲ0'ğH??{{|oMf,>.X:,~¸_sssss9p1,Ie/钇pF2 Lx}kkSĔ=G]ǝ~ssssssspb0в~q/t?zoq8_\<&?:::ZpZ8#|U_}-9999999990Łg~/gC=ԧ^;ttttttttt@8>3?3}~kzOySc/t79 OxBo(88pqoÏ~W_IIT.ݻ^x8_Io}[AN :::::::n.F]>ӟdC??>>,[&=j?k.tttttttt\|^΁΁΁΁΁΁΁΁387UE-X@O z ::::::::n}>Vj@@@@@@@9^΁΁΁΁΁΁΁΁[ā.@ߢի99999999pztߠנsss`/$~zғ~G4}g}V~J+=C?Ǥ?S?Sӷ}۷mQ='LG<"=iOK{ޖ'J{oɟ}~|˷|KN8OOKy|sss8K];:n%~~.-oG~GKe/,0˰(ӯ6}|Az;ޑC1=Ye}ʧ|Jz _|W2㏲ 0}|z_>?==ϼ&oo?:::8..::(6Mb41뻾+~oG??@z/=ʯOtz+^k& ?O__/}Kӟ2 ~*|8ԩsss8e;:n3ą~Y ӟ //w d>>r[g|OOʿcPo}=q[x999p %|w+{ի^1]J^kېȅ\ c|~ޏ81Ww}׿p΁΁;Á=a;5yM/D׿>Lwa,@ȇN~oo~kĝu':::*}Wl΁΁?4[O}jקPK=)}c-ߑT__[dssss зHߛ~G~$9 .?άcwߙ9hQzTu)_999p'8Poǻ_sssnr}nxSР/sTêo%_%y/>R䱪~s@@-wջDr@@@píyKK9 }xutt}n_קssssssss91gyz::::::::΍]>/99999999pY^΁΁΁΁΁΁΁΁s@tttttttt5}֟Wssssssss8s">ǵ.@87tܾHO@@@@@@@Ys gyz::::::::΍f`zR&IENDB`ggpubr/tools/README-lollipop-chart-deviation-1.png0000644000176200001440000023742114334142201021413 0ustar liggesusersPNG  IHDRZiCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*iРv@IDATx|TeƟɤ R""ŮXZuWWw׾{A,"Uz/!{ιɝLfHH#̽}{)Ϝ99h$@$@$@$@$@>; (D     ?P@]IHHHH    ؕHHHH(     ?P@]IHHHH    ؕHHHH(     ?P@]IHHHH    ؕHHHH(     ?P@]IHHHH    ؕH"PViٶ+Kub⺚F$@G@ @ &`۱`>ݳSҐSV `E(% LFTpP]+ o`+; X`"0;_ȮҶYmfTy_YUg. ]Kaiߩٝ7OHț]H]yiJ7# 닙zzrԷU3Q\9PXCF x訟sPM (*%]Y[|Q {`fX=H #E Hrp܅"xV #qME=)szVx3,o#2h.@^ijiY)PτΝ&h([Ց x ^zCMdbh)Ʌڇ9RudmXz ހ{[J oǫGљfk"m@o' OӸD$@-'#D 0߱ޠ¶kzI'I&a~$@tϼJhq^u?m۶_ٸƧz gqFӟ[ov_6_٧PB p~ںuiFIFu;R>sT #`شinF{uhߛ$}>͛7^uVt?g @%@z=Yo!Nzҗ,Y~};ZC.4ìW&LMMs=go8 R_{ں=??ؽ{7Zd_ ; hw"\'hlb_ǎ]!ˌ*% 0g\z.YI39A婩ֶ\\s5rJ#.WҥK/v! X0Hư>>ɓ'+~q/|M;ђTFRW+ >o}#Q^L |$hq睵a 4Wf| Lgv#FwO*4F~ ݱ_x; GBff 7ty6QT?mdWL}HiiKh'N4̘1}80C'1gHxw^~qU<4lѣB3Y߻kyr]ֵzX#Iuƥꫯ67%%nwˁq^",&NJ={!u"NLHHcG c:ɓ Z좋.<`%93;!~*U@k*}C;:0s"܊m9yvs0qCQDx`#vc {E@y7YO _8ɗ}p5PZ.}B`q+,~@?صk W 3|ng\& J@54fI^Fn<4s ":gPAn/)_J"9/LTwDt #^o;ϳŅ(z<{x}6ao.5TFS#;2 @&@ݺ?iWK.8ewS=j(HRp|7?L "ns/E@_#ٱ/ {Đ_P ZW}ev;83홵ܺ-l1&0 fC|"rʌI{}IdD(pp; :-NOl;#6t3+DWTe`vu-W+Hܱ>+ϭ߂}Y]L$@$@$@$h~87f|b$:l]7xg~rkg EH|w,]?I>j @"<&]"v2Q)qN8B%*q˃c o ]k=no S&$I.j @ bޞmb%X8oFZy+/1탭8_o ܩ;/ g_ZgoZͭ;1CN24    c@64rF`Qnw*Rz;1& zk״y"5ړJ.WoS'xj6    c@.,,ĝwމDJd<䓨"'MmoIpkv6"?=D3a ~6 3F$@$@$@$phnYp뭷bٲe+裏kR{ %=5}cefuFwdeCJMVԩSi&c{vv6ki #:ְ7Kz$A]ZGtdHHHH#_We'    Oɳp(_|ofznaR{).ZTT|b`lO$@$@$@$L 4x0bwuA5}t:ƣ;6?9=\5'caϮ5D$@$@$@$phr6 b ̘1iӦ!::[T$V7 w-[5++(cD8ģ}< &Zw߱`]"#'bڍ%3yRnG5=BqA% VɼA#   hy\@H%ATrG\ZG&'bO%fS L',;K2ot!ubv x$Xƭ9(٥Za0,8_`b⌜J촚zu2M&f{†mz]i(mV3]F$@$@$@$ (vV˖4rIz} " ck^\j 8f5- K{u^,eI @(mL@=# 0M=R:\C:4vl[HHHH&@]7Foa_3%= w";HsbD'|$Bg~jit#KG @+&@}o;x "d5i۶RP Uxx&I&LSCӆ'r)lV۵&. x @ʑtd u٢OC(G1QwWwsI8Ft^qS:x[dOqO#   @ݮкek -]cΐ{>2R_\ X|(ZUȊZ=n6HHHH3z=s9[ϖb%g&'r2araED'tt}y }գ}q}>$@$@$@$ P@7SC1}Tj%c WSIW{tDc15cPX`2N1|$   M6EzQ0VqP؛4W%^s&kSi$@$@$@$@` oX-[pIU@Q.L qѸbP?&6v>9ıXs8o߂y2_i3<ݕv ^mtFd G?^GwL e@/-7/"!Z;!!̎a2c22vR><ݯ_ODQ<{AIHHZ> fxh骠z hȈ܇HHHZ/{+'   h @.$@$@$@$@tr    n4B$@$@$@$z P@{+'   h @.$@$@$@$@tr    n4B$@$@$@$z J rT5ܑ2c3&ʧ2 : w"   fFݐz:{ ̺͘ε '}C[Tds 4  Fزyffe**Q)hO1  @ qEܻ|-7Wxztj8kBؽ#wHHH L$@$@$@  cN\wwiQUpke6hD$@$@$@͙ts;Mxnڀ< 0-!4Vsc;ccHHHHniw'GRmq/꾟r uls^85=OWƍďSO)9Թ+IHHH'@}ƿi zj8NsT- [y?,2Z,`F G$   &$@݄XR֩+,Ŗ<"ek1;h-+G(#GtqExK<Ǎ$@$@$@$pV^hMMƙɤᡍtVHHHTR8g&/6h_9ޛ8F 㺅\C$@$@$@ p3h*5ٛiZ 9ǚl @SnJ21A}q.A[PSqaf+:y`d[ۜ>B+^шvE"T<2JFK{uudq$@$@$@$...FXXXS1 \#mفyƄ[+mcYT2we=j-[v|j"71[Ozi$@$@$@$"y7\Zu"U#No_JJS<;/9 ۹L$@$@$@G@П~)nFP5 h\ $yS.,ħKD8V;cG(iLSO7og7%   #BY\̘1>uvD.6@Lp0}: AA.۴=0OJzkh~\B1Je7 q4'SO?7r=5s 5"zXh>3޽>QO@3chye+:Fs[ -ΣF"6$`da}EU>j =S$϶x!۹HHHf! ۷#$$?|׽l2Wy!u: 7Hu}}K<_M/1< /M^A}KJ $@$@$@G:Gp﹂ݻp Xvcs\hIj:o68>B=8UZ&ZlLk $@$@$@G@\oU1رdvg&"YRs4ڮ,jšt +IHHH8ѣ ϟ 5G"ER~i:bܟHHH#,pwl? tva4   h*MEI"|O)5N#   "@T[qOwO\3zumex$@$@$@͍1||#qW7@doliMIy   8;G!`:6drNC%DwR{ 4"Gi1}Bx6sHHHh7%^L|8|+[PCj#UB$.c]ֳ+n !- -HHH(` QClH;4!?L[<ě}ےUWl-+E9甕ߐR'#v @ lPOFbGn>^ٰ_KyJJ[P.b7Hl    ODێ ϭ")*G-Xra6mH|8xOsSj: pH$@$@$P/B8x dddx[n=q# 46ԢbCZ%\!oL;ߵPOu,)z ?Y 1r%4   O/e]郏>ϢRbSq6. pu%U_ٲD=x^u$DyIwg/kHڻ XuGd.*q{}>IX.>}o݉="5.IF-KLg%wBxi$@$@$@͏_>ψGFd((*DN<&SI#E\gs'm>kx|$  hngzJ';wTTX "9$?A>tlZ$\JMEϿwTC:g8czwb   B裂9<(<qzlFDnbڏe+[%ú(M_Pol oeΥk/w"  82( Wz ok6":>9>$\RTY!Uyui*ϦGY b%V[WffaHHHA8W Qs_VMY>:Dl` .ٵԱCS{ WbHxɲsN[O@:|R&F>#jBơ 4>,_fHi Adaq?⾡]J; Φ$ڏ) sd"OFeGJ7;SѹY8X @nZ1s2U. 4!fVyW_}{; 4= PK@SULBkJGIaWƎ+qaױz$Gui4V{Fß%^[H#  h#F@II3`:t(x{Ǎ$\ tKڀN*`Hbw k3: #$zM7gR -(B %*-6{L$@$@$p1~xlڴ )))4hMdl޼HJJ;#SN9YYpnG>HECh+>t}L,*Yy*V;˿3ȜQ!n2iP_l4 >4!5zKli=a&$,k60.ֹ+IHH_+WK/o]_z%o"p q54$1,FHݻ`Aj:%61X=)0Y<ϩExNRսq;/> |=H7,!O$#z)_M=(-hZ'}uL<&$sv VH8G %zz]RDCqVNH p#Lcݺu0`yyyyOB$$xZ#WH?_KR;F&BJycw>3ĶZѦ1oL <&SoOc>!vrq` 8{2ݮ||*uت (/JmDp6n3QNuCaɔbGw[i68mޅFT\   H`M4ɘ +`߾}(k׮M7݄]b;w.KqzyN$P'QJa1ģgYZ{(a:׹Ǖ}!R]=s?)qNn)ro?Bg}tyC9Zw-[l;g;'?ع Օ˶w" {yx6製<%&d$@$@$,g͚;7p1y0Tb,5FZZ!CBB!COlv"_hoDZd%ױmoMC]^3^ڝrdo<. ݭP٧uqӢ#1mt~.!c%MO=^h+Cpx흎M,ˋbrcYxnXklC$@$p9C/1** }n݊իW6 &Z/N^ :ћ OCRԫN,8kV$S gl3&^a{doxI ͷ`߇^'Eҽe\yr+)7Op㾢շ$ǯ1ĸ{o/9$b !"kp0\' h%j2qA)tҠqL:P5Z=1&sxv޷xC7=%t]+R}WP,Ɵ i:]\vFDJԚF咫`kiINX%FǏFTNQΎ=.Ò5dΗ/qdDW6y;%6Ȱv􇰕gi px$z gcO.J2~;ѩG$(W4:h{2#KZk"? 养D0Lpa.ED&<2Jl# @+"W ߎ8bɒ%x嗱m6;eN#8rvWy[5CFXN^bO|ήy_8 #:ʈsޝW!*>= !Oz od q-sxNjp6gle]hr]r{c[a/!k]@=<(;i?MG!EaxR\xW<$kՍ( wKxƾ$zijӞ!Ws,c('2\$ VCgMb#U4?쳘9sѣ {m>Sm\ h\ťf`v{8a]RݙY4N{t#5~V*EXT\+klb,Czd̕|ł~9٬}KJ.v =(b;cw AnE>0Ͷ*u4Rܙ˲"{_v[ V݄6^Di̴PY|W\vc?+IHZ=Z[f̘Q A׮]1j(#]Fn h4:j 0-Z%޽z%.WK( $DT05 mw7PJƒt޶t! $lm2v VjOnx Ew8}ѥD&U[G qmJwR&"9wsf*SQ]x8zXs29$s1THHZF*gϮEHC84cܸqڸHUzHjBd6]WQ67H%^uOs^KI5XtW%f)Ѣ,OIC$Z< ȱ`Y9"@G<7)5BbfGT8i:߯j!Ƞ@IDAT$t hEpy5=܃xG4v}?lxhǢEZ.5^ 4}V)5:q4RCFiT]ԣ6mB(5fiR\{EDu庼fRϏhS1;hq # 0&ٍ(V*ՌP Beж^!Hy#:qO`޷#!2URM78'b7sL/50Ѭ)J3E"uҠ/qAQ}qq\ꉑݮql(J\& h{سg'tlӟb*\ !i$5+[v` K2մ^F?n  ZopYs 8K>}LI3.q(mbQө%G#UxVϞ0y9~<!񱎒 ' oXNJ^Or#X ne|SZahDH;5MY=B:*c,tr踡N+ɇW݌6xziq֊jV8ʲH_B]3_HŠ>ƲMh$@$@_Z+H{跤rUB:(i7-^i.b'sV9`vH0&')&WZ0jiWnpW~7 pIdC|ZMNJa \%)L~ J$"kh7c߈X|%xx"vÒ:Mm.9otvX7V6Hwup(BV&ZC;:3$D,kc[ǐuY !r'hIJ5i6Hj+Zd,YhʽuO$@$ %F[Xlk>\LJÇGǎnff#I@h衒yUUN<>CdA}THxaHV yvU:GVmf%ѱ9LbUGʜ^;gAXRԎ9X#V 2OJ'!"=L4LY%sdEi>jB(U%#{J֍O<. $@$*%_{58|O~!.NsȲLBȝ[32mj6J*-J!woh4xwhI,iZ=P'7FeT̶zţb$&ڴ"pd(cvsiGhw7K ׫J6,6r76)e5ki:IRMOf# 4w> 6m`ذa3gnF믿qU _|E曍z,F-@x y 9yy(A L?_A^rGi;>߹i*$\~ =Zs\9&$7&07x`D2:2%?!}k"-C&Y"*BsK@qce"N'w."*EPj^qc9ճF@krt;ʳi?b13vwU˲W;2Wߖ/E^ލ$@$@͐ZO>18ӡ6qDtyS-[㏻=)]p'3bH5-rL,<^j +Y>"D۷Grui_`-TV5c"]OVq? d,X.zZoҷƥ)]Re~3N;И?.V_7Yp۹V{ Vo0Vn  h^гf͂ ^曚2KI ;v'%%ȐQ6|t+$@F1DH,)]׳:90cY4-o:V2g|&y]ubv)RYb%tt8yo.]<f|9jB+$@$~rB*nq]nVIOjZ⌔ym۶w6ׯ_2Ǻ)P~ܹ133ZC sW޽{kdǽs]k"y3=)h_2-++ f=N]t2@Cv-U<<|M\uw7bݒo>G^^߿.e'Ssѹ]g1ulJJJEBTt6}^ݔ2oLs?ˠM:5ף3g+-->GM_˱Uf6s]:׮>]e=Q9pdXRYKC!yqU I@H( Җ񵛞.BYJ>--㨬d\' CeHou2qϾƄDEE7{bzco=@b%iHED޻}ͅSPq2 6/Xs^{:)1EsS_X9ɒ%c]եKMƲ?]=}>kW:0ͮij>~lK$XO=N@EkUy՗׮y>z[C^cg~ָ?]4?_׫~~8oݚ=sW?G=}n7_lyi{͗]s~j~nuSQ?ܭvs_9]?ͫv{qviBv2/ 6`ӦM&ZKL?a9d8==q^*ũvO"-HP)X'蓷h?}E.4oVKy:gOy9Q޽l2v_&?z&ݮcyToa:Qt۶mfQM=ף O4PV? rb :j>t}tY?,4&k}tLs\κkN/=6ſk(~>:f -s^$aB&$5N2rDK|u8T7̱K~}t<瞻=7[nu"s|_2|Ҿsa?,bZ-lzط5 컷|\*ㄝhw?y5z==zTu(+l$~<׋[Yj:ktOKkܮϧ5k֘G|;6ʂsZI:ξ}N/ohh>sҧOg6kFxpv䱾]=XhkܦOkck,p˺Eָnt273ӧO7D>^ZeŊ1bc8-~ 7TO"@;s=xɱ3HH(Iǁu*;=RiLvԼE>w-;.稩G~Nl|\A gܮɥ}"XtXC\sjinG+ރyZV~9~ zBye"_-x~|qF;鼬bٱb9 G{u+O?_~%? ̟Ct]onC߸&HHw(i g].qZ:8n%:0ѿ4k.LBrG?$XBT<~7O[yT?sl̖_\OަR ,a5~x݇ $@$~ GyyGx*tһwooSNu\;\  L8U wV<, e-nfUè78+1%J=Nxt+H󻾋g l&_B[~f(ѵԽ3[IZ#1i7lcL<&L ;4!8 qAB-aiv1у3{:" 8ꞌ i*RQ|['/EVanN&N,<SB@{%&ٶx.b?~m7,C@ B@Et `X:xܟIZ7w&?^{-9#I+j iMr<( C @bRMPSiqeAy0겳gphZ:iڟ5Bd׫~Sq/rTo|SfͶ|>PXK'iAA3d]Ic CQ~Ű\0, xxq>Fu 'ކ $@_1ЭH'>C%Z"_*"W\X6w,#ūCkhgӉZ<ŴL J;W<%G\775Hyn%Tn&q-֬9i_jR<t.P]}] +< _b? L\^ %!{Ãux$q>RM0(׈*kML |Tfj2i}ۭۭ_N3ƭ\>2ThT]wI/ƾ+:*r>ufW$/9Ǵ0\'h9([ν䕐 4Q=fJg#1:Ј[oiY+,jz<^!a?mSY\hڞjAy;ҝЦBF*>}˹asp_ ^ Nݤz5L Vhsb)\T3!%UqOc`o3x-ˀT۵\U[#ɷ2(~ڥ<$@@nM$!/R1.жxj#ùEu槌Z"\DvӚ#8vrZv@?^VqOHɈy*!dʲ>V>aQ/֝ϿRծ'Q;ֵp1\`[j h0#NHRӯc^zLG$O+$mY/|(b,DeݸN$  o:/HG'N1pqWr@8PŃ*%#8v(b<$$',5teuLuʘSeb:CDgWkT'Ey^-0DtEGRp'y3-O^!)/} 바BHJUh/Cq@<^,`id6{܇^#F d-ivy*g_eEC8lk9<Ҷy!`iyb<aWM!5j jЭI$HKF.aL&J蠨YUh 3PICSmꪴt*ȫlgfi?&vԻ.-#CittX<ڝ^$ߏHa[`} Ȳ#pGaIg_&D:z $7}z%mB?w+a2,#UM9$-]kIHm/#!3p\ h([}U EmpXD ЍBMWVe<AQv +d^MPg |Pk˜tJ36O&=٩EBC*@Lʙ ڏґuĩ+W-1 `ߴRnY7,?ɷ$lli sJK`H E9J\k$"s9WHZ'wIWM$@͘@77TԨ>K`4ڏ_]p KpjQOu}`TV @I{-a$N|$d~4ijSE.>0Z},R`+,^k͖iXL8 |,5{J0"n8KɘlOSiz-^v;n"}"ډInWN$pPvS#] JOY/hGF8-(To@!i6Jhb!iF>E߸tK_|Hk>;g=s1c {E))F<]p8q´i$R_\i yE7]`*)ȇFNģ1|4YvYY mGp& 6yxG.T핅.\)˦-M-OԴyՏg6Rۊs=e1U!!s-hqco{Sg}Q!چY)oG.9h.%Kﰗ J5J8*Su^*Fm6Z^jW۟zjgcgbѭ7HuC5՝zaŕ"A")tMN{q*}6 Eu,Z\! PrI+Г!yG QC5g[h]B/Y9os`I)KBgQ)x}?] uop2&)Hm,ۯm5SLi\B9A֎;>^`\79G z#@Y9Esm[HM@k۾(YaME7Q$-}s,)sϳ!{ān2Mynd@6ᬎVW>nkG<0̑&Mx(O<Aqqɉ+ГyG VPWhUΰETMeY4%)}s$\!i˫ z%7 ǶLqxQj^QI=ūT+ qE}a+o~(i+-Uſ~iGX$.zBQIYTa:JݿG` I󨼢#`y&k';ۆu\ e)׵WsA~oִ5R:OwE[e[KsYӷ %oc-RuZje|@J]Zn Ҭ:f/>\yC_9*GD߯ WXe S#0qpz>#8#02># 3^QH?rl }@9 c5{ឣlwY9ً +>ۧ8—U.%*5ǛN==6sc8 Vtu˝L3ű.'Cً,iCGoߜ:'+ڋ#L>\|k8@go۳zAA%DyI/7P4₡jAJA7g 3jHIh!}s.#B6DL[fc[ [ ؇,jkLߦ}3\\;&2lE75 [*-Վ?Xi2yJrJ8VSdpGG\!F`"Gck+l QQ;ɞ!kAu{+ *S1}'J!IO߲c3]ǯP&O҆W!:YStS,Ń{og Y˭~BH$:Ё_n/IeF8|Ge_*K{_x _G`<pz<G@X7ڠxʯﲐcS,e}Ӗ@} u}=|#a"׾Tv (FM:=?+ͷ{!`s +r_}Yh"OQZ9J ۯec-=P  >(~U6ŭYi.%qqqGq/8GOdW)Wڒ>aO(O8Ca]M@U ;1Cw^܆9_ˮll)ef -ne :A9grV^k#{_LP?Doo,rha9/^/K[8"0 8#0l, lwj9vE?OU8>'*dҲ+P8d{ o#GٷXMofC?˪{Nƪ_;7^Ҍ }o790 J~qQ8㈀[\/pYnh|^y(箽&:YHzد$,$[)%BMFu 8eVJЎ[01HڍaVn$ v+wzd~q\ꏹSLCbXySklzKZ ^翾|GȄ+Й`Gp"P&3JeOZ*xlL_x*8HKs9#J˼5$g!aI=wT!zϭ~3կ xՎ9˵V+W,YھE*x˽MCYpMpGwOW'e4鰲wN]!;em[׆N<*t<7ʬ?]V~~Gdžϯg~ge93"}T^բ;ooli_\_T:![ Wd%辻lh`QGH9GksI:l`k>qBk.~lm,¢\X"*YeH%$vV;X[˸iDׯN8*U>yW@{CpGp& m(C?~pE'Teyumpw3;~yT.:ETݷ,ks,*ֻ6\| +xs [w+;(ζҒ++C?߫ȉvVQB%%?ݭ~!ãX䣤dK彪̎Uu?m$zfOIU@tʈv!VT;z+a ݙ6E矒85GV:({n6I7 L1ne6Y I|Izr>7#8L@I iQkYнAz>W}U8қjO9Pn8^R󋓻JKJi%$R5Mu"=קXDmYJh D i)}?>ʫӏ[MaHmސn0Yh?V]xp۲X)ay% b=@Aidl\, ~c+;5w,]+rȩ?+ג$K,iCGoߜ_ e#E X9}$G8Hꋬv͊~?!R~qU娘&8z]uͭbiBĐ)WY}ŭíZnA8cuGp:!@GHd&[{LȂB?jVbRꫛp\IxG(.cF1C8#8B5vq#Oc:H\ lJ\Ki3*Wh! YsI >5$IR;hlO}(9b GVGGBV22r]?\ &3{`uIVf8bO}ڏGnОReDj~E!!\³TGyڞb`El=TJkffj}6Db6WG;#8 f\|  v#$U)IA*}GX%AȖV'B+V*6tÇ/p[zR+R9-g6U>PRdNqtRxpYMʪc0w3{Mwu[Tp]8#RSD/ t.YrRj+ST(baGG)8:DA>LWUtEe7d^L)m%/ˮl.Vrfx%,?VZ\Vdŗn k{ه%WZU)J^Yk`%G|pu?ecwStuO!Dώ/4!J3~ 4prTs?0eΓĆN8d,Mdhh% ~[ykREr ˽Kg&ꫯw~;ߖuGp4PJr<|v^r[y4׫(mEh"[f=갊BXי7tӤsDW?7lWz,VlPZvO.3Bͅ%rCozC^uǢ|=_:cqm"rH>_gɤP5'xGh!QCh$.9êtFyNX_pGp2#P"7Y~A VһE Rg.Vұ}lp[]M#*ZHR*,Hc;Vr,DԏF[YL:Lջ~Vd;:amx~aӄV|GM*be)$cHNq]t\~q)bHun%Z?zbGl{ޫ{}(&ϷwJcGpGӢ aJ (gy CqGp qq3>=JeM~k 1qr|%"+)Ϣ" )")SӡA3od26pOXys|ܨo޺A?WaK39?5{HqΓj( ,W_ @IDAT2Sߺ(ՂdZCUGB ݄ʨZ FFl[n ./5οk8#8@EYX-J[h PCw%Dror]=ש%)}Y JLʲXk*\E_a&WyY6I|L5bgdsbDVF/k9M~.7{PJ(6j3'/6~ݥV윔=M%9LQb3][[gۼ7_ns[t"2!,Ыs=6eя4 /W#^{5љ2:GpG` ||>8RKK,8euY_`(D爞Q\g)ץy h)-rJԡ唸Eʺ)wZ'wB8`frT6D`..~NjѪ,#~HWRHO&uYk'ns_}McAtI\>AM DiSFZqۄP[3ˌZkk3" /8#8b)ҊEAa?(9V;(oaU<Ȕa8\3M}T&q"YIi+Թ#RZzaIk" YtEhvI#׭D-^.4(#34xO>ٰs9ӦMne] g\~v}8#8#!FɪVh=̓$<"ee\EQ>,ۜ;)Ĉi1VdW;Far yC-]ݝֈ2=ZVEVyz9k09C[2tpq6#8#ܱ|zBߕĭeC^H/?X+IG+8Re+-n7]iQ ./Ҩ}}@~ >"kfӿGpG%(!SbsnCNIb|,dq,ͿP[J 3-ͺdwf.weO6G 7]z U?ܧNPz-P]GpGpVJ-KMf^ wM'S^}VneM^#ћXIc_zfdLҤoވ >3Ʉc738#8Xj/Dv_ YIsE(_nv寥@d^ZWJJK{f@pGp@u}E)Yr8v.\W|{7Se!:) ,#1[YۊNXG*TLQQ g`l{$R8{GpGp|`+#_{կg8JoeE)s̊_- 3e26On»&fI: WpGpI@U+Vt2^t檓 rBdRbkO% oZi9cR |l^iGpGp9 VV92FO>jߋݣ景3'i@Og5sGpG` P"rXf3$Tk\ԏ+8#88!³ wpHN20#beGo[-f#8#8 P3fJMʦ S+i9+s}y[';#8#0N>Q6tf2xigشyf-3˓pGpG`*:T˯Ip+Г!yGpGQT?etٴ* [ߑ|$ $~x^uGpGp*+ifsͫ, _z̆~O\ sg~aGpGp&奖!X+V蹧4BVZl)+>+)~ @ OpGp(6*J>+S8f8#8#WsC'8#8#=+?}wGpGp2?pGpG`VFY;#8#Fܐ #8#82@OpGpG 7:7d~#8#8@QDOR[o7ZsOY^yWW|E ֿn/=fPfM_Ԫnbт @u|j'+Jy~8#Z~#8#8}Vd^hR+}+γO")ŝdltVz&P/`Vwl3H^^PsGpGpzB zI|U'5|{XmSﰺ4B)K~>mmdуHeW";#8#@+6e:!Ewp-,zkoʆl6eY9Rfrl}\lw&Nd~q?QI>d;}Y@GpGpD Z^޺"gliJm.z5>o)蟷HeYknC'^\#􀕖[j?;mq;GpGpAIQ-nts+{~9; }o^цO>j،o[K-Դ=ey(S:ιm;_2m8#8#Pˬ`w __^2YJ+U}o2[skd(]2(|be9֬AVY_ Wc$pGpG`(Y0Zx ו evr vH#Y_FY e_ڢ#9#2gʈnU>R˿L0A#8#8cAV̔ĤNa{.wx{ʫ5\/YCF9'*fsϧ-X$uy݇Hjv؝G!GpGpF4V^2wW?jO9Ta;[eXϯ}_a BA-]!/d\g}IJ,̗إIBi{mgu=C^eGpGpf-7H&—^s/\+G:AW214+ͷuHQO29#8#8 Feg@7MoR_~BYVj-!'Rf+q#8#8#mjn٧ZuԐ/1ÊL)ZY=+yGpGpƄ@^?7{y/ x\VnO;̶ǕTN[I\NY Cd=\li;VYqevڑݰS)pGpGȁ@u/(fr;Rৈ* +UKaZriVWGY/S^mJ˼*me%ŃU܉W~:~pR̦T]Gە^,Q"dM:)1qx$m1ciIaHQ}9ey6I;Un7ﭯ}TI@|+dcSOu]g~m% _b?m6\į~+[n/?=k7"[o5oưϷ^:EI?φ.0ٳu6z믿tNe݇6TVYU,#xyi)?ERJ +׾/~QX#)'*g?Yae>L))%7fm +/uԄ2D,Lai`uԄ22y`m'"s)/~sQXyTVvۭ2_ +S&Džw}:s1o}+2]th-,%{)N(G`#h=@75~!2-Rcr#vbҶ_|E^X *$IdLR4~ l8du!?z]w+MuYgL$2-\ _z%[x uK,ϛчr!V(c?p~;aGqDϱ:'(}g ݜexi &X6y饗Bu;D`!7}B 6jLacXcۇ7FU+_+rԾ^6=yO;x0aP24o6?OO&gBVc,8_jGYgٗc/< QE:h6]\q7p,6SdT?Lp-҉=:1|ɝiGcnVM$"~:!Hܙ!酎>F\sM8?AD|`=H?O#yF_GUJKc{EݷTVO5CR̡Պ!%V~'@i{4%Rҋph"7 6,(GQ)"ҎN?m$& '!p!Km&?vwN)aN7ԏ{ZDD{&YNLE¶li|7|sG{g$7yhOcUDĔN_F{lK\pM7ؾy6)rhC;!=|#/D# VA@i'Vn܇MFfrخdC{"ZaN,Zbv%yGRS(۴q0Vf/oSҘH~qwP?B? C@'kL^q}{_G}4 M^" .Do>|H%R<Gr%hԱ^Nb]g}W 1ܯu݊lYBnlbfEdFIQ12)CcKB']6x<,?d9LAM,r[DĤ0^{ը^P/o]tQ.KtQͬ,CX,0%["65sB:&{챇I:X:"d#%cZÔ$:O>\8[osM40ٶnʥX}r6N;bDvn*g>G{ޱ /ĚD6FM X ,~ zdRSU(O}Ҏpd+я~d_8jR&i6mr2t5mXP!੄G#{ó&&)$+IG7H! xF`^uUIOb6J GIVyh3CIa =򻛜tI|'chY†K%0d'aՃXLD##ԛgw5KDKV°C_z߼3m]7kw{Sa _eUF-Y#9]:ד}Rxab,[:/,}yq EK:ݐ!]qqoҟm&Hx~uNIfTkn˜H[z&ڡ0s’e̜&.VOa=\)a&:: >0ef }SdLhY4mok9^+VZƩzX86Xx_׶>OFDRư;y[]l*zܼe6wz0yBJ޵aao |<qjX߲,ƛ7TTolj u‰D|@?[}h ׅn!ſ,F8Nq1~qdk Tr&F]gyGKd 5v#PX&,I68ОXRaYFhLԁ\i=#PG0eٯUDA#Ȃ%,ȚxtuK\hqzlEi,<m>&ZN"Z?ǧ{5">hNҴ Z4@sɇ¼жd. kLh#y1ɱ+5&ˍxGPpC$,o< 1(F? MdM Yi6ؚ8 0j ,:YxԱKb'(yKM5e8pAX3Ɂ&;Z>c4|r-3:(ߕ%0J$uETg"z뭁oUqLS/;HeBKBbM{h#piW  C_~yVnk2f F݋c^ xr1Oqc6y8=0h ɨ&0F4""1tiMxwi+$ٯw;v<in=)(pE х̳{/O7i\ ^~?yM ialY!vV)jM^ON&:0MIeRE/6$sP7";?wmy{f 8#ӟtxX?#|8N ҿзSwKE/,!YnR2Fu1eDRypq˹l8˔x* 7+Y^Q EAWG5@{Qp)"' GX"R"5P 5ʲ-I^r9opV%+(+GG"+ׅ/C7KHwA @{ 86f[gzMOԑMLky\rIW(䘢pP\z^ԏ>"'%,%%OeN9f-"Wt/N$Чm|kU 58E؎*8`@[+,CيIMs3v<}A/}c}oM.ٴN Sr{ !K8qLQG@ӪXci7Np\D)݊'0lh965)Ute6 i.J6.oOL;u;c3ǜj+8谰 KD^g3RxhgqF*&0dņ|Dt&w'mbrNB5bE'ƴ)`qe+,c&Q!2VRV|yh`Jdc,#)GđGXVsEEei,rpt(EK,WA#rksP;-/g)cxqń{EC@-…Ce$Ty$Nxl 6e]0! \ddLjJnw"(ߊ&71|39a 0IE=Kv?',;Yf;҂Lc3 M7HA)Ms }_ksވ͢eoZx09!!cYT0&$3`\I*3 MZGqFaS^^sgƇq%J~6 I=j;h]W>*ldc=q:%l X(݄񆾀l`I&Qv+q 47<~)G1 9髄nDh~`\1D_xfg !zRġL; x  OQ)ayyp9cq407BoPII4 LIS[h:DϐB޸'BI^]GBx]Z"CE*n*!W^i&8ؑrPi +K f,=woYo9a K 4##{Y<`"%)dxXYQi;t^I'iaE7 Oddˤ8SwYv3U$Ҭ? td{GdU ;:cNx4Uv3q]x6ڷdC^7mFVw=ךuOGzMxbc`B-Q=_"L\e=#w l~ fcBn^&ix>CBV18֕X!l(σg=2JH8۸-Ǵ O"ϤgVSˉ/(֍̭x޴MW aPL'7cIYGcWs l6s:31fuXx^hf X$R?B{5J3p-fgDSE 3jqBQaj%c`vAk? U mGt,qCKl-+.377&ut8>(q|7)QyDˉ e >x2Ilm2)֖eX N3v,(0+2N|]Zy,L$}Lf[(<E)bƄ8NWYdM郈 V])RQhLaD# _߫V4N(bkf) cbE 8BK´njUD cFlZ7tv+0i2KOd2xp!5<%O!*pp |xX/cᑾ/Eg&*B(.ثT8tNL;&m^;~t?Ώ݆_ݍy8"d! %Ŷ&Ft_y^0I>Z2&H7A"m0yE ד2BtÈU^68b1 M~#>NFDE**.µ:o}P{A?P,ks~ ?+7ɶ22+$,w|oX{~犅0{$5雾~Xx֬*ĘǰN.b_+'+YZ֫@+Ѥ6y Cv*2ꚝ6Љغ/ɣTxCY#tL e(yN199?y,TYO7"i;t,+ߔNWV#ӪEpcPY;,q 脳to\PFyqgEg}7>oφ zEsya`Wr,]DYD`E&S,N#E8.1P:aHJLJ>nByڤ`I9؇sFy<3=Zh?a[⤕> (23Vɣ@ZΧ-~O)B0V'&gog>PI>mmXԑqoޭkdrt\ª m.II5mV/&Jvӯ?+$b+tNԕ>7nS(.(yeu Md'i("Jj<x81(tX3h %Yu\(2 +(eO1+06ݹ(9zaRgBscBLI~b9Y x8h yCyu+uBe6MEV* fԔ^(Lh',th6ʬ€?4 M)KR;VX,+cr&ةghiY铬CYNf 8ew+ qY}!E3 +XŌ'm1.&HL8Ԩ^N b+mijFD`H???}X_@ʋu7 :.7A}<<* uIҏ@xF4O|i<2+m@r hZH#$l;pSf&.1 JRh"B(Y]fՂ1顟"+8cTzDè ! |H$?ӫ x{<ȉ\X}`!0\UD9 tYsK]VJ| -},AεdYYg3c?ܱE*x8gAp*yw1SObI)K >u7/^I,wXPbOu3&/ޗ !FE桸aK#/}y쏐<,Wdu2hE[#XܤMޘ3~3DC}?`L^ t,EJ __7AszUGH%>>ɲ~ tQ3Ģ tX˻//N/hZ㋷ KftcUrovi[7 4^X造0` ì?d BXʆ<E .oަ))(Dɳ(NOf`begϸe/, ԱUsC1r1ce9stl/xz8}Q2XR;œ({%jM(+.zhE kz`lѾ3+Dl~"Vy^X|Y>g;g|!LF 4NyqwK'=1YQ+;u"2PorvD?׸Ж)oIZ^9poJYB.jX4aˋ8če{(X!:Zf̶FTlJ@sEflnBǹ>DB?IZ;i/Xx)+q@!ZYNRuypeeVdRX@ *" b?g^I&X4> ?>y~3v}LHE !˖Cs A򚸷!#=q|R~Lbe*$+ݡk9?jo I^ml*SSH%Y:ؐPDʣii?jl&g==oYfM%9g9q^lL 8&.T򐮿I#In4sӦA'$4TdB3^de7 t&Ed Ae9Ņk5uj{GB)M)cdi()J@Hr-i٨,}">I`z&&i\WʎJKbF`:d<%N<#6)Ude ič4J=U tخInFYLiC 9"lrJ Dݐ됸Rfw-ܴRh>'*Rh<߼y5Qs)diDMh{Ma4Cb,hoD~ 2M urgRJ5>5!QqjMHbIAk$b$3}x8Pڞx!aYJZH\&qF5$~.%#iޅiVQ'IEaQamG'Cz,E;xܗKn @27K,'IUpգ"@IDATҮl,Xజ3m Hz5]q~;  N:K!K+t]p^~%6FBmIAdBOI:ZVE9:2%'҄ }Y͹DAY@. pE(K{Gy^e_R2~NΜAiRYmPfXb"̶ 8WE Y*XZ0nir͉~ ڌz/ 9=ۙ +X*DpdRC_(pճ\Ng\ Ǡ"=$F}Q~x  Ivgo"0ƫGwjoKyhGv}vIΧW?Buq`feWH0Y]Rѷ"J#Ip\/d9" Yg,7Y>J꬟vdLİܳ٫,s2k((R XpSytw XzhQ"MPgtX`BRAr<^QD9/ Yr\ 1^#=]T0m$QtF? T,\ ;cRA΋ᤰRrR125LV@o/XS_(PWqk7㱊z ̄qsYB.q)Yq2)v:rxEycmyg*vbNKԝ EǯS10Dڱu;o2NA`27W,CZ ]Ai -CD)q4UPzåsƎ:fQlpQηyqhJuKcD{ӗa)BGA"XRR $cJjO5V^jҚck0V3c+Ό8ͪX7A!8)(^((Gd'o״I-S/<(Qy噰wG;Cѓf0vZF aL(!qFҶnRPC-ej{LڎBQɚx)iEl&Ȥ&RVmRJL7irDL;mj׍zꬳj# zmfQg`r 1 ek!ҭQP"lb 1eQZ*,![KNIDմ͙I1E1u! -WrU]D)d'YHGBhҟBmP妽⬚Or4OnJM8,B Rv!T^7Wee}~{#Sm(*Hx&ň"!&nv2L+>&*L  RpISvyCY~K e*iZ?mGIXB8@ûI|Y7{>Ѝդ6PYJhK9R)3t$Y|,%xtc񂇛Ԑѱd&XYiV 5XZU2.Ό\&,|,hyy*$,+ gxL;3[)(]5 V%XpE8c^ZJU@KvfXY&a 5sXxx8)@%[kRuqX,8a"$"+PVhSP¸%^pEEzHLpalKȰ:^eVdiOnz m.]*Z?Dm7M&\&1~BKc^I:p'ۓM4I " nRZ3̔m YcC.yqt0?WT?#e0DQa^GL$vGd7(On’%ڌxhC(,E a8,^%MN:,1.0ؠW@Zdwq4̳HRFQ-b (݄0J͇k2e +:C~QnǪ8Sma 9=+;yn߄1i {1T@:жy%(,Jq |2وXY԰B)5ҎҠ8 \aP a 1DZ7F56Y^ Krr .5alcd[w_cgKyeQ2҉N9)qiʔuFr,4kQOhMǰĚe7yQGԊCL ť B;d/8s1d!Rv8vNViw'^ۨOi'̩2EKR y7ayp)2Չ,읥,K3j2 :!ۦ5P,xXVcyzBI !#3w ! 9)2dub΃F\|٦}0&PDVS2ɉAuxAcc*8Z9HX5YFz@4<# #8:CE^a+x2ˆΓGtd:t8t+{fܯ֩Ӥ3 t؁,ox8A?h7V 5yw\{| BGÁ~>kX̠*2;M'7a=DeIY)<c }@i ϸO?-߉@"f;w56i+8'?Iy}VYXE:F{JH֫^}O7ܼӽ²/GE#/Ep;YJ%L'`H% t%:2B"(2o6׮pTŝ$*(E7M=&JmRVxSod;J87?"dXH;g}.繼wqe!k_ԮS ̍!B<ڄDa6Lc;zs8Ap9Kkc솛R$N*,z;dSOI]ύT߇Mgb",uI_OZ9iܜZ9֓"ffm0_~( iqh6A8iNU}9OʱC@H&@)ppͧ9X>_.?ɱ޷GۃgabI׷XhULRihu?_J†@PbGhҽ轿{e$hWrLCM˹mJR!<2 i7M+ sm6o߭ኴ;>(>e )@ ̤y9˯z @^AI+=93e@Ŭ GMṼ뮝7׷aok!Nui%9uKsD4hld'q@ 8escY**+\m:rNX7b5\!OΗ=J&c+k0k(j,"wBd]0G4mM>+Fu jF͕gRqf"pM?s!I" x-Bʮ30εa*'kj,ڌQyג34z+}lǔ]X)lyO/m)09/8`{9>< tc4ֵvW1aQ6 3(D0]'T}h#ă-٢+W L16L`/OϘ5u-nf3uqEN}kBW=Cd6jњjH1MR\dlp”>$Φ 6]_~5h/ /^ycʟ IFpȰ]f`冩bOz`7hCȘ?]XYIK]p,e?1 600(K4P'bք9R~Fz&TL7H2<&LeBOODo1ʈhmŒڄ@e&Mlp7CЄ{3bH/+/f&HhBiB׹zؿaR@*wք/y" ʰNU!P6 PwhޅwGWC C%R 5d i=hPQck]"AEaO3ζvH "~ 6?QHDo _16LzG~{BjaV_5B0.T\di߬|A \O[$ MwRB(CPb IT4y82 p@8n[-&D*}#½ PD(jO zHR'9d Jг dx6Jɼ&t5|QUGC(~\/@c 6UmM:P ? .K74?afBԄ_b&#" r(phpt , <"&Ť *>On<&:He K C6W•cfETuf3Jz4X$#c@ j^baDE3~hVC#2EPPf wP%)&˜((j kwWpu1bQւpi@v7!cy|X+pkl0MPy-·e-Z“ k).ː 44e`Tm7Lƿ{?8R}K}{~vOeMy-Gg3Y"wި(M Lc. 2eZDE#P2! i-Fc(d:V0.fHǤC>&!^-sH{q]N @#̇R;M5 y)Uy;!Xc/nb;Suc~9Aܞ+ W.igE4]s-E <<6#$aeY9^r:'R1{gƅ}*M])^s1#MJcmSmC nSroeּG9c([ OP }U(VT :ORPw, [k;/ O1+@0NaA& FA5MokjwaK3D4]/PuAD 1i/B!mgCt㸯5Is-ڥ!uD _X ղy(}( 9I$hָ<mmK &ɮ; mS6A&ƢwT's+4\,7]`%aڻКbns3Jk9|':څ˘fUƒ*Lq؅UdY|@,-m"P$Yԑ֧1jw-ʢK=h%= DK汽uۄ&fiϘA  I̺.:u]ZVB?1im}J +.䋹/O,Iᓓ0a!Rmel}V]?wJPdޖAs>AL=Z SjCkcJ9 iGt&ڵm<lA ,}$\K!y"2+<>77Xu$(^H_6)ppU/؋W ~"f 1C>i96Y ^l4WDub+@Lp}-a MAp`B&,Iv]9֕mUeǻ"alpd@"uc]xo܆ ;忹-A3u )o 9ڂ e,1Cp){l}@ }9/`MeAJ1޷uj?sHy=NS<…^&AopEn}aqgY9= V?@sh;cr5Ms;Z|X=)K@ }4 >~>Ŏ@ƵhkVuipYX az|,Cv K>Fǀb0D팫ڼy*>Si.A 4ط*u2C&ӡmm [l8^0g2A(Q9[B6A#} T` d[wm7E%϶EF7 @>F-t}ń1 92X4@L>iǜd5 mU' <K66g~ ɼ;4XTCxz߼DwuTE9c`6=FƻiKp;^Ids2uc .]Mysgx !> ⹈.~%AcKԁڅJ T? q8'Qh~ yG?ZPChM82@a)]YMS+@iFEu; nҊE6Zh&M6RبC[gȣ"[M& |c  s|2 Om7XnKK01dAmD"Be"p0lxFjgA 5ih1ԝBADu&`(D34ܻB9&(H9#V*^ &hjOPm6!B8bXT(( }s:d1w'mTz*Vy5PE"p0mPI[\ʢuQ^m6O؆+ar6(c ;^Ob^ha$v78WM5f1&ws*@1Wt5z~J! Z# .dKkYXwJxAsڔ_Q Y%`PvB=^;Ub?wɇt(Z0io!M+xwX2@SВ_7>cdJ,uPh9˅_ T`@|?oNr>xH?Ηp,u M]E2=q~~wVccƷ~(`3ҍu/~44fˬ| bBhVx'\B"6mm'_h䖏S\sS&pm0o,S}JkI ~URd6"i }mVژ v%k8bÙqAbp5c=?1 H۞_ƝBw.}̖@i6ִ R > _%6 +P,M ", kqLx2B0Z1 `.utN $B [,5\@&_]#A&P[syp  ˈROPB}}u,BMe n:BQhsT6zw;mQD᪑ysaL>Sϝn< .טn NXn"?}Gۮh۱kzWЩ(HJ*[7H $d!H$49ݺCаmJ0]X%s~,maMԾUEC[ uNˡ6%ƁW/zeBĚJGuQ! 뒹/Yѝy{ yy038ĭ#sO^%A-c?,U~|e.{4p3!Ƭ<֔}yD-pƚɻm}9Y>@5!{gnw7w݇8>]xM=l*_bqI),Wڿ_h_%^$ӗK Ӈ0˼{XLMLѱJWNznWcqJFa\x2gCCuا๳*+oP7!<-c}ȵk*"(C'07d+5\ ;ĽL)\k.ͅ iA G`XjCs᯶D+7=- mM>mzǼ똓QT/d> )  CO׈H۞Xb r1O1M}ь8ڀ4._&1y h;fVJE]sՉɒ\LQܸc?9qhi CHY6).¿]^c3FX+4IJMzl}<Ɲnz ݼv1V װ]𐻠ś+G=\7sn{nM2&6`"-IpB#!MXn0KC[-qGY#! nSAd!z9YF?6B9tӤ' ʲ,819]̍:MCc,:6PDRO#,1CF%cg3#nXL@JNJF!~˄)mS)sϹ݊G0o ,e;M )jP(`E3V!x]}ν݄fB?o`W|[Wnq.p/ItΣ3 !`rHD|V49cinA[⇱M+IY| n, @!ɋEЅ}pX\pHA#k2cgmln^b%}F0D14im&EA);':؊1ϲ8˚h % 1T=` 8鳲I409VߚV?D@W. E-uh F,u ͕ 3v_;P eMĘ6 %22R4Țhtx}kHs]5lW;#΃x|>` =kT-]2(1Ew4H8TK`6L17ch BiG 2a es)dP/(@C6XY @طpq밁ho<|7n1rz mKBEbf_,HiZOK6Qp?NOhUnx6<GWFAH֞jR6juۭH9(cP\i±γAD(@ }%ͱC޺g̵u1GeC T$nHfidK Kـ;'] 6H6U6"hIOFr0l-v\;hh+mܰT&+`p diieW-;h߻#*&|>!PiVAi,'XD`[Am6RK]% 1Ovo;@(w\wR6+Z-bH(C}6/e<­Bq?ݥ)F1~kN {i=S&HbZmwX=3ւMe/!sZyOn,m]Iy&T\".e y'qTCq(!7RtA Dö)ȷ]~Z*'CT 6@}ؾRvLREK >:9)\YbfܙDnh 1EEn^$*gW<{s%֋_&L.B<Qi=?ř$E )Mk&u36 ʜH ^ ym|3.Ô W}T?ydnD*|C5_\kX3CYnAE15;G"ROOAjPI_Gχ3T]#EdK6dYc>*-`b'_\NF!#)=s"Ax^lZhhXi:iCN-n)srCȪ1dfg~c%&s8MT,@EZ౼kȯ bq_֮!ϥm KLs,Zw~4th'3 n~F I3I,$wG[ѪŘ}ϴ<95<|yGc-L4;q/[æ֛Ϲ, ^`xPP644cӛRx3a:FqNziiO!s Xۚ8.{KҪĒh| "o䋡zEtΗ%:2۾ ~?8"B~v&1DyJ+}<%u%ܗ(IUOC쒉uVKKuK﹘ gwPc>vͪLV:7] Eh}B=K 1mp>IAжAٖ<"MXJ?4f+ͬMT ʑK>F-2P sm SZq}(`˘nAL'Msv;vLx(xgSڪIރ2w }$!S(5 cjAaMJ"'ۉ ]sP1m˿9l[u BfNb^?3v<_gٝc1[!fc;bu;Ϭ8_xZɔߦVGX D`^ԁ)HJ9Xm> c)6Cir>J/_q1 _L # dS$0PL{ȅSH`R7pJ9{=]Tn 0d F{5u5wghܗ1 e1SPb6=[5$W#}L@&=,ci.jCt߳ .^ B4ȶnqDϙ*2W ^.x1:!.rOn}s,B5}笏b(}L-=yws:uc.RtzdLﳢ'Z .}:vv~If)y/!4ϔX.I%Q2Ơ̔\j@6+PM22&hcxң*⹭+34  }cٸ1XXƒ5FWt e\*ǔ:8.-u Yblsi{sHyܝZhM'f)=R. ߴH:QAᗕ0d`.`Jڽ ֢el>$wڨ=l<fPT4XTYNO W 4h˽ocu[IMsE2 yXhh 4p}$(E/zQOkϙ+hP:ڹ {sd0o(Y Thn,Wrc'wiMT'IX]:T8kMBEz2Ӿ[XpYBY#C)ka!F6v#O` JS0 }[Ӹl %nY-J dLA>6LqѲݥR=(( M6|i6"/_ې9[27+((opMO#} }ӛޔj}AGN ҒX0¡B13 .h&@Ţ 3YLP|?m@dSMMI7 .@iX@UZEhpF'$42n;̝H?`f1}K~纥0t7nDy,<]{0W6>gA\]0ǂƲۡ,w}Y46n?3>onc $ļJH/ 0hK4' ]n4X2wxZ'5;37\bDwY7Q_ېוOnnu23Mc !O)qO"% ѹ-S>s-]a`ckwed(@A#< !C} ]{z)VҜ7@eG>C jzC%tq`F]"-2%hA6O$6-6)n,8G2Cލ ~y59[̜>5\]v]m6%NqIB)_y69Ȧ9{[]36{aK_ {iʦx6m>݄Gk]n{? B=R2ueR!f.GTE}0 :?IDAT`Jf%a<_\ "a gٝ^ffnOI\AAe1!wk\ceӺ X J852Mp7*_4w 6f MM=wmP= XCBcqGIBsOXF@/-o傣/y.Z;Xo.wE6f|X=7B`uiApFڂ8+9$(f 6Ɠ@v#ͭО97gK# _lv ]`bŦ,5F/cynt78D}9Ѕ}$툅.!*sj9c@/BnmXbBV+f=C ~P,b׹9(_dqaHߪL ]"6${q>&K|BC[N32X,K"Ybg)44$̓vciLp2!$QC)6q G!1\3/f7;DgHğz mug=)jM2g׬;i{cLFeb?2EBXRL#D7w‹W! .L\l>>` +']_*qSE|q<4(3&+UIkm@#xڌJmUg<=i;(H@Є&)M۲2,VmɬukNpsgK8e=ֵ Yd^dStOy7VʘlY ),WihGm@/!ٗ HmXBRa# 2(t}m&BxCTUp6+\} ͕qכ:mjo`eda#?f3\nwL\AOpAk^Rq C23!@t`WrN lV&`z]2%Kr(gԬZ' sP>`zu,Xx*i |e )Fdj |Gҗ+--cδ7H͵{M Ԃ ݣUmQ4:s'9:9""8/9J]-Hs5p….='MM9"LË|!Cm-p fW]K>6)'l֜XUTykhMzr=e1fRoVހ]6ܒVάh8ZYs"2 "{=EYy-Z)pTfƮk}.御gBfҙk_L:>rf)~e21MSݜ¯~@pJ'eZuዷ.][졓8=ʈ !Niy{ߤ[ڷs.I(\hqG܏D3!r]SX)l}zfkBX,6r!" L4bǦ F>J:n (XBV_uIy0 eE?-4\69vM KY98dž<5yMZ'˯븜! -o`ĥKv貆/LB4fh{Ϯ\~Z7X"C@ޛ2dRƉ2b!{ B|> {Lf6VMϏ|#iVkFm}?gBc.cb^/}wJ~҂6wra@Mm{ pU!? 2rfZV"4o`)وqBڪ`oRҶn}M]눦ucgoBnPvOB1ڳ+^gByӈ~&Ҥ9G@k2Au\;H&ZwȄƄ'lg~rxf@&&M,NbTJ6M׺ͭ<^eYWf^tIi`t\]99$W]z9C\IK֖><9 o,զ?W~6d Azo6'w%@ų+Xp/"?@$ }qW~wy8ĤQ!8oWg;A>~.lut+4Mlt0f3(6뚜GLtG2ʲ^021,=/uO>z1MMh&jl02(5^plQ;b{ B CI⇘/56rf&&%f0o[_m{4X\ŧJO6coάu 86 WW>9I\y|M$Jfll{'z Qb̷xy6{[4|u>CÚa@ I^:gx򓟜\WΦbÔc~4&wJ\#bYKv%n=6#.(Aaޅ=}߆`WQV9,,#@FBsyxH:A8]Uy~ȸYUș5>|&0=gRwWfe",Z VNSpKM@3e2,W=JX:"HbAhZGe쓦pȉ<"8,l6ArɉLcZd${,6/[YCׄe (aB9ϛk$Mi U>o5 a&qDu)xKb&фN$<JC! IkB߇q{\Β+E1Bgts ԙ[;^}\n& 6+`Uyxܼ&i.].~yzV&l Y6'pR\k`j!l|V^tO`bB[V'b>di)J\M f}L }'4֘QXݹ_sճ[,hx5'_={U-H(?h.AXB޵: KLVi˷.6"A@C9b;w L_HQnC`$$ *.#Cis"-cq=[_U1 餠K(`hQ"yAu3蘊Cz1[z>8K6τ4H7qaÓ(E@F;AMx!(eA}l! "ڃO6pc[he iȯт}x@T?',2gh\}U.SG2e]ٜ}{ŁPȲ  rf2OnS??q{Aǝ< ^>==w%H |g) G.p7Bj~Cτ]JdPmS;p\{Rs Ч! M>ǶxsijBMh- :\sR:P͆Ht, :c Gpi5Vyg} {y )nD [4`+82n m?}P < w%^1>\=>eHY<chg7J$?`QOC〾gl%U9Xe#ܮvwV{19S"DcK3m@!5b K: I&&ᷞ}B*BlPyY@m#q1@m |a,vv'ABC p\ E4+\oo/ߏ:NXwe>Ŋ&( d,Ei?$?b*!u?IR2p,t`ev:IS]]O dhhnݮ0 m͡D'8Z'_Z9ǦZC.s~0GA^vW+v<(BsF @QCn ?mXqj6;M!@{4&m: 3%'ӲhfjQs'aM ttoKZY 3P<M2mJCxfY^jF:̶Otf舶\m X$@mb۾9h= !cFr@>y 5m ۧV~*C!E!=klE >QmH ҄ 9B3!ܘfJ#Unmo{1'h«5o|c 4SH^r#֖i\hً"i56o97-%XI@&vM4߀{ w:4 3Ц$l#|[ ]C`BK||,ac]B%hyx~l!q]] /:rlFjush9)ЄLM5]Hx`֌3p•$ЃJB4pIfBSS ld0uH5]&Ox=<&=5Vgc`h^4&6(gC)&04M^"?@IVЗc`hP'0>/ov6Q 󩯎!p9L0\Rs)oמ+Ai'Tg1=}U1j iusYI)1 2oȬjUI{4%( &|xx($T=n \Xœ߇l#kR\-M6:`BaLlM8XP 0g&(BPgl;=HBJv[mr$T`Ȝ8f7Yc,a){,-{H.$V.3eh.vn?[+ah6>`#A+X'Y| .w+_)H+@E@•K] =mP36Kjܽ~W[c-I[piW.HPY jݷ2gt)~w~gd A{v@3Z R4ao"CMubLns/6oRaXd{8Pvg~ M XnQV(tzAKPSk>Ӏ<9\/h%G[=waüv~_q @eI-ܟɟ,BKpa@x3c8o=C<߷:͹66z-oyhVr2*a>U,: T'aҳ2HCqfl m}Hn[τ&Svun_hw-sApT#(oQKPl,5"wc'O mV+ $L~.0d3/H5-U=s`@T,ac<-jM!"|e+dw!jBP&T )0nS/1 D s*ChLh6&H ys% Lp8LI˦?e:|(La1M 8ʻMnҽe i8<7k*@ ngq㶟e\fcbrXĄ)T"?]G1W&x˹YqҤׯ9DOI͕(`ӕ `%~ϡβ"!_69K_1m֛6qc BlA` o#sLc? ߹4u74 DEQװ.yl&eZOKQ6w$RqkHuXUZrRz]c<ﱏ}ljaR6?Vb}LEvK0]@@gѤ+G?[7󒗼dnD*a-nq&`u\)HY]q(tmsiYݍnt쫑w#Z8X4.g^W7Lۛ Pt|3K$ͤ~e"\ӳwܸ 옆#cZl^.O96 V/z NtrnJ9mFP8?}hǁ}UqyA Хs?9lv >_mn#~׽uD@={N;|XB:+h/7d:6m'M v+ ~M[Xh$.!DH\:(𥗮v?SK]czOu;HRH;|P[.^bwԧ>qiͽ[ ':|RO$&]0M1m^#zL=Ei ތD(h|`L)~\('ۂMG|2=] ̼qB Iʁ}:ZB&-)@7}SJÁ]ƃ,[4Ȃ}HtI]*pxFZY9 Ƹ+>CG<z̚LzHŸ"_(p M*2л:n`6R!s@$6Jq@%0~847ɛ-l\:a>nn_ҮqgMmKmZ%8hI/qK4{Pm%pkl2/}KG\ 9椹u;TFc8G oxC'&DJӬ/[x8UJ8ʅ`.rjҧ`7}\B=! x9q/_~ks~2ʟOFhW7ͻ /Ҷ.Errr`*k/^Ll/q`׸g)ۮ ^FPs{ܝlPA㻮i+kM#eu fj?$=AC`@įGjNwآι 簣S9P9P9hЀ3gVJpRַ]5Џ2u%z׻^sk^39v\)z׻iğ>VCWFrp H x"շ9xJw;~ٟ] |/~t}y kԟ**h9izin9P Hr_v]x_IOzҲe D!h׽n#Pu,5zԣ>1IZ|+_ R}2^V9P9p6О`7p앮t\@.7C*n|}i%i'?,m-{ g?ن'?#M cF}m(vՋ+*ńwK]*&Պop Ї4]~bi=yO`|3~}h. ťﻮ}NR֐ep}>={hR*UTTi""xXĤxm"|p4oB_/ލYayDEcF$-"HyMj#?Ɂ-b{Cm"#oAIym"_'+_򒗌nod]/","03 DEX؜.Д/rrrr`M`xEw,,bWE,g.m+{~/"5z-"؀D[oAP"|u BBGIxя~('!#7ͬME$<^O]f ,fRT9P9P9ǁlDˎ%K(TXЕw{ަ!ntUWWVCm͏]%~o2v!lh~zr= E8nhሿ=inwۥ{>q@ۨu8%1. 6 `LJ8Pgqb9^m9X8Ջ"}_^wY sַ 8~7}C;@ސ YF f]E7Y@*;7 '5[LiO{ze}Gp4x*@o|ʁʁʁʁʁʁUxCҀ [E<*Uqy{^f_|ԣ)VJ|s.s+\>zEn^Wl-H]rt/~W^7:H4z = ,me/w}fuy"LJS9 kuG̾}uc~$wS SV86Vr`9py5O4W]w\}q=>rrrrrrrrrp[Ɵٟ{?[5I NdOgRiM9~G[{Ū±WVrrrrrrrlpf7Y=y2h@} _h>}e }K_\+Tz^GL@@@@@@\Rʔ1>Ogt+5~~)Sa~KVF6 ********vŁ}cke.3q )!{ k^)Ǖzrrrrrrrrr`j ӕ}tWʁʁʁʁʁʁʁʁʁ ӕ}tWʁʁʁʁʁʁʁʁʁ ӕ}tWʁʁʁʁʁʁʁʁʁ ӕ^6yC+^yO.~&3P oxUz9***"}zms@o ^xa&_|fR`}~ms{#S|woB\(ws ׽ue/hg-yizի6/| kx;6/˗/g5Y|͕mּon.ve4yk跼-MY[t<޷wwMa~~ӟO}jCF2i<%'>OO`w>1yLs;ɩJgU>6rr4q@\gU|&H}K_j5_57i\Zﷻ.7Їjͻ5׸5g>[[ʁʁʁā*@]Z9P9p*9DC\9yNsE5_).&r!!~Ӆ9~Ur_9P9pV8P}ʛ8hkxы^<hhu|sk^e]:oo2/x׭Jrrrp gU׆VT"^W斷e_ߥ&7WzYr/yKR`oL~Hrrrr ЧjWTTMnr̭=ydNz YwM;yl?mp+4_u_7zm@@Aq`=]S9P9P9pp-n4׋=iwcF>m=e/ۜMAتzs@@)G(SܘZʁʁʁIsg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ 8eXIfMM*i*b@IDATx}\W(MEEAkĨI6lnlfӳ/flz3.PP "bf{vǛs|9{9ʘHHA@+ͯkkҘ  h  €tiRA@,c@A@Ҥ  Xƀ  PХIA@A@A@A\K 0` @ @&A@a2A@:@@p.M  €e  u0:]A@A@au4) 1  €tiRA@,c@A@Ҥ  Xƀ oYfTnOhXlXݕ @}@"J˧[N٪ۻu1ر#omu_*>FrYoh붺QQNN6AIe9Yt%u;QԼj~{yyQ6mZTV5€G  v7ǩ9Kՠ iؾ)gOK111xb8qb+2Ky /4\̣۩O?Cҏ~#JLdθߟK0K.4QˊI k$Shh(oԯ%K5&\B-N._))k+Ai: YK*<5R?jϣ?[\A//p޲d Ӥvܹ֭⒯ JqAZ#)X75ٳ5o'H[۶m!Ch!L<ݷVX|jތ_q˔yiyfmamf)W.Q,D9zY:}4a"uL~:Y}3l/:f{ O<}tHE4ow}w;︵k[J-XU{tScgZ KEI,򊰦rIM}/ >xYfP5k*RL7 i-b 6ѣtq\ZZb-M5M AR``^0_ .!1 jI-XY?5: ѭVaL :={4PO*X @}Tooom-QF̙3'? N`񕊘iI`Fk_W.!k0c'%낀&U ; m$Ӟ">oz_/j_˟ޞ2yV$Hc`Xo_~{v_HcOyk?j޺#5g8hj2lW.]h{@@Z 5YRuBB PxWڶm[{LLOO/c)lҥ2.e,;ҿkp2V:j{]\RdvY򙼲Kk[|Ϟ=VZV˥ye%ΟVvRqM,XPseyyye,ɗ |5MRtJɹVc)~Zvo*ý]DNiF)s6ZfgX6mZHo& טvmid?Eu, 7j޺Cmby [^hApիb]Ë}ucX9ڵkG/hoyzh>/`@FjǔuW~0 -I,WXQM_o!lcDNҘ/ֳ€Ғ Pk. $X=FXzpk 6Ј#dz0z`[%ޣ=IIImKB P}I*x4ˆZnݺ*EA@?\Di&m=؝k)$N# i$  >ݳ$ 9€HA@"€S{A@s# 4E7ŧ., PG A@hnO]YA\@:  ܳ @# t@A)" )>ugA@:G@p? @SD@pS|rς u0:A@0A@au MaM=  9€HA@"€S{A@s# 4E7ŧ., PG A@hnO]YA\珠qvN<8oNJ7 JV|Mݻ h  €tiRA@,c@A@vM+*s/]tA@F@~/mN`7GWzkT ;;[)2.ft 3g/^9Xڹ#yjImZӟybwB8j֒V{T" 4^H1_.g!Lcv)5K;q?x憊waTZY3}'t K1F2Ɍj5qS6.3i^X7`&W|/${=vɧkGI|'Kΐ3zxa}j!#iq)' xfgG57+O(V1`LrrrMhQ1`LTeˀFԝ>}Z&*\՘#R1cǎ)1^0ʙ :դnL+'ƄСZK䏈P}ݤc8qL҂.aTn:!%++kv:0#Rp33znX} o3R!ș:_ع%3Sd َE,y6:ү`6P 2ȣ|yUU1`ɽ/oĉi ͟?ߕڋݎ*K{@cǺ Wۘ={i,,aj F8KxԩS^ˇ>-Jvq\m̙3ǥ60YYr}z}mcǎ.i*U?l}*wUtB>;hR5 a31`>ƪ$9Wz)28[2>8ņ_Vn"1ʒ478ű>lk<0:P`b٭)ZE T`R+pZQMj r$@BPRA}5>;j4 7Rwj C*"}Mͤl-mT r4טQ5֒/+7%$:bFVF:3O}5C-eWMãe (͘n>齙sA@ɖڻ?ݖ]h08].B'jVϰdöCVk> ZB@Y#}b <6–&X^?ΖGx-DawsC5 ;V'h͒s`l/-XQS=)X™~ۮY=^VOw\c3cA@"Fzh,w <F%OEJwpO&G|{TWFڕSN6Z;SVEsOhz=k)iZ3?z;S(UX="cCG驭I*.W1SGzT/giKOlNKi2;71jbc="U{3#ǂ 4D`7vތմV[k $=| 0!A̗4qgVEՁuU'`(VAm}xtiFVAZu+WFapѝJ5E>lA@"h$`1^l º쟒P$1_eWގG3LԄa̾gnk5_m9A@ j ~N8ٺKs+1v$]A@4)|Sh2 ӟ5JҀ @CI1&<}"  u@نT@J +var +ș'1r75/%989!Z#6h l̪{yyQIhtSN駎.]PDD\?(**$#y®]CnLeggSzz ]vcIGBBB]VD2:Xddd- X_ZZJ۶mGB\\fT׮]{r͙ݘj f8S{&G>nLy{{ӀV15h SwEaVU{9.Xl1h=zPPo8eƔ9~nsw#Χ !?Jc54B*PԮ[)EX*~,#}ՕuOV-$ =8J- Kv ., aQjA@\B@KpIfA@A=vR   :=,v=jܣK3og/O85#]+z?֮`vter. ph ]p_6p8p{ג]đ2L+$ иlxl&n$^  Po(eWNՙY/ºj>7pn_ozz:Ҥp6{ZMYqo(˃96e5_ڵbiڒ ),Tuqvsۓiwn>qBuT3\VZr:‹I|s2sg33>A97GkbGp3/C+gQG?B| @\1_.'8-L>ߵ@m5#,0ܛWnE>ݗVj5̏ ݃;7r8PӁα[v1:0VsD7X+pQOrn=9ZD2S 5Wo|Fמ^4C9`sPO&$rEӃ3h5\5ξVJEA@{| {VY1_l20 X+~dK!]h0^ڵAZvΝh) H+8K<K:hٺ*c֬ ʐ*ƪ~ML2<]މ%ƒΙ|=l@CwOEV  {~f.ؗ_HO {BneV9X’W^jI?y$%''[۷oOF#a͚5tE˵SNVCÇ-iРARZn% cƌm.C(;;R&,,""Ϝ9C-yR7aK:6nHŖkȑ#fߡC_ U,H>|8yyYݒ҉',eBBBo߾gW' &M<)6֭[)??ߜL}nݺYk2V^Mx)&&:vhN&1չsg?[ґ0vXjZ43ܹNѣSNNرÒުU+?~% 6l˵P@@%=##ӭq___2dH9e~CwucjɎw[lt1I)))Ƭڱ9Ғ^UBa;rhP'_(<l~[>הzxS;VϺ-Z!,=h?2|UWrFc:4K tVAç3|3D8B0{䟒I`^䮐**MתӿqHW]~U^=ͮmawnCo}=0g4~!~}74!KOn3BiYS'LH;RNA,s"Əy.#a _ޞڷwuԂ'&ӦM.:$7Ƞ88q"> 7>$\W$ڃj]!hTZ: }ڧ(YvaÆ9[/((q }BcLA dLAvT^*2`3{TJ>Βc W(88qYu<ց>JSj*2FUPo?78J3ZzcT]ha١BFB3;0F+-ǨG{BHy+7QKY)j1cA@D}mdawsgU6/6ܛ-|aTh`Pijp$opqB2qmlm,!quQɃWUӆ%0fNU^3i^ef1>+k|粪:g?l!i X9r=/mS|ܷJCSCz=bBjR 1W:O"lp|"F{f$Cll(`X k}!v#;3y\b2gy(_^C@[Zڶ%K9ajmUehhf\yDxdP~WS/O1D.0(|q0S:’=A@pبfFO&bH?_1{a̤Zb+5 jSV?ef.B_6Nq_,фԙ۬ݶ2T0}  "=OnI6<1(`5~V0z~FuosW$[@-_K)QD)C->H =X {UjQ]~4j5pɋ"s^ UəUm>[6R͏sd|"VȝE>j"$ `EX6;ƫ`;60ʢ؜Q4_͹3C5] -];6%g+/邀 Vg$EA@j@kW*t8[5|QA@!€C^]!A@A@Tu* ܈IHA#dp{tKz&ʆ ҌtvVājRp}2g6jhvr:(<8fwD|  `q=y%;T'xg=ɩsKK0Ǻ5Q09iΊgXz}Dݬ x= &qsгki!MS.?~ׯ\SlxƐ!WiJ+C=q\o$]U{]t!|\#G´j25rp۸8WƓc ͱTw%^3Ӌ$||%0W{РAVɘkɭaLPַq#53^4 l,DE<~u`J7 Ug[;ax٭)PZp`BC45tO&XR+,  !pTo[Y/'*k,ׅ+$$0/6?]jOtܗ3ԟTffp:A}BՍ:k|ub Jm]چ.6%Z!Ɵ:B,A zDao PQOj@ؼSUDA@¢9^-uM/٦d V49Qj~-Gt9DFJ!fvp/$Ԫc=qP?mBS:n%٬cm>v(eZwN mEiăݎ;jF\o=-[r5i p>06Sm[304ՍMך0`Qyh[pzp?5\ۚdS̒:oa4sZ͘)|nt\5mDOY}+~F?L9HG:JOmMbWhQS ]yh QY;fc5®&@SBDM {:A9Hɦ%jS 1v<9xX*"<̾kÖV*:} ug$v-ZD={.  Ф Ǐ U5m/;UqmA?k/خ?t_^2&I A@A5R  :€]LJ F@p! A@:f | <$"&A@G@qʝ^Xms8xC_4BÖ3mE9-KhvQ#SLfO3FҨԉ+!puT>_Lګ5K~_r]Aa8}Q;KoQA ӟ9VvtJ^z(o bxْ G6H2 7WM7|=bB,VK?Ip9.z-3W׃&u~{:t75oHٟAwF в c[)xz.u{j8?D<{ ?d :<2Ja 0㜹t-sĢ~~OzEde2酤Tg$Pn2|&Y?~s9PădAD`k 4vq@gm$sDL,Q @AKk8 B{?֦ ?_gR3] qxZCqh!ʼ@>4.<]|ЄA4fYtQ 7.yjųg""%ntIv] @#ǁ\~a#:FV~! *h7d3&LKIIIgKz׮]iіb-H馛];wݺut K(0|yhG(k`fx4/|vRQQȑ#{}ю;,;wI&Y>O,H1cu`}Wnٲ!vk(߷Rgfwm pwCQ1 ֲ F@Zan*~9/]dIgK}L;D;I68& ґ|}57R-M&k`UJWƎaܾE 0[, CK3$FXΠ$yA)# ku8!E@y {[=5L@IDAT   a IA@€S{A@hpnpL:, ܀"B:CVB AAްlx^ZR/OB(?|Vg[~DsR7Ov¿>egE/΄C;xGocۏMYv[KU9n]{5!N0QU[  Ph  Fx}F,par\ݟoީ%5.?ӃG=vhD3SoJ ~x'>9|_/Oˏ?˱/3U|p~'V:of$"`?;w'#!XoVj!#*.)Pa, ;k`Ag/\$0JH=)\W=#iШ!q?@gI[| A< /4) Vi'h0 X=!4Vޥ~LfMf6{BC;j+ԫ\5={-@wqn!Y",_V^>/aOO6?ƌqgN&?޿#H@-D0sY*ȋ Gzx9!z7\MR(FeOZs5 #Td63cءt3YpaP{ jvD]@H܃?haA:G/'Fe!FӺrh h{z Rgj&~6͙D(6XefolPgP>ŪGx]3%x&mɛ},tVJfH>'zC$#Rn,!{mnUÀ };\X i50g2u~fjU~RР_?ͪ) Oj-n 3ݳ_V黈1ygֿFP!͚`hHcgUx$WGO3YVՏٵ`fB cRsv}Bt݇^h&WǣO*p*j0 8Wb!D7 Io~aJ -)OB\>zy -_Kȃuesۓ٠˃gQt0[pd}-u3h9^LYjcMA+~뤈 j!aRbN.}8a8M )8)8|=泊>,ݷ~@ Ae2609d~JQM IV76*/,L8/;v6mdLҎ===iQŋ/ &P``9 SRR(5%*88ƍg̪_ZґpM7Q0o txX5ׯEGGlZz%/ Xґ|r*,,\1bY8@ֵN:ԩS-=;d1cZʠZiС|Zt% .T2kRNNLLL Sa#bzQ7zyyٳ-Ho'R@@ݘ cZ򗔔W_}eIz fPƓ}6!**hԩSfK:-HXlY9BCC-;vXiʔ)tLTd9s&uRft!KzDDYAyyy}X pmݦ03gXRKoƋG!Mf2'Wy޲ʫ"c)T'D eU_G:ֆwwי/"R ԙדu4\Ȗº.OP|`ͧhVf,=УEZ?K-[pk ,UrL^ GXxzCޞa!qVcB/Xn$armڻcK.l\MeLE1.zs8\}>YPmU1av uW6 i8пy)&-jY?liFfT2@d8m-xERcGnS'IvvI<} [ i٬BŎuWv=*=ƪwYM ޛV%+W*z56[l f׌U%M\G|Leڱ4,8h٘n 봟LE2RM.Vl3v6ZFjtڔH3-&VoW\5ѷ`&-7u8t>}Z޻|EP?r`Fcof)>qjݨp{A@X ZٮZt,ZP&aS}^{<}C-eʰˮ, -ZD=[-O > F%Ape3izV90^Wgk\|A@?lQBA! =0 @@@pxr  a IwA@€sDTR#5-,R^낀V{©1b)氅pӸ|xrHOj "|B#F8X8Nc*'Vr'O^س;"nޯ~Ct/+{9]-~- €M8꒣pLQW?͈'о-a;r,w[/kԄ>C3a?=6S {cNOOh (2@?-9׹syh4 #pCC]iB364}##tOl33콪.^t_1/Y0JD&G|:1|?YG݂ٙ+92)+Ea mgv A갂6\h`My~Oͩ]ve0gJGc! k&fv \fP`FS竜~?&|~ M~ -Fn$ˤiKҐ/s,r/w{|=80Տ(!uNXƏHNfӗ8k54UF gܟgUek@@ZG9,ab{2]$t M0: V~ȀA~=V*ЀH֮=qry5 qC $(ռOlNn<3QVW&-n,/{3SX49c|#E/j(~ӟap (s툗 XS D{w1 72^AUKKKe6 ӢJ Ƚ*H:oo#/ʘ 盓sES3E~f=#/ʘ `ʠ ~mqq BcUs<;`"G93 AtRȏrf1L0LsOGVy93dLaofc oXƔsH҄g1}7CD䢍C 3J#Fޫ |kd \bD-0.icJ8醭Kʏ8 0 kO-B#0/O--T/H!f$ߟ_Uc^tSdd%ɓiSy E3g1qj*pjc„ (00P?u|Qjj\?@q駎o0= M7ݤd;vǏ;(<::Z?u|ի& ,O+}[NɴGAh ԩM:R83f('tAK]4tPK:] .TNnx)&&cNLc5{lK:VXd'NώƉ pmJc2dwsU2T<'6(QQQ4pUuiZf[ԚϷ#crmȑjI?|0aߟLbN֘}Ϝ9S~t!K]gItٲet$vmJgΜ޽{[0̈́YU V5x *bD*B!la!3BH̻0I'%|!ݘ„cLvc U*)ScJ]REAAAJM;qңnLaojL47vcs6Sz€͈yoOm`B*6ӱr&u\E>Ŷ's4$bRU@A}6i ͏p9!t_P$a_r#yѹ]7I^ljtWHR<^Lvj]U9Z]ԡbB4]m#$$D/7TUg{YڂjVi5TuirL!6l36󲓑 c]ŒyzպUW&>10pj2l T_g,geMڔ3żǼ>jNFjHb35ysxcz1TQ!FZ%_u[>bh|YJ_9sOdn$'ƌ}mcA1#< [jǭ}t֚l ~i^)EdL>ZҲ' *f-h3WvkwM]瀶giԮeejg0Y%ю6ήz5& Cx{h}Vېp:lᐦD&}~ܻMIضw)`La#EvܩA/kazJ=e]G10AXFCsúR?*{GPTݽvfu_dO:*wy҃}#,mϡ k.sfxu>\_b8o; <& Fs縯1~̎F$tO(ͣ;*u   O6搄ajٜŗs7l)yf؇?,O?\س;}9eIM+61!&o kٌq4SܺjHFA!`(K9 )\\z'i*\'~,-eaؖWNA`? di'j1BFpO î,;n-y'{ {&C5guk @x`6Z~,}scs6Og-/{{'€k66_v5D<`63`mbܑ =ZhR 2_ؙJk3|3aUE?".юU q-2ٹBz&eAHhhlv1Kn"L؂$\K]tdCp?n_f?ѿߑhFL7s8ÅEі%k(ad3efk,LO7lz::ω~1sşR@^ui\!"3ƑzM sJK+ET2^׏qǏO߈# ]\\L|⧪rzff2x:∪5=&bp_ɓ'TFlZU3gPIII8=b"|NuSbfee)QkQ~U0n&<'Ns;Vˣs+L9Sٵ`Kl`gL%mSGch$1UPP@zǘ&|t=n&y7'S#*]1el Wc 6"X㮬ȪfuQM;G!27,}8a8M .M >|FxvP?--׏!#d!dzhȪcY̤1 -`~[N?u|<"#*Cشi#~9sJȯz!O0T:DW'Ezex7N?u|n= M7ݤdv)))ʉG~(::Q~ƥj? *}oݺU1b29&B &*SNe2Θ1CPʁB?<<J] .T2;w*'+111ԧOJ >>>^K1ۦ-'jB0,>%lذA98qr"xa رW8*ɫ}ϝ;͔EEEٵ Lϟoɏ-[&jf9r$1cK:)S,vd9s62ڷo7k3'k }#mݦSLK{6'& tLf͚eI*ApU8yVga0HC4Vp~之ԟ%-W@g3_I+|6:3e,Pn$u3Lx}Nh0 O Y"{C0hVn2#5x*7i$KLrUUR^)^p`fD"0cƬ]ExaveBT1H*Ԫj`ͤ[nJdmkvϯo߾Jb(z=vm!Cg꭬֎WLLǏS_sۮ)O0Tjj7Qa+ueLuޝ0vd7(^ =mTpݘT7;yMǔ|CS*^@~gs+oY2Yg8fSr:ۄg0m7ԗ;q2p7?};;+gJ6L^Wk-PzV3?WT2PW[ԧ\WSC_uߕ{@I;Gx!$WWjijڮWSڵQoW?c ƄH%̔gD$cʈqSS`v{Wqq)*^`MS[#5V`yS%jfPaHެwѺƔk͈kLjT}4CF F]I,c'ׯD^Ζ'x-A"oxivX=c*>=I_.:Ɔzs.q-9zR~FG1cKg~u¶0üo1_:acjVֆ~1p {~OϨTaqy"Ém]F*A"&oK7G_LEknH~ҭF0`7=ؙ'-Bjևgֶk/}x -Ungv|/R-ҫ/Md#.۸\v&з' ?lܛ'qVװkj:7Z/${YeiaO.mV5iHB@CEbJQA u8݀er;jŒtpES4{#?8ڔH3Ӳ`Uۣ(d8$vZ:|*wPz2oF-O+f̧ ~1i8k6kf0˰Aԓ%c!A@#Ќ-H+[#Լ.)2uVgbN:xol]z< $`l?jg6sJJCTyi-"|T{nXHut&;ϨIY2̫sזתCXA@pjq=uK-  `0``$YA@J݂  €mdA@AZ" Z.07*z@ `lGˋ=M;YW4u 5_KVe,8E]t9q1%/;H䐋9v1wqWݩ^lIްq-@ iJ 1HB1q^pjV/VNwiO{Nlɚiwgwv߼7%+KX&TB@!̀ KtۍYA`ѩL0aѬ>1j:z]]j lYO[cGSNg[v _pïO6goG2M\.;MX2W frЯh>4)9잷]^tx6`oTa~vbqYWDE[h}jW.d%-]1lmG'3e+؇66bӚ/2#U|qz 0V`\glGUZX*~oKǫ)϶:'b ) &')Q`ZOWu6a\!|*guS0_ū &\).&^{\bm!N3n6o^6%}o13N8*=|몍iƏvÔ_޻r(zoQ#s]cٜ"֦wO 3FIWvw?-Xءr, b+Wb' F:PP[B~2P jjEuG'O9rD$̙3۽{wS8?.u"*[PP@EEE#sg"9x`u S|Q wvv6̏oee%efz{t<3;u6eKNN~ya8/..|ck=H5 ܃#v06Rnn.)**J︆ӧMлwoՌ 23J>S999 ~³7NIp\ofӣ]8He nO޳Z$G:#!oo}ҧ nݺyD ,ma*1`q"+" ]g&lw[F $8k%13ۜ[(>prN%sz>J)u`s_>O2QOp5(bӕg&֔iL|ķmf*bĈR\XX(hŀw)eD`Ѓ߿T)c dm@`2 %c2`0-YxX1{,F0a9ر]NJ d p ԫW/)*idǁ(#9}+t|*Wa{fjbӎ>)٠'vY2:h )S`M)qĉR ?#ڧd} _4nOY Ч1ҨQ O?6x,-;o#αv;n_˨OTu[Nb=k#"38h*r^ZMwтUz?{O4{\Sv^_?'v"{pLP_n-8gh1˨죇N=30И1c #'#|ʐG xߪNց e!l`aÆF@BFڍe4yd錇U@}eTųYF bso է: jرc>$+wiƌ>)0rk ٧NdɪOAb>exgdgJ֣;:-3 zq:zLh gP'p_j"ӓ$F)I$aFIt$ƒ,^;{wk:nb{?X҆pv˦ॲz?#'+/eX}e# 20+ Cm:X deCkV_?Œ}c=xnuR} N _Ȩ=)7F_fdpF6@ tfYN3F3{(-ua*9vk3лNm7sȦĞggal5&](K{F`YA%k6%gH{%.aZ1u[XB7tK Wd̡ I):*2Лdr@2+R&lmQuktx܇'2Swיޞ߰5&! Bhj)^oCn> QXLy5 ,H` Z& +۶`xW[HB,c&W0EwB 챈vfH`70cгcQ[jq goMag 6z=I7 klيP&.Ѯnj~_Q)=5)^Q"8a/&{9ɸl֒ ;ioQ xp_fIxm'NKIN=[L%̄|Ap#g9\B=!%`Hp`ȰD !#$9أ .^4[Aš)g46W۾I<^N9D/NGoIci6;NT|ڟaly3kE~s(7mv,3#U_KvƎqDݕ=, 3y)QT1-tj8XK6jmwsڥ2tiO<V]zkr8 u=s z 8޽)o Geee¨wo"#,ٳ}%㌌ *,,4#817RUU>|,Zl<%X㖼B&>?^ b߾}RmO%''~F 'āi{;x ԋT^^egg{|UըE`޽ڥ>O^yࢲ @Æ 3GѣGt#Qzz1X.S CsffzGWdZ0,3" `MVc gsncgaW[XVK1=*ޜi]TC} Q5Ɗ0V X,c`>V ت!CxK q1S.􃒒i7>|STS:0"٠S ﷌[@VbSHghmnݺI#@}Vƀ1SAF e تOEFFZ)#vπJf9} '`RwOO?5j0-ck㿫XR<:Kl1igWGxZ9KBs;ajǁq/g n a{mC]x׸eL4'dZZ;[n.=G˨K.җJ?07Cz>Ux em@ސ&d4i$iڍ :yT UVe[a;f5jxU1Peiہ9TydW 2on{7JjS'OIڀ ۦ}WT UOV' ۱cfקV펍,ê^3g,[e$/>F?ei oh{k1 %,.>%jbZD?n u4n\?$ )` glc\dmg(acWz[{yz<_?6/DT"6ue2Si!ǖQҊIiqGTV/>џ _ڀ|8n_xO 񅽇Tپ݅6N[_ݒ:]2Zev{uX݅\Eh` ' X $=ֲ~;S_YCi ad#?RkJPޘS@gYZ}5  e+kTXwBKS8MC16}8fwfrnn,`,C-mcsVq-A^V0H^N  Ϗﵤ F!ph x0O;awjxuYF6q(}OuX!-V `iq:kjt/]NBڔO֫iahC}ZãZ'̅-MК +i`LZQ"3ַwDȠ}7ݼrz~vPܗ{?)7֤!q?L?BW}\!p7ͣ*6Q \ޯ ]O!ZxzJm|X 5k`$o݌IlSS re`YS|ЀҗkuD^'وGRHмYChw2 tK%m\p! Be!k 5_,e}@LZ1_cxeh8bKV>NS:Ԝ}Vmk*oCS?qmD Bˊ{7l㱭{4s4Pg B@!Dtc,m@[YB@!P(.5DZR@)R( @[AQHC!P(ŀCbAKZB@!P\|: [l@M+ūOޔEK< }}\a\>'^%"(}B<+ʇ'3l cWtN߰an7?ݼ+"]*}:W(  V6T H*0&mkk_`m $Zqpqk3tW:7\x?zeauFZ9o:&U.3Rh Q B"a0 \0 O|"\α~;VVpӚs]VDžW'~4]24HZ:*.;|v;7,6F֜\:r-EQii4^y,–qt3ͪb鲫u4S?#ز 0@IDATq>d%+?[-,PӾs=_Sh9w5;z ꫧI_vFEҵH0^]$H+P\b{k=ŧl?N>ˀ0 //> 7 Auk+f7g f0# goFGϖѧ3ny&MBҵ_|)2ƒ(wl^[/((G꣊` i۶m`SF߿?EG锕eNp߯_?Sx-ޱc)#F"}8OII:.--ï0h׮]T]m =>q AK{:uv9FDDРANKpn˖-x8 k);~8icbb">i7***h޽ڥqܸq7* լOǎM[R0`EE]yZ)8z#Ν;zȑhֹ8tҤRZZ)qvˈ95Y’c߿7EGsڙ= 4qqf7WVVJ㇇㶔4^9N`82‡Xq^B^0yv>fE999ҏa,,>1,U;d7݀N2rqxQYe": |JAF-SS2>Aedէd@72@Vlxn0 e愄-;T@wqYyCҵ٧GOOV$R}iS_yg$y. G%Dތ TzSX2 `1"uVۆ9-RRސdOL<(Ŷם|;ZmӛZbGxmpd/>$eJaX'm?qt+Hn#REy]kI_žú3 v+Kdǃ=⨣B fyHFyMB!Сu+}RLe ]O 锍,A6i7YB4ى@h u Wa913iq:LqOLG R<K7 $N"?2ԹBb 7KQ@ס{D8z@)1P/3 ѯX)y a(Q^V6A 쫅aP^}i!:ώ^tޗկwX k=4/=q'3˜F6o{zpxl ?(`Q@/O3km{夙̬?e ]O#Y"0}WDf%:%(R\H7"倀7ZԂ6`yVj'ZĚ_9^]*tTBm~ry{\NP| J~RY;O+x/ Mx˧됤T~䬙NϙSTuf9| #. |ߥ}򄗟eGI=uX=:2o~jQRg]zQ\Hvvs9qܵAߢ^SىmQKEKκT[%QgfMR]){ÔLY[D1C>?T^q? atq!W*ߧ=(8qJדH\[x}f#>O+;BpA[Ҵyi.#"#⺃*> | HJB^˾] dp?4:-%_Rhʵ$IV2ݻ7ubV8ɡ⇄+ LXn9ӽaÆQ\\)t)Sx||< :^SSCׯ7#`ĉ{|}8֭^TTDvc׭S#`ӦMTYYi7p@JNvIHtS(5j)n͚5p3"""L`:\`vP}cFRMN-KfEY1"< |l$c,Cl } yeʐVm孅J`VvځڍG\`"#`(KsAzrBT0x>eʪOY@FM)+l/TSVFgpv[a{A f +>. 7ǽ!Q S;kryJ ,O;$O6Jz.ɨQn ^C /?w"AԋבڅC|Vh&Cr;gqOCs;k S$65]-kyjGo#7o<-9;w&|Yf+~M ח6 _DTy}-cڴiMei׽{w¯Au'ʌlvX1eowRZ1p@R={/хt/2WlGm4ҷe`ѣ\{|1+%*3:3YPjj*w!]14#9kKLѝ,u>B:IQfySϐ#z$f0jwmf7g4[,iam~aRlM?⠄\ai5M1sOA TZϘ֨Q5Kq# `uT*16+9S@xV-Weh-.; ?{kYdV SL;n^ہ/Wh.Qf; ַ͚JTA g)q` MLȺoy+AYW 碚"6%~mºƆ<^bX( _Λ׫CnT'UWJ/=Œ.Na@+#pY2మrԅE*LC39~̸" 0ޯ^{}GomJ`1ce= i1 j04vU1qw ?BS(b@lV47^F bɾX_TF g)[z$|E xLM+ XBǜ`tdƾWN\ZlUbjАm?΁GU6K]˭… ?zUP(:34񴰾֭-`,'{`,]AlJ+ D~UrB@!P(Zb-M%Q( ""+ B(TB@!P//*B@!P(Z@3c!w}:³BEGeXS_S|ˎ%@%aͣ (#]7dls΢et]ü屛D5REڂ6b?O_ P(Vg؅9C6:/ QXRݿI_g] mXaئ;E^GeG_*t3xaŏe!rzŗ]'Lk]u"<=I/}3C+ A0 +0&} /0f>]O+ܿ+䣔8#>uFw}G_?N_`0CAOh⽿`!  ipňsW}5UE3g(LܫVQ1`#Pv^12f]Ws_nthƎ LK#Hn`cXOy$cR^05=FQ\WYJe`;43douTix…aHfa4ԓgsO`6ue^IFN_{\©BSWn=0^0 v6%=9%eOFlj4{i?҃ϊgW_Gal:[M 0R E̷hոCS=@Vd' %,E Z(rYp\]ƌ5ַuh5T?NG%3,}ZC ]nIQIJV}iW}Xu=Gx@2 HH3`͎Qhn!ckLCcJ]p#XB;q1\bZ{k 6`q97q?[ZGMiŦz8P;++v Aⰰ0>]>l231vXJL4uLBp|n={Pzz1t"u^ZZJ_~)~l3P{u5Q=>Iv򊋋pr@t)ψ9L~ܸqGF:x ;vLV}V\i3gRpp֭[)77nէh˖Ɓ>j*4c>bJIq 6Z>8?~0/ X)|>s}SRddZ;ٽ{7edsvJC Ѣy%%%WrիZj~T\\C;4hu]QHM)c\1` L-Í^u:^V!4(/m,q*m")$~?ײGx0;!!;*OS]1}뒼^_&#W}@SgkƪV^w }MFV,)֪OYKW|ͥ!V `QćY=Aʅ!b^ZCoɫp烂$G.Qk>`o~u!UC2*H_ypHQaM6ը(v/Q }GL G{A),9;(\ HX^(" g(bafޗcFhXggX_{|Q\+;XQlW~]9JʐOJJ"|ɓ']H=zhv辴<#"$_ˀ4 ~%_ׯT·*3""BTzKIol1HB}={~%|}}޾8?~|s ⵧ>TFr/ג>O?1.y(OC;ʏ mJ^ KY ͽ`=?StVJ K?4Śk۷V=3r=%[0ܯf ׈D)NPʜ}bMZ9`P1C~G9YYS(CaZ=ׁ> 8L*N˦_uvP 1Bpd$ڢBJkNq\){+XD+޼wFJw̫{GRW EYk?7Udkk(fs&[B#A*w yy֛ a`fz<~O:0pc0_ I,{'KY@Cc%bM^uk*1 m@*|!Iw(?IoIMVe'Xbpֱ^q1 ]BFi&V˰ E/)+RoDY\ FujrU EѰPfeG^^.iR|!azPRrTa8Sb:'v OwM1C/eGx  zN?X+σ;SNpQ~B(ioN|BSoBV*f&^ 宽R(;E D[ǿGXú"oF,N\|rP #AOq:e|Ll1ing&Uh)ðG-33֞b{m>1C~/όOXiVHl}+ ">+!R]Q6ky[F tswdy= +Uh| K-d^|ۭYbH[o㵎~8oAۡHvP@ӗ B7l[V kzzs F&305m$M UD;5~K"V`P/l6 =%M ~gϞn( #!4ϋ)'c}lU(9`g{) @JX-Jy)&(VC "z}cRKP(.b+J\;ʳߺUY+ ŀ/G| krP(6qjB@!P\(|?a>B@!htH\ztJ8I7=D$nm:A(^V=_:>r<~ZX I-syOtT'l!-uP(>"С׀]l:o-L 3^m"ǽl :T,c- k`ָFWmߦi+xnM22]:nJ V( _NPx6h6&1|LJH~+ S~x.AD&7VQ~鉫CET+@kȨck!VZ;Exr͢pS*_t\ < K$كu}Mi=C_ot_3s n zr<$IMxz|p;E rlZn7"l:ǎ|"z|07ש9%{S 8И؈p=z7Ejxc<#\)jiQ!Z`)hW_NZms@{@CK0Q=\x WebvZ0Wvz~56Ǽ#L[&< e/,81h&'_ىRmJ {9r;G,zD8rNHg%bUIrcXcoZQv3S r{Д Ǹ"O&HF]=>f̘NN'.f͢0\l۶N8a zb/Ll*ӽjS5y/ >ciڼqEsj^Ǐ>p1m4JJJ2ݻ*ĉ Dx1{3͟?BBZ~=eeeB|SAAAtuיA%KtoԥKSÇiݦ>})߃>h\ G3gEEE֭[IU***+VA7,Lo\ 4bԩSeSHꪫLMth `0 ]~oDh*Yyj 4R;q3c]"\ׇ<բ|?,Ff$d៸rr9vfhlR=Y`8=dײ^@X__~gI܌1tTI[NKK#aNChi2~~~/}B:#l2G;wjSvPF\V#.>2#|dk ׁ:Tt&[?Kdv[=uJAND)Lѧd;2T }J*, B)ga=@lD &#>%%''Fz7SM)cuUB v\0CӕcR\܅: ; lp1:xm"L1,#%G$JvV ]=F_^E6f%])]#FWH_?.g@1“S]^JwL:sqW=n*Z>Afl2Pl9*3W>> VIF!qp?XǾWn[Xd'6?XyCZ$W!)/Ү3-"@;@C`m3 O~^~׀GW~_T )(~%N?9Buʒ"_H*3RS._Q{2 R,f!&{jg=Ֆ}dsWx`_A [r\i8%֔q"FKCK FWRBd.Yu.MrdڕH+7Umn@Xx6FYF~vZtջ0dUQIZW}!|Ȣ=t8GDrI/(^aPҪA/Zռui,ŏ{.Í;ZZ܊@px4slKxN(Otx \Ku>AFgẲ?{yaCOōxk`Pi>X_a;o}jSSuV(.&Jm0L+KV8n) @;G@P(ŀsSV( vb+ @D@1T B#p; B@!>pZV&P'lgg*嬙At>mU`N0#IW>򾺚:9 u;艨N Bp XC4zرٔb `lKVv8*Geŏ8T_B+o$MY~{0M@ pͦ&ZJv"aphتT6Xa\Nn{~>lOiWPjXջx-S2ޥڧ׮;, GzE*b+1X OAZfNpBXҴW:q6Ǽ#5'LYj`/w۳kp9(?f_P"ԲC8vTf2}1Ǖ!\v1;k<"T#tڰa)<<c5ON:u2ٷo߿BӦM3WWWG}d G (4lm48p 6KW@P|͆PNeee{&Lݻ=J;v0ٳMVΝK1114۶mǏSRg3Ax #lT\\LK.5僀nM:ZjҌ93/)>}6n))6Al5c JN6S4u[B_PUU-ZH9)$$s_3WZ C"}xNNYF$馛n2#`ɒ%T^^n7qD֭)ȑ#sNSxBB͚5- y(::ڔf֭t Sx޽i̘1"Zl)~;rJ*,,QFQ߾}MNM6###k17apXڍy mTxO03rff)S|a4R;)Kl4W& N^#`uɊ{ Yqv]J(?NH||l &2 ($.  eL2##H{:!$ѵkW)JLLA HVCMM#H`2Ly ^p{@s=`@T؋\_r`^@`4:ើOZ^zIVhZҧ,k2f!om5kϪOa!+\}J6}*--d}4.NOnTܹ [> ”.220QUe/?^ZI"<%xʎf;4THy8S],')z IfrF7d}&[V !UB`2)*|,}iI V#K_ː̛*,>V ҙUd:$y 3ZFϞ=My6LZo*MGSp@j0-Kyh}J,%} :_%}*ˀA8YQ'MQӮѼW$Y~_V bHAE<5zE K(ژp5h=]ݐB]*PE\OqR) (, ڪOY9OTb'I%K(nī5pqkK?Ɋa)-!T%.dk_K]=aD!G $ <{+-b K1W飨s@G@1`.a#:* 9YˬHcOKxx k}}g\n*{y-MN֞>&Zh4R=*Uu+<;p嚊U=UxB wH!#в/<*4,r/GOP7Ei3&5e u lusxɖx]jl}-.KSpyM HW -MCc?5Wp6.OS19lUZB@!)o-7*C0;ֆσ]E%uu.ukV ~gϞmV|I!Pt4|'঴ϑ?k̷=OY!P\l.vt>sn&[Oߜ\z2\+`gG K@a@~T|nI2`rh{']kݡl.jT=T~okg)[s@kBb#&mcwv`X(r9{;,PԹө!T wPa(9x]sMY0XU䪮u^Nܽ˘Ab:>T{U*-ⱊo/P5o.SuҮpe:,a[$/TwX»H!h#K fܲ0= (#Q/d |;ɕAN0)] HY{:},3^[ƴPnr`Ooo~}\Z_^̔o {bI"s C"~LN]޵h#uߚJގ??-O;mI8QU9^x ">v>/?K۩w? qD>n% y؏%u|?x\3hp\TWWG.g`RfMNeͫμFYY1X\NHhi᠊ ct"22 u3ڀv#AyٳCzG:1cKqUEx``/,#>I)oDb{jeVSޭVUR)2RS)c\0_^\EyZ,'[/.S3[{WYT{ !<;= xٻW/UV"\' lV1w2֓kI_GH,9#[Dqviא8 q6ŀ%QmWOY.`0AA!JrKoCa xMɹ8tkI k.f,=,=>zղ$l >3s1bsdeeц fr^{y/_.}AON::D׊SRRhڴikK_`io۶233,eksV9#&kbɟ?`<CqW@X <ŽËe^$h%AI%>H2Bٲ6 .>f2ӧ)&&$QWY2Z]m- D2yf p)@V$ʳ⁹ǘ ʗ12IުaPѣ}ʪ)-ʶ``FS`f20saEKa++#$D>egϞn$gђ>AOE=Zҧ׮ ?DڔÚl ɩ[E{w[@tdʘ!:xa_A:gJ?O{4lp'tA<1.Ku115z ֢^e Z`` ~KJѣ-i8>&VYLc!eyka`hѵkW-y $ 窓M%Ǧ,¾sǔ0f.cB8kէh4}}j(~M׼.ݧ5iޙ7k^։ţB[ ÚLr-.|{3J)B̹=rFrׄv.v[ZOw;ҽWTx-2EB]RҤf`[2S?A[D÷)OYCNo|LZ:6hgwͮGK#X@D/G{1 5"orCģ0 xBonjUwT{r(hs&BS(  6RtI|lRZ^QI#kMB!Μv+jCY8ަ9F(dvKABlQZ//|+OUa BrE]MA_AK!P(:wgZP(mŀCPUP( b+ @@@16Z .i ƦkB@!&P !qۆ撳vsX>e1?O)l4Д&tTPX\Ύ*((~<{eQfgk?)],r* ]ɷ " p &.ung~1\(plr=Վ=Ms(5T~]:扦y$qR IaQmV4ŀ >E J ٛI.Hiɞ9g̡}p2~|IF5[֞RRQniuOߌrX`HΟ ,Z}AGB"ݲe-birl'` s\Pm۶M<=33oIsqDeͣCz6޽[J*x`999:8~jݺ?w؁H$1e/#ۺu|fp@rwك1^:9qj\i9Ν;]|fԫWOg] \y8>k2}<{\?ZsN>{޽wq }+N7AN*>,ۺVBMIv#3'qy RuqZEo٨ݏ#;lV>Y^p3 @[@!3Z$<O!!6VG6;yIk T?@ u۷wpM7g5fWzfL:UAd'k%Kl7 5"CƏD@yTW%U A|TJtGBOOE—ӄ.c^;ۉ>}ճ\mҶO߷ud.9Ka3r-g.{]s?x;KsGk{2-߿,f9O-4k2MVa3SNx !#euc fa ÝOF\Mzz#o(z3{ȈW^΂KէX)7^>:w6m8^}'LzƍK-^=ȬzӦM4s֫O)ՆY%.{-:-c,}4[Gdv{•)=͹q>fUogseOXHۧ#< u/M܎vyj@ ^jf^2o+̟cs{sn_k}9NeSg:53$C*D^eO%CAN/W,4-/˻&at{J~'lNX{ ʑYN2PS'!<Ϝ3fJ{i'uAjcyYy$@+9:LɻMby:xR9{{@[pZ t:Ҝb]&`Z-6k- d\| zFU7.{?zi  !LeéT)ջG)͗#3]cל+H;y˱Vfgz~B.c-~2q4O`K\3Ι{+MfAZNFmAEit!kt913 %Au9Ѫ(:(  r@2<;AbZ2&DfLȍ<~mo-,6|ro`炭 CJcҤI/ PP(nƤB8l;*i큔yxJ,*|*B@!8PsGVϪP( J2B5D!P(&>޶zVB@!8dPy! B@!p4!6o\ B@!,CQ${sƼ_㷟j̟X4pGhc!:-B'4FOʒ)<"E?|fGg|#6n(sMx ;кT>B@!p$#ppŤ዇ܸfGwƕF"읈Я"#Dh@NUDuIq/Rʌz)?k[ dp{sa|@ oFtʛ]y/y!NkIfz*ī`Il`y/s7>Z0Qϩ8X*L6wmGao07á'A0 t~7 s0 ?u; ~v3`c|/myu^ϗppK`Ƈqp"~4yONpm^:?0O 7A—)B}X{`D B4PԬkؒ|OkȔV7DHywZ`?t^ 3&9PZ&U x%?f+"gu?Ǔ _}2 kw!6%:Rޣr "\1<)mօV*0wn>dQ[&\E]h> F0~Ibab$>E[6 Dk!"Ii"~SM[Cgm"g;_=K."]Kh>gιZ0f~+V ;&hވ {ʻsi ,ܽ0ϧ"2\;{^A} mg^ƉrLWY뼼T~~>lIp|f͚9M\{),%gڕ8X炼cʈ'w$~bCԧZl,F\WDVL̃,LBFFz6"wBcZiටbE 9/7:AŤ6x>jo?>|Ǎ#4 g.XwCiF4?^]_Cu<.G#Mz(r׏qewG۠Dz/!4E30ՏW/}]l&-> !Yeߩ1G Ec >7xFSwډTfABzV0Kh_b+kb9Eݥ,={ ~ PUj?2K,ŏ,dMLXB*X:v(!/<|釩o߾RsƟ:Ꮨ4R@mۦ-l\Z `Xu ): ŋK=zHO KϞ=ƠPn֐!CثO5jHڧz=7 yYZ|9XP8)+++>BKA'ܧ#%A<*O9f͚RnZ*^z -Z$HSڧx)^}vA `6w'kYl4[C,A;H|։c@?֘g!nO#*`,#M432J*LXӿB}dy0͂t _.\3A6?4>Ҿ#ܮڷXr"iґlq36AV&h⹵*Џ%myB5QFJi?>\ 6LXAYQ۶m G󧦦Jx/#=0dBP2d4hTKilnM׹R @fΝѮ];W:fÉXpfzյ{+= AY%?>>ŃP'y)YmG11Hzv`$ӧx`%ö>kA `LA'J5V_ܴ̠n3V Zok'n#e윴Je"ڒ MHW_nLH#ȼ#mCl./W%4Qr2AԽE%@UC^кӒ?~ooO·pȊg%m72|!Y@G&]'US9LcĮVd66WQWЀC;^$=&>m#cHk1g3 gmK9!.^ h }v׉ fW暗̉es^]hҠ ;i䠨H!88*D4y+4-;b*y5|XjoyBx#[eN7#|hph>*vXtXHcon3{!tiUk d0LIG\?4.gB5j'/y\КI |Ԉ'!4lu$$ͤE~+|@.J;zy'h5`qYby nyP(!)B'LZOʤp LBc5La}{k[f ̜w20@vl f9\'LӲD,ny@n&W;0˔<0}4&M̕;kB@!p"PПȟ!xfjDlB++ 28hNmGbJ#"iZ:7.J{BR}%է)  1AUB@!PT|$hNE B@!8P>4UP( A@=W!P(ʦP( A@ A ny86~A_z ]!/2ՔiH-*gR{?ZeMd2/Ì9b) JP ^ Pliߡ5U`~i*M@J, wlN8bpgؿ}Z:BX!p!—h cRkƶʹZP)Pf' W)YHVt!ٿmTi`eF,i9\4z {`D C/AgXo4D9т LZE}lq-l wۮ֟!o8]ƶ_NBGoD3Y|8+^:9|wbӗ0%O_~3JA]}}RrҀvR./Wއ$pUۡz!vξjz/NB{"Zw`%? 힃$|SkE.!okABedC' obTjun6/v90<wҞ={qF'[nӆޖҥKAě6m* m6^Ǚk.g=$ӧx` T ^tiIkC/c)h8ry\abpJy+g޵>&SVO*{AWk{s\Zex/-Oz"5 F=چZw;KXvR@>|!X yG5H'q\8e4Mm :YP8-2ͣI\~2sG̢v:[{ܔ6:YQy>}sէ@T} }*_bl \t)1_!Pط_(>iuB.]*rx}d%AٓW:5JSHȹVi5K&mHS^xU!ږ>=>~l U=>vxʙw Rk:?#ԭ3XuɯAgUG8<Ȩ *F~WCO& ʍGӫSu( >*Twup?rjݟ9h?^%^ }BAaSjAp|͇J>DUz`vc҉NJ5м*r%, Eͨ+X*7a?D7Xlu*DiלK2)}XB@!8P^Ї5")Z~JM^۷oE BҀm`-nMw-֩:*  4E!P(ʯP( @@ MeQ( ""wFO5CE=]ii9\oH!P(Uc8؀/kGNj=>i䊦оeؽ6 0CKOi)Rؼ#֚H&̿ []Sk]G maQh|]$%|)5Kwݺ?}PlԚT퐔Zb*R( F@i.t&Fd Ei`P֚=C~Sm,팔/|sY'2$E B@!p( ؁]*|#Y-܎ŪcE:nB5"Ɛ&ؿn2Ri3wj| "ڧh(1 Ǿ!܅Z=_xy8C7/YOw؟mOiqZJmtC[*UY"ֽI4k@!&Ϡ˷UB@!ҀФ7C.av⽔9b;v`w"Z= Elq[~M_v N0g.i`Ô&0~Yl3i:gAH1ȠMkvW0@5:jk,bi }4tE N=؎Z침u+qkX8DoQCYS]rE/|[I<Z8BP"ibhKH;oyaڣIh.u+Қ֫47ڛ84y ڟцzEZXrlʥ ϢE9 9)5֏&e4?c>Ƭ[i6o-S$o5_\y0E cp\0 [7MXRޱV'Dj<E 2AK0fK'c.l w,@99Xܳt*7=Kh|F b hL<-w;軸Fce/ 56s&1 ҈5߯JKd4 <懷~ߟjL4Ҋ K5㕝t ?dw#48XgeפIԫWϺwڅիWǯ!ڥK28w\p`p'mժE 6n܈͛7'2zhӦAϟ3k׮رVݻ]yׯƍ{ŊAoGnr-[D͚5]yn݊lףP3[8҆i`YYYHOOwձvZCkF,qŋ8csҥsS;wĚ5k\+UΝ;HOmذ[lqUF n?*OuMyʕسwѠA4jޖ֫Oq|ݻʌST:Y✿)~wTN4kd^}s>'5muuE{d}*-- :ur/cg`qjfМpJN&~D8"Gs#hO}?֝e \*_)/cevFv2"y>T֠oļ-g{u_:j&m;A$x):ĢEE:Ee$dLU4'Y&Y0hذTpXɂo۶ ,}.((Aؽ0a ` [Q PݧCw7JXcA*`0&g={/IAT2}*##S[p$xs` H$"M߻x%8G_&yp#{_0$dU֧x@ \2=go2}Ju.Oʃ'J&NUVMZ` E[ːjyWhIщFFֽF,@8ZY,C#' EOl*C皅F2AA;}(PbٔBhnWmOrٴ, (M+^k9OYeBWTX G6ozy-g=A%|_H7LLajtv>/͚^ io,B!!oIU*$іLܳKqܷl*KMAl>}Ԯwt1*#ɸ4>95hW5E @!Pl:X֦ ܛ"JVXi4OY8=kw:FZiQ{93~AP6ǨTg9m4Y)s֋H?B\;4w}p5֤ۈ?εzOkDs~fj>54puP(% J'[?{ӫ,6K3}EP|Mav$=xݳ<m[#4ckC BB <+A@S(rbdCsyg$n|ҐWQ2U+ @91R) B@!P(\ B@!P:JJP( rG@ rTP( Pt\/y=̰{? B@!p5/ ޯH1i FBuwobw^АFBYGs.:QƢݹBgB3ԉB@!PG2$a<bSa/;7 #|ͅ`7܄ZX&Y 0W-BDZEwB ֨97<C+"_>ik.}W B@!PuX֏0o{T4sv?Zq_uyNhZX A_ry7h/_;e Vغw_7@KI1 o/ YX9$'!4JK=,RhM[ͰlF+|F e.ađb]7h$"!t@D"!M蒡N#833H!|h# n`$u^ _[\Z.s1{ǞE%GŞ>ĂE)bFm}&@t4/`. cʛQ5H!k804&WO9T}_DzI@k _ީ"7 џ4y̼:iZz±)|)@~m]!-0U0S*Im0W!tik)?Ɠ@gV' I,Q5#D1Pzw;Ξ]U'BO׌[B!X:4ë?^k<'jΝ mO!0LG _AYٻ ZZDah?A7dw|O/ʕx<=e[7<k'ޤ+~̹w%0i6k4o;7g@oؿVCR=vJ3!WL8!C fjQN,A5H駟\el7vmۆe˖iiiݻόiӦ!BNܹ3233l]ׯwkժ,? b̙.>3T׽ŋcΝ.~&MТE ?'' .t~?;N>5k }[(XLuUv8'Oݺusw7uT={D*U\VX-[hrկ_mMuaΜ96N/sya>jժ5j^}*==zrgWҥ jpoQ5k ;;UVyEa׮]:6mc٧:t:u؋6lի]jժ[Z|9nꪣAh&p~377sY7|}T֭Ѱa2Er{]N*O9ZG?޾Ze1NƲ-̠5oa6ʂI7.|t=cLV6|; -Ǡ;Zp $A镒&@3I]XȦ=1mƯ?MA A>![;셳 FLE.˄2ga*yd up2瓵ڿvElv>IV6=Yвʑey!K \'J\2vY8A/lR pb]'%)M\^u٧I) 2Q !O%d _q0Ųegܱ)o!r.,F<8|sCew$vȞ˼H=celF Hh?K_-;x]6 <|CuqlW<?+k5!j>ܩ42^5n#o{eU4$),4mB茞bDVqO[Ʌ,)勀^>=630#i9gpֶkYDBM#m'3XHgصؾd&#l@IDAT|cK"DŽI"3\rF\\8֠8īŹkž6fv=u~!mߥ ?RdS!Pq\Yd$hA^Z#DiedGyS_C s=Qq}%y3H@ޢ >>}cN\`:yD+:y54$4^G|"BEXmkQ: j?wMY(C27`\pwebM4#1}d9;Zd6ׯ_#AMy[An&OC-r{]Oh_3pIN.'K}I iU!3wiI:/k"wm2SksFJؚH4]bOz|ԇH!88j0G'?!k!=~_$jօ>T.+ iZy^Q3y ߩ:9'Ifa#AS z,qiC4wM;iEi }g\/)^K#J˟k>8-X_)lCD* #p8ayJM$"T2+nY/!/K*4g ֜i@ #,V7-坲@Z-+/YrJ1^!885d^HLI㵌E4'bP)Ҕi Bb8j*fUB@!P(P8uP( A@ YUP( DNC]) BBPB`J70%ӨsB@!s8*CQijFQy't|/\,؏}( x+9\b։ (I=(Zܳ +3*m"C|LZ;; e͉9ʒ+qB^ة"B@!80 ,@ƴ/)@ĵ.ed{(P4^N2΢-,}n-Ͷ)=m'$(3k#w\cϴ1Ǖ$cӿ;g2ڃ8pE u n^P(%!p`(d>Mc%`ڥ֮Tr0!A]sfسYbn?E]i081E{ҏ(?&m1QxA!li_kŷoGQ[&|Wޛ >p_j=6[0p'8 BAਙjׇ+fԛO(ڸSQ]3#xJɡ, ]2ѩ#t`wFt7▱l·]1_I`|~?$~L)L$NBśLBk _|B˧8ao!7D|Q\:WXK>S(ZwCITG7G׬?SB3ә-4M EJ _@$ik'^OgR0#7P>M[ Ĥן"Lz~ߒf[EZ:ە稱g'UI9ԿBxZ!\:]) GX*h@@{DQ҆yΙIi~-VMy 7?Gn?/o'Pg Qcf9@B "L֩xl~GN+d i9+mbxdlE y!xgxNk_oj54~)%/9Nf>b0|$oE~.9[ -̜q WoE0>: fy(/p%i߾=7oo޼w1h ~-bcA+Wa%֭=\Ĺ@aa!~tT=`;w.mAZlm:Ν;1{l?@CMghIksJ4hcڵX4WF Yo૯rqqǡjժ{-† 7nN(ۇiӦ9#Fc3gbݮ<:t@f\M6a.~ʕ1p`lyoA|EԫW/ԪE:b ^]"Ժ]^=tݺO͙3۷UVhӦ%w؁~ŗ)+O?|2~֭ׯNTff&=X+Y߃.Ź###.\7M4AVV,޽{1}t;+~>rȸ/LI'3f={,qէ=.'UR pK>0㸨$y̤yW-O0v2Mޭ5`2Na5OKsH>ۇBx[?:Ib9o+W y(#"o~!JB6S$ᰃڈp:{e-*ug<*L 2MsBEh|?VœEF5W_Y(%vGmpeE|OC2nY^me|?I.E=;F :ߗsK(/{%Û^u$\yaOʓ>7I[Kz$k>:d3^ux=sTj?'9} !sy79}c|`b[7F~qײ_;DOscDfajfNB3 v4 ,+en;GB"?Kٻ1\iWhF~-raO[|ФmYteD t~Y8e,J%S(b$*>"np `/5H5~+EdzFJ*|7m򻊳 UA|}mQ*ݳ+#/>~C 8_]^N*x8,! )F!"wu$IvvH9T *?ZZP$a/$lL~76E01G/n@ "w]$B3ZyG |yFQ7W!88MhwlM8|L1Bq4"} xx'Ck_壀 aҀ ҔK#c|c!,"ѫ@j4W{O':۞$/'`2 ʷb/f~I+ 3{04AuXsق^D\I[xwfmťTEIӺ\+@a˛d\vmڴq7l؀YfUT#\|f|B{Gݺ,Ye˖7h}u >1j(#\͘17ovծ];deϰl۶ ufCIژ|W_!///:ի4_UVav8Y&?i2(G}.O8T|ܹXv+O-н{wϞ=;?~3>1+=WZx1/_nO*6l>}/\|ftITږ«Oo;vnݺӦMsSRR0z4З_~]r%.\J_V- 4S :ժUsݙ3g֭[{ݻwwg)"~@NN+OnвeK\Ubذa.~I yI*N!״5;i;̄Qg}a֊FE)MҀ}'ΩCO-21z#ZHWIszxhfkE+":Q|~j<&n _N; -9`h./}P~`*#f2!gg!D?425jȒ'Mωedq8ePI54ȫ*uԁe}SV+jS\,}a$'ܧd6==]"z|K )bwƕNXdjT0'-10| #VQNH΃;I4]@$sa{a|8\$ .ӴLt_ϿRmժ.KN:%YմiSd5dvuA߃$5|>d*+:pY-3v;oYh֠Y1'iG cn/r%0ȴZn0|{/M2 )w]l8}E :OWFUPY??\v8Ҏ=':]{_9-}  i3i4^Ƭ`R;P9-IMXzozeaS#g3v ?r%Kv?i]0G<`-]P)mtSWhd;)G$7@7 | 1SjZ$|z}%0-[2KKu|ހ 7ߍsw!4<3ɔ|kO$\,.<߉PFG  8"/܇{H'4oǷL6ϠGɌ:`s\Y8$o^$)E]+ 2!gy$\V _0l_;Q8x?ՙ%g]Lgqzי6~IQ": Ϥ"PXHs-mo}bv[I[O#JỐi4Zd2W-$z%m/X  )D;(„)0aA9 a |.֦hgHyo(K ;+ʳo|.Ӑ6Q$a90: k%*#Y"(6E]q(I0HySף텭W22?/l+MQG})n\Y `f!fAaTQ-g !3".~Y < aEZCD<e%ÁW+O}9d,'XZV[" 4:<)IqA\s2/Scq9B̌+4> ~)HQҴ-7:G!v$,$O^'|ޞ EX9 r㩱sMjs:Şe,3 (0 T~N5/}~u_ӧOwcƌq"Y$R <wY`,Ys`A裏\|f7鴵~lܸ:v숮]A($—4g}\׭}y.+0w;FZ0|pWzw O\h{usE$7BBIhv m:?&Ne5T0=$&tkcf_^؝qM\ nwodԤI'ÂUWZ2}1u˨>%7\e,@MbvW3o'33VۦBeB;2Z$WI8qz9>if*f.#^ AnQ-[ۘB'd-"_\k &~G63 kq["%=vx_.zW yQYcY[n%V%ӬJթSnV,ӌ] ,dyPFr΍VuOvZ?>7 X'[G6mZHQWA;w%e%B}dS~d[}S^}O2 FsrI(;Ȥ9Ia31/*"ۓdE"lٝ(RR;bҸJH&.l*&YhǞ`%Σ<}) aϏM61=94W&t{&XE^ZE,d-*Z0sR6T! ]e9h(*?x{^ AL־;[~U Ϫ$(i~zQH m$Ti)h)~爍MZ#Erf1%޵m%$#Χy٫mDŽyej#; 7T!|MJ3Kg, zw!uRg|e6E<`g,4&-\<^1;g_ }Fsn͟T*V! (L4{}#K]x4GSy ]F?|E8(db^k`Wny%@)6-]JB\`3-!o_si-4"?ilb |:;=U'5Qk4( $xYҀܹIPŖRN`b@dD?xYP^yԆAM)emߩЄe*´Vwby-/{>g6 \^RN1 z7n-:-'س=)G6"yQP?ZG%od2%|O#㔏>.V64.g~5G^&! y>F/O|$kBF&'\.kLmq}hq\2UNS"o]ڽk ^E 5CO^-}Ae 2Dy]0_5RW"=֏#)Z;u^ vJxX+m2Y9eMXOKt6!lRҎ+/_0kyQS?-ma7o !f9FԮ`Z {YnK 1c>^B*oB@!px"b "qyU}d!d0|'as~yQ">: |e@}|Ex; cgQlr 'Y;hǗ|{B@!#_.tw+bOXS0=Cpig>Mwe ǵ(! ?5|W!8( Y)ZyKwNƇCol=;lup_rU( D@*`V6$= M3J B#pPր~U  B@!ppP 8t$1B@!P= EZ3C6Q`ϰL`Qd'[2n}iaDfQ^_|Dږ EWQL+Q( amf'r&,Q#퉟K>EsMMޢ?!,~}3FJʎzthCl0W. C}T (Лҭ|tԂ/ɹI 6-a/!+dnx>~76al(GA)wA+fOfBoeW 3. @(#`XaӒLwKk 3%IMl$W&g }e)3n}9: )Ү4El"LR ENw |5}Q6aW ړ&&|!uIS {#>:w,F]d,E{&/E{$ (~`$z3غSi KgQ>cS$V&x: g}4$,xO d:sf+Xf(i#\9*qumq~Id ^ p"Ҽ,"YZؽv%sy= &DLcS7:`Mhv mɛ Q|lĚ*ȱe j܁۵k,kQ&+uw~Bq^>z"gl Y <ʄy%ިlD+Aغݻ>+٦M[fW7ѦKt 0T{:3.AnrI`Gҳ\030 +3'2n~$~Z}e!0u1tftH?f=wsL1aU6ݙ`AoS^~gS%Lˊ(Mßy<*h/  O?%٬Y3W}͚54i$;^}D+F>;Rr| .+T@:tCꀀv MFW4h@M4!̒JfM?_^ 8Лhǎ>6mPj|˖-3#CMz>~G(0ilG1rƮ9b{z~֛֗aًcN#4λNf5>}S/摲650hW+_MlJxE'I?8?Rb\*:E#kB@!8h~< mvřc*Wӛ\p&gZVUqT({6e$1&^gWgNanjC?FQ a@zZⰂ$.u&trngP5$a|HGrT( (S#"( B"[eP( ]$ԯB@!P( J@UV B@!pP EiΎ>f+.}LGEW( 8ZGmCEle s0u0+=j1 с):Y'v*Q>/mWJpl+Yp(T\)Y:| sLU)zzO3J B`(ǐ׬PL9Zτ}(b̰Dk%,/Wg*VOg3(t]jW)v] <ڍD8v% ̥7?wuo0hCI raϙLkC[XreLYJZ\Q^ 0 `gR@1$ @WZ6䰂GLXdm*%FW%>?l\} kE.XE{ϑ~qeKnP+k[z+;+b׳M)Jxؙg [)y+ x 54̣}%-'K!8TH|˥*'Fg& ;':=5~i/[@ѫPӴg4&ٻSdͱ}d>}EU ~aQƔq"K"r ];`f V%ܐ:,z;6y 3sl"+R`zc$M<B Q/L$l 3㔄 ڿN 5T`"2︈ſQmic?Ȟ/U-2z#(=ބ)hb{/'"8LP( f*U+ţmD4z6 בG:Md D%{Բh3 7t(6nQ9ؽRlJoڴIJnΝ;i׮]ެ#r|Z?YSftJ]u/31MScpO/Z%[G .WB]hI̴t1˝p4%^m.}5kF_4i$;^}a„ W:vHʕ:ҥKi|x:tH[Vׯ#1gZf/ P&MDgR'Ba}1m/UKNPx^iӦ UVLV3g- T=zH6p]lYr2f͚Ժuk;^Ay 4HONtyyTn]3_&Os˵O&\/:^N: x{PX"o\t΂ݿKٴvZ_Z 6ƍ܁^At^gq/H;im۶U\f͚sGk׮>ٓi AH_ZU>=65x`i6mݢE SNrzݺu4e;:{P(61kOtV-q.%!`3Ϯ޴-9̫dk%J.6KN(_sDUnz_҇^yV& V;}ad0&2(&{nLazEcjڞ342 \<͝`tgWZAs |v|Ad4BU^6r+Q@9FӲ.%+0j m}^ e s\&]ԤswrylR$duC`FJYG[ ,ĩ]<*:0W~)(rPP٦mxn.L@IDAT~;6 8_c$&V6vBaV+Am  }'+O75&"ŽV*4zMR s&6h< #{?}l1w3j5d,;۝A l*Uwƴlj2%)^t9( L1gR4m桷<3zTa7hlt=b']!]3[2؃^A^AaiB2zMyˇeLPmʋ>/mJ ^g2ydkOXw+)k o)Ns{nf/lqi&sK:[A6O2: 2EVDsxCcUK)ڽ:9<)^F< ^Nڐ )f,~1k6Q7|f<~p5\SYBikC ]S&8*ucr;$^@)~} ط|/(oB#Ph n跟K<›Ć+X .D[7QnSFĺl!viif^3OIK{\5}Sqʝ!5ֻ|מ+bָ&1ce(uRWap~8ka+X깤a4!b狫D/yVo;ki /ŮEу7pڇE.:B7>U]p4)Q(O nO?g?_;\(~81qdǸ x0GdSȝE0Pq&6yf5\.r\4 Kq6Gn~A4.?Ylc">">Ԧ n~OKo5vCC0Qm>|CbR;DZ՗B@!Pdƻ 'S"j>4Aš\&u_Fxnu B@!8P {&D B@!p aU BC@)C) aRCVUT( CM&*.J|\NaL+(ɉF:U EtP8%(zvKZp{[B@!8(ǐv`֣†n2Ȓk0#Ft爚ԻdRYcjDP5L Ř8T&<o3-K<`ЫWiM0ZLbd'~FZ1;C ^ &ۀpZ  JW"'-?̈z2"SB@!px!P G?}AԔ,Hb#ϡHPL7$=)Eڕ' d0"7HתluN1ǎ&Hj VE4̗P,Ld⶗yqlx$F' ،fgxosEcrfvLV `~.YLSęa[Nz*B@!P(#`Л,l:!'bኳ9of&Y_I{ H~`ri ZtG ?|elxobd}fv#Bv,ҘPL/:AnVTUEC=HoKU(`&Ҍū|0 {횬lx/o;ipzw9F3(2gbsnR8jMWcVΠ ՅW VXgHf3uիPA x̙ReצMC@a)zC,YB˖-fA5k֔*`X@evΝ+U͛7lS'ԦLBP^ԩSFm LTy,X ҰaCFGS-:NP21cTٵmVQY#Pز6>@={˗{r UVm*So:^iѢM36 *ڔ7{_0*ih(tQ'OI6X_ 5pV.ae:]T9B@-ug,A3>/G CqǧLFО@KUNj'L0݇+Ά#[~sҳ/TAbt>DovJYi Vt<< %"f_`׽{ѦLʕ+' t/EQ6OAj׮-}FtGH?e^^1=OI2c#S@nSN9E:J~/"# =;AyuƋ+P&xFAy=O^0gE+F\R%޳cwjzy6OCwIgO#֟cW%n~37;YtDb7 $ԉJ2B3!d^&?!A~n,We+<^aBrUH~F6\.G>[!M<&ڸVLgk-<,;JBR#5TgL"fH4xzy3 ӻ(vX)ʇ/`CPn]} s;n{ZlR|6 kNkYD{Y2O-J-41B@!PX^\+@5OCOAS%/5>UK ֦L1em54^KZaeh4Y_#SNj28qGG|Lg3Yu9:;6ţ֟lKR;aGć+;Ǘ(/ LQo+m;YO\y7li$6aݜc"ZBLGFT"uyRB<1}yTF''Yؕ=㛈pf(^`tS Y9@Bx+S>#+)vM| X$8; J.c8J%1-0R?XZ ?1{8E=?қ^ 6p|q ~:+u∗Vq*9V( I )С8ZTnlXgxFpP>F*21#NbGVtsqAEYBV ,ӑ1c>8+D!P(Z.#|"{S07FS2Qn9 U[P(@XT B@!8(|@V) B R%( B A]eP( f6z% B@!8\8` Seh @yZXmrŞEZ%PHAI7<|xڇiHdXڵ1#B@!;ݭwؖp`[ٓƱթg E^sл$F}NG% G º]( %]8,8l)|)")-X!̚1̛fl;c1vУңj*(i ߧ-5hA|3q }dS)ґ/:,&Zp;#mGUSS^d7Zsd>xg6H=y6%^WHJ91ֱD0o9Pt|2cLܚ"=jR9>q@3ݒ1Dv_ gq:QK6Edb^GtJ1~;N'~Hv۳BQm}V"YthxOAkbQ_]7mv'g{x>^"*B@!Ph#`gl20 ;Ahp+FZǾlU2o9w~%pb}ug:J*d}8Bl{8rXaak16 :_z|$ve= E^rxX޸]ho9X671=7y󌀽l>٬xccn^łmz[cl6c%)| xb7EYoN s;-qп Q{fg'`Fg" ԃOx31g29dgLz`_2eHJoNkײ P۴f͚EȲlV*W,ݸq#mڴ)9oJ| ^%posմc*t,qqH^yB.;wUV ԩsòe(@.ݲe _FZG.\sC ^Y~=mꧽlriϞ=|r;cZQ;cŊkW<%9bٲeI ԦZF$AmJ*$#ijSXb"]"3!K,qoS~A>/#wTJ`9t^gKZ>Ѩ/-AGyfڰ!HԦ>?&Ժuh۶}Bn6{nOS~񼒟mʛ{_01cVYt 5X.E8k ZRfdz ;t&3~"y{A?$UG.cwԞG%W=6x rj['&"zʑF[6R/IgzDF@OUf}d nGI6wyqaa6"0/E#qhqƢyd]љ\"#a뭧(tO`BF=Ib9 |q &QbÜ$ ^go֬T-  F2AǪq>/er;\۷ϨTɰͭMGV\ʯ6NL4MtI6)l e ÓD[7f7ԦбjҤIEPB;(gޡCiK])2~JR>K3]%**%#: e>/7$=^&#EHsq zQ{ŋ0@x{Pmj/%yRRv)U#'V#^-z]tP+j7'?)sIZ~6Yo>Yd:ޮiGI$SoٓYAAOYǰw0#71,{69D2Aûxʑ-\ʔ $~=x撿yP1O%Hـ!zeJ&W0]j&>wBGWGބ\#+OB# wjcY2OUz{h&>^ ykz4-Vo>~$wegJmq. dz8nhW0U̙kčV,GNeo>:O_s0=u<g]N^),4 kB3O(b\g ;. ;#_c>q+`(>e4Įxi< ~y"b}J-64Yox2S(v|\_Mz~ $MK̥J_K*6x&+$Įj(W?41}_L"Bw4~t4xZݼQl2 ?&Fv~1Oc6>ŻkɚIPx8S8+3f J B@j@>$槈|n|>jTS+8rMc S0RV(1wxgvuϩ(ү>tOao{n1TCYR&v=x^Y*cP0ڮ+n|P(yC@)`nzs(C^&.gGTr뚏bFHc`|8B~+ !9M6 \6 uIo%n,%C@`(Ҙ"v3B@!;b 87#H1H(-O&cK6c͗ ; KL%)dѹ׈PlMWazskLkfL(°(+eHO"K"&~)h8 2kk *B@!FiuG{'::l% b>/#SH`G/Nހb%be?JQāq*=xakV&30cG|&f#ݪ_za\+i! d ~=f8ub[24΍~ƽO1Ʒ(L&/vdZB@!!ޢ=S"Z4B8Vfٹ DH= >g(LLX5Xd`ZP4f02x3^c{ʹF(4qrouv ^d;[]A .cc@|$*urMУLc+ 'j`n=Dn,\ 3d[qYF">1QuV(rG@MAOW+YZ\;+e_NxJ.@dOLf,:!MC:s& EQXa2uyR8p4:[o=Ez ;u|CaGtViDhӀY60ʵ'|F6+ЃS a;)R-mArR)^7 9sfX zlٲOmذs~QK bf4׮]KmH N Qo-ܹs&5j iԠytb?Msʖ/O*Tp}0׹d +UFF`ͣH$ATZ5*Q8Ԇ h͚5s խ[g7{l;իGG}oʕi&OUTڵ.D5k&^/HJt4kʹbŊd'q զ(| ' ^t)m߾WeJ"WD*Rթ7֦ׯ/Ƴ3JRr^g:m dv\T)`# pؕυK79V_jlKT~b<> OtL1Ҏ;s^~``NɉUtZWDIÛS7S ,6\ѿ- aY'0!9>@1B7-lěo eb唛`DW.SY؍/Zh /4ge'SP<))`M#?(";}7Py\Ċ/K(Y zR˗/;aR|e x֭<")`$)+ܫW.U^5k֔*={ѴiS^jD:2΍ŋ:^^AI֦PYdڦܽb{N]PB{ jS˖-;MK,)mS0 SA8u>te x2!>:u2 RH:7zmd1Sw* eo-/w\DvI kco(ܭٓY-ҎұOĉtug$"|ʧo}.zNdHDL.̯iZMqߊϤ${~noX g/pl<̎)7Gv%T<7<~ uU !F.͞ţS&*Tސp QMP;l?/9>]&_),Q)ZN48e&ue:4l[1V1>TKl[I"!LIIIKs"&jS~{uP(ڄF;2@zsrh Ya6Y?%nߧS3 ;Vb>нS{oᴔLZzDLs`|tYH; d~/nUI<xnZuN|`3CB@!E@)`"Yb1v[=Oإ]yXBH*g% 8Tl-7grs1☏={9{vb*zPPor^#?XF&~!9gE'sl0֦q 8 y>9;!7A.Y;/"oDM6J,Gp)!Z?oO#)0A!P!.#SΥ+1p)ٜ]zMD*ע0o=_Dq'y=86c$18 Nņu[jv Lޙ Ul xd7@/y'n!4>)bwQ5BOR)꼁XlU7>h||Iiݨ&\ iX:V8B%EOzEԚ稏0guXot>3[DYן,Il$)ƌC`B@!#F~L2rю)GJEgRӼQ79`Qkn".O&0Ai*Q~ B@!G@P( RtB@!P(Vm@!P(*KB@!Pv y`JrH(09)+B@! F{lP#کE7ھt hǶ)~)Һh|Q/P&"=jRS/N[9%0m3Mё *B@!88,!ϰ1 > 62(%,>Yl l7^8ɾt%% 8Ӿ'Xd+d(GBzBW-XA]ʒy RP()^[BQ膇E+9 ?z&tq ޴~DίH:fӓf9WSh "ޠ0i}JB?$F۔清] ~lM+Nѡ[P(@WlYcŢMc/!\%si+f”&nEt h6Y޶}Y?BcmhbkRz!<<ҵL&;(tmw_IL^'a aj\pCFk5w^7yS2rhHo1QF\h8}8A!L* 0${3>YG ڹ"2NeH*USeW( v>PJ $dd B,śqUVei[bbDm/O/R LHבbfzv$HI8 fPlpO8Qa|^?S7Vyѝϓѓ"P$. b1olTCv,f} |82︈n؉eK' 5%Qö7h& ӌIrԵB@!p( 0MGSyYLjQl@Sr@ȖzKҙYș1>M&!HdxV_ v[Ҽy|Ϥi3fݻ}~uԡҥsHCk׮˗bŊQL/yd}YxӍE/Ғɮ]yŔ"I;yLL4d Y=J(! ./ +SRl(m(0<@Y]Ȕ5c,9q}.f 7\Xwk5ΞΕEY=|ױF8vt}!)[w=z \`g)/0PU(]s<)hv*~8LԊWǹw&њL'?eb5WDLrsH;]$˒sV!Z%}o@XQ5W")t-)y{z):vo\KXVX%t˓1Z5ǻ( }E+`:K>^yM&_ .G>Nzy49*_%tQ=3uUc3v,KkX\ʴ7sd ,ξMZzi<[ҿ֘`]7Ie NrIw1+Q(g+R<Ē0 z~T\ٶ+[>i [%vkOdc_F~8,F'9yWkA3擷 eiLb^\žB85lɋ{'Rđ$w6k6pzjHZ|FJ%փq~X1XtP|"R~BT#UBPB+`m\uEɞ>,s{BA zKǍ]SLRc)4|Pb΂"L^}H7|XbC;0/\2;Ù+ FuPĻ1+oIÎKPN 3Uv [RP(yF@tcLD*|G0mJZQ}#'7V!q];{ie+约f0f7( +4.EkO>˾G EHR;Q) B } B@!p(#tT B"p}b B@!p(#tT B" LkRJ B@!ث"J : 8ktom8n>fq])کEOo@)v̇߇c rCζML$JB@!P*ഒfJ: >R|.Vj6oQ`uO|ldW8m gP% B@!p`ȗs3GlAW 1pX d|%`TPu>aC#+22۾.Z6"( }F _F6<9D̗ þp6TװMf^[MW):4tJ.!{VÄPP'ϒ\r7zu_tsN5~\}\nt6h\3I$)6jEz֊Ƴ(g}ou~Lإf4.򊟽lECΕ(rFc2׮squgS(һOܚc vx~LC=ŮOEo}WGM?y4IW*]B@!pPL`ʿ9Q"2_ź4I#:b,͇#n}YwP ,j;n#Ծ2iLL`pEsȼĮ?#>O@ ;{d)JZ!8X[6RݙWfMMG8&CSC9DlBoL1-l B$ V1,zl9,w!ο>&D0GɑĈ1Srm*9)- ҳ2 zzC2_CᛟʥiږlVigLc;%\И$z>#rl3S淞Oy&: 茄ǎ 32k#Б4 F(0̞$u\,&gg1ƍ ^NZj;: Lڜ&nxdOG~X,gi޼9mwɒ%|Ľ{Qtijڴ{D"?&/ڷoOGyd={6mܸ^zuU}4c {mwy=_kN8ʕ+q%Zr%>c=Znsz>w8iӆ-?>Y^bEjРv§LsC.]HWMF۶7F֭[T Nׯs܏9:}pɔhѢ,Yg9`n2eP&M={hĉ:G$3mS6m32p:vK?3g} jS+VE:UV>w= jSͣkbTTׯsϭMu$4嶩S}iիW*WsGyP.)Rڶmu~)r/!0Z{ә*g}Pd`,2z růs0߾OΚ儑LZjDRaqv,`i6*_ю)Jz^7'a)-K_HgE,_HJHpSx$7:`;k`6BzY ?;>$D9 /O;\F^G6dnnrs$fZL#2'׹.:8+ /ss~eܸaTRr:^&qSyϤHvljOQ gd'jǗ";(֭ɳR5ވPX{`_ lAݻw%Dx?J'#Ga1B$_cnx'Ũ*fe3}Y>'6?{ϻ {!?1Ob$kѡNaқ!L}|X?s(z-% :41Č(v2&6(sс;SȾ1z6>֝}Eaw̝!,g 1c.K[) @0OhCG`D6LyDԪVg:|ԉp,\Vdl΂RHVn-]6!V"" ^+JcNZbSFcƌ!|p,@B@!P0E(Q,/ǹ\ʥyɹey]m5UPP(pl9. 6YtN84! Amk 7Ƞ #jk3Spd{挾]A4 TP( #iMAc̘(r H')tDfu"mGvHJ9ŮOv6 :ҥ2nSN'/ԩCoذ&Osʢ=([_-[RŊ=DK,yJ|}&Lwԉ+Jr֬YrJ{jըI{Op[}[] nIwO g0̉AdEr+8Y#BBXc?Ծ@e0"WamI'ZZI,'Y4"yVL/`N R'{8vt26`{Z!i=((tzO1#w/RN&aVvIw(?_3``6*yL8KK}(ދׇN~kAӭA_P-(^6Ļfă}@+Ruk>ۦdMkS6T{f9^"mu)h68ݸqO巺|۬3x@9,k6Z碌Lw (kU~?L[[JA'AiR2NlU/l(e8f.*mi|uqaKڄ#(!(ab U9b%wZ<' !孟Y 9&̘Dx< HwclM䓌/r":Pc"@* ߇74SBsRic[;](O̷ B}4j(zuz:.ӧZ9&tԉ1Җ qK$1Ɏ; ޠ| ag}r_k~4XPE@*v("P =;zyL; )<dN\Dv(|u:묔ᆪm)wH/~~O't 26oޜ2pt:t(S~wIRAͷpiѣGi̙oɓS8뮻ړO>)P/>(g 3RW^yf̘aݐm)|'^n Fk֬y.X@,7w-/(Vu;t󩧞}'k=| /`wߕoG}l?ܴiKA:߬:+)9E ;[: m۶pP ꫯ9t2~Gsu =z0 ÇҔrW 3[oM`Eܣ;_0 ^NRũ/u~ي ; 4iRz2PIPͷ]{rp< &hMDd9tPZ,eLyfh-ZnYi0b#a?7bYO^z,;|bfǵ$c k ތ6S:ެ\tEދ=pbSsRX/{뭷.}> uyFl`̻OBŸŞX?曒V;w#'pp@NMrE L7XOo oIB/i3As~É G3Xdel.uX> .K)X|2pad֭['9&1glL.] t0l|Ax7u`brȽϻu\;w5`f\7d1°'M*Hr yAǿG9~B|dpo{eBM7lrx8`Ar݋/8gqhR:̱|um5Dے(v$!+P6&jY4.~A'6B8RpѩjdYͷ `'\(": E@PD@ӦVE@pϠ_PEIT;9m:hE@PP E@PD@ӦVE@pϠ_PEIT;9m:hE@PP GFO6MݛV\I6SZZJ;vѣGKV H I8 ={vB&"H Hp7O?MW_}׌~*9E@#a^m\Pj@˖-'2/{9IاOjժ;>Snʔ)j*j۶-qdK :/{W^r`nJXmڴ)5o<~w-M43FLk׮"+Tڮ"4p aye`J@>PE@hP ҥK%e!q 3Xu0 wn3E"pA_[n1V$8|xF#쥒"/T iGPE@!&hz(" BZQE@P|"(@P/E@PE `z(" BZQE@P|?lv&IENDB`ggpubr/README.md0000644000176200001440000003162114334142204013017 0ustar liggesusers [![R-CMD-check](https://github.com/kassambara/ggpubr/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/kassambara/ggpubr/actions/workflows/R-CMD-check.yaml) [![CRAN\_Status\_Badge](https://www.r-pkg.org/badges/version/ggpubr)](https://cran.r-project.org/package=ggpubr) [![Downloads](https://cranlogs.r-pkg.org/badges/ggpubr)](https://cran.r-project.org/package=ggpubr) [![Total Downloads](https://cranlogs.r-pkg.org/badges/grand-total/ggpubr?color=orange)](https://cran.r-project.org/package=ggpubr) ggpubr: ‘ggplot2’ Based Publication Ready Plots =============================================== [ggplot2, by Hadley Wickham,](https://ggplot2.tidyverse.org/) is an excellent and flexible package for elegant data visualization in R. However the default generated plots requires some formatting before we can send them for publication. Furthermore, to customize a ggplot, the syntax is opaque and this raises the level of difficulty for researchers with no advanced R programming skills. The ‘ggpubr’ package provides some easy-to-use functions for creating and customizing ‘ggplot2’- based publication ready plots. Find out more at https://rpkgs.datanovia.com/ggpubr/. Installation and loading ------------------------ - Install from [CRAN](https://cran.r-project.org/package=ggpubr) as follow: ``` r install.packages("ggpubr") ``` - Or, install the latest version from [GitHub](https://github.com/kassambara/ggpubr) as follow: ``` r # Install if(!require(devtools)) install.packages("devtools") devtools::install_github("kassambara/ggpubr") ``` Distribution ------------ ``` r library(ggpubr) #> Loading required package: ggplot2 # Create some data format # ::::::::::::::::::::::::::::::::::::::::::::::::::: set.seed(1234) wdata = data.frame( sex = factor(rep(c("F", "M"), each=200)), weight = c(rnorm(200, 55), rnorm(200, 58))) head(wdata, 4) #> sex weight #> 1 F 53.79293 #> 2 F 55.27743 #> 3 F 56.08444 #> 4 F 52.65430 # Density plot with mean lines and marginal rug # ::::::::::::::::::::::::::::::::::::::::::::::::::: # Change outline and fill colors by groups ("sex") # Use custom palette ggdensity(wdata, x = "weight", add = "mean", rug = TRUE, color = "sex", fill = "sex", palette = c("#00AFBB", "#E7B800")) ``` ![](tools/README-ggpubr-1.png) ``` r # Histogram plot with mean lines and marginal rug # ::::::::::::::::::::::::::::::::::::::::::::::::::: # Change outline and fill colors by groups ("sex") # Use custom color palette gghistogram(wdata, x = "weight", add = "mean", rug = TRUE, color = "sex", fill = "sex", palette = c("#00AFBB", "#E7B800")) ``` ![](tools/README-ggpubr-2.png) Box plots and violin plots -------------------------- ``` r # Load data data("ToothGrowth") df <- ToothGrowth head(df, 4) #> len supp dose #> 1 4.2 VC 0.5 #> 2 11.5 VC 0.5 #> 3 7.3 VC 0.5 #> 4 5.8 VC 0.5 # Box plots with jittered points # ::::::::::::::::::::::::::::::::::::::::::::::::::: # Change outline colors by groups: dose # Use custom color palette # Add jitter points and change the shape by groups p <- ggboxplot(df, x = "dose", y = "len", color = "dose", palette =c("#00AFBB", "#E7B800", "#FC4E07"), add = "jitter", shape = "dose") p ``` ![](tools/README-ggpubr-box-plot-dot-plots-strip-charts-1.png) ``` r # Add p-values comparing groups # Specify the comparisons you want my_comparisons <- list( c("0.5", "1"), c("1", "2"), c("0.5", "2") ) p + stat_compare_means(comparisons = my_comparisons)+ # Add pairwise comparisons p-value stat_compare_means(label.y = 50) # Add global p-value ``` ![](tools/README-ggpubr-box-plot-dot-plots-strip-charts-2.png) ``` r # Violin plots with box plots inside # ::::::::::::::::::::::::::::::::::::::::::::::::::: # Change fill color by groups: dose # add boxplot with white fill color ggviolin(df, x = "dose", y = "len", fill = "dose", palette = c("#00AFBB", "#E7B800", "#FC4E07"), add = "boxplot", add.params = list(fill = "white"))+ stat_compare_means(comparisons = my_comparisons, label = "p.signif")+ # Add significance levels stat_compare_means(label.y = 50) # Add global the p-value ``` ![](tools/README-ggpubr-box-plot-dot-plots-strip-charts-3.png) Bar plots --------- ### Demo data set Load and prepare data: ``` r # Load data data("mtcars") dfm <- mtcars # Convert the cyl variable to a factor dfm$cyl <- as.factor(dfm$cyl) # Add the name colums dfm$name <- rownames(dfm) # Inspect the data head(dfm[, c("name", "wt", "mpg", "cyl")]) #> name wt mpg cyl #> Mazda RX4 Mazda RX4 2.620 21.0 6 #> Mazda RX4 Wag Mazda RX4 Wag 2.875 21.0 6 #> Datsun 710 Datsun 710 2.320 22.8 4 #> Hornet 4 Drive Hornet 4 Drive 3.215 21.4 6 #> Hornet Sportabout Hornet Sportabout 3.440 18.7 8 #> Valiant Valiant 3.460 18.1 6 ``` ### Ordered bar plots Change the fill color by the grouping variable “cyl”. Sorting will be done globally, but not by groups. ``` r ggbarplot(dfm, x = "name", y = "mpg", fill = "cyl", # change fill color by cyl color = "white", # Set bar border colors to white palette = "jco", # jco journal color palett. see ?ggpar sort.val = "desc", # Sort the value in dscending order sort.by.groups = FALSE, # Don't sort inside each group x.text.angle = 90 # Rotate vertically x axis texts ) ``` ![](tools/README-ordered-bar-plots-1.png) Sort bars inside each group. Use the argument **sort.by.groups = TRUE**. ``` r ggbarplot(dfm, x = "name", y = "mpg", fill = "cyl", # change fill color by cyl color = "white", # Set bar border colors to white palette = "jco", # jco journal color palett. see ?ggpar sort.val = "asc", # Sort the value in dscending order sort.by.groups = TRUE, # Sort inside each group x.text.angle = 90 # Rotate vertically x axis texts ) ``` ![](tools/README-ordered-bar-plots-by-groups-1.png) ### Deviation graphs The deviation graph shows the deviation of quantitatives values to a reference value. In the R code below, we’ll plot the mpg z-score from the mtcars dataset. Calculate the z-score of the mpg data: ``` r # Calculate the z-score of the mpg data dfm$mpg_z <- (dfm$mpg -mean(dfm$mpg))/sd(dfm$mpg) dfm$mpg_grp <- factor(ifelse(dfm$mpg_z < 0, "low", "high"), levels = c("low", "high")) # Inspect the data head(dfm[, c("name", "wt", "mpg", "mpg_z", "mpg_grp", "cyl")]) #> name wt mpg mpg_z mpg_grp cyl #> Mazda RX4 Mazda RX4 2.620 21.0 0.1508848 high 6 #> Mazda RX4 Wag Mazda RX4 Wag 2.875 21.0 0.1508848 high 6 #> Datsun 710 Datsun 710 2.320 22.8 0.4495434 high 4 #> Hornet 4 Drive Hornet 4 Drive 3.215 21.4 0.2172534 high 6 #> Hornet Sportabout Hornet Sportabout 3.440 18.7 -0.2307345 low 8 #> Valiant Valiant 3.460 18.1 -0.3302874 low 6 ``` Create an ordered barplot, colored according to the level of mpg: ``` r ggbarplot(dfm, x = "name", y = "mpg_z", fill = "mpg_grp", # change fill color by mpg_level color = "white", # Set bar border colors to white palette = "jco", # jco journal color palett. see ?ggpar sort.val = "asc", # Sort the value in ascending order sort.by.groups = FALSE, # Don't sort inside each group x.text.angle = 90, # Rotate vertically x axis texts ylab = "MPG z-score", xlab = FALSE, legend.title = "MPG Group" ) ``` ![](tools/README-deviation-graphs-1.png) Rotate the plot: use rotate = TRUE and sort.val = “desc” ``` r ggbarplot(dfm, x = "name", y = "mpg_z", fill = "mpg_grp", # change fill color by mpg_level color = "white", # Set bar border colors to white palette = "jco", # jco journal color palett. see ?ggpar sort.val = "desc", # Sort the value in descending order sort.by.groups = FALSE, # Don't sort inside each group x.text.angle = 90, # Rotate vertically x axis texts ylab = "MPG z-score", legend.title = "MPG Group", rotate = TRUE, ggtheme = theme_minimal() ) ``` ![](tools/README-deviation-graphs-horizontal-1.png) Dot charts ---------- ### Lollipop chart Lollipop chart is an alternative to bar plots, when you have a large set of values to visualize. Lollipop chart colored by the grouping variable “cyl”: ``` r ggdotchart(dfm, x = "name", y = "mpg", color = "cyl", # Color by groups palette = c("#00AFBB", "#E7B800", "#FC4E07"), # Custom color palette sorting = "ascending", # Sort value in descending order add = "segments", # Add segments from y = 0 to dots ggtheme = theme_pubr() # ggplot2 theme ) ``` ![](tools/README-lollipop-chart-1.png) - Sort in decending order. **sorting = “descending”**. - Rotate the plot vertically, using **rotate = TRUE**. - Sort the mpg value inside each group by using **group = “cyl”**. - Set **dot.size** to 6. - Add mpg values as label. **label = “mpg”** or **label = round(dfm$mpg)**. ``` r ggdotchart(dfm, x = "name", y = "mpg", color = "cyl", # Color by groups palette = c("#00AFBB", "#E7B800", "#FC4E07"), # Custom color palette sorting = "descending", # Sort value in descending order add = "segments", # Add segments from y = 0 to dots rotate = TRUE, # Rotate vertically group = "cyl", # Order by groups dot.size = 6, # Large dot size label = round(dfm$mpg), # Add mpg values as dot labels font.label = list(color = "white", size = 9, vjust = 0.5), # Adjust label parameters ggtheme = theme_pubr() # ggplot2 theme ) ``` ![](tools/README-lollipop-chart-rotate-1.png) Deviation graph: - Use y = “mpg\_z” - Change segment color and size: add.params = list(color = “lightgray”, size = 2) ``` r ggdotchart(dfm, x = "name", y = "mpg_z", color = "cyl", # Color by groups palette = c("#00AFBB", "#E7B800", "#FC4E07"), # Custom color palette sorting = "descending", # Sort value in descending order add = "segments", # Add segments from y = 0 to dots add.params = list(color = "lightgray", size = 2), # Change segment color and size group = "cyl", # Order by groups dot.size = 6, # Large dot size label = round(dfm$mpg_z,1), # Add mpg values as dot labels font.label = list(color = "white", size = 9, vjust = 0.5), # Adjust label parameters ggtheme = theme_pubr() # ggplot2 theme )+ geom_hline(yintercept = 0, linetype = 2, color = "lightgray") ``` ![](tools/README-lollipop-chart-deviation-1.png) ### Cleveland’s dot plot Color y text by groups. Use y.text.col = TRUE. ``` r ggdotchart(dfm, x = "name", y = "mpg", color = "cyl", # Color by groups palette = c("#00AFBB", "#E7B800", "#FC4E07"), # Custom color palette sorting = "descending", # Sort value in descending order rotate = TRUE, # Rotate vertically dot.size = 2, # Large dot size y.text.col = TRUE, # Color y text by groups ggtheme = theme_pubr() # ggplot2 theme )+ theme_cleveland() # Add dashed grids ``` ![](tools/README-cleveland-dot-plots-1.png) More ---- Find out more at https://rpkgs.datanovia.com/ggpubr/. Blog posts ---------- - A. Kassambara. [ggpubr R Package: ggplot2-Based Publication Ready Plots](http://www.sthda.com/english/articles/24-ggpubr-publication-ready-plots/) ggpubr/data/0000755000176200001440000000000014336762445012467 5ustar liggesusersggpubr/data/gene_expression.rda0000644000176200001440000004643214336762430016357 0ustar liggesusersBZh91AY&SYRG¥(<yC`1wB R )EJP(JU* UDT*)RIV@ P SL&hѩ4bhBcSBm `4`4&0M&E< &AD Ѡ&LM2`42`#)ɉd#da 4zGCSѣSiGj)f꟤mI?JMJU5DҚb=iS@ѐh!iѓLFA4 L@h4&U?J=@@tU*MTz4F@@!d`F&M 2b4LMѣ@M0&`L&A0F&Sɴ›20L[L?7~߳yv W+ .vrn`BI![߭eZ$ A4̒@!W @m[]_`@ PD œ.\r˖̀(DI$: j,, ,,,}6nӴpbH1I +hKw@.BT&} "&ֲuy;Iyɓ(6˲_V̬WQ\+[KҚlwX4 7}#_KҀqS@Ll^~L[l6B4;zR+ D1b҆lPj^]U| + 6MuW~ĦnREZi\rW(xֵ7(M0dS0~?f%4 HYaj쾹);vۭ'jC ]Nj2ԩ*L6֜|Ҙm6 [؟U)@荇* O9XZ]c z5c"]LmzReZ@G6xIV+aj'#@bB@؄V7 fHb姜)t曎babb&;NR(!_j&&?O&6_." 8`ݷ[hHBI$-]B65sSߤ\Li$i~rY1/zws{xŝB,'C^lcN͘yEL#XPk&J W$;i k=7åIѵXHjV#ql,$=emg5yݕYz1o̢fm1>ݛ?cӄ_ѺtY1 &p]SLLII*Ga [}Q_<M6`갰vk5ҧz&qpr`SK$u1#UȪJkh*#uFơ?]ta!l'{ f*Le@npkxL# r_&*F2 ,ׅO5I1庭냲]7>4voi5$NxM6 ]#cs]֩&:;UM+tCNӚ|)C -Uquv>~7$Q WlD0&Ì`0# auk\"aM&f]Us@Ja}شMV-xI.g.1̆+#H0Uѡ.Lh2>/ OeIV1..)r'Ezx+B,hq[v SeL?mfHy};yFyb<в (-&$g2P!W` i2Jߙ@ '?Nvۯ_Y㫮X=Ʊ_Q7}۴.CϱЌ¥* 7/nŤ ޴VW;;?]Գi e8۫& D,8woeTS#/yfk!Wv с{JS FEgu6VXIiWagY'I#wri< G`@1mmaFePgX)X5bX;dR:)p"<xޱr5?8oj7=4y09xlfuR: B1pg=oS~+m? ZֵI$I$UUUUUUUUUVUUUMmݍmmݍmmݍmmilb"IaI$ݻv훛?GuͻvۼUZ *UYUk40iUeU`Ҫʫ\UVJ*sVUZ *:S[ZϭMa{DҸf-Od̉cpl{UTI$$j0'mlzquUYUk40iUeTQ46p=9MtX<amkm܋{ےZ *UYUk40iUeU`Ҫʫ\,/ۮ: (-$j%V3@Y)0ppUVJ*sVUZhUV` ͛UUsfUVUV͙UYQEQ6/Y |/YN|\oür~jȴ't0 YJ} ϟ>gaalI$]uq=}[-m UUK@$ H H H LZ͗8𰚳?[ץDQV﫤dwߨȾ| 0 ^UUA$I뮺&Zp]u@ $@ $@ $@ $kV}Vo;V;<{o_ܒʟmDHc{?˧l[ЭnK|l6MM{UUA$II68|4<m <ӵm^{ZϜ@ $@ $@ $@ $7u8]7WJt #u!aaaacccc6lٳ`ZֶYeI$|g 9$ӵljֵ m m m m m m mm~˰~nX 9ϟN$}&;7n:V$Wj}^hpV.'6bbjgqBɿ.iqbD>|(׌GYHO(l-WwEn< &K ͍=o%N-s{IVb0l 8_"`_4/}{dj1#|J9qM1v"6DQ=k? B7zۃ>?Ȍ mf4ƨ&i/Űw]JUHI5~gZߟ2E)_n3[*A[H#Iϙ( >| Qq4zYZ*dl ҩЗJ=J,5;L*ڤ{T9WώZ*-mTg"yeI ")LdR%o*Ҷ$~@4lUTkAFqP8𥐪(@V!6 @~4PdxܙNJϩAɿd ۉy׆Lx~ `z OMƥKy"أ<7U/cYoҎļMbww}n.<]C{Lھ JG1f;݄\BB~ j׵"iŃ EᓱOڲǐ=t\M~"]&y]M% WiRוZ{xI~v'a-S4< M1ԽkwSOoa=f$-tHWp09,T]:}q`BAbę(l5*z2j~gfqLYc󈛨Y{9WB0AUj}Yv+u%> Jwem:xO+t61~ج[c<ԟfXG_П%xEfc:03಼CVdejwxkJm-v7xū;]ZV9@ޗNkaScq}D6gvy] Q[lj:f`#^[cq׍oZӲn1QIi~O6ݪwZ8. i(`ep0 a!_%}>KDVU XZVqRYyt.rp : ==xDlU@%p|4 @2LU)&TPiNiݖ˅&s1yTp#ӃE^)l 7o\Q{LFD; K<$lk{Q}dO,|-2 r _)å>Tm%pMV#NpζG6?,db~`]EёP;+k>,rcx?q.ڸ>*HV}*+0*lRT֍83%@l鰰ojBwQoO)ԾbvNZie=ެq"D,$V ~٢p'JGv/XK-1̼ GA=4$ak%c1esK6[ da~ZHj_&#y2fE*8>'%e̵\7k^X/~tIevzJ{nr~Vm9ݳ+xY7pZG*$ ~wdBH>Ϸ5 oܲo2|[}[=q3.m@s} YJu=':k ,D6! lCb؆6""6! lCb؆6""6! lCb؆6""6! lCb؆6""6! lCb؆7! lG77j& _{W;y+ rXЁYBFr{GH+jGAG` Ad4G\R"%.ջҠ"? {'eR e\/j Wf|nDty'_?o2vzO,4dDl]#(*W* Kgl?葺QQ tߦ֣z]w#X{t.߻Yx.oH<8: [}O3~Fy[f.j2:~rEEwc v7+:B0 Kzurs#nH೨_S3>R,]1RVNVs/oQ ns|G{1|{6j;^*jf\yVfqc;pPctT5?o1\_B_栜1Arϴ^Sο*Kp! lCbC؆6! lCb(]W+_#JثK7䮘'ڪ[ToMK~p=M6\v727q{[3@!d9GʁgckTj89'B]g2M+ At^JTCb؆6! lCb" Cb؆6! lCb" Cb؆6! lCb" Cb؆6! lCb" Cb؆6!b؆Ly[p'_LqvkR1?e#f7 c-$b60\%O‡XjoзPJu'P T@ȇgʇʼQT" 1[x p7_CqK*RBLGqvahk질W5kMWg 1v{E~;* yGNMW;_!#H.06vXw %#tY? q;Iج,Y 9cpt(p7#wY_ $X-:+\LyQ^TcZ4Zс0.PD4^)rqp׏gXPqDzFΚ-ZNZ ꋾVD+ L0}a scvgՃS*>bNkwQk D:-qW3o!ۨN>}S3 N:ȷS4YK^,"9-aDwt7}ow5^K|ح@yځ⦶/4Qݲfyg%b&iW vw2o͸Bj@Rq @߶X =鸃w ǩoGs U)!DHI|Eg>AeK`K%·"s&@b+o|zxhFEլ.GOUu#C'աc;X7cw26+on&Fn?[:"-,s='60M>eW9pSx_y` d;mEMq> lNu/99x ;]l{p]ZqG'Gb5i6{#cly,dnFtBW`K>3OTnHSYl,9;3)4jkwý =}#$o`g`C m4 ᫦c[:i}eKzwHv,ĮWsy닑cio]vS7%?L3|+V;*дqb./-JSLCR?@3}&)(K .>\mO~Gđ,jeHHJZϾi| hgѯw[XF~R [!{Fhխ8N_W뗠}5Aa^mvBSFc]8t>+ǝ->\0+K#VUetKmfsG m4F3íQpu/kXrmiˊ1jZr?ݽ\G>,GQ_x쎃sxz_uDoW%kr3ڒ sƢWLLL''IEmmJȦæ-D2ש(^KLv꿔8h[vf>uH])QE;>& CsW[X(lha|CO73ӹiA֡9v`@]C v]Mmƒz\ZӵR=FSwY!quP9+2~ :˘A O(i*Mj z.Oɓu0e~@t(y2d q,.\H =:g0i]v} ^7y?`L˘|cCuR2ߺOh?>6cenGέ H]jx{qP"cZkXL;c{!_畋+zYC@|cFk~@nѵCl s ٝkoGJ&nC L[!GXm$X+<2bó@9ZxdSΎ7Kp:m[?9`)3h-KY.y*,DdL:`#WgoCUlz"j9]r3 EVSYٞUd["㘩/@{B;{pC%MB8]Ȼ\[!ްb^FU@I{YY@FML2(Z$b< XZ MJ݆bct%u  #"j}{>R1x<'פ{4Xg,L??+J 1Sq7SmO!zmQ7AtBm={n:ZG-BN ӵYq|#j5oM!ywI_IA#3^r%!\o*r 7b;R=GqMFߞ_9Ƶ۟J6|vܴLDr3B5^&ʔY^iYݦIu(z7XMZlz;>/nE,)&mzR5OPLM"l:k*{HW%j6-&Jկ>fznp; ֱ#F, ̖/YZEf@.9:~̹ͦD##uc'HF*}6-SP6Eܸ0 Vr5{ \;x<1{k>;p߷Lƥh.5r!FNRu9vb6eJͮ.(njG;! KOw+řkN[]+KژA%lMz՚ݗXV3E  5ڄ%6 o:/xX߸\# 0 6Ŏ􏃍Qw~ĖjYq`kՆ&f̏Ew[[Qݕ1Uh}7=+>?Z>g+ gS$  %@-+ " 35 /]ie[?)^j\a ^R}34S[,M4ѫ\ 8I$EbV!jZW!p,Leqy+XoGU׾,=U~ k {">.1^̣]vv_9:Ȑou_ziJd Y%e8LټE7 J[6_󆯂Jֲ1殷vY܁2?x~5Xmg']S]~I~׹G4v$o2l-wg E}3RY^ta2 `6.[b%Ȋ|]d_qE^Hx.춮G)}NxO[7#} ڥ;H&H*tnNA[y;:@==OX U5Ii,J=ul~$^AU a!,p;EƑ?^x:imvx0 ezw+WOdO7v?EV+סZi?Fh\PnP3m8d&Deq@&4ō!'TYBSXڵIx; E1PvTC*#~ҟY$:}+XC4<|c1d~3~=\4%xhW޿0v &ڮp/= LJj4,@𐜌 S yB{ jnptjIx7y^m VY^i*̭Eƪvs7 f \yְ7mTXlf>jϟ| Mc}bqyϝpEFH i"r=5ۨm¿a) \+!{R=| [mE+[dZ:j]\ȵ\P z=8;iʼnx?ߑT}ZaaA pײ4/~9iI'wrvٓ݇ v}K;8j(86?H ]|| S2Mi*vjJʵ㥐^ͷ2ѺƗ<ʹq`?}1)_ϡhTÏK=mIdr|LE) űS{|-~3 V"c[t߶j0"3i'ڃ_2'ƱW5GMV[\ D+فw#7._GZ\qsU߁q4Ǘn:"Smr0N2Piu{A,{f>(;Jntux[œA` ( M0 m֪n͌:o~OѸaZ'TL̥V ৡ3=hL>-<W-݄L""bNna vx)KGlt*@ΰBZ?AWҬuήg=}\T=>0=x`B܌[*=̪jQ_ő_?4]_RNXtvq5?ѸO 1PXlTaHa_#J_3U!ȈEvBz|`;rq2YFDz_z~a `Dq-&s4R aEk,7"ڈf$hZ*0l #Ucӆ#䠒9KVxIM@iI&N MaI-B0WBd]'Fw93pF~vZg[Hp1kPhKCTWRs5W,硇{w9WG.i}MkTɉi}UMSi4ą5U"v6Ek㟥eOwK6l5F{[G0:;hfm6``mu Qdlאzz ̈[Ws~NEIm [o[Mi]2l[TTbH[WB`j#FIeGCW:s3k[kW"2A.b[mX jʜLH6UhlB[HIU=kK9MKW^]NG*wC{[b6*A{{L %˷ו̝^3b>vbY7Wa$).]cd#!˿< >1#Ў^N"<kb.ʼa5^޼ONJ#7Tp?^Вb4͸`R|վbwN67-|S]SS1eC_ >_O Hs7Y5Wl{0M\VsQeȍ{նAzq1M lu0cDJDu? &J?}|;bѧ*H׮Xe'n@g\BЏ4fߡc+ ~^U_[~rZO|>HH-ޛN39^f|KP&e6qȤ2Nl(sLKvHwXX u LSW?fzحJ:լXΓ>kjSt7fUg_R޹8@ hɗd,P]s*l-9P·wG-ԪHU} ֒Z~FlDvMp ,ߊSX["窃[ڬ^Xh]Mva[&!U_]}ͶhTMIǫ C:߫B/ŐoW6"fM›~sqM2$b^?\5 Ec&X[DӴhbj4znoaY=]F>F[J<4IV߭m&&CUg)f= n( ?(b%JJ-<p81N2rh;i&B^գRXƗ@).?!'NL~k7Y͇ȿʥ^$W׬|yY_#KyjG!~kv3ӥt"r=+ %0O71= w %e|iTd;S糵)%%{q#ksY׍'\ggRO,{O+A5>CT2 czF 1 pC9 e%#b5- /&:3D1ә s%(#G m{ޟxKMxޜ~Q&譼,я:{ˆdb{@¡Xȃ.#ӖQ cnpҳ]pAr|/&s$j; {Ll/i*L4sJײ sV/E:H åJvyyF4t8%VV[F?3)*9ּL3dYB6q9::o^=GeˊDxˎh/MYlcgz&~>'N+KG*|{189"kPTG?2g}gf'?:HrP 7D_ͣvˀUͿu~TPBln뼽5`YM\OO+d?1ΐel4ˮ>1ZEI@gKg'P}"S gƗKgyfP=! N3fy\ #a;n;_EAՄ߯pn>mSa>3]\HTFBx? i=WeV UcW2D'Қ&kR9&#F{( )o~%Jnhmee!ٸYH|F;WDp?SNdž,id%vF5<I^ӇgqҪShg!UQȝPyx E٘Yq9.HU^n{QvV3;fT*=ORaQYhn?+q|IpNlmM*kscjeɂtYUo9)y-Q'[%)xlDXd۱7vRp2R266{<4yd1 ioFU}]@U;Q'(~0DHjH]?fM&)IܡZՐY>ֿlcoV#HWpԘ^ (ўÒ'ohA˥H'%w zՃvDheAvO;c^Z% 0lzPV a̓dib 2˞O;q lm9cU筟E@ױIeN(McISILz UQb)jr6|.8LӵbKbexMd6~)vdqlRm2am6z^S ]4fE}OO?WÍ޲[ZN\&m5x8 LBh742^,\-adٌ sjm5)6mj"2yjŐ6{#ǸaGsgijTN>!5&D cKODn3ߏW4blO-SdtQ1+̽xr v 4[ V)ȡL_h;&L[SI3-ܤ0egjuI Mxg~9*ʣiB)8<+FGGN0楒 `e!ْV9_dשbN:!LqIddMPCF*4@ s~>'th_{ciZ$IG51;9d5kk~9 P{A%{sTJpBson1#kemo$BDcmhCV{(4lz64c-K8|=JSjq׉lcޢ .Stʛc'&ʅ2pz38BU,nidGNނfooq'#[oR eٲIH'X!UxE4!'Φ3|>l{{J0"y 7SE&1͙̤M0Øfc}OeH`"gH4`&.$1y0; I6P׿cCs6:޹ɲ46>{#i;Si^1S{إ^/2D.VԷ2yͷǿ ChlrE8Pggpubr/data/gene_citation.rda0000644000176200001440000000227414332553655015771 0ustar liggesusersBZh91AY&SY]EE $OMGhѵ =4I&i= h4ё2=Fjb`L&&Fbd0dšb1@ @4A&0i0hhb``&CH)je64621CMcHL$!}b!9pgEN!=KQ*'[\B;MT67gZY MT`Ah!aue,?-e(L00a>[1\bHMGklE!d]q>-V%#ΟjU $R(%ӧ#rWj:jGC93dʼ$$B:ܾZ eP.Cb1j_k58- tY[ 藛Dma{8M%"WCoWS†ZYl$em]h޼ MO6ԫgInEՈH>@41`$ "B #"a+!cClll1g$BE =ӿfns&E7b5`nެ`V-N/=н[dm'lJlj\M3E:[52LQ 2kՖi%oJf^M,gLi x&C`)';02vhMΆz~gٸ Ṥ47shR;vvZ|AUqznݯ юjޡKR֡R`F *+ZQZTc xK&Z()׼6q!Љ%1))k,"1 }EF-Oe%YYߛ%q2d,ȏ[WHlMlVm,xp#!C T}a -k8 ZLnc.mz9o$"_9esV3Vlvo4rJ^[v Ѩ;QO; \ivLr4Rj3 |#3=͆b(IA\ TǕ"JI[_w,Ӭso9MRKAF̢YB֦!vwy IKzuUϖ03|zNS` Sq7*X RJ4b_w$S /ggpubr/data/diff_express.rda0000644000176200001440000275544014332553655015656 0ustar liggesusers7zXZi"6!X])TW"nRʟbl$SJ !5?;9Ps7rݕ~8-IWecPZ#*iw͊G٣,RTȲPYic;˪_CFo2<[cBXj!_{x^X$.⚒aw$V8sR+:j+> 9n B"{s)!Lֵ$A]O)ڏ28b/  ]:w彵/q'!P++*H`W6jx9m,f Oy0Ԙm'v̦L\lMFLB`REk#dJewdҕD 1tK:o& MA*"-&"?'^ڒgHӚp_=lzMi';qr sB;X뙬Tq=|by#8KWFѦ>(faC;e0Bz0}0|/;zv>x8B 5*%!.ܦ/5ŴwN`zy1K[l'ֻҁP`虩)}d/vzPWuRlN Ef?}RJqU=x"cM4Z"6")'<<,qџ/]x*Q"F7O+NHDpp(w^RWXfJӣl;WKZE큒GI# ޻`5OL$Xf|\߱~eXD9Qgq#^(=HΆ)G/bkdC*I}Y'rx_~ܢӏ'*&)wl ٕ[VO!"hT I)@aW{_yΣ턷e2+_Olt.:hVſM'V?* RHFmq2}pbÀMQkhg2ѷŘ-> .ͷX_". VI?Pa V#VU_dיY55ߊ!\b|x:5:wbOtSNiJ{Y}7[kr뼊\/V)˩u1e矍uP\]#Ɣjdʼn7 2ݍAgQ }zu?qפپ+[a˧D5 tYG? ٯANJ?4)&v.2^"k~e}2RJ`F 2;KL󢜝JvUQj˱GQ+^'|2u_ޙ[)UV #"5c8&H@,5˫z hCzݬX"[9""M(7X'GX]z)i&m|#e{ "7lCr+@ipL IF@5oQgٟgq]ٻX]J<ImqIުW/60@`HDwjs (kY1DC+%P XdUHG9n;v{mpoDr<8?X(zZX[zOjp_V䱓tؓ<3t2"Yaid f]DiϬh.{-k;@鼑/oxΣ{bPn -Po@ 7ȕJtϑd+ ] sD(P^}ٟgѵtpjs˜Ml\ԇN韾i#J=@4O.w~(Egn̟epYN'a[m ~.]Y'}VJ%P :Jυ| v;ܻUFJw|{HRyTVrYapvUBkkcL@yȾ.otvr |)SuڀI1b׻>uٗОcyMي#eP}GK V}ń}|,JtЙf- Ͱ GGwYJ86eSgG%0GsjOb鷪U1sNu`~>JEq*Q)y[Gϊ]e$o:xDV_nMX]V(A㏍C[kN8­7]ReoAHփ| UsߦROFn@=ʄT{iJMfӂ ,c4ױu6i)-b^?tO5S +XAk'd?~󬏭fsnO]8#wyք bh;IBm>x a&HApsgv#.Z6fe6D\X@L3 E 9^Dˎ rwhL\$|ieCëfyh{~}6kCQvhz/K|PcM zum-7(ZɼDj܌NУ9z_z.u!aC\쑂^ ?RYb؃j>A[vV 9J @ȏÛQpi7!Ϟ5'Q3g&ԇ[0Q~.AAkr y?i``R3 yRX22j‚T 닚jX5@> }eD[O#; |Pb=q.65 @P->-w^ᚂ7X<hctKMMoF/uzc( 7MF@NE\e W^sW=`8Ο(@ʂV(+n_"_]KT׺eMZZ" <,;xPd̨: Et";jfwg~R U* OftY0fE)2Cq&C'޿^f2R6Fyh@(vQtx+b_mI;jalcMToZ`rv_c:NDWv4 "PBS0 nvC txfϭBe)ptAkNn}`/wHS94\vWWɧuՀFÅֽ (/pW(o;.P-WYUFh*c3kw6nˌE|Qr'}Ez0󀎿 &nh'ǽK>x'߸Rd7RV !EViX \uA. %݂cgLv\6Y,h-8{b~er^9D ;ple:ZJ!+C&_hoW ]OӗښpVH?_bs\_bggC?!H f&m Rɪ 羙67ޜ6ڏ 7J K`#%_"Dӵ>B [~o-j?fdw-04\ݎV=)S蕽Aj {:HH`D76˟9Q.TxE)Bmr"_M9oIȘ|I߁ryW1x  [[B1Ym =4zH=jUNs P5kq=onZK>#^֞ZySvx@l,5==+XUA{Ά#̳^[kJ331VP'l.T(b8RE:-GR+pMa|dRAh&="MQ8ֶ{Yf@JR ȆźԁqPɞ{JA~v0qt}GT^IA]k/6`F  7ůi:.3ǹ#onkNnUe9nEopdCLԱL@UyoHV['WP]RaY, |vz#׃ '_0ȒQa2|)VvIm@*'#6| LHWdjoU y}R:8KsɅ5 4I-rYEWB%y;8|lA^g1J_`kEf Z ^Y`XV#q:yO9mÉ$ZX \~b$eVwBn3!x}޹>@a6T,V>y,mJn ] &= @+frt8T逜KXKB3J= (+RJ%ۑfI;(YJݶ29G Y&ȢpIw5+Sg9sQ J'F:X+ŝc Kkpxm%+rB'")/2AQX'[(N?t٪sN]")Ah`xRy̜MZ$x疤Rwdiakf$K} ؞kSDsԎu(&^yԃwLH+h"cI`Řǜ}KX"9ٯ'+nԂ<:O++5ٸb۫K}a8%`HY}R[{J/xa`_*rpzջNbͣVNcBQx s/0XxR$>deaMK!l?{&%67s̖ʸ_-˸_Da$+JĐ?,r{ʰG*A(v!ι2+෿wnUЬrxĊ$Th(6s}句C f9;O,jA">croov  K[/'815^3Rr 襃Α69?e[1H~|),>h /t}+#Gӡ{2bcF9t7]8BXݛ˕ՐW=oMS*wAj)jC6?a7tA#jOP೬nsLɷnbfa,w3BZ3}){u4 !!O9QN%GP|8#160ŗ0A!Clq\TDu,U|UC!Au1eÍm/C0Up-v@'-gD $ . 3+zƫN|ܯπJ5PVSn#5dI}`+o&Qd `Igjbxѝc~.$ƘfWwG\b.c~ߢy Q5[qs`D1QB(>A2څkblڧ!d ]|ֳʠ5Ijձ!V1óbOYBZ9t-Œ1ʌȳaרsZ5$K 惽'7jIuJH$yqdC* ~iӏ󓽹A_pVA ՔI 'LOy4{ژIO S B9 xlv?j6IϷԥ0t\4"v hk%2Y^ۅQ>8l"]m龯mBcT@$h*:-‚ *j༊͙C=*jE@֜/Q;2CQ\\?`;.-HA4S:gZ, IjQŌzќ+w6к/*Jҧ?̬KQ0=ƴ-rZCwBHqE/5q(McuQchyg^gͷx&i8sԶaNwێZҩ3Ҿmx{Lo6H>i8ofwaGD0G #]9_*bqs):R]=1Qi1cZOoŖ\6v`Y X/$zs)W\[96wQ8:_dAT!O.[LXtC'k~6nt&x1c FVY\0PDҴ/=0Xj= mD;V+H8U:Qy̻*G]Bg"Y+A0?ibȾ>@"HJ7GH-)nƒ 拀e ^9'u?j:P"`A-_~G JDAah}s*$ ۹ń\B` j&GQ[)@|`Y>#-'ē(&-Kc C@- `ٟ}dPn~pr zy,ј=ܘ8Wp6 wN9?nq]֩{p.XacIgrAYE2, G/ee6:Hw^=J践.-1nF #VJ-Z^;hۊAo 3Kfsש)O=RYª۵ dCKB|<4HC t73H̋Ž!)I7͆tFJ1u{Ů0T2E͟P+Rh3wԞ#|*IzTQ6qHO bdR?) m$-Ukt_OJ!p4-1" ,x5?<&Oy})`fh)ɻ-q*oJE ޵ƒ\ plv2E@idejS㣿5G5cZﻣ"ߟ/+{;~WF{,Ў lUaci|qƂ f8EB!Т8[0:%0[t@mD l%,Β>{zE r\;=ɯ$Eԗ6^EI_[J1+xOl!ZEDUpI+ )xoj J=`q@LRF`Q7rJ,ӸA ̃Sj-ehRY&! 5Ql:c8~Fq^Tl6&!Ba'sI8F)%c%|jPXt| Fp\\6ύv#b,Mz()\"7Xt@f?IQݡ2}1ޓP,GD( b!)`i yh2ϟnؼcC,0.;^6Cbx\a JTib@Tni觬 os"w?O,~:ywFTҫ\S %@zb{fT~rUwnUwٯj3Hx7%OTt0 @ЖX?& !QRGl=+~MB1 x *$вǀjepU$kn^I"vvQ'NDCu xnЖJXWU-|O9+W J?h󉆛I̢]`B0.;dc{d52Zu Jg^Ɠ?^Szi"eۄ<= Ettm>(&4 :2 Wq/H$p~K{`Γv|BQ́MI͉X(`@$ F*HJ¸m@ -v %mG0X>ȉń/ƫ( :7 `,CF_T9NNrZ֪Ey.?*F {lxis`r[{cf,PO]]Q*-lfN_MJԮP/lCSz3B^Hx8w(Km-X])~Gu:Ľo SirrXL͏nhU&-T3SJ0\~BpCH_:/j0[89Bw7CrAP훧Si{̷{a/yxa^d%?BELOh:,PhE>C_4]A.hŋCenHI}bwenN-e|6Qm{qlj7JFr ~|T.9#怊YvO=_S]tAG%wÒt$.gS(4˜tPck9,Zz⳷꿂L msP4sp'˔^Gp3l0{uP)5&wǢ;P/.zS$$$4yGLe[Strs5j5$ںʳvmCGw4]Ԡf,e4IWU hyCMױ,L>w Y, mJBE}h@]?)w']r+ҫx)u bGe,ʂiù>c4k8Lӽlbxi/ZUϣօ]a8aGM2CfK ԺJT9P*Z8hVi.[kwKp"xF>,guɇDʡG%z@f`% U[> bLn.jTN6žXC)S+s(dD=$̩~n}4R{ʃ',-mSTvpK2ΪLrpO,*92$U}>G0[B_X wD^ EUB)(bгa' jBH Lpȓ8ήz@Xzj6x:&wwy0ElFd򴴮!%DB?l_H3Q ;ZD-ʬ g`4NO$(:GoΓڧx{ Br7re]mG+ȎjWQII`INltRQb8=3%|[b#H4KtA7x7 s{H*Kg%mt(CwA ,?k)L!ź$yMCA3ݏX$DIԱگT qo k-".D5inN.vl.i9o φ]L^`l H/g˵ɧD8 K4*5l`+5gO;+z:zh?K:2i4l Te`3#t,ݫvTx9+k/ {o#de:VI>)Mp,_e=n8J]*d*I`\A7XQ/?xG2Y6q&!Xna/&!JbIJ?n}Gg{$[I{ئ>ϼ[eU1;huiI~B[ wPRCFz&lTx2 # 1Mщis;Gu~ƺ0d Ju/aM/>eyS+=*/$sԵ_P~kx~ Gڡzō".2@@&|\:g4eq4E[NԾ"p便;| !*NA ]P qnAu' 2Q  x!w>Qf8B52`KXDx?V45p2Yf==R"/oy5ao64Uꯁ+βlRϺP/KDUω$Z\% ^B 3ڍO<)~ z]FpCَ^vͥ|-i @6V=eΞQOKxD~FmdDr϶@zR;pVe7bZ+$] _0k:~X@!Y]WbS eFdG̅%]3ךnx'v8X+3viK,VƦNCf lZDYǑ U*\)ٮ!7 'qq 2|?&$U7q]ȩ[cCsh;OZͽ1PU6䌯nNj2zw;u_g5p 4ft+ ~ʬ_M/8͸4^Z<ms*IU R}?qt}HULI4p,>vj͚{jt_-W|˖FX͜5D #A<~q2bcP11_mSFiw^,n]UdrYS`ײ 8=hl"d&q4 j28(oiDhhڐ@w8L`YL϶!_KTSU"Pln=UPms1i0?+bkfSG (c#h2h|{1B WEՊsBӣq'oQ<&1LNu q[ߛ]$3Jcr?{V38J5;ѶOGu/D ^Caݥm,ҴE1suYcb܏հwߩabNGE^tFHXwl{E=MrCc0 aZTo蔴0=`AÈZ| iУ?x1Ǝ@w E)duA?$d{Ҝ҇^o1%pEHSk7h] !)9JItS0Z' *70j|b/( ΰFS0p-zP|f,3mΛ"{T*!$Ubw+tn݀1V!Xe1 O]5)%$ {̶D8K u܊$2n4hڅؠib淁y,gK8&N P]ԸbsY?΁`.\D`jNŴ7+@@ըbJg]jz/&k +ޕiH6s]MIQoN?鼳&K]51{ïu*^e瞯^/)nvK~Y}FYDzo2zMdَX2> oi0<{?TC|IJwxq_`o-.O^~O(*bY^Åvhϰ!vNEOQnZmzf賤koDhU~794%&t¾"iXHDD\Yr 'q?׾~R$co,º#K%_xb5ZjbXN02|2Pa7GZ&s@zuvp+RFz|fM}GF:X]/ιȪ0G@j:$1 *S]D^Cƽ>sO|5=꼸le$Ѥ&<x1o3H[t-<41|Z~Îkw]:~ZuWfjz nK~az#0<1zᶛjʆt6zODM`5,j"1r_M̝,Q \A\ %IO0[+-,چ/EI~m$8S+*䗦~aPTD6*Юf(Ȼ n'ªW_&}>V'uFdhW0[[<*$tzyؾߵk!&1o3s~ꯢ eXȀ2ެVl f1@LmbE QT/_M@-]yJc!E1Y}<T*$d9aER^|/仏qgayd+:r mxbKE"?WXa5>VeOS._R'?& NVI!RVhK'Z :"$cBb_W- kg1Uhq0Nn3#-㫸Y&rj)P9wiQӆcoh6_V4ڿ?/7sdiWl!5ʔmjB`Dz!֑de[$m>U 䨂I?hNJ0݉Ks_YA4}u%$vajppZwGC7z^ǜ7JULq1w( 2#+4vG<=9q6'O]0\$6NYDQ4T0RSo0N>S`Qg`@U 2>hmrȥv^O`>1h_(9 "ɼK1-+JyA^X#:1Gډ)FCAU zy:06}ݩir%10Bc;#R rZ%}xzA̻'臄L Ysh\z;ks-})] nUJᝠ{w}̡lJKYPFiqmgigtߵ}|9#|a ~#fk -ZlBlƒ!6\*[AΌγVf$f~UI˿n%/#Qkz|:2? Ș [Dc 'ZI: ymuWE޷Օ,0DjU$t?Ģ~} A{ pҥ/UQuX1;<2=+xM[ߣpnÿO4vÖ挜xO^G*"{!%>gQyH/ /[27oldk⺗fM'jG_.[Zp]K#pA.&qGs_ +LkrqCYn,j-Hp`Cɀ!B[YK辂tudu;ȠZFXMz !oݠnz0gS,qsj#+Po'Iu]e4'Ua2}t?y+wd<(ex&<C9T-b;WW`Ee*.H@uAldqI/odhuI\SR(QJ:H+)~dAPܠ;z'tM;*)Y&Ff8ߩH.AƞI؎7-!cw Sf>VP#~-iWCV(閭 vobP:uF@˱gԾ(hOcGEEx-U0D3' E"A30To(׏5ce~W Wgas@I.KY`k,yH{ZjG#d\aE({i2#Q pxi՝ӱyadB5('ir%;[L':e|!*H.ˡB~g1Fh6|<(em{ iG+ ^ԇvבbTVgf>rE"_L[XF 8o=uajB|U5Q hi \2ojW9H3CG#:"# l 0v){U><@ʳjT TxёMFugRuESχ կ0X5(T GBrY, EU鼑y#kgJp;"Pz@0W 5ޚ^OaH6 o[t'}F/Ov+ktTvylS)#Vd|fP{ÖjEЅeoJUmф3CYՆx v'C:AY[vf,%_y9q0_A/ A'€?e}ْP7"zD<9>4H!QUI̚|ԗXɍEﳇcLf"Lj??Ƥ/^ZEQT7,,P?}mAEkBZw+jooACCZ = 84 m&KY/f3,0RyTؠš.f'@gZ$t@z 팃o-~Tx*\c7ٕsqj{"D"0)Ϛ+=Ȃ"] |#^1^pe,5jK5MteG83dc%45\ b@?el=oeH4b|*sy,78=t @vN龪߾<ί*HҪȈuiyr8.LeR"m/)5`o$ɬ3߀b$$qʧ:buep `f232hļ63򾱲IqB*[[wyc(Iw7 %҅F c:00eJ9HMTLjaX# 4gؗ.|cK%`Ln)VJC1B./^? ff͟;g)l <\B4:`*/c jBr]~7k8yO?ں@F\X9,^޳@w~²@(D/* ׶WJU-d_8BԌծ2u>XɿQ˧6nPeh{Pm i2Zgدϐ0=:\˨]ܐ:k0k'qp/ q2 ШCjwAJe$*&@Ң_qD_+DSPlaV)1hR/W@C(SS7&H!%GMSTv}=j^~Aُstuԑ%*0 ceo7^=-C/r(7,-c@'Vfҧ?%0upl`x~?'{ q{@U!UV@ijY>[͓Rbgѕ%֓)/DDZG~42Қ A&|Ϣ)qLudKPYc*odQXScRdJR# ]$P*>tZ絮Wy|l-(i-r(<`alLr u{Y+ԗEAs6ϪXUHwe01"(0Ϡ}vߙ(xk,Cѽ%؋ͫDeA&f0e]Fu֘i:y}!'_ڄHƴp݈M(U;w+= % 5)T\h{Ȁن$< ;_ki<:1bz /q=Rڭb3m4`>Ť(~d=7ID I!hHZ|!N hnn`tk 5LEhՅK*[l{ yU~í\WeMM].N:lbKRτ a[Ր!:K+$R䠠 ]S 5m<<Ä ͹A,(Wwm%劘/Mο$B7x/ȇ@op JY6B4Nԟwn&Wb|!u4g`.?kh]Fr EeUp?s@croz^ErBhX?y[9&tA լ2 Pdxb(/"8Ν#)9@$KMMH?.Oy\1;N@&61nU0KÑ3-z;!Q*!g1xׂd:$:ҒX7 mm9oW[5gzPTG[Tm=o 6}V!nl8nDx6lQ/tzO@r8~[,ƚfFpz^~Syafswp7{U`#ӴpLJaɼxg# K&HhES2عA{E3Ui|֨kyDzN±ge*. $ŕ~k)KӉ-pާ|Lw[Qpޠ*:Ѩ!_g5 %o&Ra]I>]zYC1ן{ǯdu?גTdr,.`WΣh[g"!;We(ߍl[>҈ E/^쨢\ؐDzfSMEJpEyq.pٛ[o>-2P`.na2Po# ኺ58Br_c>X=DN.#'ogu9aZ0 " ?ԬCKt*~SAlo^, 838ߤTTS. u hF.Jb(zxjBtrH9X:`g9Đ"/->Ҥj:("]O6T$ \jz@ eZ ߞ C>X&>8J9?ǜ<_kRw@FZ1Ia֒Ύ=|$hBB7}lN,mLzח%l@ώӐH9O='ѬDiTxwR@qj_hXlu^W %@#owt#M2(|sr_\3$h*4W)v=f yʗfl?—6GlKn4 iBy{rCCt,fy|Vc=QYn%xn^?QQqjŇc-JZ4kn zS,I'ك4o[ j5|pʔnmYicfdO(5uQ"nLAt6 ~+GGQV{ c:.9f u$ɲ%!}ڙanYqK/)*0lܐܐ9;` y:fs3R+-2W*.ՆFJW@4pXYYTD$6#BvD #m\"Rr( k=rYWX3NF߿ tN4AG mvlbKH>)Q)v bE C/Xa xlü6 ̵۠:[=q{wfK=X-yzS=Įgs/W'*nOʱ[bh Lq i#X[M_ m3D|$'c׾z53=1l)PrW;Iߟ2vz]f$@>XZ][/['}Zuk$gqBgN[0`h@&"]l/d>f}w>i)LE(o!Zlv@m;n֬>+u\MyUqTX!98&bh(W a:ݵT ƴ Sa} Q Ob`r9qPN$+hY[$:b9,Es|Zp+VNGfKذЃI㶱B޸̳uL56i:q1CjF8n72XbvXJbk?@fOdkm*;E ]Ꮐ G/Fb]bLX̫xѦGĻ˙M;L3HVN$q 2V85YD;?%P:˳&>Y/i s ݑ͇Kbù,.u+QtuE%_lSvQ]i66p)WsgNsNi oH# `-Z˭I-XW.fTo- D<52" YmZn z3j5Wcd5 C @1|u81g` ;^y@.}U׋jHQ[f$SB^1N^heZ?RA'7Uw$J**Zcss5E@pK7/euʂ5K _5iXF j4}sG+}0l՞FQ_Qڮf;L 햶.HЫ758mx_kMϚSD)c'3^o|"r68-CK`u qfOʒ XN?"Dv{ O>J;\|@4}T Z,PXBYvLS#21}%4Vw FQl>Bcv;d.U5Y[q%/Pѻm 㡵c^nnf\m o;l_ zU$i3{$/rNc™C;fK 95p%sH[>Yѓ & K_\'AD-A[8J$4h,1G<\ — ³ =Zo2򿶱 .,tOlfz)4ꔊf:dW}cjz)Œ/fࢎ KĨ$A2P8<)8x~-YbU,~ 6]m=\OtZ?-ȰةB^V$^)4/m*Xɖ{uj>4FJ#Vjރ&'T3.\Rϝ`ň\ y0 ph+:}v:uq"zVmG0@IvȠ(q(:?-81ZS}]y ?aQ$ @zxA(XX)j5G.謹B@/Fo<+Q&TW% Kw{S.q9],uq}e^ܸUtJO!C BmˎU|mQ>vpOX-jM/_rLoA`ըGz]YUt<"6"uuo_VǢEҵɖ`ؿXy]j׈Q.b7閮M~ &*9ຸx4RB{I0z7 uΞ69~'lp | 9(WfIz \BVAs0]Z7z8x\'G#+~O?dkO`ft%-O =F?EcLj}e݂;zd9x-*xц1$ F)1MolSdcu yh % Ff1Ʉ(։j :.ˋsQu^Y"%-k" %Dیc֧{ٲ֫˼󮲮P=lnl#*X Ȟƫ fP«@bZz0U<zam˿S ܱjQ&&p4ڃlb&Jt~z-?| $-e ]Q۲oC3WiO7e ʚضzZ"^09dPP ^^kxWۡ&/bDCnB2'm\Yc,?x ɚ\e2YCaDrct(zmas u+*G fْ@Xɕ"*Cy U,f+ifB-e,b0UjR! @p K WS֟^돆 i>N }QNh8۞sn`P]`BSf^(CўNB Mvh(Ox 3du4DbU/:h BF3-}:td<,Vr ؗL3; K N}7܀f$ܦ ozէtpyyHeGV`'!y|oşo%>E A87D}^ ₤R> .xd>j]?j=m7{[.ΡV{PG@P0w\ǚgv S,xx=[}H&%V S.Řso{yy|jE/a:F8G'EWܮ܍QD3})[ y2]BFǟζ֭vt{Hcwp6Z.4njvkK?_%HXJk2rj,:.&̖tW9bh/s}v.P5 I0G2 0n+T^+[VĀ2,`_4GrICH+ KEIQ1C` s{MykkAzcTɢtre_~oD GⰫ#; rܓw25Ѿaj=cɡKc&1}\'.3F1|)VypvR/\4 tJ.a]kY)Ҙ8n5zcn4՗ P~yh. pPCmÔlBL44kuk,iVZ0:$m yqfRc \4 2 e@m W>߼4#<{S t=g>5nJ =mP`{f} h z)䆑|O O6SPugEgϿw\_-bϏs+^?&&_;ie,GMtPM\U5vqG1E<^chvIGK`ou]E>,/34B{{ENSDɍ20ۮέf䂘!*imRRM'D$LKV)]{,~uתb5;؇b&}H'ŹIty"tC!UjY (oϵe خt׳b)3-bwO*[` (d>,Ȯrm\:דZETY R͛&"zТrЅGLٔR$< )xyUwTLZRF{"!|d =3h+HQIČvj,"*ާWUI4S,c/^r ޠ)O }jkLh>tpa (m}&紏C.V.6h u  j2X6F7㦧m*C檭c |qD wY+@WOv.@2 =#`Ē/3{}AmOOq5kF IE`ouY۷K,u{ }a |FAo$%P}3Ve,]G>)!k[(%.T OODwJ6FtF,pg ( ׮5 ӶDF+6JyYJL[_L1HDX1oA j4aL|"UH_bItkFh x@@[Zss|8+vC$<ⰆkW+nI_,u ŵP8jz\<\Bo?̈́/iG_I?gkP]@^cۼ),9,Lb V-6ur35S5,6*2΃ߑ? {xn-0-nuJc̮ 54_tDZ1;[FF0¤Z3/,)Y'}w;\s#38`fn>v}+No9X\}'V61~pYd7êz0:d4Nj+BOӓxsփ<ϠR81}tѯ{Iw{iV ~ӗf8bq7}"+(T`>΃yV<Sz<}n_1/]Փɼ:" @)H~1-?^lVa1I |Z+n ΊZŞU%,ZriJAʻ.n:;cB U]RmMjW2GagY/Og`2ntY3#@*{m[*c3ZUZ$tRq>]˝ 葔/A8*!;&bdؘq@{t(h tCַ`>Sa輏1EZ9;ҕ=TdL1 _XEH#&Uݏ8 X;8x|SsvXe|2Y-4DMns1S*uX%'bnH]zdz^ݴR-Pi*Gb yâb_g'30I 2kqwae/O}i*mUʖko4fB8Ga9=w.  Y_ ƒፂ$|FRqT`j:.q 5YA/>{w1(E~u5V%(,W6BԿ ~(j.qZBa-v4nwy1N's$(VXl6MP6F56؟N!&)@UoZ׎qKC5zjGӾw|fDbog~pՓߪkxb-mV+.AZ71aU3:MvF`m-idzaE[,x-5s/bȧ8 ?LV}ݴ%7=q"s\ϱ bv˧(}$K&UDSγ0E% }= tepWE额6] Ig{K :ޏVFZ0g0sui]zDhNcOx&I_a鼉>F Iɨ7d8||A3w3t#]@)!^7OAQ Wn}bO#JkZkGhw'y q ؜[C>c3Zʶ$' =](YM(0iُ;2UKKk^wT#f?$M8c@ !>Qƕ N'E!$ŗ&gA p5xTT@in>G]F96}^kVOTx-]ՅQD԰7S]t2e ڤtX5+BPve)[h϶gowPԟ\97j--nDy_ߺN Yh !TB%넾yF֞wk %qXnV}9 O fjJz*b$@'^n?A J=ubbO[]g];cɪyf(>6KmX#|MNaIXPʷ߆$XzC1o3Q;3\R̟OZA)ځ7XWhهTCzW߁,MTY|S-9WTjAR͝wr^MF¦( +*ifek~,R2GM o9v)5xعkj]ԓiv* vee"4tSCMlNǦkC2SY{=|a6b R>L{3]`7ȁ_vn< ~Hk݄Rt1Pra =ɪXpݓz0ϑEy8,D7nWwZ4͛}2ìZDHp56-ܟyMFd#Rϊo{U/茞Ӆz +.Aj*&zGfvs +Gg8׏OŜQ,MfF~-+=>֑)I+:Y(Hytb.!oH9 C5@ڄZi'}t ǀ}]J(NJ4`c(o)}%+Π0ӶY%~\0Vt"R|ƝW,a^”dN:ھ}8[lęHI._!Н.!'@WgĊ~ђIvǴ E6\ C2¹VIa% T/'9DELfzkbOJ-Z K佄&X5&a^ث ~Te-]Q:3͗JH{#MޜS(B|ASrPjhAGCzKagSM oMj60HQVI)X}&e;6I& jz&0ژ&~un0q,yq?1MX]sX^F!>JR`;JwTg"2f,PcѠAva!JM`% 0;'#ߘkYg,Mk/M[ Ӥo*U2'bK˴F|~~iHrWW{>~]}j26Ro[pzŷ`o[(s(b% Azc/pDK ;Lb'6c#qx>8@b"%FGY18(jt[6O/M( :IyUgu7~C|h[/LrIS}3rjCvp7# =:ژ)=y|쿌Ф78-iAؿ(?-Vt7qFƯf%,f,eM9M%\1J1>X!{|Y$R\{F;JkI$;5#5aHAx*O`+sj殑*9=鯩ouVĂ?0WRp0P?&MY#HJHѧX|'03zk0׋ _e%"C؀ܧ^00qlO*Mda fsl:GPH&I#yYP05r`4p,:c ţ7߫e\Tb +w %=a]P[;cd r^ T3yC dUUSUG1M;hmë|Wq0U}l^g@UR~:a@Q: xۓ@ Y0WE8k][*Rդ<@a@;t$"P_bп2,EY.~F-=s/-~Y~ !r^]m[MN8~pshAռN\F¬SH({!Q8mBHpM5)ʼp .eĆq",0s/?+*@6lC|!iVFt 2;k4nffɦxJh_xߊL* %,&ǰfp$k qizcq2K9,8HHR<|FGJsMuT@ w9ѱ'Z+zbz^eu5tnC _+M *3) ܪ(I(IehN>AWzE~`<&=\L~a \j-^~A/qJ^/t:ŘakG^5%[Se@_ZWlѩ=L:[`'ԞLD"FR-3|ћiđrH.O1"D gkî)Kc>?=\ d1G;z" Cgl]wkE4?ݴ3M$ uq2ZCoYj[!=lj{BJIކ$_> ډ0C*Pb CvSyNģWH rȰ͐YlvV'xI _na/DRwYQ徘G|lvyk@9ZUښX=V|UBT l !M~9?kY;BΗ$gX=Crh65RyIѽ(P~\׽k|%H/wx>V5#Y,P& o%L|:(3`I(djNm0/#_4Os;pP ŲCE՚&^G@_ܕ՞=)?bF\Ipt[誸cLHX }Ӄ=Sanw5Ԩci8\G( I`.tN#,GA8o Q02<◕|`?H0zq [gRNáHk=j#Hޱfc=&94NH(2IS'UQ=KNp,huqY_ܯjm\z㨰P"3hB-ܕ2%(&E i/v؀yu2AqȞD{`ljl\¢VRf\1wh,(KP w 6 .h] y6!(g_XA-D)5nvX Ȧ3(\nJx79hVϏ~"(MΠ"04!d̖ Idb#zƉE/^Y Q|8DIxȝJV՚vا6Dh'e+n52FxralG 5\ä¸3@e˱RlIH`H1iF8h=e+VC? }V 8:de3>{.ڝsO]ؽOoZ]Tj$09^[߆ǔYs/5eC{{)1IH0@swEh kF+u 6# ċqI}AKcuH\&TlHmb#4>Xga\Eb\Α)t @Ol )l(߉2^f35Z6BSFe/ DtXe:L3H(9,/"JM_e5i.,"pBJS]^f(ksP>_m-h4)*=OUҜ-Ru!x<:%yV\ ǚ2bc2-T׍ MXbYxtg1yXs>~L̮& ھuỵ3'=-Е0ȏW3=YUg&LAKB-a6': ۗ Khm LvhB=b㫀RG!X*8X^&"=PC0j|-uE: #?hG "aUyE?;X5T/lR;Ubo4$/l񋒀:6< >^mt:].Qb`lam&Ykn!rǝHqVd4^7 vqqdc!FOۙl-$%wvEڲB̦N$C Jn c Zsi#Z{(:]&D`* DrE Ś!)$䇮s Q4)jے2D]٧^xX}:2bg;y2$iE-5苈UG-ε71ks!C}khM@ =󐶫WK%,I1 }X'[.ծĖYhiKq'FMte(\ h 0#Fvr>!q`(Hh+urz܏hd%I+*kCc GiN1\xCT왿[K@IXj.Zsc B#Y/pGp y{0 LCjڅd!(`iWS.էqUæ v>CM]8@h(K#B'17xЖ"9o+:fg |۷?d8/HTVJ0Z;J1,@|}q4=GLQ 8k4s(QX<  ԘK888!,'臦~r62M#5kAGuh$1],Blx(c氼;)5a2.1:~-7c<1Kፋ RHUGkXȒHՏ1*Ja֣Gࢴ@˞iͱ cjc|Lt[ׅ}) ͺ~k``Z,AyQ&XqE^J;^%fM,OcNUsk^@cq3 呙\ٻ#'+4fdڝ=6ZmsT](5fypI0ZKx i%kg &Z?./]uNe޾bi hp vjVH"-UOI)D@Ƹ[a!Ss0+ \4y#9^3 1VFb:c[BհS;t'ցi~^f1Pu! |UOrv! c}WFLJ.VaSd&ȅ:R"ǜބEѲ\!_*n: ) ߗtڅ#(C/L;LjE&X~p -,лZׅ}3 !|MF-zJgE1~Ū]^Os8ݳ*7<@ N'#79NQ34iP-aTš&&@2$zXa.jGz} FuYDNuJ̇z"XK4u>GEtI[♕={pMw^F~vLzSV-8xհey %ͨr=ry"cۿOBoqcژ:0a}ް5I VL.9Κ$Lэ׹Gt{dF@)8+Og`#gy!'i<-v/$]͸@l jǑ$qkYEKǻh1cfh.ގek)iET͢H 8۶ o5`MYXg.[!0񶳣Hjeۅm?J%{[C2=k!cE ιd8m&.Nf;.ipn[4 آ%gEY8&WYKc6{n8];Z8)k'ȿ{rD`㙧b-e'F@mJJ"+%m9CLInZO$s{j Ic)Y U?O-!r:|rGs`qbJ=aɧ `qjwŸ` :NSxü{gO[Rœ\qE;hpb2m/=[MJZd*qg YS;S >7hFvߥR o^ 1QLY=H3W7v֏ p%(Ry#w|qj_3y-mމ%LE_#(n>-&2}RTQVnUsгRrYk*gx!P[usK .^k|R6y9;3.~!2Lɐp\'R]2:x,e~+Ejp{NIN Wk!]n+Qב+'#6&0AjMk ^rAzKld]e$6N_o1E\쬞ow:zĶru;d"K,>f4o54__u_R BKS:oX\Ee]c- -TqcJcoĵ ܩ P"̥/KV]qBFx9irQw^bUiT/Y7Q4icltg[D<`+QሞF'QbD(2\A*3J?KIJ$+UAϼ曄NΩy-_G9\"iW^Xs g,(-(G(F <XhCk\[戀f/8tཉP~TK ԅ;Ĭ(]LXG&tw@=Ĵo~xM|-SL `9Uԅapȋ'?»U&Ob/X3?G gլPr0;QlsʜXy)y }_KÀc=3+ !NTڸC Enh^G)B.LWT&FDAcm鮄"a0e!rƀYȏ;hӳyηj}K]&o[_[W~bq7 1*Cu!D% TmOjMPd&z&+E7DQ2v)_L@OQLot5}4vmSX-"褅e 3sJjq$xX2Ӛ{byFM"!ZtTZ7f,{Ԍeҏkd?;OvTMJO їiE16Lb&-ꛝBv7"Y><Da[gEG wnu?oLCK(&0BV @A#olz:nxG~cܤXv u}e?)̿v$%BRRB}7 &)XtzBB~n\ x әY1IeSh͍ѝc*Bz$B8y}zB>orX>vAaL`$n<C%Yh3 K`Le7R;6ǵ8,$LY+:>Ia9 n/{B ps d$nw}pxYy|ikYq6>E|Zia~EdJp⼂T_oiԫ^TR) C6Bb]0|F?hA])>Yiz΅;gD89u85b"V/ gc/8|Ao4i̸.GCɷ맧6:OU-J#'mZʍ.GG5!UʮqoWk 7ZzYnM b K oG+Fo!sS3 qnIN2Kupqs ;4nֿaC$]3=dWȲ{ytNX7y BO --j_d,/r{ДvoZgzx b;8/xFP@gPCY&<ںم5W+?b|/ig Pt!m7WJ!O<n3jOJzL)h.TAU?Xb)z(&asR3D9JcyhjL/`ׂE%aqa82$Le[ց:/(7?^M&cS s>d֧XhZp}quq7_ʤ8y0Ms&꒪m8nyR{wwߢ״ UH7 V~]-jj F8R<㝙(G ɆVgfqv5)nxt ^wr]pNOzϲ .jOPM~?j:{̕ct6\SF5זUtւ 1GnY!\|?,>|yuD4F `q!9[U+QSbT>:.].QԚuBu3φ0SyB@bؐSr^a zѤ\rZ2x@(@Ɲsp-X~{;0ב5yy+eleݹ~}#"y;mLGY=`M~n5t?e&-bVFdDU\݃k GS'RkvFT7í㎠W߼ať@I% Xa5NR3>Okim7ks/EAq!$|.m>]f :icI=: 5޼_<ć/\n} ?Eo.Y[zErc25Cs~BUM:b u񁘥av,X퟇&0|NY4}Y(c1+u؜Aې`BDUԅ]u]~+HC>Gi@#!dzVYp=rz.+ǽᜈ .ZߛAI:SVTXxʱhd~=gFAwV~Hj s/2B8Di=ɯ(_ w$]Q(W56!33c1\N^xy`E]P PxJQIW${l@kpNjFnQbläPh_:8ap[H:4|hG6#e;gPհaY+w,Bqڶur{%"eq ,zd `lo{eWV';Yfut&,A{.I4|CǬcJ)o\8pi1V<%㐼-$po$< o5"}hZph 4 .lfkTNy=TDm C|r=]+d,yg-?#",.2&}"5 j _%q_A:1 NYC%͈KqELb_W @5*- 89cB$̗gp+Olӟu{2{DqoƬ?T׬g͊ HKU@p!քQSc{4sb8",l.NN4-̈AB5AvG\oɡA( ۿda+ao{A*zbcc83?o]&OH*N6g(]<:)H(LWL7Z!nP|C Dn zzbIdޮ{.u.'ҹ'P[QUx?S&bZ˯ܴǘ3g[VAjcC%M]9>؜Өg xz|a8GO`3Y%w T.l6ޝslLq.ӦDpz2$YQޟ0%`Oq`z ]`!5t uFk"FCTslpbM'5;=2H~%UOd,vU.Rrxs\z!vH_]7"XOvS_a[N]*G%PGIC1$}FBь$=U[+jsb;T]cx# RNE\SoUm).ەp-DS|l<`8U~v*`:pm$<ڡ8tMƑF0mˮZeHmƐ(Vv?V5n1G|Թo5+m8(EX,"]=3Q 2Յg_W%t/i%8Zu*3P9|IN9_Yg+Q8 ؍L⅟zk;H*uKR k=g})'7XhI<|*^MK/%v֏%$=j Ɩ6g`Z"Uy@8M iRs#邿L"OenCd0l<bA ;Q[,n$,\̦X){m+>g"-&2M, Dx= ١iP/cּ[Qf!.e I+!ΰy#b?4Xg$z>yZBoC413Th{q8~j%9m_*_:-ߑQ0?dV&aυJN,CK ʇ;ɂGd swV*J~ͰM@VUܲ#0DG'w:$d0g XOhV\YbnJ,q65Ggg)&i Gzj:&cE1D1%/hH~97']/&fh%p2j ?` r,ipsUPNi _TuݝSVQ] 'KQ%Wܲ.ӓC7D#&a2o5لr@(xS/UE|z.*3ouHm 3h-74Ǘ JBLDn ,"W-P?!{۠%TT -[1b"AKl؝w5}&N %8[Ҙ}hG"9W1y9-x&yoM2l R^9gz+cf$W]=.<1l+:OCo {PO9h1R 8L2HCX a9:Qt:cgiʚ $->hΎ]'@D`+l輹)‚nV-A1ڙppi{>k ?FaÅ) V$o]e= vrΞ/eї{k~c3mKOckEcW177}g\NDUޅF+.^x/d-SBֆpnJT+:}_$cO\P7Rsgd<{+vOLgC&j+&TEWgg|k8`%uy'+qP.j,QL B*ٝ:#s yfD31Ye4Ҟ5 A>b?*BԖ; bQ:y;¿~~މa/jO?)"D2>8j=[@зƼ)#(XԔ8"@* ^?>Yi><@O^ωݚĉ?#n=ͧ2?Xm:Ͳy_A/%>]H黼+/o>CDrG_/V^N;6d#/oOI_t[z<C<=b*橆݁C27?6xF†fXv\/PRs}Ov*V囿9`pfxe$H=I\WR%fY{0 `F > (aG ^{gO7#o*/b&laKmGnh[osvXNl4̬:~#8d4S>:D`*x>jqu\~eeŸVДȽWzC}L(]@yCB@+|xa<I{YmZ 1DXV#z,fs+Hby:p;D4@B[CjIןEilb|Q={[y!S|#7>WTl8FIm׽(s/8 2oԿ _¾ȏ|Ot#a蝋UF Wig/џH2IgSfZ [L~`P9\ qZv\Q䇂35DiVOQ?!8&ୠic+py:7غkB.!\&5QL&+d1dV(b y<2φ <=TZACM0H5v¸y񁺳q_e1G+^-!SP$VqX[A_-/hYNE5Fn1Me ciP!(OvUbiarNN`A4 qdDHjU'f W9[oABALےdes2:W`xP4̯āf?yO ^Cw'f'1w;eB /{tYES::EBv~d`8Lشo4BʀC|Y ^ =K ɋ ĵZrmK~9rQ;c=y4GFKm^$tOW8eE~&qJe=`%d:B#V(INu6x߁v֥x2Ǐ}6vn4l,\ PkW6!jzR+"Bc8$_'.@㤖=ff,d3K\dٰ\T/0,>@ndpɝz3zHx殿$7j\zv0K.]Hn2|H 6|Ru+ .oIN"G 5>ƝʽVp$5+OWr }tb*ub':U'K&i sˍz4ƤTΡg3G.- ]pl=[8 LBV" WQ51wlF'{{@J<"Y3ٗy@.d@f<m!Y)a繜)|!D3x] 6H#`2̙{0=^d3 Va쀟iYе7L5 Q;_;*u7|\Ք:ѯȖFȻͤxfs< cG-G48j^ ?(ѱ,( TYlJa؟g_e-gM]bbX\gqsf`e.X 3OԺW0&7?%8ʌp ' k>HSJzlnM([mTFtG[^t:\e{y5):V ޯٹ%]* (}u?U[Hi Hs?[4Dչ|cMq9v\1d8o7{p >N69i+__QQ15y3` mrCI6  һT)uvNAV姦^4+; F1k ݐU)l#aE=ndnH1j9_2WFw"f{?0OcӍńxRD {(Åp_uJY :Z`P'wJ"}#Y1i;]i38B*a$>|78q@&l_ dʱ ZFB _Oْzb ;Y߲egpfq&B֒_**$͍վý.u郆l@d0ɝRP-f摼 K!K4ϟe|ATDT2RPeJvB_hjpӁ?}T考F,8f:&-75ӜĺjK6ȹXtȭ2j-whM_W\j` h0ГoiPچ"C;a/,ś{u޳`d^$Tډ2BT0R UMWq5 6 HhSMnݹCh;thLEuFiVLqdPʵHL T}L)Pt便RXX %Įjv8XBŞ g |8?VDS%jMY~FR62t٥p c|:òh nd*^ed[9Nܺ!r>0c>%8}^f2.q5g|V,o𢛦X _AY)",M'rc]<;ل=E<*ӠE; O80\WOҋIGkǪLl[c@Aa*b~puzCO)A՜@;ot.AjM^)`*h/߿|.*Qg*:NL&:`(`< O'u١hL S_OV@J˼" ̫srPAH0.Oc 2z!m|*xQjyvn0@Q 0_ cx)p m;!~68G;k`@9QۣMsHʔ~7l n0BT )دV7FkyzB[]eҝ]f]=wy*r)[afNBL˱ٔRNVT=ߐ+JL]<@f8_K EH96`#K֍6m5ۢVk'V}Sg $%ţ~昺& ` - $O>&sv܂.N_ZBgޖ'b=p.Ro aD+8Hk{# n$ qy^(s'7]{%EygL-HA5UTM@eq#MŒ/E\L}C잠_O>~z:rE"|h +n!PvBrj$V(M yǭ$wǸw)ֵ|+ߵr'\cKU 9$ErC=%E( w7O˽YF1zSzVdQT4>G| ϧH-}{r??+sͶ(+Û>J0I+K"k)co'/M6{XRCBt::a,Zi36wȰj2u<`6G> j5A_تG ԩh [C `4H;W!'$k0r61p,q&1HɻEsVNUo;ĭ*d9qf \[}ʬ=jpJhDU,#Z)jŠ6il+"j5^Cu b62陶el7\ dGz["#7e-m]8Q%喃l&ӆ9u*vuB&$6ie!i_ýes? YT+FR&5)b]4-ybSf^OChT>Mtp8P39~7T=M|G|1V@eTe|sWsCqjVý^7hܙoWa^sа8^N#4E o)Ҵ&kD#Ƙ̄b&5F@z'PG?ՠs3Una_r;B;N]4_U2tʅ9n] 8 7vCm25RapjE8*4jīrKYH%z_!^O_rDw0&P 6K;P,s y(3Y$q ^ "b/ 0Z-H$0$)'*_l2K]<?,E(G%bqUj㔘L^}X{ Rx#\@-g)&ϦV%ЩX|M9ݟ=+v~ҏ(!-ʃ$8<ˮԿ%X*]Z:JL)J`K*EVPӒ 3"621%|VjC^ jv/=dP)f'͍moybJm4 h`Z!ʧSնM=Fu~E HD: ͱ/ngJ)}+eT)N"gB1YTF8qIoThx4aCӶe@.eZX: m4az34˷%̀`cp, _q/>/һ'P>Y6#/ ghD͸ kF벤v)Y|/p|TŰ5` %ӧ[$j*H̍*X,U.=^⫸Zf*i^٭]PmyV~]W؃l6?$?DC F]ѐ+>$9V>o0 t(.[HꭝKFDu՝rE]85=!eo<($pt#[ Ghm:"[l߹pؽODOXi:-uDn塚Dw+kbj*ƜXvKrCv.9iBgbodɌ/[)io( ZwY*X{[$*>!a>С k/'* sMs8Cؿ`' wQmŸԏӑ0L_RUy~ڬ qP$h>Gc(7݉=wX'E +]CHBr L6vkɨ(s56; @Xm WZ45Ga#8VƐ0_v ,u7MWџ~EyU݊0 &^h*&kAD~an NuYM=uŃ խ_ϋו_Gđ/|:Cf8j9HU &UaP5-jli#Q>bQ3^q;UN&6Hs SkLbƭLx@*0 R}oްr'*^&H_jsOxIb0|Pm? ?0##Sh+ld:x$LM8icv$@Gƺ$lPTĬf( =w_23a(|K zhLg4=µMh;^$Sq Á@p0qT߬f7ǰ+SeZ\/I 9`.dqސ"^Iy?jp\mk+;7٭W2rpqQ[BOgm?{SGv|}^`"#w>7L.R'.()8[/62 9z$GaNM{&L7$7c.%1 !!3`7˪esrAÆL@TQ^+ߌcA}[\#z?}=u-f6XxqM p:P-E_ 뫑iRU)D`0*!Y%dT 'C+^t7@7lZK-~$nbN֑'ȸW` k!| kKB9{2(wdg>VhY/Lٟ)sBe+K|m+|O 7ֿ^^U5$ڈ.q"~LPr]%{BmtlFHYK9<}2YrLV!MF7gǘ Υ;bBzP0s5N^#=TC19t9^>ƓH!4[?bIq`БBl4?N 68Bga6f;2!l5hsZaQ "MeE[BtO!jWrngfh L/ <BK.@hEF(s`ٯ) Xj*).U)/5qKpہur"#<#˷ϠJ?>lqvl#4jQ 9q3;nB'hns;gl;c[T=vN"Dd műg Ve;&)g._PpPi{ȝhz +vlk$#%) ˎuv5sgE,3ec!IGNF[AhQ@)iz4VuS H䛸@BaK,C^h9*o';#+/B5xn0#M E0D lS~~NV.HLhǏu<;4MC4ˆMP5voZĐ4ZF5 N‡Z`)$؈FC@i¬r 0Z&ZM<@OJafeS`´ i;gG+tS-\_L!ɆtV|UXûQЍ$?J,.˿l0Ӫ56^SssbnV+=`<sѣ_nG:5ߒWp:]ҏu\o ,7N!y9ti]P"sXKN[h F'xt:_u@1hg EzJPxUS#"l'= |ʂjl yc5Zf$ը;Iz5>$x3[_=JhXuvPwș[--7)-o')ʁH ۼ^ LL4Bȯ]M"HŹ TOX`qȲ>ӱAUGOCiMKO K%bc>kJ%fvO:%(KcV3Bm8#ЖlX;:R? +v.L}*Zrl }+[x J1>˪-YCьT׸|os-EaʥYdEH4 Bk6%Xdܵ[J׬k [k4ƥO*.Ak|>ɵ *LWW>=nYEc9#b3@n[5F\^oaY.^Qc%ٻVdq6ThU`u@u%(&EW64}2I4~_L{wRҞyJ}+} j4eP!|5ԒHqw}Y@**a'rs[ϯ}[ѐgdI90(beg{ǡfGDwrG幏g$@nN&.AE&b]7q1FOΊ7II8xq ?J,"gmke؄NO y)ux mPW(Z튶MƦ^T@Ry,f{hHp BA֋ASF\nFV-PޤMp!jm66^S%dT/tyE| FKK=pWfXH?3 )B*QC*_QI:o }a.pW"(i$kf7O>ri?ВY/$ZKPxtuA1÷BAC#Mĺ)ݫoڴtIF@Ԉ}\4%u~gU-4ķ.=kn29 \>uxZaksņ ~R CxB~&r sSK5PU7 v-nHrbߴ3~t%Mֳx͋k-|LW+FR.@d]Bh )yc=~ջ*ڽ 1\b{Ūޔh鬪꟬N2PF!1WȨe\]7hk0H3 - LD=&&Y/cvJk'hØD ȪqD]2%4s e1sYߤ_1C9ˈ EºgaRVJыǪVaT> 5=N)<}?Fң7ͦ+#tKŠ_o] ϫDGGnfP;Dl*kf:LvWYeN`QaM6LSA&\ ZWhn*XUuN@^ G8`}g<@Uq`D{-4t#Nԍ]Â">C?HwF)t(k/Nk<ЈsL2G~KgNXAH[אґ"lXGx6Olq?`8:=g lW¢7;͓vPI9ʘɤסX= A=(ܵuC$[bQ.Ԑ"4m:z7$|Ngqye7>}0LCPG"nD tf%ʇ rS ~0 Ȅ:4joԏ1* F43R/jx2S'ҽljQTyyO >PrMg"NTP!i XGYݲpe\KS锑rlmK xh_T?(i.,pʹc>`mD|& Cm+i }yV)؈h٫8Ҕ(X,f]H}3ڎcHFm@=TW]3ZC^^5!"Y:3G~G( ߗN0 dD#HT n9VǨ\NB W^:oˀވHQ2}^bkTHG`*M*jhH Kӱ/6?:L%i6!#-I*O3N0b sP'/X)؆iX̼*dR'!f<-Dpoʻ16N;عw!7vNom*@ZGxdx uNیo]*ҹ0Y5ֆ3;'^J$YY.pjYWRz2^n3q:5$HKx!]F<\!t_Fs}F^}wv z['"Wv^N"P܋B Mnk Ӧpr9ѪD XⲲJߐh^u>4nl{Up3'i[@I)CnIHyt&)Gjef

6\ё%)j eZ rͽN\^\y.bF 0:W*]ϼǶHߋZ͠syPț$k[N>K&IqArUu8ohgq8Zgh5Qg-'}[kxn0#̟O\;q9*r\P%s:$E!D@DPI<o wϏ\1' ).q[Z)Y2U {x{u<."Tt9!Bz"H,\6Μ*A)7o?P$h S՟0zJcҫ/kσ"7xY$>k*!:h6]V'Hd4=Ua ozf. `>mBѭF|IRxA(DNI$ _ xVd>x[~Ma4ΐ1Mnh蕏DtI kuQ4%6>b.ѵdaQe[BԄG6Z+{CA KQ!#*"k}2">VόT_I񨾢TNըPĂ.*RhX.^Y-jGيگ=|pVٓfLBYB?g`E$J籜d+R?,E. ˴Z D0ЎT/E)_"u"nB+zXG0𾡬DٙbL%>96SƳF;KY{ϪvP =4x†==c=^&K $7Qf{/ū24߽<]K ! ,B:U -z+Ϫ=z T ob}f%gIIgG5Dy[C&ord#ܤÝ0>tǧF]_ηr}9TγŤ?Z!ݙ@Ktz}8MLoۊ:h9">Hup@xP!L΍3^W쿺]tJ)E'9eoq?Y|%`C4.xIg["%Jb5;(R<]a^ Alyl2ueRd7Qkyq@#qfT-6Z>C30Ш =u̡${tɽ9c& ѻBbs"6EtΈR" puA剤ʭxMO !0> -Vk-Yh @D.d.i:J p#nhҺZ<ߍk< kl)wX0C#>>ҝf!>uKpvѥsRC7@S1u ϬF1ٴg ϗw-BxheXtl"(8B ϋy?Vpij{5z̸9Qu$'PMa|).vlͿix0kZ𭥰,Hnaj8jLE ۯ&d{Ċ |&{D?W̍Cf0b6S3Uu9Z8a=3q"A\<+#hڰY/7xuEv ;l?)IWh[l ~ˇ4U۹/֤V@!ZTd) h[L>h-du 9քJ`U`uT ۱oU' =hXKЛmp(ʩkz=$HT::ɺx߰aա|Udk$gH51ix7zlO1}n7 ,@k=B%b>jPr؈mߑr\ϐ-^[wYBa-{ʎXH"/"4|EPmI)C95yE~nNчjdyV#]J-_[:B #77E-m6ʔ>8;~nݘ@EC{e`7+\)ns:gE5,].̝A0E-MGÏl< YS=gT:C{"j|Ww1hˢc0]uf#>M-XJٖx5ݸB鐊%)YY0lnsp`g`Rŧ_p^ƚxߗ)yjnn85/$yN@C)촴+Vi!ͬ+s0h wHw `9ͮWە9"g{YwAϧq òc{ ּp Ն`:/; #&7F*b!WOG㫮'"+rQAgjZ!"mF1Fl~[42 2)k-|Ωo sNt"fA|5@G(Y<)2(9I&_B* ,غ'6Gsnlܢ-=u:^҇B еhA?V\W=|W:Ǟ뜷Zl8;NW_ D/YF2CC}v9g OS6%pTH9mRĿ?Wر1: +Tyq{s-&N%G/vERyF2U)F`+y",#efHV&ގ:w$}b{R-Ĥ.!;l5+|! :yN=,%k=bОSت@4$Eܤ1_ q"#y@v% }||mPROW93o$=PdJ]3/|ןnY{#A%QIv!Rq/z{/l,ʊG.ް} 8x ?4 w{ @s6Nׂ PsfI@>-VDoMd}c/(|xDzsimt>ʊR|RMݖ3 a76'L!Ak JyGySiz?LSe7 |msi\MGVw LLqQ=5}OuX; |"9YVߑ#M;oEyV*Ϲc[ u +(G!΀=_"%LGK^%|ljGq?ƇixH aJ:WFF$|1;Vkge*.|f$*Vh.-o^gS,[.#d+ sSůZί,:[ F$#oVV{X{#v#gu©к[6qoUnWyfKs\ZE\3t-STƅw@\B@ou?WtkkXT^"~!Kf`[&Kj5Z*q<6նlL7u(HQ@v+iZY.Xx]~#p'YOV]trĩ rP&i>R=%׵zg/|4SiB|0D8ܕUEyҹ?e/{/2eqY`jxޟǻN}N?tdҗw*` ɋxp_ns@%d o<}Gp?;bbo8_MM \;-IՈ_o!ds@\Q*=H͸"u5{yLٸțS3Jp#ytSBk_җ S֤42dzbtlo7ď<.YԤ'l,,z)Z0cĝ;Ц~d]lkyk'ƪ~:eq.К7x"h aFg9QtJ AF?Iӱ0O1жpR{r ?2xO )̑e~}|Yijٝ}0 p,0HuNyF_an 2\ @eʁ8:)M0o ̞&U!d ygsR#wya@dVDb1Z`7J}&rG)6zc>-bN::XgD.B;x +%"[:=-{ZܕN 3;f1"Ii]n2zM^_H4FU}^Mt&,(+mʃmuF9K7BJ\Qh &թi-`0t\i@a7vxpgn4߄& G{ц3D%m2(1e9gᱦ$Ig #(c;N΢C{5U^5f8j x_ʒTWb T2ciؑ4!Zw?1Kh6ux}Y ꇾp2׽ ``Y =z b(}FL(hG9=1RX׳{Jv'0+  /yuPb^ !ڧ2ׂY]H:g ~\tF 8\\.dSy.V-Pr{!=EhK^ :0g&a S!y"WvH$*^|SkC( a* qmg9꽓praqKk>{AnC#)0L6蘍6!)^LJ #(<4'i]Ŝ,k'} 7w"zyjoD I̘eMl:qbs3oì h.W Y~.&"epOymrwM08w%lbԳHE)&ױ$z\0 nedklBِ$rzCRآ/}l[z͝"2*ШjÈ:!QĪ)~x(8֖ljq6euI7IfZ4W^ sGH [t럍^w07iqq7Zp$[5;ulŽ C;ߏn 1_+>WAδ,KEG)!.`>2Lj(+Y:@ .[V>bϠV;N% ok2:qy+,ܑ)J[,]x+KyL5x & y%X"h.Ibt^G~8icp_Ll¾gNUDyhmgЅse$vR]ؕbӿ3&׌Slˏ@$ƈ RoQ2_ KWN2X` .Sc]_O ZI)VuX{Bש@Bx= J^Pzuʂ䩅K-O+; ʇN^|)*'!5AǦd!U ?OA&Q^vnh?CA5fp8_];Cn#7f`xŢ)ˍ\LG!ξF.l]YgsEҷ$]U'?e,{a;ippʉբ#!zF 52I|[<|-I̤tt0wHmV8 IStj#l'1i2֏|;ћ ?J%M:ѤĘB `fT Zk}!МhmjeZw0!E]86ȉ Ӊ..OLr )=Q#A]셜v 88~aEXFᲒrUBcJEO7<7ˎx>*cdJQa(MzOZ!NoЂQL݃鎕=~bg-ɀ xvϭ0m`F}&+@׻zb08H3V"JS\{%;*D>`8@J~v;;J>f3/zz_:˪j"]E|RMIڷSS~:d|_x`x}oQ/ROhDEn&oOoAkK{G򇰹=2@,+@R0Cb9d!4X:Z^0lʼ^\ꈺl -wޜ60+4l@Ҩ;s\ Kb$Ff \=1R 6);Փ/j"ףڈ%2|:}N,E$I`7Mp+8S6ۅe}=G'OIi\,`DA n4%{e!JSv޵iPTHzL! ؾ+(؇8uxQ`y#"ޱy:zdG+7}O-k |I!-ziM{f OJt X᥿68K\~]Z_?U!Īqiuc@]iyUbϣYKŘL똬R2}([TEP1j29Z+B?{~>F;%?HQ e\`6C<2#vVߘcLfT,-z\#CiEԣ,yM~tsoEFZ*xv92U{=1g\8 x7K.&Tȟ.fNŮ RD+Ƚ{tZsNː7dYo!?9'9Z7@GeN:oި;#G—DwI+՛{<"OzIgjKCJqek-mC~InFƾ\qt˃#rV&8ɘ=NצF}d4嗢o=2?[ed eN3T;"&l-Nafj'Ԅk&[yE?:nD LC=<.6w+\F5s/>~I6Γ"0e<ҳ2H%;rtg&RF~snAGf!oo9NelSGȫ3BmbkLY&qPwڊ*]j۫vOX㌔Lg9i_H#Ȼ3[$В=^Ad6)q,VBi4A ^Z9^iUQG?y|Oh2Nz6u`D?[beYBk-\\>=B߈hQOpwxgoʗ5-W ^,DM5Tx܁&4~"Wz'J@!yE^ㄯ vDdكKa4vJx j|axkbP;Ƿ}kw7Pt΀߃HXZw+@)\.ƭ_`WyN1BnنHnO~Aڄ!r+O2!Ͻm+ -BH_Uu~ii$Qgx;Xv| vB75;nS 2ѶWg'\&<'pM7Lq ,ɉEÂT#3*AV3Ug"qy ޠ*DC]*Ѕ$Ҁ֪E Rb}]7Q>KiV ;rL17+ NbzQ7OCa<\*=&7Mo){s=xV2+My~v}&hL.@Q6TɆ5Z4D*QgjOVeYZɠ(7KpJRߠ+. E-N 溪/ʐ*P9)X)O>)#$MûT `MW3l F{{5A˽zbSa[i,ärgBIhYM'R4ԓl%]߳*fY "Q1DzNk>П,'G_Ȇd,5@֢: ?ФS ٰeJ; w(e]^H!`'hR-զ_#}S7`!WƄjG^j#4}ylY7Z2 v>7y u "ބݠ߁H37EFwS3DȥZM>0[*9h=4y;GzsD{PS΅mn}e@iy#s&6|ʏJe) TpMG%wf=<͙: }BSj<ׂf<@uQz#g-KX"SV ?;}Rta'f%2OpHSi\)=%7#nuLk)4iP')0y4WYrt>'.ÌZ}~PZ-!$=T\K'{c*sGnxM{/N :%HWǶ 0Fs#p؇U7!?~w`ħ )ڸ 륶U`A51-RQB~X'᪢$ ϊA B̡0)N rE0Nˆ}YODNb$:Ʉ%LQ f yvDݣ+@#K:BsS;s<T:ʳ ?~_nUk6BO+"|Q}t>i&^-[*x -yV"Wc>ea0rO&qzIgY)bR, ;ݕWjhf=61aYMpC>zw!QqJa h, ˈQc`w"|a +ǫS1Slr'S]qD 面HZ!*H2!  i{ ܶ:]!U?;h?}^1ˡd$n~3lZw׽55Kv(V3!AzIg3ȇw1/ѓ̌Vk+(tEX}Ӽ:NzO%G.ȡ$k"k[z +j}?_ΕIV@E׃F7xT@ޮ~S_X$Od=a˺9$Fqv >=G4Ptrh21w)=ݯ173jr@j1F+~D+ Vg' ٓC뱘SZg,_U 1(&$N/Nno <{H? &nwm)1sT2kȵ08(1X@dWo-\SaR$0l6xcYVk:R8qYi9d{,4hjbVB,/ŘBQs'k{É["%ޥ/=KW}E=[_J[8`:_mYyN< ٷ79M96 zi#ŗK6=|"[E.:jQ@6FY<9G̾lt +IN]_ol:eiEЗ*XͣmZy;8G&>f9OHs횰!5)_ !l<=-0tvwTevQ,`?mA y0\Y"`I5_?ȭ.n({%H7*JǙ{*jO-x Szosgqd̔W.ћY->2ivYNvI0AА$@~XGI?.&iEc?7@B6摻C(dC[.rQ A7P?u8_L͂=3,噏RVkC8RS]C#{d=1$<{f*`6=ᭃF=^WCÜd,Mw"EeǏЮ [XQ#%of|vDcg}p?,*ߙ7cCU"ښ@^='.xRZu aZcmG 7"v-S<I_#ڻT.-Q)<Ü'Q9tNpX_i pV!t*/eڪ?wB~( yuk2aj50Oh8@nS s@4jz1@ZmV<05 [H0S :{,v7noLu0=}3=wN&Z_> Cf> 9VSֽSvv}muj\;NLY+Z킏O)q'oXWf-Osv k%Qrҩ$*ҷDNO H]hN@+ODHh!Ƅ 4@3 )WX"Sԝhr|2KmwMY#U u*~b\n:2$%d^#8 Nppk `D=U9oD\8}?9:;Ӷ~8}ԏ'E{ѐx*509T]F+ iHVT$?#cklޯ{仁(1& %ThJ.bJ !XT_K[ V[vK&0!ay< @GS"HAj˵g$^cy:>}Kh I_TfMB -E l]ַuM$[AKȑL}o9wx%`:Ώ2/Ch[N]fE@B Ir~~YL{1\Ufky0SYm$e{#| v.;t0m-bMNg[oUC"kֵJaH`Y,!iot}+FB5\?r e(ٺy;;b9%oΛFkd͹Thw?iƚS #_٫Q>>lA4xg3 Wibe7չH#e&:NX( ;/d8()uɨQ+]bFp$ p~ I"۬Xq a0Ҡ{zl*".+Zig osHc莤gyJesc$uF [<惺 !yR{]tydn ז+:|s{#q)ʐSZ&8N/Ԑq4ӭ](qu@N "УN ڕ,K7#3$"V3oʨ(X'F MzԮ v>_0n @I=s7 mpy+`dN2k+UQ&gU-U8̙i֞nG[:4|3Mѥaƅ7FPMj!Vef dW VZ;J }hDvGgC$R'w&`O3N/ Q% 3Vl9J gS*'@Jؔ͐DT9`=}q/ѿM1uZלoU9GRJ , tƔP!YpˌJ{$8faŠ,I:5JCܜi|NFPJ:ą?REJ, ZH?1Xt䃏dW&owmJh3Px=]9F=@X E4;uޮ+}PuI\ǎ=4#]oAMc Jb{At,-C~J{4I^ _R=MHqd']^SE wqb-66 25+3d PrÌk/f]AE 1e\Qk/INRbnjIn$KӰ/伫Ž)< zi_ȄXFL 9$FׂW6}-:x+9[*9N=$:6?1= ;@_irk4􊀍4 Sp=P:z &ﲐv 9!r};G.{b948az77 mP-;o&R"7̫..33tMV`\h%7%-Qܫ𶲵9oVhki倄^S`|c g41⽉Ke|SN͔A,Е4\gL][h[OL1V"{s-XXqVgJQJ>whpغ#Vpt PJQ# ؂+0BXܛF`dDLaj`#:Bjk50);<ۮmܒ^l#kCNu5D v#/Fz;b9-c-\ƊD jeINaZkE~ K>e輐(.O:W 'VUL~ǥ1*ׁ| ܘZ?("( Sנp@ Zx?~C/:Hh#k.}+#{A߸Uo˧z!I]=W^@l؞%:.0Vx$!Dhr甋:}lv(@y&?C\:d43XKPn [(z`Ba_ӷSM*{t=M_bF$9qv9x96XMuZ-s_eou'GA&(Z!ʜԈIA_nWVbѐ冩+% j&?pKGK|zjOK)q’#:v9g1 zqz<\QSq, }H=⨭*MBa>f s%;me~ 0:+*\;eJ[ꜢCesypČ:`g?VDo7󗕀ſo*@3Bb^=q"31SPRPq&@T&> (8[NX 1 @E7s)TE+fՖ5;s-M(>jMΊo2X †lmTьIr) LmVehsG*{= pUPp/j\];=5av*}Lj Cv;6@sAT#zLWe>~|TGHpB/ g`8#&+s\Ez:vnPң֬]y9Nɰp#S} f$ض5ga ԁ$J';dSŋN~1L.(5#]i M+ZP\v; L”H>Fsn<K=YcRAZ}HNͪU ӅdakhExT.K}rpzTjx z dE lT IWsl~Z(䅔Gu>=)NjXeOB)Lа;?lf&'F$9Jى6!;UZRB:5=EA`:wrA.rj)PWxtԘik Wv5 :hؠ``kGBVd[3D|UH"qd,u1:}P77<u2&咡8S:LUSGе, u$#dt=޵/xU7CjTu R3Kk^a ܾ؋gpLNȚ2u*'1X,Y_\|4c#PJKb'\&6 qhOoŅb۪ ! $6u]MiE~y7'btvu;.i7Nlg v1S\@CZސoGoWJ[qW8F Eb0FCjzԹ7I/gx2 %t?[_f1L:~o[~JMIp!P9蠷T="vY݀p>z^vྋ@ `V > XrVN $]"5.̉N H? c9]$Gx2TV:nLr6Ɗ"L#/O*0-Y*@1MIT.a)O:vKmgN4gV\e.^KGMp\BS<;0ᥱ @WuV-ڍr 澵du(暦#ZT{U&+Mo@£G^n`l"^WF)Q`Mɧ6{X,7 p5zv< nE`F#X+Mf67JVw߼p\L(ݴ}4ttL)3C{YjpI +y+ẸRCMi@ܡ|=V$ לbrBh +FE}y 6+tDͿL}wIVI=դC$&}Хϴj3(<,4$s:rR >c_¯27Fm2qC8QkIT^9ffp`+P@:k 42X;{ǡCs6\L !],6^]5㇡D%{GG*j1dlOqH$gJN8I(PMuE#Dm61ԖJ`;K!SgfD?/ZJ,q[ZwpΞkJ#eLk+8~jJU`un|l+ 9]ѻl,_좏]!PB*d^fh:#6D0+^-'DӀ;*}ҩIC8wm8niQû]`69|)ż{o:<ګ[]nRvjS 8׬"Ѽ=#Tj|riȑR0zz7ȽOs Glx?In Ok71( 7`LЌqzF̜8vjd}r~6> W [?g ]ho|HKE 8{" 쵋 4q9f(p'H*d2DW[k$?DL;)0C8#6nV&GٞlQI Wl>qŖjlvb80iKNJ_vo$i"r%C+Ks;ZV'{zx$Ra)`LW1G+$+{-ѬphJ@Ʋ={/N?|n%'?N#Q]#BKY1ƺmL9bAd0+/M(}*#v5R1?jʼrn{zyTb#Ig F'jnM~4 C2{,KN]#&,s:-@ė#t!mDy rEWNq 7hqn׋7 ɺatidF >ZT]ԸO؋jbJȺ||; (m}& U~uR}.SRҽmz68 {ml4;p4Zs yT]I "n\to?t?{)5Ŷ.RFg.;0pe썯nL%aSC#f>$DS['K*A1C{댡wz5h]co,K)u4›%l+cV5hM~am`}0unsf؁բmKZ\9>:J(OLO*2qٖMfљ+x筮Х.A{HT%23N7JÁ*?,p:0Hdk CT0NPG݇@/S9_,mۈ^=o>[_* "Ka}f Ϲ]S.4Q+>ʄ5u,(7~bC@?Γ5z* Y_1̟oG=V G7m@H/6z9XDUDLpMT2G ~z4 s2ƀ~9zjZ #;q4,GڶdQ: HV|`Pr&A8h \'cΗdܭ@HֿB a4T^RI$ޡݣUQ-nW/ri5n$sq"\YZ3$u^0w5 A3qZ%"v-Gx_/i]YbW?{AL꧚3mB? \rod&By}Mk =jK 1EP3&ӏgp‡h[A;"f5B@V֏P;tcתk67xQ{a<1 6:CtQ 7jM|i?顣\`sa7[ yh'ÛZ`pG&ߔ!Vk3 v 4rx-16.!sfM;3,=P^+N1j,1YZ}ry߉ Q9yL#Ҳ9-=0Qc8hGqӐḿp ) t> 2Xؼpc}dak&Z#y^ūؒM Y j_TuʄteFw7F͆?юMjk„%6q߰Rr޶K.i8 m[ NUfQ9F{x~-/jbsx'A`aҪP,+{%H-FvGHLrE횊0uxOw.3o/ mUUkĘOj!(3$vω^Ƅ8Ʈئ&*4\¯v?G- BZv-ʵZnJMnhoM3~[W/$!r ]xkEz:,٣2BB ˣ1펬ǸOʅ.!'Igsxc^oO6Vѥ05 *ak65+!*mÚ( hJ O8Bfl`k_} yf-d{|nYp>dJ$ߏwE@Z{Q !uh!򛯃d1l`, {׮ԟ|b-l9μYe.A` ~8MwCFRXFUmG4U0`|?D.ZSc{Bkv} *JI#4Pw[eB0cA>;> ;}FP9Lϒ3. ]&)֏ !UفWkr -MnBI3ME^t]uR=F&]I8?GgdK/(Ec냶]s Ocسzt4⅚t+Fh)_ݴ&\Q6DO0o桝$G|!X^R}jiYQf$>gkܾ`srpB4Ԍ;Ua%׵X>$j䇊fX3Ս52cSl;{k'8n':FL.3ENL3=K4gyg.`tP[9:K]"RhefTzy!@i[f+Eroz'CVffx­v7X w!_v4-YF֌d=dtV\8TjVו[b cU9CX/rﶲﶮO0۵_bqQ>~-~ w_H6m>Y bF:ɱ׏kb@Et2V[.Tߩ OEǻ-VMWk#.@}\$+lXԴ{l v[)>j^P';øO }!PiY@,7GI( 8m+\[m-'m7jXJ!N%^]u)MԸ_A#RhXR,j`%|^ l}:K$'s>{$أ}Fa)s7Mu*혌_S9m6.άv~ 'rU6Uz߼wl9‚>a. x4]oL =~Dmdqnq`R2de zNYjͥ-*Ft.QAܥo|:a.J vxED?pmWkW5ȄN#E[8VCٶb1.ۤAB\*APi/Y9K/w/,1a0zϬ=oԉzkg[X#ApN =QQ6xFwu=iՐyle^A0'>c(8iYYVS:xqXl})"OoT0v탕MZN p ~Dcܐ6Tc@o g6\dD-Qƒ`RELpo+pejcG]+m"qmQwbAgZ)&Φ c^NǾ$WxK " GN,8 k2=0N $-!xs8 SV};{'WX]ɬ/@ׇmJ6@Z)_ ɐܵU&7J0enm/."F,A/ڎILY+'&I·"WXiRA/-:Fv85}B iVAO scJGڮut0\ڢjipU(1a#Q]Z}Qv櫡]K3C<= Lj:lRkHS_82[`O.TZ1Xd4lh%8fJvP,nHk͡OhMjq3UHBt.]k!޲k[ƵԊSf˓}{W@% s]YYAwx Ia:k2f>jF,`gXo #쥙Yѭ$ƶ'lnW5_Onm)t1d|KV;,ѯfWG2_IEMP{.ȏ7qu;D(ԍ]Rs DҬ2Ft\V,Pj,=6\β9 "1k &X8 I7R*S|!YyU(7Z,v(MmA.*Huuku 9.9.9isCĿNohu<$٤Hgnm] ) :xpGSCjRNϻWBy~xq~-U /~jEh@*wNjK$8 goo?p]+z\-F"1!undZxx͎`D$A֥O8: Y+%OMO9oܣu}th7k 72xŐ8=ɑ<{F;ݿ=8ꕯ{@.ɾVaaYN35)]pIe!4#ﴲd6ޥhkp8-1iPU:.u  ºТ`C&[k8>C DtH1( Th3]>qHk?&^pPftgPLzK#zXjDrJȾ/Q a~WŸmS}gHT4ZY!:Ȗ'9J*aꏹǠ%T,ޚ|5u6ʃY,WB/֕a_4c䏍5p4ګV~AYCvLxcɵ!S`\%j -iN߅,iGs&.,,;Om0OعA~s, =Q=o.+K5ЌvRԫ$QbeTH!7F^O9"6Y*ȤLa Pd ͂F+FF6Fm2'؊\(<&ϼ P,y"~AU؋ ,6W$]Q+.TЂV| "W .cqqy7̨Z\a ?j~\S7\~j6F@ L;u\x_9S6ߺAXÔ9OW!n[D!~iEScM|.z@[`MJᕤ:NBH.#<-J7 OsS aOϾ֖5{@ɓ6sp2>~,:X+͟?̗ <:({!x&8QF.HE8ȼ ?̩븙$)wr[{O'nRɓ CE Bw}n%dg[mk24bI m f ׬Fz^@dIkIc/y>Lقj"VOO5丌WzP6wt2TXY~!pXn7a]5Ȣi [GoyE[] QqܒL 6h3-c6|Uy{-{m =rn&q`pk!پJ d}ũX'ƟEUQ[+=L\lBHBۘRI}/mލk"hRQeER9NQuE㏌PJGc86z ?{- F3_E 0xVV>?Ȇ~>C#rX1M%baǟn +U6 1$pC!j~Ewݮ3'^䳔Gc3ʦ {!8ɏSneH;XH㬙)>HYx(\Z$ SAWl;og cAJr=o"4TC?̸~& `a٫f<ZJ-<MP xbXOk% 2ɕUT܌I Sd?2txlrGkXH;$R@M9ɦM|4i<+_~: 5,G@U!؂ӣ&լEs9Y+Z8z@d&: 1\d(*tnDD~Cgz2\WP+ʂX͂09.^SgFYy7UsxztN7Ra;ik*. >,즖b0 8URA"tNen'C峖IqR&'yWGp[J+h5-=lBّ_Ml_1%`Z>r0Uo76ط}崬 BF0˖cB(i#< C08;aݨ2<a+8f?9$;p3l_.(d &/lY(tHH~پ8kKx0Fەi3#ZY wއ#t*Oނc jR1奷|c8«#B4^%> paIaDTE+yM.<6aV@2,f)5-);mX *=Fݕݩt.]~ kf_ҼojoNwA/z 9qITR+t*hRDy 6B6Ap}^_f.7'uF\+׷U3{ʩ!w6n,'PײI0! *r*jijboIYyǂ׊b ojbt]Tl{e>l//AN_x=?/xTuh6N9FfM< ]l"#T&Ӫ61x2C;2˭B.UP9)^ u;J!O7R2-έs^|G7sI`xT#pGE5c}xz10l]Jkq}[1ґܢ?]A/~9-2PbJ`J){ffFC"iډ.70*/8ZPÖ", mL(L Iêbb -r(Tw0g@7w9syɏFP31C7VHTo:`^6Q z{Qi͘kއފCI%ikY]d-rAfx,Uꈹ-gOґ*h2(!_tI+I׿9} znr{"`4݇e#='7JA~ v a>O#u ,6oK{@.6b cS ˂%]`sVK$:%܄J ߞT=6wz[YY.)56cupa;-O 'em検u'icY0[ܡ@ k>8dR/`ڈDάs1 vgRh ̰c ޓs\ +"j"~O/k 48 7 Mw\+ʛ,(ڀWujGKn$lFu9}iXS}Ff,-( ϧ1(G XEHDZ ],ηjI NaR rv<6P醙A[\FUzkvUDКO]A?ҋ7*vtZ HNV 4ң*K.CtfKyI%wW4iCj5ߺ6IeF󐯋$ O ,[IVh;E2ӏB1vKk3q"A[:QM[Օ\u nݐɲ[J?fOo_$n!Dp07ۆڵ `ڛc!2a%`Wh0'D'兛E~JZh#/Լ=,3 |Ux+7"A8u{uvT?rJMdo3kYiv[5NHIE T]xYܙILGf2o8l֕9n-z94;G95ΜĘPM61jr ң5FTQPH#55^ ^#(.,"̒p57Tji7F-pӋw٢Ҭ3#3+B@$BQ?=[NWzES ?)#bnO>^Jn|4دŠOGh?)`U ]U}H$J)V jfGX"E#ێΟ0ypH[pdDfÂ~AޛIq4P8,k;(ѿ %ڹ  B &@C)-UA2t<#@^Ua!*+$!B:%y5Mj`jD@;TL߸rFR㪤 4lgȯچ̀#;3.}/jU}/?+-EGj󣏂vDt2nJ+1= BF? /S8t[˩crb>Q]~|8oE,_f۩ W_ݐP\U. ]/s}а;6B'dOבqI}+#R*'٨λŬaNN!} t(!vqSPȖiɇJ zs0V/ wtPlg ң~n!&QD$U6-ڴ :ux0(_Zh+%rwi;IGr:_JBBlP*ȇtҧzZTj赅/} ƞWr4W~qj%Frnrai&]sH#q*'Y*W0 /%UT9,t"Ud+MQ ]p2;sj+wɡ1H7s[iRߩi8.Qocbvu!,i}<&+./f֊Xn[ST~xryxnfPg%>Ϙ#RT/ܠ܇]dt78}dc(&br uolm-iȻ-l$D9gCFlt2mdk4ijPRpY&ҌS@mkd[Qm9Gx'!Zˍ2}vF{Sܶ#ax+dl̜./S94ѭ `P7*#'pY'̯xh_B购5' %d06'GZ_= A_ #h((B>!,KB){R4(N,90y|`9@.Oҹ<)ʇ=a*Zjwqղ˕e *Pk%q.[M Cmyq86u U$|qw> 0rj!7mYi0 ?bv0;bg Yb x2fSXv׏cۖ*཰9~*ɰY(UCJr||jogw\CP&Ru5E/_wG:DW|U 3L}+KM˗rpdI.~t_S4 D]{qgʐqd^ yg\p| }&mW ~xz;X!H~OdD Y \ E)|my/s7I2md6g۽DrI/w}y~ʲoņos1xNy*yYBS *`6@{]MU2,Fw':osAfiF 6*2"ڜMԾIbnK^eFNo j3h^u&q$>\>g瑷3LIYYR$ds]z̧MQ♳4O+ܞVm #߶ߖUb-~ e<)9/?~2,ٵnڋ_ AXך #1*pRz8}k:}ڸ B ko'AȐ>! d|58sAwl?%J4ٱM{#Y[i - `LG#׽8C32Vãܬ\DmĎo熶( PȠ^jt@:VnƱGE8e7$#ZfsRHB-l#bW%py"ϟŅGhZ-jf5Hd<@gwIdfF 2aAP3:J@0fk}5Ps| Z9ڇMe:҃`J\SgL &xsXfbu|" RZ",t%1][ӧrU8˺ ~LN?~.CQmמ!YC o &hwuoWXmJKs/^>"/A)vT rCW XWzmDAV<vj CޭN-\PX' kkIIj!2 .f<5!""⾋Tj|ߴ ,3MisyOdNBg8lEO@*I00MflKwf| v8t+/Yy:}]^S M&*)4 O)!]~0 O?@˹ UϡJ*&Ym|tb-2+ F41( `6RÌ6])^c(:!]ܿe9/`P]A56o),Z`Աܢ(K7IK!&J0 ӎu!׉ogK[4ςt )JYgׁĸ”} /TwAv}PeS3d㑼'߱R] O8zwVSg j~q`h)"v9VUHpƾ!oF3: -bXDJXvpX]Zy3G^)Aw@1_W/c5|9]>ޯq 23^ s\w [|zqR-N`l"j=7Qѷk%xy{Bux6NXR%d  ѨƙꦺɵwcԂ87eN6A ]HP%y }QJTM/7&a)Rl_ZQns7;#{U݇q1Yo=sKa,'}V@=,x Q7=Ʊ|N.'MTMlYǔFߔ-ڕ, # ȹ~d&tb_ l:58Lv(_R1ؓ2}X Z8+b!&`z#fu#Ŕ7 ! &V=6Pիz徝uEAi6e~!t ՜ AǶ}B|Ac 2r^p#x6r EWlJ}R[ QI=rLetbrQ->jw\֢,X]*0R^[CS 4 ~lX:Hn!.^RЍh OL.Υ ދ3KfUjS7FbγXx93-& =W!Ġ3e[B8wvEg`j` b asuP&IZgsD`/oQѠu:Kع$L@DΪ_^S(Xo9NvNmUk,8B9 ) "rWyA ]AbsN)Ƈ2ZTYER&$5x~&9̀;=pDua!CEl`KB #;:M_4zث6fŒ0jlYb2(qwV_(LqN=Vt)L,rN O7} N˚I|!r@J""|G*Uc,T (֋޷Tt6F%p "8?1+&n(o4I0 WOR ⊾w2ۇc+AȴʋKF,pmW!>m f3;LI9e6܃C>tVK<ݾIhwNNܫ Txxyx<@f~A%_: :gnu2 cftT0d-. t7$L 6'ʼD"j%_s_v&O_#OCLg^L7+HuPI{pJ %yripȺOD́ jrڡm mU[+?k'.4ՇM42'ScL"`"HA"tn*4k𺊊 qA@uո+;29ܹh?iS2};JxPM))GX@G`@"G mMZB" s H}. Ǡ?A0J&A_X󑠂i d'5HL"N&hp9:'@pe2NaȽC*ae0XMg 3[BFΏ[* A]=WBW}mLxiyT>Զ/(ŃeKX-҅(Za=sn܏wu9ٽ (AM:D Y$9k=a]]zנ0oX^,ǵ{=jvw$NΛƺ^igs2}?Š/HͲj=; ${h">LU_Ʃ)JKRL%k-dk,/ #ot(*J}vgkj!n1=XU.:r 1U}9V8ȴh3&F{VV4G yzrIQ?)G ǟS*zWxQ܁|[)%6'tN*J:ի |1mHHCBMȡe`up^(B;EQJgP'&M~B&밙27،+ѱ6 bӵoNEܺWLiT <⢟4uʯ@IB7ͺf"6{F SBWmWUAa)-: K*< 6}q ~ R -1y_s*Eox![lʔC'CyqًP$#ol Jir? -itUx9 ( A {E kanGX!wm>gMKc/;pd4؄€"bCM~LJv㹟\ rGJjIBdBDQڥ ^F[3RۮVgcbfdsy0몚Y <=wJ jͣ@Jqqm xCPxa5_ոeÖȣ a>D.:o+fB҉uM]!~@ Tڣ0  -IXGZ0C!W/"Bu͚w N)<+wOMvQC Byh[fչ[Jx4W^?3"@ KʋWff[ǹ_I?YK#Q4W bA^~ #Za7#.ެ=Ų.(g"󕗭cz?L _B ]NK<?,]OoO gV1q~ jf^dXMR;->356- ~%˽=@J ҝߧ],9xPI>i\?c`- (EC4)'`Z0Rۃ{sFK%-蒷?DYjZ,)Kwckڽ,A$pYY$*[fL!g``F)ik'qio_}ۘ䢉 K 鑞QX|ྦྷ%QSw");Ot; pȇzJe3i[<]Kfv6~!jˠDj;rC`07ZbWŖCzFE> ƫro|SQ9I}: XJNĸNjNJ(nzy(*wܚ뫫(/V1(#.KLYY6ȁ:dVuQyk'`71Df̕څ4=YcŽjvdpiܑʅЉbV!rcAVb~6N.eь=XbAkCp}TXMGG9R2`kD+>_ ys0_ρKg= , $l9ňuT਄!E6͜ 6vjAhiH۫9)'끚o؝P̱viubw`~bE`tucGe-n}U/ޱ $l@d>1Bn:K',9llHb̈:B+ |9!7Vγ8 0(_\ˏ*Ū1+xm+> 2B+&Jm8n>4uP*1b} !Vmn <-2aʣ$.~?v^ \+DS wm\l0E^\|9zz`cB|Yo6n+ѧIAVոՄVl]^p>os2F͊ &ɞF{Gx0#) fOU?32ژ^]U}z/X*rَ6SqIuMȡ Y߉vfeգҘ`q  T:!쒍ztbt[_xŢ*U:O} ^!a&@YMO\_eYJDd" zSR}> =&w v<'ǭ<~CFGd"8SKRh8 ChA>}gtpC*WpoU =U ԞXzR^A,p5Xk=7U/@M\|Ғ [/~;hANgSޡ;;iqg -QQ"KF˶+MufF= Ȅg,g7 r1N<;'#(e>G}XQh+h^^i9}̻BQ#k<\Gʻ~p G@LoLld+ǦT"$U^?3pi ־I  */y%#,24ܘ$<5/*X)?I;w`yJHB(]Va~X~y6k-NLE^8^"tѼc<9)NʮĦZ]`t"*hZME|R!*MJ24Mj9fAHPl&mTY>/ .{ >bG|~Yf'R2bIԉ-j^4 ܊&#R*D+4\B0'BW -~XHnDi4$D?GFYNj拚VW:'z?Zف##㝝 /[ Y'.`u|( 5k\yu*RyG)G8(xA*QB[?EEL*xP}>U8/Y~ :{IdN>tu'XB2+_(sv ~ c!= 2auO t? ݃bٟUXmND3e3х G[Y \icK ZMɁ@ʛ-P5X!_c +Wu}sIZՀ;sDs/B62A3@M1uNS0E{W.>E2o*}v)1B]cqlO $~"ޟ7G%'^w27s 5$`F|ת>*[aVPo]5PluU}%"jӟY,is&Up cz_:{k\DDeA/h xgy2IJqs(R5}k5?C%h!"[RGW!])m.CΎ8hVQMy㦇up۰A">\nޗ>vxd4?q %~s:-ǭbN sR%v ֶFlv6`(Mm_ sGx6'qѐ{9Q <nz`x !uo8fcNl9辢nc`ک\nUI\aicRG=Ln (`AI//heAzc@͕qSWq d*8|,צ'LU? !j'ّ o_A_8Tߙ1̄/q7o3vT {Kxn"ܕpDUΚ4u`}Cxp!i~Cz=-W^γ.aCQ` jC*$`x$5҄ |:?eP73-5<9H },q>rY wHBPD!o)d&@\ُ""#y핷7E rQ׎ 2`o!b0),XsE剹ᐢ<)F^^9R7?;a#߮y>CQ2{dC9@ph?jI$q"&С5xJe˗^SěuլC-+MCܔ^߱9V:RvЮXh%\YL}} B*dc۟oSKI:Sz|˰z8(s$W(1eV =-`})T2䖻*RE#vZ4elɴnizS"}流pLH` yOB7>F1ŝIhSTmu{]u+ pZ ~U8|Oŵz% wT*baf7'v. 8u =_p<};/\MUZr=c|RՑ"mmҁ45*H gң*5ӿkoY4IK&f Tq(:=;ReX)L]\ҭ rm':F[ m7zPu^%1c~TjEeܵp+1 $]E3I m.B3jR-J9׋~suX21)c HcVXj윒T:tʑ`N>n Qe*%eW'qݹ%WbVj=J(ŞdM]bfƐ#P~'@Vו y_yw%͂H&wlwCB=F(Nm z r H+/4yjqi+I 4#f4<]y$ cUm`Ԣ~5_a=b*Cpl 13 4dl&g,|ò*c^4tYL;m]!pvs۠,gOvF/9iziAQ))#gD*bIĥG3+^Ck]-Nʔ<0?6GU11$c>6Iqrag /{ &p[)jI_LQ~oML%_Sjq:EDClkƷnʫ|sx'}Ǧ,H*fwnbwjr9KW%'A3e0[]˷R`HgP!MX,x1 9%4.ewBf/]aX<.Kd9B|^4od?:z(:LbY&8gju%kXzYƗ#X/[^&(b;4\Cv{> @x^ KL?$΃3۵]KQ(?! 2;ENc> I O\0|"Mj>nE̛2i"`dX%C :GE%50Zk enYoUީ $?HFb$zxiT5=kBQ iEѦl s`5NA#x׫8tp{@@ ]?Wu1q>هZ@mO{ +zV4єlcM Z|~wP;c^Ԫp66!) ='6L9 Ͼ+N|q_XjoLi~BOMҭ-dNOVyCǭ޾4\e['"n)G9A)Il -J0nbtj+W8c<i/,T{76nuP4Fr|0eR vOܹYMib6!0g.TU(]I"wVc#XbF?wD-='Bnס╕tyD j8X԰Ko8 oCĽuP7C\bo-]:?ztws@/G@z7#m`ӵ٫.A fq6 #Z TonXvf>$ojnr֏rs%hzvꀲ`[ġ M&gGQ^d(11JJ4)8~ j7-g0VQ_+)*}FafJymܗ76ϬNG(C2 AP.T~vwnVf`#ͯ1`lv0My#($$]nR@)EEы桸?Lӕ$ k.)X͈BtW]\j9͋Hm4("Mq: g'vqhՁb]!\}}I'@iukiyZ3 HOC!Oeh%:X"UU|{Qedjk&[>?r9ORWe K^0q4_"K[@ci'3pDqOx/!dφO%co2/ 5D,>)X3*wg~d ɵ;zN$vj sÎ@^Dz`G0J`GCܽл@֠E:W`"5puqns3 ѷVI *ٶU:'~*KU -BRŷw\e[ZظiIU@Ν݋ص?*,@z6}Wb:մOM06AΑ )T0uZu%?w뾨-yOSzjpqwD<qFc6֬n=@Zw*!kZ ξ `~em~٬cukiRZnum~C*mw0ޔ5!CdMo@f 2ӫ=~afW>v&ObecOijXizGX7")HEXO҇-;T]*86OeM֌2X&mPkp,WSB]3߿kg-Yu$9'"61珢q\Wys:W GMÝ9fl\kP68U}ҦɁ&9\{|*?Sw(:+) {*Fơє+O76"i؏`D(o7=+{ xޝOn7=O=Q\l}* 1@BL gFNuv"TRF{Gntp`Mvo|R,mvttѻTӝOYjyUK\k-jJ!v.01M }hZ:UԯDtPٹglsGX[ 0}%yAsڪ}Ol3^d{qnqЗFo!Uiqd;x͊o'i tZ[(lc\ۻEbSa9\jQ؛Hb#tqWx{컱~wddljl??X erQ,,Z'BZC'2w.J: []ߗfH2b:XƏ_u^ӄR}h`plv֩D1L8c@9G+˵-(72  kCp,`8fD(u_$HL&ߨGo? ئ"3Ի3?d@rS إiYb(ӞR|wkWthz%$ 2 '?! L 7V7K[**HB9*'ASƀAE^n#xHh=+O -gG3Y%;[";geh96]I Cv\Ig6Bٽ(XH r+"`}ABI|UFE>Y'[~Itb(ħ_5 E7b#Iߡk,!8ފ_-,BBX~7Οz]"5UAт%h0u DuvR$;3+Pff~qNi UN{W9{kZ(~i0<& 1 G|\3ZØBt-%d4 Ff؜ h͍yK_>|;ؠEH_w/[5̋EiVX,b+4"YAV]&ФuiYdàpMz?=tGZݴ֋ebm׌3:?%[+;ҩQ4XCiKi({}4Tt+Bfʰս-ׅS|RxΎ qϠ ġ'{Ud+5[2 ^BBO-/'Z729g2؞ F[{r~ r-ea~Ʌ\YZA#|p2p.bC194N#ޫW&9;Li'tW Ԇ/d3W)~y_ yjږldHR- I<YC%LCҺlVG!wCND]"?&7J:W8Pc3GjGUg8'{{fDtX+{-6t N~(y7wR$L` aЇ4!Eu<[^cqlfːd/{|\z?J]11h&3?zzm쫽*"Jz f<·ݪu:/j -υXna.Tl ' = ŒФċ'R}"rfolòbب"JP#oI\C]Z\3oCOq4Y]Z׌eȯaU"-ZHiρb; p2U2VЅD,jؑrrJ" &L偑uŤK~A+r.8G_̵B#l啮ː~Mn!{[tCN430bҟ6UCR.?Hnn;$5'́jD(bP|'&FNkf@OLd}2I|7GI ңcB.-+9d>GN̯S"N.DQ:vc9,m6vPnhJK*(c{?؄h7rCY'3S[Au]*VN=s@Swf0A)_w*qpop}3h}y5M,P@F*1g7 TDlމW P%{ͼ^0w"cѨ xW /0~lh$)YAH,Dq5Ht(D{p;ge3? 24N4d5F_"6Hxnrn'N%LaVMYV!?&sA+I bMz7XX Α 1>IW'M:VU0"mL26 N}ljF .A\Ts +3)Ѕ6FqT\.O(CJET*xǺ~6U\)zcdt).f46΁"iM|SW{0'f<5"{?(NP坑 ^,#FA^3?f|# e8z^7K$uXGrL~N|y|f8_W`+cIj"TTECt(fޅҕl'Vqs9N'-H҂NOH JF|uWtϞlj9 B/F#lY8>>Nzo{g6)q.fBzQ\}+ )e^GL[+I%!%ُG&m7؄=$_ aD襫IGMŇiUԜ/B Q(φё8@̒/ ԮwC<(/۠&J:np֥=2W:*yJ왢_*յJA!~<|,d[h,;1S*0{K2 |>RBIrKne~>"AW!\"HIZoc\ ?8 ڂ`wI*W؃7G74̿j bik20n{@=U t(Do;@Ii8awLa*:.\HJ,?Jdh ƿ}s0l&څ 8onQmqr4FQyNuRR?ѳ/b/HTj z&_ 4e5:v܂ ˿{)Riz4M̴/i4~Mlbi=,غT='i>{Bj0\NޯMFWn 5m+S9M2KWieBiG NVuyT!/^5$KS|HET\9GCJH N'^CN;6znN2¡ŤL>4SB<2f`!$ o[ .;X'/ޭ¹7x=upprԇU5@RE,/qQ9fB_r%uu(R"h;/a6HyRv` v'*_Q›{h'/]؁RS_ ,ZR<9;DTqdZ)Xnw:+=]+Xg!mR2Ϭ\Ah.  CҲ鎟 OqXloy8_>-XІһJHҎ\$0 [oAr*zkWȴ+e@+4R3o2fS9C_!)p!9>COBwwGWo\#M d4h=)_715A9W誯 :Nm:Y &7*(0i#%sMrahx1E"W*z`!Og)xء3ƿBFl0 Uэ3_~ʈМrW4S~\p],Ob_9lŅU_N XF[N}WtBtG.xjqu%amE~qTW"nq⃗#s[L E.!J5RP2E"3H'&_gJ`:N%C.MQ)0F߷I.a3j% S6 _?80{N X9VXP8ZB`y{fS.@W=ӿ:҅\[ Ϥ@ReG%}=gU+=Mܔ~ ( HJR I%/w懵Z1\4f0Ll[7{?k1qaSZH)Q%'{T<=n< 쯴 ߘ*=>KDŽfS2|(A%OݭMˌ@(KаG /$8!R:',.Ma_ z۰يLYg2L`%GyS:jӚKuIPco-)]Ѕž#0FP\|40U Qj%&&o׻ fo(eU -TxH˫ 3LjjQwM0Dq7*T~yZtUNJ\QBdX)?JXfb%\BI k4:] *A8o6kM7юZSsl:g]-^8QoYf2? Z";-Mya47ӁLۯl- F Yf\:logFwNo,Aףlc*_#.ff/ ?H(:oQ L#Xp15ĻSΥ')Nm1V\}?gyJ"_/3.H1߿ &`d hL Ipo63{;SFk}6m+U|u(BKmUw^Rk[ #i{8@K`f$p?Ru'rVy«8@sOAFu!6vBXÝ2m&Jiթ&){:EMFe=IɅu3dI/*Ym hƪy*K>Bկ3"?-j<ՉE!2tB=--ij9E,9 i!"4nB)@hGV8P۾,NQ=WEI} ,~$cB-FNdXee!QдFrh,jteǜ5M%%Pfɑ`+;;s@ln%rBq-/wI\`iHfMUh>6U<-4[nj-QLD4G|b.1tY3,#_VnD?Yہ/P oNv 亃?P&%sLKT@عA1uHA)}員&Ԑ\8̫VEY;CPiߞ _E3V,U^mcohKhzs1z؉a4h7yB.9k|z-1R_n$uT<T }lx$y"|x52!k oF]ށ/7;]rAVo-:]orgt' moD#Y7HduMܦh'WhŊyUZdX&k^g2жA3ۏ>6DW%#Ey|Sr<CL t* +T;>t,xi3||D@~-z]%݈]adPjhmUAlY^!ZVnnr&ש C/nACG5 O[# =GVȉ?cmPmUji3q{ĝ0ΝIm[Xl |٠kmxH'Yk/I#f.L}("QU(x&$"{ m 'ս OwE02`ܥIhN1q>$X *. ch#ߋ>uֻoki(社*0Rh/6Q#I̼iΕ>\"S45N,DG|.boai|iYL1#W.Etd,aN7$B ʪʠqao؃2I& Fv9ϲT҉"qzG!q^nYQ{ըݓ ah#-ixdSn"H$)a}p\,Nl(pP4P)*5X46PZGk , I})C@-R[Zo69d J̷Sw)W )֒׶ 0Uv2tr Q4)ґ 妥-s-9 nob_!kte;>AU#V<8SlFu@@kEw,(K@=/!Iun͵ [)H6oj|%%ϤNOJx*΢2$c{\d ('d&T͐K3)N lyt`-3WxDlߵG;=8wiɳvϖ<@SÑqVo*=S4$"G8SjA?5].J\DE^Րp04Rp.ў^17mqaKDxzEfECxʊVXj ϼw+Pᆳ?dŬϹMں]/<[rL?4`<y\_,*=.]Ix-BL dhF0( >8F ʂmyyu g 6交JYCv2 ӮD--JQ.j5IP`[O;C]odÒEս88g^\3ivKCNQ?;n6 U3:=w;b J-A*0AQߢ-hsI]j`x 2p^( D PnkG 8ĝfk ML~$W/4LiQMeΈQ0#D(Ȟ\D<|8}u? =qI \L(ļu[STobnNBnsEUz#%|bM)hz G dz`-8, Hf=mO uTD,hTL㴽;".XeѥO&-TG`1 hg㰛-hmx4^Ki>u]ucD f\v%;Y?>Ot=͟\|w^{;~nUQvtJG*by*F`*32?f"ʦO]hk+'L1EkZ ⮏WkMP#\m`\ Pj!2Mcb kV]hx=B|^x" K)\ MW5=VvFnhG%@&tW!}lkK3k\µљ2%Cs)%=^5s8]D;&)%RdAS$U|pPtgqkۖHNQW-BJ5g}lC|Ώ/BM<{Ƚ`lkGW'#$iQIJ,]BHˍ` 3&ZA!VwD{֧3HX#I u仍I;O鯂WeXkD 9ljDϨ):5<&v(UqF{ JV; A;suEe_1EacPA4!:Vh +&9Rk0Bx<-Y̾[$ƈT&2nqtx˸p6onPT4 @VD%'oB\AeOfzxN/E#p,ҢW%ki~E,f\Pܿ~sށCs,C}cª~p;\KwN W>z"=|D*e‰|*[.m΄4{ 2a,RWY;uj G<Jl+ 3yo$<]^Fҝ,Wekt;n3k2!AOL^H,TM ڒ徇zV5}*L',[zW) H*G &EpeGcH$ oFqF#>Qrp|wz ᯡaT7qba"0(ox=.*E c66Z9pnf;52ĠL,JbȰ_{:ڰw };'nM \!ALð,`Şډ G&aյta L(vnW 0hyIYC@F<}csM+8yc)JRHI и;'CV6.]ۑ#4Q(#GE#F2 VvTvz+vhԛ6|Ub[ْe3A~aA::ճg6Ϛ')2 <|A`&J.چÈ<(nH{`ߩ22^B8\-tޗk(h B" .ڢKB8E;zu?"hmʆ ͋!%;*.Pux-:ι R݊db7m7Z*!3=ήeqd4J޵L ;Nh7uɔȨ_^ZbSh+oZ4}}Y*ٿRl D>#? LN(iPf|~|JZA4PPqus4pU7,A󊫉J (0>: ܯ$mVbrd= m&ZLj imA`VZ w✼/U=#d{3ڽKNؼvxkACS=Y;I~._.Hi`z6.n|EO ,&%F|ǥG5K ytK#yXީGG&%p~/s{w%dNJ7[̌ od%6,"/NbZ&gNk$,ގއ #,Rފ8,TG%j8)XNU4䃅WLsYxE"4I=2TibD2378.8W 6:tjӣϞ=C|/0&9Wyx~Ǻ?1Mݖ&)ΙØt6p:&׌Rt-*#S"_yQ k{>g*ZOu-)V{R.iUV ( xqa?|%NFglwG0Jl\DirWVޖk": MZhรi§dΥ1M"}̭N݈Ң05p0f@>Qvk[SFH r)ǾX,YI_@`4^e_ZO]/h`tО92RLM !.M :a]/!c>dlbpR=O LN#DsEpQFN<`f|ref0E *C28FT3yg9p*F+Yf ^H8·ξcȋg}e Fg>_>J[>9OY޵"- d<(kU;Xb|ID R'f7FǛT^5MvܨϳQn$kpK>*~*yF`A(_)fFۚ"j r`D(xb 8R@gcvD+ِ(+i[cE#"r|~kr^? Y]{ S ˲ E<ԃs([e=l"Vh3!MZГDbvX3 JOڔ%Wd* ")Z[VkaO WEdFP놮qU\DJQr{ެFKdjCvҁzSu$=r~W >4^11_Z?Klo4)Uݨ\l%!&i.4_++1BamxNeى"-tFfkeYR̈́#Ʋ?:(?F9ڒ%KH<.?z`.y0畧{ZF< a5!g ;1٠z.u/Tja{PBk0 =󘁿+_NW 83vE'׎IqtsGo1c "0${|N~ks%켢5ZZLI]S}KCưENg!Fgliyg(v/uv2M7 N;Nu5M`gRjE;:ԌU|sZ"! !-HY42ѳ jکTDl>4f'a<,7z%VK:K[FދBEo_beHs=ee5[ aP8{HV$<bO&fI{rTKJW6P K![b#>HYΣ]Mv R ѱNGFrIŨIP |-g/ps`1INfG<˺'F7ɪ(]eb u+`f n#k : 2:B ]Ye=LTi{y5'aFe_'n}~Pȅe~XyG4 wƃ tՐaq2}1A@4 ?G%Ι8 M7ZoF+>vL!G]!.I8g@X_`]*Q*9'VC5ޣB*/sK1jHHOCUdځZBHo< s1ãAeJJ 齏.IV+}2:ʬnZrD@˚?Mae\(7rI@3QqPybu{]jr4@'>ESQnOW1@B6#ȸf˹A ׉HIt 7N4NV(z%#]]'Ԏ1Q}L v/󻀈N/8WjF>i儹bDo0bhec =qe'ףCJ_hVֳ9[w *;U:Wp0G?S0.R C3U|aH9̰5R_ p0+\#9S9G3QlRn[(å}=fqh3{@x^ ev(e}܍B]]B eXY,N>[^_+j.-:xb I5{=%͋s­uӚ*eʎE̓0'9;dXKjM*QIH[%>)ӛΙl!˽cE$ +41O.mb;v-g7, C„SY7{8grfKUZP~k݊f!~\8)}yp8!G1cvsxA [e:II&p(.J}5(ZJ@=>21>;quqnL-BR%&~}[F 0T! mc2Sdʢ W7z0?G(SNKǭLJN >PY`Dn&Ϥ l=vI1q +2 L8EZ c9pRj$ ? <ϦN[r'e"2PU/|v&zG kw 0Ð )= C*4 PT؄2?(eTr=.V_U s_(4Us1;y%Eg@Yt5b{UeK |E)c/ :<_qKez߄|{ `ƘUVZVkZ,Y0':b`fڣp//*_/}T .) =~ ɲY7Cm^_-8Oedrz$;,qcUU`Iߠ8DITy n@ÑmVX%Ddh݁EʾE:]|`l%ik!gߤ*j|xh+ &+^yRI=Is)6臗4NXs_  Q>sfN&NI2EǤ5Oʋ-炤p4%T!ȟ,!PyQbӾ!ETlaڔ=[в(xvxw{!gsmp@6 E+#T6lJn&\PkLdžEs/"A&vKfwNo }9l v@ ;d4T9Xڈ^ùVLQFf~2ŷ@-h6 !0Ar c_[/, 6 GuPg&j'ufeBw4fxY|x3_.+ []D 4+sd 3Կ^0<Җtu״XAަX\sc]][|O^=`>zGqK3^=bwQSzF~j>$,` Vq I/JyQzgpS ?̏:MQr^Ъ6%"濍 Ti,k(I =qryj|qZ#-kqPWC:q)af1.N}*G1__ ~Jhgޅ겣h/50X]{BSآlȸT6P70|HS!arkdpޜLd m>FL;Pwp,d:P|q< pԊ ^$ٚ{K.+'J?)2nݲxx)17l*Jp1Y| }!`a̷L?7o?Y< N1w\:WIT ϹSw{\[~FcY/ oMsA'&5k]CH#A!MBQYRfpG,!7jHgq ڙTyB-@0^Q&U,~sdNRrc Bbt|v%RWXΕ@c"qXG<0cX"$?G4GluH w4dT+JmrP]ҚGǛBHn<Ԥ:;4֝rͽanyKΰ "3XʞR#_b?BJSp3Ï_LZ&ub@+vOyeus(5C_ KVi1 .Z6 ,U/KWGu!Ґ%IӖE"{*#%`LW)޺oDR<:ꢦ BP+ۇ"b$/ a0lFw˾}ho%1tcrRP=NJ 8 78K-Bm8K`~nt=x߸9Fȫӫ 6jz %f?)'0D*a˖=(X iX/Q{3 R"FMN+%tx8Zyf~rCPut=MJίyѹ/Aojl G%n70KݗG= s iϧBD2[Wpj)g=tK%Y 8ʬL~0#Bz4T/rJA4;ix$'Mu,9iC!m0գyǂn@Յ"A~(ܛAw\ C/(^pf394akCA-!5洁9 nAO΢eU[ct}`5 nnwF.쵂T}x)Qiq[d_"ռZgUϨ%cMpw)ee+u;-;,rB44{aK%Bz[Э}ߢ"E\iԬƄ伤}bCx+H،И&c,@f$V\ƚzhU'jE_}J :7vx@aV#x;w0 'Ay䂭V29dp /4O=Wt)%tʅ!U/hY,1H1BX rY@2-BY.,ha0ذ%etwYbZHGa[(6,cb))wq"30-ͫS&3)K;v>j<ɈI^TsԠ! 4yj&bET0795(h3NYUdJЦ) StzP4PsoNu1k ӴK[J'K=n`TA1k%@rf&E37I:z'ϣUaMW뉛6h O drȺ8$2QO$阰Ӕ^?4G)/BB?Bgq( N3\p^oR)Jx1wr[i׳ s # MU`J*'m jfs9%ǘB  K4s2SDu3Bl;|Y\ |gyG/%&?qp^6ۤnE޸1)$Q<_ݸ3u~`(9ۃkM;Je:x?8(Ŋsv> $xS::?]@oR9ҤKXv=M\ mʑSDƵK:$xcL1exdpjߌгh)lZiC~_FF{4CWn8ZQg,1 izRye%-d@ PofceϋD!ZV /%7G-,Z`L=֣(skɑ6"CD @J_k@''@ZϤo(D-nR?/s h;m%\d>&2eNtQ"Ĉt?mDӣ%s`OJNj+n4vjf K# . 33"H3+Bs-[MEYA Nl]ZDDI֞kF4>B8[`DH*ٗcp.|L(fne 9ㅽ{I/}SF@6MWʟU0aAiW Bˑ A*_XUW 57.Q"yaֺ WB|h8o_l0k {誂Ѭ߼&` !jn[ bza3ߕyF>ĈCE\xLyhx0e'B%:*cb:6V$@ Q[(f*"mA3+c}K,[H]&0O;T%$b8AB )^L{EI@`d3m(ME)TL9WOMi/ӎ(wnK^oB} e 8P<90J9%Z F&fBʗ #Ya^F0:]MY3"z{ԔC _j(7l/y uVb'O[>>rHVw64nm]Lg !:><>ן#ZgOWΑwхiX;ȶ#N dؓ9 3 vf5 d!z|Gdp&S` .{/?+{h r_xG%P;j)5O,>4SVOS3 m1Ⓐ=D]6+8MS ljYs 37q_.Du9y[VPE[頻k~>ۨe9bѫ.4Zlx,T[H…HQf3A9vuLF{#A#̻KNt&P[2fԹhKzV!FBľdyl|6Hz1&c\ol\Hw{ys$ 7F'r-bRG7 MYKQm`. 8@t͞ɐva#'x#!.#k5"DUa{hTIރIr|pئkfcc_[!WjqZd<$Tib&å 8C^4֘ 뮘cէ,f9<Į,yUmcd Γ<ɿ]1u?Ig;d{S6U 1)ϙIG1f% g;@R%r~zRn }A'(Y)p3[&fL {5T~oC"?U.w|Z# **fXI AW w-+=k06\Zz(3J?;5ch_'g(8mA9 SwQ>+ըOP5kzmA`᝼dEmcx #iʗa9&/ WqXy I;\_EpH,iGTokIj kiչQPk]Rk{c-Bkyi ӱhh 5xٝ0){PSQm,3 9L]cÌ]h~~O/2 C[͐OS&X&bvJ*FRw/)l+#^ ̻%\buvedW"ʂ+Db+ Kj-?Ob>xX!耹+ K@z?ͱYͰplAuGΘAE|N7W Iѫ1f}"B+d@.)}n~ MM'mRݲZ:AcUC92p99hi@fiXC0Cʛ>rE|{z/ʹH<+Nl17(9S'wkZ||-p{ +Zq2t&QH9ѥ.̨%74t]Ƕ(ޘ!g[f ܓ&Au}vӃ0F R퓺Vp$03& BN3;J {ILO'DE,{9;y)5W|1S! GMN*=̠3lf _<,cn(ƏsK5 QD+8F/( LI|HˣH"r׽cΑNhľL̄`ZQGaJj)$ԍ0G$u&oQQur)kt.|g\,q7}l. ̶w,4B9گ!Qo]թw +ff!re8=d$C"͉އQ z(dSdY415/|_dF&Yޘo G%΂ou ye\JWW-_;D*u @H?9aIA Iw8ga|r:AP% !;B?\]IvE W%oOSv_oܒX#Ē&@pbOɏ|} J{qT>c$paudir2!jj g~rlehfYfi#c5B7`Vlu>xxa&sGu#c3ZV>^ u9u24D y$Ί.}LQ" J 6q2ISPX 2͏ h/4dk)Ϙ]Jju UuQ1N lK`v7d/Qn+wGe0 @@_VT5T:Oՠ[\ d ˈxu#Aku0&\`Ħ2e"j2&HԢзG()O}5&߼eX؎$M\3O.RjTqׇq 5ƯHYPsn$NmK/ s8Vr M„[{ uŰ+wk[qګ}|t72G:Xpp=^  S+G8D%AknKgb_;nA0%q֊؛ hl<'vq̭ lmc26ч#N@$c&;%]8߃ w;GMTrAK69|Sɒ#- ^Xhff]J>`m"zFHܔ"Z\V6!G8-M{BѹnWa,bS[KvÃ"w41C'KeNvUD5Ǵ0;3B` R{5W.a@!TFc.^fo2DE>bxl_܎J?L췏pI:ϕ(ZW3*k^z0#R&fz 4@t I`RKVyqķVr &mQ% Y4xQ^cbɺS`!}r #?N{kHu6 I.ّm6}2JvR|*Tc=&MǓRD"޳;u)Vce(֍0a0?vt'"y@:ng"%UpPH "~;GNQrr0F8-&@ԾP{όqɯʦ"!4.Ǘ/ae)pӈ1g ͞{!&1b0,e#rͅON5__+aΦ#~Wyz)SSRoUM=Z_Tw,ŧO*/U;bm!lQtbz9l䆣f:330{x^~O`6#cvC|I"EyPmLG ŎK"$> 5K?[rYp "v^b$N; Tw]]>6%5B []bxD/Lal}/v {ޛW+"Qw6+]"d`ؓy|nQZj!!&B%J3P*XFǔ:8U%rw]|Pڑ& ާGV42IR֤nPg|T-b͟ hUy,}wHj"`DQYnˮE%l/vm|I,MfnXQ=TY7}Ͻ | !e@)>9eG=h$渤 v< b,ykfWsE&Ta&d ͚HG'ο YAfVg\-&ttUpN.{mq=}/|( @E ",MmV%L9:P5̷?n=C`$ 6~҉2S/V_s 2e&,%4VЫ̒mE 3utZǝ\`G.wd"!l݊F>s@mfO{7U FNL]Tbe0g٤wS3E;pɝhutVnB Lb, 4:d-#\\$̔ S_kcP}XXt9KK(05Ͳv98pcmUG/N-jAv [$ >L/G؁Y}8INk#9]2 }M+ 2\M;6L%W ɪ(nh,8.86HGc_r fx)_H}m$9SQ1$/43,ow.*KĬY)wIߛu t&)b1+NvEE8.ӑЭ5[-R⨓Nlyp FC׋ADV騂Vl H 5i#a<=+U79==4sE0٣z ~zl*}Mݺ;Jpdk|[E [?*{Vᴛլ$kX;G?P+T+NgFf 4o0"kG2?JUBO(QD[.WOpfNiC32+!Fǩ?+R}Kzw3$,w}QdǗzic.|y[lrOLۣ-ob%i@`+(R9]$g656;{b7|  @- TUVv{%%%mMcȥrRCTB՚חQ} {3Z1&Zo, hQ- .WW,:ì*^p3FT53C4z*Fkszj_e ?ctrZ؀d,Yx»JytTpfo4/-sSP,#Ox 6KLʲ oBTrVQwõ_t Wfh *ij얈t wY&jhji\KIcG&PY:IimZl>9Vf+]&)ʜ$%6ISk50T8.YM7i;%_|"KcRǀbq>|/4z/uKë́;2 q~r,-L6H8sH067 j\e ރ!%vR$I^Z&ğ~Xvkp̽A >4Qr:Q#jORs!(o;U'*vEM՗$ 3I芓䤌OF'FK(/zߡoD[o/sUv7D_%#"SE胘HV0tՔv38;:;Ä2 &Ѯ9jY N Mφ@r3JFbɩsT̉ZɸR0N4]?KlEN:9m- ML-x;+W< s<'rSw։jC5tiUZ (y ׎C"~0CMäONu\pk3鉩*01Xm}9^;o+'<-9' 9ŇV$r?.>I7tv">yj~.ƭ/iC#N8eߩʝNGe;yU)Q9!2N)IiSPgg|:58WX^@S"":/CDÇA.1DZW44QTsîrjeʧOEe Up2t.}0ؙXg޻vSJ$ZՋO)o2n'5gg@:vnUbSi-C|}lNhZ3gC%Jv6n3es_@N"Ji˦PV,ٰZ4$Dn*(nqd~6.ӻ|ZdEnTk 83|=(iCWr)U_e8 .ۂ"B72tF-sExHFq'.)#H<#Ը[L+uTA.rc`P|<O_۳%sz˱&]krSA0)(FX1'e6ћEL.tMv8E>Zh{f(+%r @z(>wsHeGJ#-5m[Wr{ zȃ2>qnD(v %c ԆkqqqI@Pe m p m"] 2t0TſAwgi=QTV:g ١PtL$`*D[dLxR69r 2v6{]K?/T4*hv%j8>8"5d*(+ mpNZ  xeW8Ljmat#ͷYyJq6LJ%[VqUPa]n'z&ȍ\hV>{a-AEՓMپ4jЊ'庥9X̳=HE7W{Q_T 2=fj '+ Bp(<뵣8LdA}#K4縻S)BT>GHYvgW JG|D!TzHFDhsM,JDg w$;tߡ9]Kp~D9J + |enQ4fLFp#SS|ވDb$pgW{CX T` V佹  o-)͖7J L0$ tBdw_ZˌnąLxAƘL'>.~tn椒3jfL0(7E7^["iĸ`++sW 1izJUH>z;eM@!9a:E7/&̆$PʁՎy G:uh*́fBxz~g%!Xe)lIfg7{UPs7\AbTJ[dW/?sI0t3X i_QلV֋R#d#I l(A;'}:f䮜 GT0pwW-qIM.C@GܛɪZZ@ƞ&,fA.>a^Uf<;`Zj63КA&ld)Qr'#Z<^`$D&ID * {!jZ<|u7i8^$h`0U{;SsU1Ɩ n׌p"6,B0Ѻn"20T ei +.ӉEu=l6+p4:j\烉XX7Dʝvo2rs.*6[ !w>oswjZ_.ܴ8`o#7J WLH@ h閦RpO搈a{)>ZĤmi#sp-jNa,El_ QQ V0/, ʥȜcNl^)@szl>)Dd`<%b5ak9A\@8i2;@D=g|ՔrYRMd%PI5 vOIWz?QgႴfk'ʫb2fU 8(sFD֝? B(1b1!cD cxsq0Y4x\ )Xwm2$Y~";$i%=3jWe壝K*P[*PYezBB1p!:(2Mr?CaތQrkɪ佩7}+(C}b%U4A. {-U9Z,+B a[ks _|aי;LZ>v;U Kψe1MYV]QڐUrp 7$wg}j.J];8 A=Aݩbx5lζMCM7Jvmg c?,и1rifTX^AMRU\5DqaM(ؠ bJy^|l rh4_ɻt2FT ||\&ٻo뻄?hv-%1Ū}wQ'13*m$ VWs:CIKָyߔ,^\VZ,iO]@S=;ګaqebm9 l(lę¿;6 7$66FA!H_>9zԒ灹p ֤}V};~iS PXوNJke)tR&;IV J %ޜvdD VL5Y  9W j^fPU*{P -Ь4}}|v`"6/<. RTvjb~(fH*`qC#K\c@&,:rc&HVes&3SSْAt[4QǔM `nn%;5 x!Tdf# !w:$e2m=TK<mi/wbӚ5̹{_=d >a+3,='=C`5O%g!o -"}@*5̬|qDTC>1_ 9! TYoo t~$Ku!۔C_L!sK1Ggw 8ԼW_?ĵ'fe~#99<, Ϧ(JHtT p-'hڵ/ZAh@=q[JO.s7=R=aаA(Nj%uH+ _@:Us+|ؿc~z^xD^&uKޒ 8V}juG1޸$p |(| b]Nx\܊%Z54 +) jJΥ:RwZo`dIB`T*)hQ`QEqл1k1$ETZ .jړ[A Zj!E\=|aK6{NwҐWIf&g`V o!'s}ǡfx_,@~Heu=&\t+iP\3@N|fDH)uZ̿>-5XK`E~xC_N8Hn_bs[_#5]N;w%`I:Q6ec w1iMpMc3;n F ]HLu%hZ{EرM W0Lk#nzsHVGRWb2\dCb@QiB#C -c[Թ9edJRXWb%etRa/a-@HxfkZ'lt߇ߌ{噽0{$i@#=ڎ1h[X&gluJ0.|:ZҖ~z )Mea42{qWC4W|ʹOjV;|g7TtI^zmD@$S\ߦYdYNG)9dp 7=/^n0~\RE)`R43PHr!D2(GM6~2Ac~A F )(Ea@ J̸M15`\۱a5A=)=vh `&?mV#e2@ͩ4tR;_5p |;(Eu"Ё FXL:(3S|DdLv d) IaHC.מ 3zyN)O 58o\i~Oɍ}VS>a vʫdނqL|0{F&HrfMW)eM\+3(%I5"ZTDy7@Ӣ@5VtXDv_R՞vsf"(VJzbd 1.9iupomx!^oYj2 pPl(kR>## i{xUYw,oI*Pkr){An07XiC-!>OjoVXOo"?% @>#ì]ZZ3W@PóCrS}گ]$ִmsD}q*m pZ}[Z#@ ^pT!Pn,TeӮX65^M6`9C룢fkhDèI"* e_-uʾ#ٹ@w w @fqCr6<ڃ֧b'7\Vޘ:u_V;tWVHːAsOƟ-,\^C]W}u!O4 T:SsYh/ vb9r5| V}ֳ(@Jc( эE }yZ[2KVK[i6u Hh6Ҝε/sdK ?50~ͮ~3|q#mHLSQ7xd\B\+.0ZRm/ 'Xh3Go/B#϶)#E0+h C yZFvv!ukRqq~9}46gXvO1;4}+$zdqHM!,b6+v34 .M $'!^WF8&gwϰ@)"ز& pxi#8E{PO S$n '^؅K$Odj4:ސ3XbGa9t^?,2iL+ޤL*Y A0T@"uvGml@v=AIJMвT#p0 ՝v^\,PM)GG8X0ضAe6Cis 6Sw>2WOm1nm RxH k :5`BPWiZԤ@R]gb*Z@PTL/XåCoF\7cvhdK9 O7]; P:o*x}[uXX֣ 8+ÔxS1|Vuroө۴K|{ q}}{RR}{xr!RROo6 -fllguXe3gee}%ef y> \:6,'(8F ]"~,;QM\W;Fʍ3kR-\x6P0 (̲P*3M@ybD u)"Q{))?e,wi~?y|ՇTY wGXS ݚHe5}Nd@ P}S Llhpavh*eiOD۾zrE<.]ފ,'5x (5^ZS1CehJ9 )`At`}51#b*~hM~ Lc( O>BIL-ijڅPګ85@G)gVFM= 0& ,߆w6iZ3L& Kb+ \d3V毞P>0ݬa@|\ DQ@և_d"BPSD_kmk =bvezf "c;蟩( j#}vTqþ#y(kMjPktƢGn :ժXR^Jnr;Uaiӆٟ+'=jyɣ{ GB@~`ORL_E:uȢ`ɧbr)glQUtf&b>1Z¯ya'VZݨkfȀ3.*ЀqL~ s8͹+ \ 9=,>tR>V[dnkR-'Ā$Vٴq}>e@;T xq|ß;v.B0CQжhe0Dsq5(|OH62ʲZԷrWJY&TSSm ߳Ts`EjlR6ɑjÙ1(>"^T//?wQNUN. ~v~|6SS H$?T/m=CH}p;QOu)_vpO[cam zO͟&by[^^^o.J7/鎵dB$˭WTwl(ꜻE6ɷ+*#c1DʔiJ 4jS < shNLd(H@!TQt-3Mbr-~?x5 j]HI9G$テ },+uN O#j!' j0(dIAMTc6G\Gf# ։@^A5Z+:f.ɮEY)@mki^y׶I5KNұTSAfHk>Voj#lyOpwL3 "';q298d \GbH>,ۙ͝ü1.a.+r[ ԐVJu%+6kʬQ}px83,cF))6Vi.% >E~ʵyZuq(I+ʮ;qU6=2̣ ` @ߝ&s€sQwEĽ$5NqpxR|wAgOo]q, a][8cHSWG'Ӝg՚'TOsa˺{,nfk u6'~y-@ Ο.6XZ,* wN }X-'C56T$Q/Fok\C@g9%oMlI >C9H7(#E?e܋_$p2RkEvpq)TȰt4x".xl KM0)TӀS7-,ͻUGc@ɯp(EED ?9$eh)B=e(ڛ}{X"!4z-V4PC9>'8V(99L7[ɸВI꿶q&u&ibn-; ;O mCf 4ူ28$괬N:n"$&wY"sGTR*k~ /,e -}2l,UTINWx:x )n~%ǿ'-d =ibEM2n2LSkV8}\pձ.F\kߝ*󏵎@KDG/-NRzKU@ބ?ُj>$DԱks̽ݼˢ% *dzR7 o\TPEL4GuƂC vZnΛXDIUe;_ 4mGf yw5oYl6i؋)$63vC H*V\NB3pT43 !4Iï9%N`o=y.{vC=Q~#eQb'y}a_,9Ui<l~޼ڡ>Y{%Ip:Q~+B;KP2 OrK)fw ,ȧyx HӀTEy L/YyC:zYл ;ҫFq| 4t|:/P3 14S4X|Bڮ"[-o13sM3wCh,YnSTSb:UzU8j7N(i0 Vsd-pe ]2Gψh[Tb9]V.92qjH2a_8427cFin,69Kߡv_&PS $>J0Rn]Z)+e1br/sQήNB;{ Z֟dIJc)q_~&_+}or5^TW~8mW%--5:>qԟwz=$2~@pjAdKT2*sfZ apo?!$#3sZ42EVy 8+ /Tf2PϽ]cLǦb/ 0qG0U)_}󞺅 r'KEldH`m)SL+-);6Vە8&fcBE*`~dEU )o6sb3~ބ:jI&+ y3*?Xd;gG]O_O#Mޥ| 4ǭ%)%7hD7W^C01r>-2bnL= >#N|vň?!@ZMdpȽwα\иD>h!r3n6/0,kL8*2Vp5OО ϶?;Bdu0 gUhNAtګjk9npU1E=\{j @hy:h`N!KqH~H$K::K|zqqJSI1 laMsd^԰X-acldĒp|K|K!B]}+cx=5pdMD'i?=[92߯7zt}<'yMƵEdf4b8qGFێ%")_xt/w#–}(D}ZY֗^HrIG(qEdl`6(&B\m !/9k`^>fgDO6{*xnFyo/˭0ΉBE Ŗcܐk/#-80{d+p~Tϲ{XS~B.ĪNZ뼼]3N*$U@5Z2Eze%Tǻ^]= ou?c4cif|jPb8 ^֐ӑ 9[c:Z/2OdJ $ 1.5G#bCZBs|Ĩn'N$*rm bPhPA`_fz2Y D%WꤣB]M ZD_YCgk\+wBL,[dcdg:As^U@EBK;o أhjþIe偂\sɽ6+Ul78f9;97s4;#mԉ2d >lSˏÕ؂eg9]XP dvj72H1d/XOlay >p1lqI8JI}(ى 4hQހJ𗃛C[ IAGh{( ְu hV ޕ}n#QSm=sBN>xR,|9M]|m;yBYߗ+[ 2.my  ȱz.n$iV\@>M_y0lK$F >(@X 6> h#E'DKXYcg}O>C\^h)bIubi@ U-̽8N4e@G ;"P{tCtRʔ"RgHW)y,UZ4+C%<(,t܍e@ [TN2zH3Ӯ'Q cc4iQ4Vr̬yW)"j'چ(g|~#<(UNϗD̥UDC.vR^;b!D <}}n' iyҐ0Ob#£!H^S쏀@f:fJvеj[of뉓m&?1~"ɰIgާqGrd)vrKl$Ox0vA az+|**XuxyZ%Iu?'Q\y*))Ot.N;@ 5ޫ8WG-9|GI~;D C*؈U0GfK@n*9 NIo?-ҿQsLn V,Wǵ]Wc\tq?"i+:>pLh̓)O`s",sdipȗݬ)*za=GƗ`+C+RJyZm3gWX׹֬6гo%˗Y+RV0k`SOdz92ZF7#Eٰ抿)Qy |&Cb **kKlnUA0l^]!v;OStD D]W@[~ YY;F0~-a?I`K `ockQ~mvzw`}"dCZUt#yZ7Z 0-]ڎzWjG|uTZπpc|* ۿA);}4Ϩ:^3f#n' f -AS+uVV"l,`%4ԄVka}ԠL )N#yW-!(I[T7 2U}~Ib]ݦ@MWS ^'Cut)Sy6 Igq>vޙ-h#vńּDUBKAxLޘlSYr/;|6Gc1*'MI^0}'8"%#J!YA|8Zڂ;,rc 붗W)]@٘"'l 钢jDx+`w2|ڳ>:WU>:IqHMbh௭7%C,b=c.sDؖT~ϕ<fnO knYFk MOwQa'M#EL_5@\+ݟlͭA)1 1j|IH8cƥX'w(U:OY{~{i /=SZ-oƸHZd(eҟmb)>m5 JTj׷*ja/яn<ni>5czmK+!jlq~>+ww Hr@>=+'Gj֮ڂ@CPԨC2`)8MH0zF2R=6bw1U& oR6 w #zlzu{8Ca> e;8knayR3U=桅:BY/T'xu5yx*9iݐ8j][HVxe.ovɂH{A%ą7Â:j^f/x)(A2Dޛp6INA`"S#oM9}0bHry&`-13 ug8J)H^8۠|$GK)P<-M8)bt,5V>̲sS> L>Sgs̷ڿq[,T>OP l9= ]4Q9ƯzC%07}}n+^}6ϺL()bʨ LYA:QGbBu$,(eRС`ϔ$좺NWƁ\@Ws]^cl WdK@gR>c\@tU.3ᩕ,F⮨ۇ˖ei'щ[k_>Z}S=[rܕx7E~[>.j4yG-.4P *p~'y Fh?6X,Pa-@cwqly/]SRS-GISL|!^7N% aJnїIeW '/ޢ%1B+c ri }i7EVw8Ls"@-sp<֌)X#iV-nC5Ƕ^VY=^lYrD= _AS#dUL8aG҅蘞)/nOëOq$Wݶ7z#>-`Du:Tv M>0i(`4:1@!RA)뻐V%8Cՠ |xz'VPq6Vv@ 0L(FlCoϪp@|]7VG1[qY6(o9Ve:S V}-?8>{߽͉ . x d@Z|mk,z ra5=`UmLTY`ZV7**81Wlj0j*T2;0 4s-Z)hYsSgHbW]_^vFEo?Wv$70 ߭kȉ25OGƺ &:m-^=:)AZ~lHb:3yf+$E6=jD ےg;-uTSC}Wri|E&4;Ll7 o/ErzD-'aX*q5#[-mK^Ee,S/T+*̳Qo=(i"%s,*j7%dKw~⠚i[mj8fx d K2{Q@v=/)yqW+hw-^.G@[KR|5#p8` &}aY^XyɦpIaA?1u!+/9D,#RZFM^ tgP FH*'g<+@Qb\pR\cyϘۨcLrs"n|Q Ov6(Fy`h, g$gSFGi2Z>p]m+w􊺪ΗcޕAgcr&nJ5F$Tǣ-*eKJP |3J w^C͓m(%\3>5*/dew'Piݢ4Mj~Va2] s syUcsd+ P[ddjiکQVX%Ĕ'z̑dX2n> *SҹW;@T{+vc3P_Há89[C'0\ސ bOUufڡɓDg}=nT6[. g&U'Ms}nǎޡ4F5^y\]1۬ă,F25!W[%qsIduc?McY!2 O&Gg[ u"g'Uo$@2JB>es">|E+V]VV=eD\,q]_1A~+Ԍd}-vƧ R?]ZΦRM@&q)sbߑ?b +W^@PW>AlZ=~2_s?k!LtUT u'+$ƆBNĀiW\$FC]lH>q9{odrKռy㝽r%MBmM22kB?Gw$>_=PLOSv]¦?  -H6ތ4Y܂c+6|Q\*(d\FL"GtZ Œg6a2xxi!ZU-!<^a_tIP5yНX(Q*!.q]IbE4_ӄ/$oC՛ iQ0|XYI{"fIMr9>;Q5!q3SEiMv׶$=Uhk{Ou/R6.:bmAB/[rOL1ap ۱#5l)ኺw :bYUS~VTL-`xAP+Ci\ ^̭J8Z&x+ds+9kxw:\8Q9w5n"URB% =?K_҃ƪdωe6 +bÙ5c[5N>\d@h]ټmBf 3%u-uLi__VB]zT B ə:bmݡKՠ]vUą䮕ԵOh-O G؀+B(ǎظ Q]4UAroڮ̖\32ζFg蛺NL\T^biwsf5%g &c[P7ٲX/ Sn@jks C(e I`($ؔ,1Rk0 +OpE!WIpVOXcQ;Q,v-4󷥩/TTg(SNuÖP^;5LΆL9CثyF >]ɼĢE lfo9f iQŸxњ$l-/X%?[lJ{glj>UևKtg'J>ga9TaX7EQ~i7Ve:B?{l!2Q*j[䭀q݇akK5`o*nI19T)q}[-9PP]WJ KTlSza+,\_$#5K6TTx?+OV?ʄJa{tFGܺ92ѥ{1$4jM+R֊k+mH X N݀~@>Pk|H}soҧϲY$8fTmzej#C|y$񧱪`W ~PM,2NW .R~c%;7k;k~^==sN.S.Gc%SuB]+)t 5Nԇ$0uLCoΝE7Ҝ1D>QL!Nsa:kFET!dp"lk&Dme̒L6~d~g ;QCwx>q-W52HG 8-1E$ҕoC: nCuc+o\:i' F:&1b.:F94b n4Ly eDܟ?1ᛑfit ed*ë=W6m )^CYiR6 97|_tm3PWr[;%K>)ި(hKggsWfȷSkgStKU,.8vmYТO; 2z*ppryk=2sHon;3yVkS \)%xS|uk9АasI{U>U|=J҂o55 s4#s \s]a%rLԼ9gL\ŽT)j/K-S:$ /7F }2=pd Ư]q\{BT3(`T*F 1M`*ZvBLp^6fJ_{Sr@bmý/(dOEw+]/9_ݫXrTFU<&@mӓ?nu!{#͵>m4)췪)S\qeƺ*:Rs0XpFE9sJ 8rB}ݗv- pe}ȭܴq#jY/grvo 4~_4pLKM^BiM{k0HrPO\ՎPsCD*G!w=|dg6G2a*w85c0M%i,VrV)^XǯKN&,Kwl{,@j75J+uqzd0i]7@W߹ ‘ .Zxqf>*HA:`- ;FOfG/|Ǫ z@]H35k蛩& &@dDsT-_pY1X$¢VbT?SKt |f9`bױ:Q"K0,6ھ?;~ύNUIÞ(O6ŕ?{vm)o&E镫 =% }"j\|`mcdS(3WS8EV&=ԍdDlu e!!V R%h.0du~rXĎ*$; ZPyYŪ 0"8 ]"VUFc]I>y2vHZˏs4|4ͭmonNl!/_m-DhbJW`.E}<))'{OBb+˦{"jM6:³B+uQ*݅4G(dxɆ>EL& Sjc5@n̚b"T`+  ( }oBxDųQ<kK|E[B:s|o Δ"8qcCqf ЃOc}(^; ~)ry{6RκsBK8~։Kv0Bּ DA*HfcvN ݲ*'5qhw(͒~O-=n#ӇکMyŃ!|*x{S#`dbL~LE!S, ٌØXՓ5~jzF:.=;R-ԏ.Y$ 'BE3 zhV~ӕ {N  *]w>&;H&*+7K(ϐ:ʉY"j:MS1cJNCf/rBަ@3AͯلzA=o%>+iX)Kz<:Mߜl{y/w`7 gۊ{}=`AR>lDR ]9k5~b"/eEa $N` yAa6Z)+k h۩` і" 慁eϚ$"0$.eM%'+ qGx?p\YZa|C7D ۭG\2H MGƃҟXnOsjԄ1DQ; IR1Muji\& eIppYrgQD%O9R'0 @R\E`4?} :J*EN'E5+zwWRKml&VRM+ngG;Vl|Hޱ{ G+; (c?ޥQqOx]&Fs!(3÷i\,iK&+nN[1lϩ1>ֵqҋSr:b!`9dVCm\IfE2"p{,y;!^9[Xp%95g<^; , ţ(P!ycm]HH.@yI0n"Gqzm5^e=6_yI&2A = i(G@VD)̀\~bw%w=CLtAm)>,oX2ap9@4rY"Ho+f!}+cvGmbxܐEO|\ ̮NO#w#Af3ٳx;8yԛkbw9fvEd@ǰG%)ttƢQ@E}1q6'6qBmf<-]koHt)3T>-tW$k6k8@#϶8|V\gŷRV"];4]ΛIR/) K<C)(5suODޜ% ]!gvοgf/BCp6r؃νjSwP0.$5H lL i5ϝ2Z#XʾͱzxdVҰP6C=PAG=2^hVFݦ oG!O ~sSWWgl# @ _MX&p5lCaw}93GxYBe=32o IfkVVl}ߺ8&Zxu^F]r1a{6k^139q*Yg&/Zg-?@ + {"_*g&ё_9z. \W-˜:̛36%и&j@ڻ$ Ԗ|?G* CegS.ɅIVlN3ly4{0dy.|:lxXIU89Cnn@w D[t *[w'=1z(rTVЪ[l-ڒ -y5P#/) i{ OLa [i|`טCЪhR(B|~a=%Tz!tm9_1J|hW! f=9]՟7` !d/ pDR-w:gTmuy'PGV:}Yd8%|z N )'kwh:TTnb;ŵT.+7LHY~T;ҽI lGtXrkCR3CNBZb XJ^QQgu9}ȼlzEVAHp f~_!`*qds$UP2^iqVAKy^f]hPϣb8"ORK'k'Ǖ샡P@ 8c_2DH -Ԕl\Gꖉ,oJ?+wW< %#]W[ڙ'ovilԨ̡ Fw&Y4u0g{};t>1 сHT=^q5l}?`n\$0t+Q xX(j:i 뾷#,&ގ"wtdK ԴށiCvX/o{2՜H3kO*ns AM^q,q2*6 cHޥAɰr4%ov? "(U@S g uϞ << VzvK"oWF>rj(RLiF8$8z9nQ&P SFﯿWFy&#G3x:][:x 8tRw!Քdt;/+$Ww_Kກ]08H`WtɑTy|+Geb$ \eFeҲZj/J*?F/ M" WP=--EVh+1UQ ?HByB7"@*EKLA pɒbw 4Ȩ02G נWH;-3F4s4$Y&9:e-S9˚!]S#j)Njma{1h7d3b_HY-҆)]YifL^7[0,D4n}xU,W,G˙aOڀ?bm@Zh>F<ƨPR>JEyܱC4{bY/2/T=)vrTALHWEPCA 1D6٪i; _ [ice[_Vܫ9*QuT'PxigcOx)%T]r7 k<:NV*+<xT.t+}FQ_ۋk4}UVUKyaſK'jӹ }Ů.6#k=[~ IU^HS [kv#0c?U*w&dj.ɤ8l}^o㬈8cA2 }.7 `4:DM8{1t5mμc-8Kn'_6߭&MTP/'J|K!ԭ B}'VpVSSxGMT`A_1)K\4/"fn4Vdκx~(ʍ:yj;O,UWS9BԜBDq\@@ݒTpG?V+4SԃEf_< n)Vw[:r,I\Dk7HP%V >0>\ڢ>QڷG:4_UHhR`"Uc o u'Ⱥƥz ]$-!?CQ~G,;,S&ҕ :bAxt>CxJqUr@ /-p(\4lbÍyTbm*aG&;X iɡD;b~- z/j%ۢ^&z'̴ABEג($$jLjqY01t8z>L|#X+[ }"0\<'S`h-3H׮A3TW/_=.BH룼izS@#]#g!amԖGa¦UY/<8QzSC̶>(pdWZ[P^^v^2tj͵g=,uRT)sr^ N*żVÕv&a3vk9Sy{%*5*_x+A#+9y ZZ&F4)%{VՎ"R*})U l`ͳ6 E*"ghz";?iX hFG:"v^  geRשi@lG5POp+e#@/}JȱK}6zͼW~(ub|e :踁@%G.svS|ȉ~iG_[ϓ8xy:eC"=̡R8ZfZ5tEz(IS(ST$(EW碲C.Itdl^ҟ>ojc,A\q߀}Ja-+O~uD| md⃱IT$(z(\D&&l\ii_&6Ikзʪ7*tV&V]1Q¿ TPeu Cwv<'h`2xcQ~ZSJ#մx' S)ڛ7Ȥ%PzP~UURM j4˾Oߞ LI|EC0>oSOv7"ɵ|^Gt<ja<uy{$ +k_tyW|Yw[EonPxoU}\q{J8(heGbCIob-^ ԑU7rcU@{2-7H؆oq3)I >޵&M˞c\evp{Y:h!RC;Tr00<:8h*$-]/&Ȋ M[ջ%Zml-鈨숛HW]cǘk1YY }lB !90&vc)3xl2OadW |Uץ;tA1DvVzVbõZS:Wrv{ CuFZؼ;:ѹO0+}`LE9=u20\p@xVqI\Z&9+jֹP(̡0:7ZxWȎ2$6EH &H/9w5䟅W)I> ÞoBu uÉ˭}'CTi<,JLB59 DQB7[Զ'GP:3aeUؙc[T.je@'g |'IWHL~8*xf|Ƶz8z={ kPNx l%"J8|+?p5RA}:7[cF"_5U*@gcYqg-#apރ7ADFCND)>J:aL~GzA`-4:𹖩0,>_LOel" [I/PZVpŸPl@@ieD?iw͌"&Ylaʄ]Ǫ|FDW=0NϪʋ # ).0&f䔴U5ɌDt:[JZs߹elq Q<4~rf- s~~w:|_L ?WtChaHLO*x'}2b.LA?'j;/p nh> L뫊{8 &C[ߜܬBZ V89qFR|Ha;4DԐ|i[R &/g0\9b6;TfQo{q&kI-wYչ tr#9*,,)vԘ/=I(K./Ϻk gwkz$$j 3_E{oxv 1HN'nB뜆 >&=I [  !e.! ^ACq>o5I.-7 \.}6j6 `Ot\?sVk϶{edl|W!vR@ǖ'vi8.-wNĆ0h4gËJOvsqX 怕.[?t܍(`rUzG.%+ P&U.? P9/9>XfYx9\(-{yzfAX]OÆ"cBnusP=r3 ^_/ J_kQ|œJjRϻ˟9]^ApUrS)T4 gg0LIiKeV%\eiXĮ4U i;-cQwS ֛Q n7Z"p(k-3abJ;جh'7#Q<wU% x}⺸R뽘s,W7)C0-dr-6i};eY>㋫(ϩudD_n[:CRx@NuUt!hq4 _+ ɒH Z愿DŢ}cV>+s,9uǶ]OYIM!quK(:TD,yg\-)9cTK%]zl(Mkc[(d v쇖zӪrOφMB, ?jAQk ݎI\%ɪ2߮9Qcܰf{ FQNAR"ZEyLunf]T( Σe"12ۡe0LThyTK=S ~yR㻬᪏;@a ?.<>B:ռVeC+?^bMP2Sl#W֙9]@%'8wv9 ]´8 - NϠVoXܒ\ݩᵣypݫUJrnmOcL ms*~J'"cqBsPL[,(ss¯Q>L MkƖC^(BˀA6j6]s.:BH!Tz~<10j.ې8_Z~^g0h@d9V6^CFX?2!IZ;}Zz5ZO){ x<"9^u#=]٬c4GWx#Y[~G!R${`lpaW<%,[Q] )5ĭߔEx .y|1V6!K2z6IYrbVݐ֒OGNǴn&gU>{QFU+r!W$`Q5a%]?V1N`ΏaHġ090Q Ft4E9.3"% \])8Sʻ :U˷>)HzY+߃eF!hP[9NkgL9 XgdAo#(%иݠ`]zŏ?*Pؗg (=Unw{/D1v\G (YZ̦-9EJ*g] \{AJC~ﴴm['؀&c3u+$::yTW_3D\]}5JԂ{Z`EiY|Wؿn#Gz]U1~Q~ Ҍ)uLVi&H@!SO|嫈F/Y^[݀K} O\b0\PR%pL>'%\DqaJ10_+sywJraMvXzQVig8&VBDa1gsk»Y-)++Ji,}o"wڹt6Uj׸` 2ǧ&mJdFuH ~{AyoX˄Z/WgT쳰!*6?ʺ[b\7|H[=WUnGaaB*˔,ͧ*hV"x#0s>e I \' \QV|ώWqf׳%e e~63NxT\N51;KA Q8L|,04#yd$_22Y77>LO2\A=\aԱ(3-К6WX8>[c%gڑ@C JGV SAɆ*:gd~X~l񹿺*+Vg hqv@4);z&Q*'w%g2}D}{MM[k >Taڊ1gT(R)Ȗ:8>CMe$үМ{# LP*Lr >ni{xmI\ˮk7:P3mT0I/>z>p?UeZlO -A qWb/&{r˅"0H퉁JhG2F eDKJ{^H]u癇DacpvNFi79Mz`A~˭VگyU .n Hz% TYǰǪG\Í*eGX)}RVҒr{9GT8^zx=%蘢E^YԂ3ᐐ!yrWCY'5 e|o=wǝYbݓp  ΪRaߌD789>((R㵲>bczC?!LA Ͷii+r@nZ7$&|22%tGelD+ߍ!%gvַg4G > 8PF^[!V9J4x=C2bL??&I-O*T-7U. C·6{y$tDJBk8+}<%md_k6`MXQE,Uй=j?rL[owZ)tH5{Yj5(j~tlЂV>5W(:9`oc5u! C)G M6;y0U_;T s,\Ub05"NJ^֟ز_<}$#3T&-3"m[$n{>O"M 0 X?}jA.*(}Gn?O+yZ8x$}lU8Xrl-CM`]P),=ZR 5J iq|Ϋb/֎Qet-0*דf&达& R+J _@?  7.RET;DcCs-`PZ}Cq„xP˝z~R~Qa$ˁZnQÚѡXSڕG$Xr~~|7g|&UTF퍹ѥ NZ U| \w FvŃ:ò(lk-.` FkgBY]j$Z$%=[b6 np.@ 0?jp4a,)٫zWL8c"ӕt!JBqKojds~O9>yۤJ7V5[Ң9Ss0pdU@$4;-uyQ7v;_'0=)" !L-,j!<>E+w"c'Ǚ%+&p <9J>-xij2c-t pA)8}wWR;Y?cQX8Cp^Rv77K\޿JE G+:nÛ[Zk@n ^v ARmNxcX#4>y).u6ځ@`}(,lR>>>TYne!tcπ;|z^)({>g苮nnm;<R \J뿅wXCwjԢ7T#8ôaD6R1Ĉ2{$>]T8㐾jL.}y@uy9@|1-Jx65&UD!9BvJ+4jFAo| rA@іy1`=gm2n" X'pN|Wɴ`ea3ķb47 ? `dEX4~#8046Ј 7s/Ty@E& z}xgD! t@9ھ[9:=P"T٤{Yɔ[B46k .j'NK1G@0kv_8)L9-Rs6;݆C]2i6MP{pػd!pD;FJ.*q(^Y2-QySL|7ř3%j!x/mxdiEDH}.z ViĖzEb}02en|0'׺F7d&h6ԝ ]ZȐӼOL/)?_q|EYkbM}Y&a#xHiGgX1K0MXC tɻFu"$6x$HD}:Yw% $o;y9C|!yKtб yէ5tCV_`&.Nםn3^%k518v"Ͼ^Tu ]WINk`##KL̷ a}Sd-e_;F(V>q\+ '-fM+gW( $(Xcyݞi$T9E!hD6 wAՃ?d710ϥY^nP*΋SV-gS  0[>xNKpEO!SМ9Ȁ>f-hɵ\rs\TXmo6kY|ڡgc) Q< DTfJơ,&땤! ǭǻ\D*&4!g ֲPNckF e{_Z#E1Rȓgr6H$ M]1BKh@.9$CHq9IZoY?qfE"0.3q=o &BCf$u|sQ#{V~ʔ*+ G|'L.n`/{I+3Ή:BotX/@ang^nu5\1  "P+N']C{l ȴbWF}'ZY)},8ˉt%zLVb2!= ':;WE K1vmÍdcN;sֺ\lX-l&~Tb~x"c͚w;=%US_@ g ΨP0 mw@gmVRRP*ّKQt3Kq4wOAn3J6(OD}/p^͇Rj'~]O˅b Fw 5UuBK Z?w>fmW&۹Vj&xj[IDcua1SZgRkzoԻck˂uL FXUJr G \ڷ8F-tG7{p(ML}-B1:3K'"=0Q[!;;qdɻ8+'̌TO,*/X@(/q(t5'yu)C}Gh|8?ň+jĐ 42!)`w&"Qk -tQןN|#H9Ë^U[gBIY'x> 0U:C1*j̉Jnw+nqD!~qDa^G0lW>|1>)gsFȀ7-{ G%iT`ou75*cGAR%,(R.  _ϗs36ҳM0ɫjI>U>7\bsnr2H'/1r9~q.Rln.(}ytXWLR|c!vT}Uͫ: lj0fnQrVNꁣr$2 w RURfNfjڙ8W ] [ݿġi=1S*֮]Ft21s D.9 ov~Ψ:R_#o?pˢG_1|>WN~=!x1p |h }7SG}?MouS\yT{?fE]l Yg@ȸ77Fmk: P2LGTෛ; SڷB&E-$g%O fhP:5$hT ^]^Mz(RNPNwkMYs,)areL?pf#$=ڋzhsVvx"'5ZUJkCY m{}AxyFB"&ctm,4F:p AQ×؈PO zM]Jgk{lYB8T J[+Di2,",)RcTZJEJa7yZJNY@ϻzIBQǯur::o$>Z83&o%%Wj8[/ʤª )V#Bkk{UGO_/Khc7U[L_ w7{.kWvA?7CVk 2YRQؼ}BC#]ɠPkpFnJaL# #Odr^ Z 9>7Ї`7Y8R/K0;.y r~&X7<`vysfSJI+ c ~G/ JzOLZŇy8W 1?wO2 KP9Fڐ%.&)ݚO@Y cOuSq'6 $ɓT{Rv*0ٷPa.w\>X"[b?/ Tba jF ]ekj@mmK. r^|HA4 0YyVYFZd`] r˸v%ۊHRLlMvʘJש!eJؒ+}oӱXCn+vimepfUAؾWo.x i&vُ[L!HQב Hz$ThWi#C #/<]4 h4vQTu E[)/<ѿٛXhw:(ӭZԗ!RiN*ᶧ!H{U K%lM?a=%o17q['pA(EF}a;Trs udJT c+ g4HmXOa!d>Zpk(L);ד%}|teia\IhU+mBd{'TJFtnٜ-=KG9T޺ʈ3ѝ{2ٝŎI%GaѢ1m|7_u$ʓ8yJH{UjB= 9 V ; tyEKxp՞gn\/_?zc+\'q-.&neL iDF[܆ATuʐ`*sgQO/lZ v ׶S(< 160ܫ!C5wo!1T0ba7nlESOakqzG5 C5#IOTplo4I}y`&?rP $NBJmZYG l 6C*XA[}lDSXqE. uʴ8﫹__HNА`g4]O8#tT9a7:$ Lawjk[{ e:DJ@cW9ԭ.E ȣEŵ^Tn.5vPw9 "gBWd/TsizKn*Vb0Х78[#i 򬥓XhC j p{Y\I sm8F֪tt&A`||WQ;|)#fUlͿȸ<؇oW)(ל ˆxß˱= M_n&05'N@Fg[k%vYQ#@jp#d*̠PTwF5 <P:@9; }i Ad=)+.AC,_:X /KϤ;rAp_4;dpXAZy[=j [ŷ e) 8Vpw`Un8HFPz6DJܡX},eRre/L/87ua t3w?<} sZ^SWC@!Dw}YPd˓XS|.[g Ww̤'E?_%5\.n%UiSXMbMU:.DZ|ը; 4"ь])ǕncCg 2*=߬ /WI%Ld$^tAuV%0|ECle<%${w vXϚ#"y6sKH /嬨? ڂ.KW$$[jA_=SaY8s~Ԉơ`h}@nXcɢP'lIOsD$M9BD`[@ĉZ@ >x2q,UAZ~姴oȳPN,Qz~8 +. dD_[yH?dHmTxQV3dWo5%FSPͰ@wJeӌP,7J[ޜ+,^2\6_T,&qÕlKDG(7Qy[ZyP9$Uc@-lr~G"xPgE ą 6'y&0_`ncE0ZP۞>7VԽ`}~ ٹvzQ-4]g6RKɛ9HݶPWa,J;WfWu"}nw\qﵦV'ܝ H "/*6D YTO;*;fk{5-醚t "Hf/~3,_ | &Zt/6JF: vʒga>Lk;q#Z4_V:V=OkE\HNc"7QA/$Yk5Vڋ͢  C0;ܶ_ڌhP-K9{n/U,@rI 44)g(cb3rHLqE_>7,}q^o]]ue1(7Z [/dnzK5& jJd3a(unԡʃ 9Az|\A"rpNS!N틛tcu@&Q$N%΁8,&p:wNjzVyQ9Js_ee>qV3 mmm;۶T7p Ex+©"وyx:|_ls*zKrW2!3. huՍѫ7oCswTY[6![r+ _fE 8_#fD\Q.9r\"ESDϳ&3Ct@dl9Gh#﫭hyBVaQ. PW)PWg~hE2!v/{ҘgU=8kC [U NQYԮr1 3RcK٠\O?udu#DU]Wzu\Go;Oаk" asgcmr8eaѢP/sQ1,#L`aS_kv(SA9t8jxGUnH(D5rB/rOtmn}z?cbz_a-8*ndKླྀÀNY@tBۢYc_:(dinc-Jg!9˥("sfe4u2#..1WD];2W sbUr~)P .&2qJ96/2{7ux^ fYmX@ՠ[ߖ*۱ׂ+ Jљ@WpdF W{^"{D=HM=ق6R© <u=tfu54nrJ'*c$LĆcExlٙX0^d [RR)x&xn4Y5 .̑3¾8 L~o1L+ jtQF@1Pǥ%( 1؇۟SV)zYU^s(nkk0>o+[vtN^8t83”_CvV NDšO- P''keE~8Mj7f~6z)M yc; v 9YU5mM@71< -.41c;Z_L_|33I@/1k/MyrCyNؼdz2+ <ˍBr\$sWy08 [=QŹƭiSvSZՋ:fG ύ3H++ ݩ+ _tFZel Ca3f'^!Tzܬ[%+,i֔J&nTj蕬ܚ|G1!=wh F4+ JnD[RΫNU~PO #_ -HCwUqt. io$>A1MJ}avdIzf֤{lˍKAN@HY tؿ 8j(5:p-"329FksﵥSn0yS{h|kQ>:8pBCt$PQ¶1yd5,<dg!U0U$W\:]|Ǻ9Z*R+ MV *JyfG7d>EWv뙗Fh7fs@fo,(Ώk혞ش߹} u&6f˷t؋$v@BHqӭ4NFEO];#T~$Ҷa>ML`%Dꍚ"3 |LV+afN1P}ɋzulOWI{(W K)NgP8XS^Hy1IT$JAdD3i0I$ͿεPB[F]U%8i̐r: .D8dU6Fcsg5ق[n kw{L 5obE_A̔2{=#uė.Df;z/-%0$0_Mr3:k}S/HppE-4S8P.+\*2<(#*dWAc~/Y 5i7tB`G&b`0ԓl߹6gBAA:KI)rYӂIͺ5:A|Oq+-B6R|aW r;6}+BhVM(˃5pvi"*=2jefm D}+˷\0OOf͘2%ᢱEOl4-A5/);dT]|@ӀyLeۍ&a&U xvU+Af຤GCɵ w`z<˯/KK~dd pi2jxc;y5ij%"uæYxk,CXh\`K1E8Hvww:k|=umn9Fo) -Օk|NњԨ#X욳 $s.hdqH%%+=b̴4H;@f}mZ=[l}l*V/08scܮ!@BAzH)(+ofϚ--V6FC ydM{Gt|lUSFWv9UD\쏃B85o'( ZC|3X^"X,Nj6C6bWm m"?WB͏e3HHd!E6=Ÿk~>M6bݶT.ғ ԻO KE`޺E{sR^^@>n4W!v,sVe!=CBv/Yw1 YwLn?1kU&cUP  5uVbM6B 0X83@h;ehŀc|ng8xT3'qvSiY|ԑ(￱9֦u0@~W0#iڽKW>E$(| )<,Ǫ)pUh_HrEɇȕviᒹ/?)On^nᆤƲ!bF O}5`JNq6[Az,SE)('\o6ٰٷWLl*+8cP}nMәa|M+JC ~.8c]@\G%BL+)l\3m!݉SP@yᦄd@P^ߠʉk-:N$ȋms~fWSajxDM$ ᔦ&LM zh1?nӻ_@$|)cLѺA󝆂֜~ W%+ R7;R BPN1{Ј*wHP8wHӢ|cQ$?~O$^9eIpޔ A9g&@1h)3+~ҎxHx}@ݺrSH.YP}~FiYns9yUk=@W2Qq"_Jwpr=H¬E*h %Ѿivk =6۞#k\Ss6 \`YW;T°,{Gva3$\d u3o12G﹍hzoZJbq@~9+Ve@%؞+bREPφZGA@eCZH`8*3יȋ{ovS\ e=ƣ% ]ق]4O4ȡks(6wsah;uLO f4{5Ngj@KD ś]@M4bKDwfy։0$їV [w M]Is+޽y\ߓ2 /<{VYvg; 6D6#dG0}hw_dZ \Q"T!ԕS~lA`F'k$l^"I(K'5G Q9]/sPmOky0viGMU]!#KE 4fGV**mD.tQ,M1!,K+Va@$KQ=-XI]u+i<vGcYt|ocg.A.R%#&4zHSJ%d#Sm kd3<&^I*II0@rMZ }ANtM.>e ]gK]U9@gg"}p[ 1uI;B_ K4&t&Iwp% ]Ӷah;q}6oȲO yhF݉M@qlpWAwp+/FZ>M1ǥU!vdߌ~_Av7dƑ@N씹G{H!EV}o< <ҼWB- '1մ D*WrX lm뙣=@j ݆r0nOYią]&xcQ}v/ي}zA/%SA E0^gI3C˽_fvόM# 2;(!ý6Ca,^D53LD:s_N>-2gzX^"h0ZoNSi0iPXZ[%(Dyy>Lv)[tBnAס>sUag !([h0Ƞ-٘w@$)8W#sHnc(`6a>?}2pIٱk6Xd(MPWnK)HZ 㤅\AE> 3۷<;۷ηxP O6mBG*|DNB)Wf<8&BJ>F_d{Yc$ O Ox׊hmub.;NKMyw3S _@};2+j'SqK|!;` vM1 :>X_侭l"R] ^v6 Ct{6Z̞~4I,b+{$;U_ng`܈`RN OމQ`)A@2ߓ|k[̋\̑kؓK Guy["P8Vydk^;c|I8g C*dzO=9Fr I5so(H0^ORIڕzUm"邿~.&ޤw _DU?w8m ݨo2 2&ڙ+jA%Jǹ.M7g .W@.FGmf?5f`~*q6y`4ݔb;xg,y{qv'BPc), Mʠ.xs+d\b{Wk'A F.#GSi!3{* cK{f=E*W0[aɬ/]sU_AUOHB8,ϳ~O s6yȢ5ʱլ̩~/BrcIЗ j-M LR 棼 ڮj*>~yƀNiEfq<7'O|lʏ"ڌ4HATGi}ށ7\o+EtE_/VXݮ0?)(xRՠ-M,յ'~bN:@M2 Z8qL) K>YÉa^Cs_ᴮfتv5RLA=?Lܚo;.> Y#<|8^bvQrPo(g\UHE_ޒsq/ɅMl#;ߟymY>q}kq;wӯ5&6ۮ+?u2FcEszv:8;99J&}Υft#'ٍ~yXo>"ᚨ0cx&j Ϩ8 2!<&fc/uB$t?,D xy.;!vfO#? 7{|eIbkQ*H1NF.0|1=GN_}`%Y.8@ +X@8}BP҃CD 0ZSM_SVOcWi8WdcKm/>‚qm8^sw \TI|pnZ1@#I#6[$rJ2C Ao @}o܈kL_C]$(M%: }t4ig "eo:)P9Q3iE}[6P Jp/Vn\E/)+_MiƄT蘺 |4^zaذLA2;jXnQx7!#HR3d/$e5 mǖZtD*o =a5;P*m'l՜ |79&v/R}췒B }yhSz4h$\m7D1N[SVz$~AhjVJ.t!nC&{E}s*{.`[jަٻx DjM-UA&k1osxm=r+M:kΈ@mn3 =(q W_ڷATu.miT?5՚T J}1)<O5Yl? 7Fߐr ޣAYk9jD4 g6O|Jԡ(MfV "ʑrG}RoY`5  ie>(m`fP6,?ۅw.<ЅVqc_"Fq.O``(ׯ/*2ðɪs|Q軁8;fi{b cy #d2ۯޙŒۗ.Ak_%dZ0[%xn φwVoK1k}4=nI볹R3ME+wS!+{HKV* I f461 $'^'`+mqWL0PαdI9lzN%|s( pcebyZ6QMȰu7/^c >X\j|: zfv|Q 8swI =`0viLCE!spqBw}Y,JC]5QxR{8 ̛VPX~6W  YT dg =] ZgBa f3fxbȲ_m ӌ[BDXAYmZ aboφhl/) 8Srt xFQ! h"8k5k6 ByܥdQ 킡DSA-g ń;&;˭

_O#`Eb̒Sgao[JЫ8."2u87)Ҹ:D0MxNa*z{3Ϛ/j2&Y*R3*˔{0f}Y7!C.SV/jA) 5|Y|})!4WN(Tޅ qH[(0ikG?^>jI’jzHQd笀iF6@ri Sޓic,#ۧc_%*Mitǔ)Ȗh#[` :]5,V Grq ٝ# *R#E=<}qᖰE;Egq:UJhܢ W3=c:o7bI\Ts+k#ݝ1)k,v#UٟeF壖jnR7[J4c)ӡX{K߼gq,{Nx@^vQjFjVT&%UaXQ wbW#˳U@Qs&ژd3>jB&eҠ`@c?#ylNߧCIUzWe7oTF#]ef;oS+mE0)>^y?U2=i~g沰HegEly`.~pG$Gic;m ,(zY}J΄4#7\i?^QAN+Uф]E}]oXX6W~?Uc{ l@ "pV8UZr^\ Pm?<^sOkKfno*ʾĕ+yZ+RMݕoè_ Cu+ T-(2z'¹{;Tkv}d8:I_H-Mo&6w0Y.:fcК-#u,b%mmU>]t(_;ô!zP,Z`hJ+ &q{z(0N/u G1D^:L;m q]; TBH||~q))(1f|TClLЪ-B>j?,] [~fV ۨ(!p1Ԡ;ڞ\ULvfV҅asGÏ*]{p<_s- ) ahUiG$~[u3rI >Nih~|2D ە aD؊wbcx+͛Ӕ%Ck?'|  C9lo !ąHNUuB^K~Wn`u=T-Ɍ1 :kI&3|ac*Kdز>?';G_G0 (KtCwE/@%\w_ 6Gz{s#:]I. 3~-]OKu.wA4[ѓJ ֓~7Q*BFmGe~R?=J/ħ4?qY'BES8s}R+0USdtNM.`*S1ikDAz={jCJBk9[\uoҰ+o"O{XN/頜|`dOS3n0UBjRj2(Նry8fu.HqϥQR"}1!7F y8/(}DŽO%Kq;fl|ܞR"\@Hi_<_D+:(tl,/ MD1_m 0N!l4o6K̟I6+͠-LCWP0<‘g!E2l4ȋ%~׋}1D!) `ރe5(XpI: f`x6R`G4Ɯ-]qAҨ7coﻧzHIGe} dxJbk@ eow3^XJH08f+DF;>*mRFg`YD 2#|Z~Gru/Z vsp͈w/;R/:tz*D5/YŚό152 Q."TF pz,9~#gytYԊ%aHD!$7 FUalTID-&ãV^CX_˱ KwZt2β!N2EmcUo["eЋsoLN ~s?ߖ(nk$SgKKx W!TS,3cpw؉2Ac^XMFTٔ*Ltzth)sf }V~$ TByh0ߴɒ<~ZiDovIRYAr. ċlSBq##zu=(<-Ԕu7X|&C!9?'~Ky ,D,/;FWjܛ}6pƚ~YݠlTVw#ZYׯk)D PW")k̯ZA0_ ?Xؽc=SU#b'& *֞TUM e\{h>(_Lko}HfYY9S2A72鐿/s MRH-PJĸ F1Q1vW .xh8yFtQEDL2#S OY6 %Qx)3hߝ x`tL v$mWSAO JW {B]NLgyV(1= 1 c-%~AoHLI=P:r\^,I EPU3e0(FdFo^ץr2> Cf*.>9|<;MbZ =ړ6&2wQ5RaaATh]a:^g+3/d@ʣMk=O {iOI [D 6&a '%شnr>1LF>FܠQTz`tE?Fޠmo]j:,L|88)FmwHX|Hh]M0dR *迟pT 9]NHbjVA $8+3\)v4"UIMK5 m:+LxYiQ᳓PV$E\=FlA/@r968 l]ZW7$oI 8(!߮R;0!R϶գC6\r8LNl.ueW-|wVLSv8X>tf0 @ЙN 8ck6~#z#&XQaU-ϕ p p8$¶l*cH\L:2xPh!1u=w@_rNMa{Ɨ!j :l{e '4-}'CH ȔzB%@ʡAPQ߮(jAŐ Omڒ I-ɞyebU0u>Q6VȪH<^X![sŤD&`\Gj{%{ XBJJ*+&Y^0]xtli JN8e`E~&)_uIԉ&̷ .':vtRwsu[a˙"1f9*#{( yUP݃ǩہ5X0a'W+LN CJ7)RrwY~Vb.qTF!ac*TpxUO[gjbt F?u6G{DMN,w ,M_}kR&$+Y-Ĺf]I'ٻ&EDz@= \D[($T ;]L;uvoF`N3z/E\Ƽ$8&'YcX{J<`N?P4G_IE6dzmsUwYϛ&]T"N="G*s']$X~(lהj(wh `VY3hp#UPdKhU 5۝0}Ee4p_'HdnWn'5;dr4o-h0Ng+dF|9!?qDrI`FC#Po$Ѕyu:aÒww*ݎY놦t(h1Jw iaڸ^:(ۛC9A&9N>+^lJcAJo//3 GM'G ⸠؅p6zۺZ!xvt}U_jQYeYtX{ 9 vڻ5u1INoJƖq*պ |PN2n6XD[p0u Oe/1cXug֗'eӈ1kC܌xⷌGyd-Q0? X8Bw;\$i$v wyDC}ӶV>B!?'m;eyGkz\6h . ,vm$ nECZ ;{X2X ޯ!u 9tZ]@TM"|]%jqա$^\bT5q$3{F2.֛ |M5?;QضzW̩ckuZDo{g\)\NĨ/|.H7g,xmOlQzɝ 3Q4 J7HV > ]8Q@$d\jbT!<{ zɈ- 7K@>_^4saH:7i$\$/|X;[&}R%zTYRRK` 7XAuQ%MXbĬ3a$_U$dF^Vͨ GAX;k%bR.W9񝐙Id~!HHTw/^W F$ڲmuj8|ܲua|т ~Uh)l㙾~Kl"q! #K+˾dekey{ĉG_wq/s u1b6xdĕ16\~1Ux቟jJ7kb#o?~žk >&('i:nNDuX{zG~Xg8++!rj#.KF{X"hO 8lgL8I8WSbp =Cy) 0bn);*Tcs Ed(80޺v=9dUz </}w2_8e<~>8+so{)ܾV C:&*.AFOt\%i>ĸ8`1?^hcQ,Br{i76c>TXIܙ7Et#' mB1Ia4 tܮrݢٛUkGk0( "pOtнi |7/EEqߙk҂.ēwI9TmHL}\D YK SDP'.lJ<4ennʷ B] {VB"G |*L^Œw*%LLK?ꌵ*LRGk²d ;d`Э`')EYHC',ܒ\b  8"3 Oĉ 41+F%0XmECgR_4y}[N0" 6UF΍ g7 bO}I;cXJGm c'!l_ mM A;%J[MzAm6=:vg#c#"؀a#J55i[rZ7F7BּY Pe, a=[ЭpGW(;X+13e:t߇9BT0Ԙ_t /|ί*͕1EGB$1.E)،3lޑʫ<$ ܾ1Ǧ16gAheS=>3>\s8C6]wa>K+U&;YyrK4Uǧ$ƛ-)+W}P5odHjSQ{kfK܏qxd6ža(c9W9nr>qlS(ߌ[KP>3b.TFeIZ"DcWma4&oNgSY9ڕ)Ny. [09HG'X𒈭<Ʀiy'oω Z .021vPUr);d=OX+!Nztd_\I8HluOs:n8?ٓ/6wi^*pZe5{+m$#ɦљb!y8pyX De=$V'UO`˞hՐKV65r*^dUTy!]g&A_+5di$dtE+P=F5)!ţ|1I@.VtLy$3P_]mYWFH|r<x:ċLOm4f(ҝ s` 97"" z*2:Wl9̚R8:voVL5cB2dI oa"o&oQW1f#!*qŅC<ǪlŌPZoW'R0/ֺBԱp3~ \i a!2pQMyfZ[}_2=eʼngJX T<Ӣqb>哿W^e4g9Uʰ~:ӷ S* V 'gaGxέUZ%%wke~SK|}bbk7ɰ}b9Żw AD%_|N4v"50Ⴕj)GN@#'szjGxw@$Dt;p22y)kNB{zO!٪pslg9N|rrTF4r.~sߔFz6؇|Wh,+џyOѼA1{ x 56)>$3>؇1G4>6MdHWpGjPr0ݣ:KY1E413<ڱߕR7*|BD^dQ_b}<{رld>(kZ<@T82%⋹=XpJny5> Զn_|`t3y^c>j LYx@Rs.a_ ֱ.L|޲બ5QlB/-qz\ʤUl!{8dw= 83mIGZ%el`VUl3R-,5T̘"^(6L |h1gȅ^Kmb"-Nxş,c,}x"Xu^0%cb# ծY`1\e)M9Tug |)OI3;9CPKwWg \敂Aoaa QD h7E:< RG&ݲE'}Wgg{C.=b!Gp'Z`RN?#@! nM(EP)1Zki.1#6܆PfJ]}lI1?< ;$,2LtBhZjFiD-?b- Z9Xĉx5uIިK$qTjuh>FVWҵ;G)T-4mgr4i Uz܌=Sdϙpd:R ̗=ƀ\IKW{fq9zlV Dࢦ$ᦒY@I1Asf(( ?]pBʎ,KUŸS]0yD]z|F/t%Ho\+Eo('ۦV6uX"ml9`Ndq_K6A8A4$Q&TAn]DM|3(y^M n]0YL(,g_?yo7:?S_<X\EYʠ"hinE#XԐT~ĵ?0`Uhi&uX`ayGp A)~!z&MdxIydMD˜mES\- $Q[rh[~*X&X piPyDPc PM&?}s8ҫm]s~ͨDug8Mf<Т/"GOpClW,w7 @V睲U+|Ɗl_`TxmhT,8:$ 3)bKՊ9ím#y4a-Qȃ:V -Fٙ~I`:P m|)k}1YO Gұ8T.=97{w|W=D'aNfHOI6Y-qS9y4* ҝ z`1ةJP  Y\0 v1!N$Bs8O6`(JK=3#0ojex@U}whJɶjkU%ϥ@"w~dA8]ѻݓNSS (jǮ'[ O8O=5G㞸Z~3 * zHGZcά-E6]DZ{33FY8 ڇa`@<,!,JA+ ƈLM K!xw .LKb^@jB{qf?%XM٢ufvm .u$^%#6f*xdMPor7UAv j @e#3>&:`:u_93Y8|#܍ $k>!^`xa8lKYf`XjQS+! ?8ƼUU&YJIE Gzhѣ(,r.=ǣQM~Vɒ :M\'9H*h4V@W+"4GێК>hD\;谅: BP q aE&@^M+ERڨ]~slK1VC G2C >. x\PmC`05﫦<-~&z)KdO3E{|wE;)R`G7uW/ @wi;~1EH,;N0(wIvGD^9TݹdְHeCfv}txUכu"'k83?LN6Nv5+ 5xjRc KѼJ &ڸQ>^@1h>Gsh~?x?M&0V4M{I (?[o^,wa,qt Q;>7u)+҂m٪ÄunJTb%2Cg+}Obgn8ĒoqcSJ)c[}j(ڳQNk+eU!eѐvEw" ~%'vWXUrxs| NWz pCQnHSẽs~`lX}w bĊMvcМNL,}!20-׸%.2 k THGKF_z9&N= msH\~94#ڪ<;ZÛݬ8klnsmD;zTn5Z]p|K( Bk#RWK5y\*1oV'T\" C9G r)1 ]9Zuo9iY( ?m)[t]V78B"F'L? EpS*N72WBs5uߪ6[}'/Rb& 1Y9/M8~ʹR/w vBa+{e@&L)˩.(܂ELA-ӏYc "ֽ(r+暴O4n"#䏽 +j=pu\A!H;J#H$Ac)ϗeйH]:!3cS_J ap{JdkWS 8͝pۈX@Y l3%knI@;N1Dؒqrһc3S <5=YHo4QYN€:(?KNtʉF^ゞcm2ڡT%.RBxP&{Lx|d2uV 2-/rZ8SEt+_enmϽezdbG۞m9c j CV .a* iw!+0vĴN#HV|-F.mqJ[P|f_2&kuX;6FHk.W*V1rL_ŰJm /mAP+W^ˀ*BKvos0e`]AY.T*SEJ5o*?JƷsg&R`|{65  ~ΉN|Tx`w}PrFJ{/ l4t?EIM~3n;@ /aprh `qU /|q㏾1u=a%j-ôU{c72e _P~{UO9?@sPQb: p7洜+}l&EM$bƪC3 H,JsSW\Ɯ hwZ)o[q}y?qvН0Jvˏj~ӷ>Tyə> ff$V7+ Ι[EgDG}bXh"`?3,/Gcdyf"yôu4U+jR[V2)HEo.8LegJ<]+2ƫ'CNG.D B텈Z㸪RtA`h6@-I!uOk&\֜h:KwנY= A;X4f. wjz ~嶤+nVLiy+p vb'd%)M9wb`= ɹ3, OHg7(d̜X|,x'4>S-M zNx%=i٘-| P'oQY.7FhߵID9 x*\1H+-?ZtW3Ki5 pty~,UuzY{&ZOo^vδv3QgTٗsf{ 4yk7cTimu|~~YRjc"}VC4O["+frs'*B-^X=c RKjb~{=!K;Awfga '*KC\Uˋ =dpǮ~ɶ^b/2&gZL.m8AT3VseL5OCH탟(Xp4HͨR ut[Rxffd~h)(3h( +sJ8#%Cm+=I)8橁C9\4Z-J~qi.{)61հP-1fZDDiPl:/2+Vk<Dž$*@Re\%O?6)WV%?V,J}oǦ}P뚨D:+JGPt8E7>2*Ӂ ϣ?aE%FυLw^:G];5upX%Kx[4YJnWZ#T)rÛ VŌ~S*=Me/bB`vwc;b<${'Ц.2F K&Q?odKȩ[`2)3$ ns Z%P]dxII@w: >< @//%N|nL PJ9I@#rHSǚЅ"Xx'TQəPĴbgy?7SDY{ev'` ƪp_ׂ >9O.q¬|nW #h N~_o sac+ 8YY1my0ҙ.h2G!;TsM_$MU6Yվ?'3Ba!bN&x hcv-9L!`5B;mrI `L^p3kAO(9ʘ zs/MLBD(, wro2LXdL =&=w oq<4ɀXCv&70'eG",:'_|+l^b557&̱oS\',gF 7E:!ԋLw8{rp^^Cz78òK} E|¸ALk3Ǻu0zL2OUYH$_x_Qh%&-}̔lj'`J04~O,N|&Gcwnc(l dʄ-*#Z$h?um-pɎ4I~⪣uYrԣKg8`AX _9Ǖl1ѳMS!r?ViĥtߏMP'8J&.ݎ۬LD\|MKE0hnb| LѤ!YE2}\bs_%X2Whgԇ^Eþw t$3<]3e\emˆ1lVUϵ\f`ۢ A Q\$#0$aFqw@{}K{g1_yjeV:M;'z1n;ZtkT %#Eͫ l^5D} [E/SSFaHRN0>cr5M NXev@s h{eP*\ K ޢ1\ $7:izӾ;k~KQ/zYqi""*`y=0wnp%ULB{7waeUt: /TN~3o\I0kg fy)w\g6Z2<+,oUdM]G$f*/ty⾍(Py ̊s$QeeJn%h,ژ ow 9Mp3S=FU;hT $mHɢ:$^;PEG*pcB|80d8LBU7ru6iqE1syorV "Ltz܈YEn-b>25PM+"[f ZT"3 뽻=,ۍyuپ|E4 ?GEb*pcSN_ȃȪN¡<š-)LO٩mY-NXrE@YMs UhDV?xCyb\b)H.\nϔڱb(aߕfK$G6ȲDs"qlݞL`G7GdZ9ryM;:'AVfV륺lE+>XCɹvЦŹɷ.IH^k?5EdX\{u)~B+pxnHECLdQi2ӏ~Ex~~$b#Ho>kEABq9ki߁*d` wJղ8FDQ7FػKkN8t;Da o0"/-9d@xբsMWG {QfV?hbx2Y-^P!7}2[igCћdɺ(6qrݪUI6* ܶL/3M"ʒ] /ph=B̡4>Dl{Tvv_Д& /د$'y9 /OñQzw僥g3 H>~ H:>A7} tŧJm@.^3$-ѱ#h7fERmǭy`.giZ2k?*ZUVCa?{l ˿svN8tOratBb7WSќ@<y҃D`E 7naʙGCxEc|j%-A¹FE\ϊ[)[D^>ΨIB TjÁ` #f~ѧsurС0wNT:7|AF "jKkpsFތވ GPwȖG:zfb:Uo Ā~#T{kH_XLJ &+[=hgzW=}e9ab5vg jFv~gm,aH8`)J̈́;} L,[L9-yng%Yawk3}ʋ!nig`lgMi2cE>]lqɺ+/7W~ 7*A{J*dEMn44º#5Ε(xC̱/'-'"$%2E-XLg'5~ 755^ Yg$Yb ڀou 5 Nt<@' "Izsߌ+O7yNhH8+Ò` e9|}Ia>pj)V&u=NIMgnXKn-$2v؃ ƭ1nap> MXvi$~1|琄胏F7(zhOma@*p}P mr/şR+fݔynٟtTo>@./ఐ9m'k),~6ӭ\ämPu;kD8u'ko9 1QU VUvg|}e?XQbo5n&ZWT<qhlb^Pr.p0C3DV=€P Cf tfABꖫ}dpp?t›)aBspV.:_P͉>0ޤM{*a0ݳ7y9>|W+Fu|]9HrQ$ V"h3Ь@95@3z7Glu\6u_|ÀonS1z5Y+/HBw'dXUX1rn~anˎ6 FED놸suw.2Z[>viIZ8wh|`(9G֣bqP}J5aXl)<5eu >3@y>v ')տp%J tKa9tL!eTmFG4yT˱Rf-U2CD 42N]EU$x"/}R`U8x(z_Mƃnp註Rg"`ׁ&>ɩ}خ 8XN57ֱl[\9|MN \.Mm"txmj׶}(t>֫?yw+1.=ךDKYq d`56KpL7aoowjޣtK. c \KDT >e>oܲBvU')۴}k!{Gr!@(Ύ8bce&e!-U0vM"l )j;]"(ڼT z 2 ;#IJowXOJW ";%!at4iT??ɕV? *5vtm_eiL^]|j誀p y/M#d]`O1ycv%2]-0O߬[l?֬$(6uM1V鐳j8,f G !7y< d%o _>碔`M@w;f>3+Y;otIֻUkZY%R]vɕ>6-o>w>6Q&X#5ap#!hYE 2iO3+'NC6yM_>1hR1pjJXrW6=̩w4~ O˵P|n2΄i,ƍ34Ûv)121;S:rshh|k,|Mm kkNWncb"+A[89~eܖTx .KBu&(Opbu;HRj\YG鲗p /$y=ʐ0dԺU2$W;A&C**(8KO]vp裞 ;9n (V7&Sp׽ʻ%*>Q$,G`¬[L ۜ9MSeݣmnW~ŤMG+ 㙹pX-# /[! v¢LGzt&%5 oeD,S{T#g_beNM~k%$LTIꊇ4R&`RBɋ6;:|N~*JGx+u6AL,;(NtK g4AtrRʋ%xSxQp&7ZzUwt,J,g_?K@u{ߏ; V$&?mT!۽W$Ln}sCEY[㯸Ai^ʸ/@[\or<̒dLSU-gjy?)_?W܂!5c 7 `m_" c3t 9*~=WGIؗJSޛ,ji5;N~-$<N2yZ Kܾ͉Z|m"T' E 3o^;^tkfbxnFMOnf54lLl, ЏZZˍu!=%AWZ  ."'_5;oSiApV,?h E@vU8*mQ,nG2at/MUۣH ~wҦ2*r]䔞A%D.ic|3S#~N ~܀aƛDҔu(],/tsrd0|PB]~m IԖU(@0F$jBλ]Ouo3eH>[FL@ Iΐ&TP£]ˉUBŎe>r!lWPkzܼ]h{.<ľ<](8%`E%E@5l>aKSOE߼`Dm J'ݟ t[kٲH{3iyѥWSYJ1Ug2Ӄ>2\BkYFL|4ɭ%]w \aQRfKH%N]7M4ax$qߤՀt 8}I??Y-:Og֡o*PVDEEd̃>U]Lk>RӥʯuFk9WGƕIC$# ,WF J_+x pjM53D2P92,D)7-wFg>xwkK_A^|o6o-Uݩԭv1#|J΍g(tv~G,YA>&Kc u PqPLRTⲾB &fo44v;[.a|8WBb&~>[N5Ƶg屼܍B15qd)-R Bn@P^d.L|aFiou!Gt sgRB)ljrz6s *(4pDog m/O<7k e,_MV1˼?V=+~)kZ@Px?§5O ȰܝkBY_33^!cLPo;joH#qw@Y똖9u彆>xҁJ'"yck\[p(oy8sKȥ"~gGՖ3)^o<,6 &J!c SBK`KvD* dD- ${.A>mq[RnDטGW6SB_RVr&On`0-ԙ~^;vC6y9lӮ蹳ӂK-ayϐt#|5N U+B3WiP9B\]z1Qs} mrJ~")K[]dM4j}J $~-M4vZtZx9!_ʛ"c1-`JP'\x8 \VvmP*u9] &7I^kMeR ^˗NsЕ~a[8z ]ڔo &sKi`(`ĉn xCMPD9U~~r"8R]kcjnRdb"i@np~OΉNX5FcL~*xsj#M!c?@3 Qr_Kqhi$ dR!revb@}j۱d^qlreʨ-G4 C>ztMPE$ojs.#4bBpMEl>dy>lF̈́0OvU$l_z|ysclPv-F%޳WPk C4R24g cѡz^T9^˝v?O1$sФM'egoަ"h+ܧ+c>ܐ8B;IB52<&S(R t ~OAQ=P`ӡDaDEײ`I${Ff O3G}^жY`t׌V$`.Q*l Al?w;ILuQYO%<o.VBB-ɆPbwlo"O@ک&nL%u9>_o".]UhIT澔_k? z>)(W7k/g^u0OX V1|KTw1P`릘SA.DV2#L/`9xHaM1< 1@JGo嵵Ќ(Q.吾]?]#@?yQ7AkK6w ZDMkLwi%^zclƣr ӟ0̇;LLT2ƃqYQ%T/Q@b:DKȶ#6zB_j@zb4v)aE&J`J3_z{'^^ݷtva#hk"-PvWȘX4LjP 4w8`mKL .a8*m*lC%Vu,yv??ʙ%R/d"nq)vQ0mYc'jjK91,d}Fkĩ.d2xg87|*Q~<) R,,Z¡SW9aQ,*uwhCtcsGl%J”|:q˂NH7P :%Jo` tQ W8D__UfUf:{yAHSj/)㕑lkbw`a[p|‚9Ζ_#'!L䴎7YǠ97c!|04̤*[d1-7+f!%Oۭi%JxVžmsk+fr$8w>H'e^%7Ȱ`Y*':dØѶXBXc.r5%inx@ƿue7Pf1NӐPભ?@q;ag꛻É0( \eĐnԠuT:v헿` b 2c@dwܹfh0"J_(6{5BF/L>u壭EU~>>F~T Qõ_ծ'9fU|cU }%ƿ< n #@IalC "sxJ8q]Mzj<2UXyEreSRa+'&jNj|oRaRA'ý}A BM` ŇSAJ_; D3M ).U`=+̡v`!ΎfŶ5=gS:\Uiʀ9B dC.0 1 M4 `RGBd YlŽܩ?F\ZC;Q؉$Li}C 4&Z@SpVZ{)=SiO6ZB&pb>/ P܇ާUi.Dz-*0^/X !fKkJ[эpGMli]^rφߦӅ 'D1RL ]I GSx G$Ve VRrN҈\΅&;[pleq{~ۈmoVU çɦaB~I,3 bwz,CL,֐j1HeX@}C?BvX9 ZZmCEB~0N29Td15g<07cq0ZzP#oų<#}tz[;oe]F{by05O}'b:qrҶ/@y=JUaXWJLXWsZg Kk'ZqCs)ΔL3p RL"r~#K 99YFXQFgm۵X p+7{$m䅧]aI1a(T7H6њ|/dר:ÙOyW}#.w4uYa`X=@ġKV̗83$Aaіs, Ȅ h2E\T{}9ON~My &vYri07u]PЄb.֠NӾkߜ"$|b"iAT QR_|uW :6~>yF?jQ@B1;sf.-A5;MJq-zpMCTGbkW ,7+Uقc|qZ{<]5̓Ii双@buR#%?/^Qa`pAABgwQzGS;״}kz$ܒ女g"^.|)wIяƼ?8K,52}ʮdeAd &,oAS&[CcgNqI| u;a Ida"ܞ<K $ j](7ӕ ;3TIghX/ aG]u]}EK>.L(*]>1 {gxbS;'˶5psarI.HV$MR=7Q/غ aGy$btAl,.g~GHab%N.ޑrcϼw֕sSQ&r*O-BnND*RCz9đyK4 X~ƂCDu(E^?DݙgY-T0FH($[72/P9GI!U,ղtmmBiڙ(@cqmxHƵP$ݠa:$W6$WʨVrf((OJqhѠZˬ;2ſŵYJ 1v8{-TGAbKyJd+"y).JNt`UYm U!I(}צ>P4#6M9LUV\ %1k$hùݖ LE2OWYN(\pmz=#8wJSI mB;pjX9T\\v,^:޶ލDyR et5JQّڈ2ѳO~ /SvE&2ᢊwfVc32oO'jTH/U8#V7zULi'֓g>rwu>KnlmGDIF_i^<uR?&QK',F@(\SDC%2FI'/X9(1d_=X,M쎖(B7<u *fIehu=Σ0<|i ԥ(W7?(u#PhLe)N{r."oF?9SqӃ6WZO;Hh&p[ z1 “/R(sFG;M3Lf<4Zj k5tz5 O2Yz3+BmVg4*;@V MZnv;3ګ"uBx(+t*Ԡ!jkAWpB,]8>t$hglU9-jÙ MB`+#W_w:UJǍ{z#>(}]z}M26d$PH—`#2פaOEHrV\'B`4`Ouydx+鸛 |bSNTMbd抲 ķziDA:я'R26:kܞqG:F Sj}lk푰Q#7i|d{SPoUMfՏSW9^[ 6)`,vCwI$_G-`ZZlZ~xH0<$RUǜfbHg]qїV}tD91;x(^:5ԪJR!E;U;] (YomLf%ĩR콼A2PmM4\b= %}w"Ȳ$#x0~ F&G %EXgozK& &H-|o C%V0O, :F/bmDͪd (JW.~r46ċ\ AX!MP~8̓vԶT0WN83@Jѥ͡ӌCMBsWZSsnx^RnVrѿk-C@GAX)̑b>ܐ JROVcL*is>I,~xT&mZH%^GAsT5H&J4AL )Eb f2ݣ0UDA,Fk/vUN#!il.B4Pb$,dw7ߴG 6x6pbڍI6l$[[.Uiك)RcH$!F{B?>O$W:/b] F װ!,n?F9}Rel ?)]KDːSVil|KYcY_!__@B~x@E2Ǵ|V?(u=]ѧ̋s4C=gh%SoYv.DW^s[g]?fok{m%chA`U:.m_XɅK`i"ݹ>)*s'HƸṠZ?J\5kĞ֍(u7k=׮|reU<'T'AD "HT>p3LYX@;DuMA0_t0{A Z/}UK)܍c=^'Ҡ88RpeKb/Z&,֡O.ZB-q;ta  ߋ# S𸉽(zy. ͔?N"{\{ Z|ۮ2mmN($5$L,Д}BrUYRj~_U }V Z}J23eL@x% usny2XvhJv8X~NCQIW8-xzw%f\;7 TA]YƯ|PN۱oY 3:;&4UC.W"[:#طZ?yUշ6I( :^v́p><!93*#Z5S`^_iWDk Ey>Va5? kJZi8)m4fnp~9đ0mlxR$oK{; a>7Md ƷWh$`?;h+uZZ!lxF8uk7?m<=AԔק&4S={_5ZegkM/ǝ@?0?Nc, O8-U^F] E岗ץK5Ɓγ}1 ʔ4K+p"`E2N*uJ[᪻ 3}Ji}0+"۶顺߮p@X% WE|gF\7gN,|22[P}HYh7h\|9+ 좸%1-QutHn B"p0m1},T^#{EaSJڕm Qe%uIJݠ-E\oOfS9=/Q>۟2GSF%5oF$#G?C :Vb\Υ乲}-j,CA* Чp_oy-fLs0"~B|yTB0(ٕ!+fQp>g=ԛkLE>@-Dʩϐ\HvP^?"co\xL@dHc 09f6YrխT ~ Yc$6fA}Lw,~B;_b0_}!X<,>,17*o1 wd/Z[`Ѷ8Wg3LJ3΁ ̛Ȅ{"҇SQkAaYv;7 qSpϮZz'00'ЫH5YJem TQA`bK!"jА:1 pdk%Q%UA2 O[|(8!;͗Uu9)/D'a3([6h@S'n_ +oBB塵Jkg0_H%#)K{!ъNJjon):t$& ?ETXjLuPa3ugu`Y|7sQ=_H>b R+~Qƣ&:Okfپ8a>JGa $'9HP?-U|fMLUpm,5Lb/ N].zw%&5%mlz0z\5vyoD]mYDn+Q Vk"Œ]"[PbtViHO$U2#{M'ڃ酲Vf@f;]c"˔L=[s{_k@p֚ ! <N4OU3щ+_ڞ2gtmoЙ T <蝱UxqjcP%ǒemxB7BؖGDgj8%'ʦe["."j$X^~9WW)kAۿQaArLWc Kz })M<4ڒ;: )(MQOb!SVBCIYRP)T`K={#}ޜQSK4v U-&A K9Ι2xv{mmg1hB5r[ /Z>XB7G0#D -ŇA1zwV;. άIDc@'g5q j>9ZgvYkVDJm|ۨpȿ@nqܱ{ِ|9G|ۢ}'cv:nG3"ǿ N63lI_[ ljZ/O|r_-asvkbkA. _Wӗ'.kVG2gCք}A MGpDG[//i7ά)E; XATe6vJ}t3Rv"`͖v`օN}|?0L ә4ٲ&h晻p;`J3bŜaznq9Vo'DŽ#͘-!hgX%KuHo/P`[n=N&~,Ioq{ 3F2጖Tg:޶}X'Lr[A$ EL^]a;VV-,Ƽ=?:Bd'!;VV^)k}S2ܓE;)ՎشOYČrz(uw .7,qR?^ixoS!x gcU!:ѝV7 LJ;KXp}I/ē6+C@\Klf$(5I #>=)4Ӄmh_lwǶzќEz|e6.OFXZ~o W  [;22oFZ4cBd* p[^ʱ <1 4x (Ͼ6r4isUU!*]>HΔ}' 9{>;q—L#rrVܴO 9NwGSpch RϝzfH\albb$U3$-{?n}*.T0)oC8)S°0wr=9{Ҥ˗oARwjF*qjHB T)dƁ!M|dlŃ8{&Y: *L(\rlH.Pb+6FCud ',=ȤwH:CEy5AT7y`FtAOA }--ʕdp1H>*B+x%xOT.^%t]X"# X6[Zy{oNC/3!x\Ji<)B~S@0s;OK/iƌIP8 `$VkWްY3J@|Q!"'%,G2S⢄f#'b_+ڜuո(:> B{3 d ecu8SWGmv9<ʫ|1+VB[lm;¯*0@v/ӱ9$Z ԶeG׽"y݊jK9W-$YBrRgɊ+VCF wP P93RzH 2WP) | ߇Z:e46F"&JטFMQ;K)8qlzH0'VѴUC;{1_VR?ũe -G>MN笉<&v RKYKOlef>{s?gL,FXE DN[$OHAZdjf2t?8 0'SeZ ?KGV>-[ce%˚ZȠ$<%z٥EF-r$Ld7\/}sIFrMpffӎ˒I{+_V>jsSTt{ Pޣ:4ow-Z*ٛTOXTxo ?rYLKGjO.0Kdd$x杇bR8;44GDS>#_o']ZcmR>0P>prn( R$GĘ]R[RMJ~i?V+'/UaBqɜۧ(nq+y{݈$5שr=Be:rn30l_+CXW$R:XUR{BUT iAObK&CIRTqyq,*}iC xi+ҝ 7 2v<v B\+d%8:5%bLǁtRggWqd= f6m} IX 4YCٙȮtE@L4D~ S4sXEC` Uu 0[MSےCX|Іv (Mol5gQ0YˤeDf Ȃ_.jA! ,>P4)ˤiq 4FP*ztB@%'K6$3967bvLM=^ .Yni,ͷ<ӨC)y` aDnRc2ߌX{3?w[6hyeP:l-[td GcpozOoD cC&>CЂ! IdMtP\(U;j(|q d46"޺md>Vٿq+2w%)a3Qm[]D;˜|%UccN#y<ǵ]3~mWHI "Jt]۔UP%ۅgK9}\Z nK!#!D+I.FIl/H m:hӾdOvoxNE@iFoMʆ4 wbP.o'Y` @ze[GE^ vÝ4 }gkrG{bnq>,mc;:mŐȷHrۂͅy6TUȇTnr$p-itn$\$Oi}Ey"\(QɊ}"-ke jv;̓y56-AD ]֩/ V>/:yg#00Pp_sS.^e0<9|KJ)I)u|D wfl nuxf}bӟ% XDZBءi0lKsR)SjFtn0|߼7M>'^zǩZL{A(DZkA96!*iKAiw}g\">/E u#8V} IC{\#314e;]va4^fXU6 `8"E;3[ٱ)"2B!kMdz[2׏u_EkOYNaFT^`M[y(Epn.X R[\CyTxbyX!l*ᇾ\$},4 .r X:ͭݸJvO,_*s ??7Yh>4ߥ/*p;@ q6rnިZt[]5 |^=c0's}bV/ ^8KA_ٲC!VMϽɮ kS5;MɭAC τʼnJ}ؽ W$Z 1 :7BOjܚjįN[8}u9hZ߻s*aso~JK[j"ӫfhjᒭY'8I!;KO[^UЇXJ O+= !ҪVXTuXÜNX\MHj|8Zj3>rs Lx0 %lr 75HLםLQKN7b[iQh|h'rܑ+95ܹ* RD ؋*wjl}ٞR,k8Wchcqyτ;&WFNE|;m{/MԽ#Ѽ iωs}t:ڱvq0liX" R,B|id>$Kb7{,XWVwhʆK,mؚPڙZdz\8%lyK\I Py]иq!v=kϾLM`y?Ƽ# [t pm]THe_A#TYdϔ Lss]ʤM-v˜7]kY|lǶ!"-a?$:) z_wtƳoZȸs)_zG!֕l\ LXTƁߣ ke߁.nd`ό |u$n{{Ik>gcTL#së2$9Ǧ9Uu=$7H% q[x色:rk)H~ px4 «u?~N{4vUს,Ce-gzJ=2”R،Ԟ !7I+0l8 fL']YvyKcB|.~sN,|4%Mϛ,.ѾlQ*_:MO/&&Ol7U{:uH;I{=6'Sop R9G]FYh>ɥ'`>#4KR i+erd{\i4ɯLVn` UrPhH)cvPDKKwi;ĥT{InۇJGz=94=sWX}qU8CER0=mj&W)92{`oћIoDŒWXKl 2vlL !</7 qIEK#SWbVXLC.k8-!N<!!X_k="ەu~gg![7M%Z;$ưwRJUFסueiCjJG,0eV}獵nB[pV4DeWvs,^c):UFJ7<BDOgƦŹ)í  Y^?(;Eqbu A[+U D):+0 Mg|2͈F>ޠהq{vWst,#׬ɠC3G@v(NѴC%GX&~V?, Oړ:![n-nOe#`l·3{v',(1AU֋`}o:G(< R3E GThHLըX15՞ǒbQRk}ߥfK;ܘ !YQ0 }@f=@0,B j1-Cz5'( i>g)lΪkO,dum^&a|D4ᐐB+y\|e#-Ei!^@3K<ܠq Vc6QرI0m~N$\oR;dd>ԑbuԭ.c8|mJ1T$A5VkoD-ReDmq]htpLrU׿j+fvcR*`^8cjhC[fNBz* ɢߦuBMhɋKeF`5DmdžhRh"]qEfl,.VL `2vkU!S`aPdC[s.f5}]oW<;C#kq,T|yl;2?D: >Y$Z .XM7p<{TU1%2O):wE6oD Fbdfx[<*~P{j,.j$~_ԭN)W@J( x@/ʼnH^?%&=8K7Υ߲8>_w`Uhx^e弹_xMGya:k+-֩T~5T|M#}g߀0?jƢQnС Qa`p`'i:L2U=;"#ČJC/:c;^{TEH,eطpO?Ѣl D3=F\ w >t8܉$=Kj7z|JCVA0p eW#E# AN#Y} m_:G#6,ѕcaT=Lx7lź/2ˉ})LN{Vύw$+Es2 - ޿vI`-,Hk*jMd) "_Ihga>Ŝx;65QqYB}5 3+);g)[=j&" SFg[n;G 8 򳞢Do*oYnl3O$B}V@?DF&SĸtC BNFG9F>*`;v$V1 gSbD؉d⊬X&kXO&O)c\7q}RO@ xr-%rUm1>(tQ=?3-aaϢHꂔ5,l>g;&RIAȘR3vYT!0I d "|xl+SCjmtu3[/^kbY:Ig5-;Ea9ŠsrSGBAϐl{*rn&:2t.sfrYMŋNtN9^uTɼ_aKIWrB0ԜLvdz.@=Eݗ!#%}9w>Mhf:#ƫUnV`]+9J"uܱJI8[ |c5'pttkSk7mfWR0")k@OXA:$.yssנ^Dc\c ikgU֐~_ t +-9`BSgR 3ׇĶYl(iwў>#j)E3p*|uXU>LхKsd9Ջ܆@kǷ*~A=qwx{'trG PzYQ/3/_X]M=*B ״KUY9 G$'Sq}eQPݲ tD'}2KTjD5W8YpGhdx`$h/sQ@3E>F~|E8OnK6q\0z$r}9ڡYuz,c ?2Ol#L҆(/8i[bvYd2*0 9+hI$# d!$]},lv# j^=hЯ&iDDd9iWF|] ,,۩q>ᨁ9dϜ0ayZQI|c'C#pF/54QpeW6B/ nZP?>ɬtx>($UJ `e˾xZ˪ϝ 7:!؎>"MpZBW,[楛C}VDVҤ; 1JkD*\,DŽmp1|h `5y,x3^H[HVOs >}*狆.oI/LN uo7}M"$E¼fzK`SQ&=4t$̶K9m~*Z֧jn(":Z[I&'P&`h"_h&Dџ*2z>ĖEzN{ 쥷H.J,p*J/0i'e{ͩ1rLiB\K4.C 9Tjr: bCln;qF8#^1%(Z' ƀeY*;ɭs- ~t%7'V8Ql̫֪4uD ujs9t TOZ 0@!~L3+[eW%߬PWO_>Ns\+) \1@5K1?ƍŵeč:jaC:u-X>Jp 2b]K).~O<|"R>ljy~)Ocz)Z@Ғ\P]3EZ{U8ÏNuӽhbX,] hjY1+:rrE6!\ڷ)+zlR8 ܌-֧pacLפz1QyT/>Nɧ#)MhO+x#r_+9:S/#b4:cn ⮭Il|RxL􍥬\ % W)qey^Cx8[Qt̽0/'>AT1#8 jn $P\zeaCԁ$k@yiI#of70M}IPwȱ/By6 e=#Q\EĖJB$@BT>\  op-aOp.SY5fkN g 5 \?hwt-jsB4T+3G4%]-3KvSZ)9|{zyD^sS2+/!Nev?sYrU/|~c:;8pu E+iF+]iJ#'rm/y-CCa_h]L,aNp#!A^|nzNOva@aꏌ[Ǡ6sK1w"2p,6q&w-uuK5aaiTD!bZX1@e':`uSQ|e5 pAH`gD7oFJQАfvSڀ3$03}/, (4W (X?\cWXb !܅wsR,PALxrj١xDʐ',9(1"}z~#BRYph(! Zs(C<MiCN'?ۊ^EqTq8a's*wۛpgh=TpmE՜õ#Sy׍rf۾^aB1ȿ #]q0e 3,(6ס8MpL?AjWˣ]~@b"y ԬPqڕ}6DI- d =T%\?}o/ݏ*WK F`|{  Se9~8J_B^MI$-RJB%n-H0j';X^ Z7{[^':+{an0|~I>]?E#v~.#40}ԜqQ{P"!*cѠ{AhR|R-+kb.HftVlec'=P.P"0d2,d(>gXBc :{>gPA'3ױX5 |l:W2Vt\+l] Xawprk#WwicWm8^78j-.8Y)6܌gWL_~^ɻ}%,j [ %峳 rj 2])=^Cdܙk:|F14 & ]! :mYtg@:Ld7d<UCj@(cQBҦǁaྫyi;ܥ;hNV[V|!I.Zh3"#Q_ҭ }ξJjyӟS5`&0qCL9uNtvB߻#OW_ ݮ@=oaҕFEQiHA۳=F4!diEX j;ZFE0a&hj,ڃr|k𷧢$i,|##AɧֿrUyj{"-wR,4*$ -m^FIL%XC I/mѼP a0m x@AɆٓ/{ԠFu\#W*euw660vO;6eL4f3>cԏ/u (u{Vʯ0)ߌp# .4}^QY%"܆l¢>MN.N GKt"P>nr^1=}NA~dVЦ"*oYQsY T"ia v+u(0gNA![ B-$m͕绳.3z}y-OXj g!xϮ`{0L17ǗXZxBt]HIVנRTqbYإ ?Cv*5|ˈ'SJ*HĮ=?^uA &~E@@$oWhk'O:Î^f(-K >ۣI̯S6c'8Y'/XW U U<9DqgN'X#288o2yHѻx` V~=!uosc|.5@ ܖUf'Y6hٹ#'7"Ƙ:QOyp]r uP5Pnsj c2[=L7+h,ޞ~Q)Ysܓ^y2ZۻRXE5BuS]jnmk+evTJ遼ȌvU7b+_QZ|#Fiܤfɂ *VG~wjHaG&SX-u h=W8Rg J0T,4ꭍ2HL$37x7ar(( 5NǛ3#G^9j[' VSrsPm'vl-dHQέY|#w]3v5]`JCsd9[%d]7rѱ p!:m\ ҆cm/GpCµ6\_pUD@Wǻ [=rpIXZ.aZ8E]50l4Ap)C1 8?[-{a[pwQI* Ct˷VL;O{ج  &TޏK"M A0̦cFdYBh3LDfL;`Wx|Gh-_oS9g AÞ \]9i6.협L:NIU/ʾ ]5~h9h+:홵Dwd.^h< nj6[+(Cد' Z*ZGD"L6&LnYu0ekawhO?{jZa4c09 11+qki D~2߼G H+J(NZ*9S&"8 hDñuMUi麯p"s&Ji#K!,ogZ-z-?i>#Lp_`UVz_ `iƙ!BWP>{`n38-c?)֌k 8H~+ nxj;Z1#R#y)s=XQ vX" XKV|D?Ӥ]CFj?kbL|7^[rZcS B ,&'% BuXF4L9vXG=@+`Bd~B+߭E]hE^铬z,ŰeoϖI}nI9>5:ثe0xrٯ?g>}Rܣ0ژKX<+#ˊ>iKV`s_ 2E7om;(sq1[5qGhQc'5RU~⠁(/B"t~&#i*"-8eMao!|8+<;:^3tlO9؉ Gt#H cǵ.8 n2! we!^U+Ӊi#ݲcxaIsNe4:ī\:Π:&ƫ"q|P>"/_xO6`|<FD+ںG&RQ]ܸ.(D}&+gx6oѫ߇gh󭼸i. Ĕ0\5]s1sW*G;yU,a2pۃ);˚fN<y+` Da\e0cknIZ7|>s4eΦlǫY.F{%2& "En:C9g)Hy[G؇.yeLE>)з(S Y5iحC|BmJ;˛u=lru)wvuqj%H'k)īD L f`5msJQ6"bnS/ZuH&8PT!ѱ>¨ǢXs0rW 8B&r([za*ƫQ>r6C,'>3h?8.0J˸ `o,AGO+ks-hl?VYJ':X%K Yhs7晷zgĀv,z|>Oh%w p壭m2,9O~P AU^2}K(,Nk'hЬwGnYՍ;e[u~^ .Tlw>Hꨁ &a0 e:\jm)ҩQ8i,ZM5C&M_θrIV->5A([켇G=-2ZLl7M9x< Lb| sаR!YsKw$A)unLP qJz?[vҰ El(_tY, {+_pÿ⼌VY5yY+ Y#>aEEGy+, ίLnLj@jr^Ăרhk}ېGb +JI;ZV)rNW7fþ(* KdYR 1Q`\NP+btm5Ʃ3L@ed8t&- h5S뢈jРSde s%A:6Ik@*UA$ ݒ7N"3Uдߧsql?z8fKVʐq%DLujD*/0J к;!-CfGd_O&teJ}>*;<Z;DzC*鼕gIKw8l#@oyWlM{ͭc^{eV8PD^+0 p?2j2 PMXq.o@BIV5py'/-)'m Db51>RM)zQ]. ژ`Jn4T r";=3):hjl-h;)I|׹F/υ4Ře1VMȓɠqEAZJD[%@rH4x^Y#'u>RoRK9.4{(ldÓ,[9e^lՔvQfY9ǡ@YTPOU+W?4Ȃ!z7QkUbI+:bgp+TUX(:V5/L3ţ:Ũ{$?b4Pݑs~ophY ! {XC%i!,Ցe h$j3=E,~}8cbC{#u-pJ;6eBHN aJJnA,낃`MPC$-Z6#<[N[.UgyC!? vk®a#I2lY%h(& BG"؟ʭؼTH/s?j"68qS/}mrwc? N[cR>ɰ$rO8؀\69B?$4. ko[GZl:F1kA|7zxj׵hd3MńUQ@DeO,QFާCvV6B)7[y~ [t@E^u0!!{< u ذ!mcZCgRg![y R%!tzH"BҀ*DޛjJ;Zek%V柋iz >voe"< j*/Ub;m*-R<OdUmj v5~ձc\D(xxaSuZFX yO3ǔJ|WUm\󝳣mfB-N"`qH`Yho["b6Ez 00KKi=?5.ń:},5] 28pO%.Xŗ5!d#w/H( `;b*JL5񚗣)҉6Fm0##js_njoc@lNv \88gB:-g_onߤiT~vod%5mL'I*;?]no@%{)Z>®W6kFϧr5Qf򔿬6J E>z'$G5}).Q5㔊 i[˶5A#83yBMꇐBOv agT\m2)X61ȇ?#oy1a?®o[Ԛ[(~1$t d:FK:i<:LĹV cax$>Q%ړվ.+Gr%-I+g ѺI܂~<3̬R͸u_5Pش5E 1Щ:E5 }J 5PǶFw U+bXce9#CG'{-dqKݬt"+MK֡II@v;E zjdQa(k*YhbM|U*WsqnX^؏ ]oFn)2 A/تy^ yg͵ʝwJLZ&%_d.͐^fzKB9mݐѲ{gjMxb@Sg\ 1_ n0e@MJQ/XJ`>r6Ju?o$ctuIUS#)5XEs( 9nk۷Chtۧl^ѳ9P-z } Fa _ * ;,Eg>?@j4H-4X^"}P>UM Mˣ.5݋k(T6SgTk3ƻMw4V9L[3C*1H<an>OrS]PW NdY .]))\uqMD~)W_N -,܅$rBh~NAH (݀ Zoܤφ'S;pEht[ۿFvxThY&! ^ ]P&;iN%9V$lGT;'FUHIl. hhyv ^b=Ti7ݤìh T}4=]﷉HV\}6n%Cʫ$gAyLi+RJ vώqñnENeA0T:U樰Ʊ9l9`(Ob;AEHw3ͪ1ڕPvC?cQR (jݹAհ 1y}NDD'ciAyMi=TZώV `.W#XF?Ǯ E1.ʹO=)%Ozd];3w.MlJl\>0R|Z#.}x(ЌΦ6yֺoNifevZ'ͦxbS@_D`kv3Cй_l$GA*c'e`g'BS6|dv I <:͗};~k-j}R, m) 2 LZո>RWD'À#hmF7LXS>aLu ?$bҋ蜏t&=}( /6l<bVT/ IKDTp YҚ/6Sxj)8dԗZiO9&s! K(J(M0گR`v}ʟd ;4|Ǿ,%DŽ.ut7MpkhD/\Io$+DJmfs+Z>VQpΧ{W`;ZsTsq ϻxFݸ 爾f5b6 e O:Hs5vȖSՓ6'´Lx{RIBގ i[k ;Eh$0JpgH$\ikh7b/TpPi 8ZJW#k7= BǾ_6_ik*įr_h՟o=[麱&HqIѮR|Щo[7s^^#wTHY/+un\vsC/=;¬$GMb!:vo)*?-`!lË%.h &:c&ALL")jfDdm(&#~K4yJ(E! (r"BJA~g B6-OvA2*l^3:eJCaSEI|=-Kt-n@ ت{2c| ^_UUi b갢T׮?|mt z,01 M.h"#nPLNT! ]u,n8qG-G!M 2j:7 &\Xn3SMD;cJ71QZw&/o_RRfod/v]jd!/]I68ٻ?I=3rE ~̨hI`_ r]hQj Z^ֻLez& ( =G^Ei|v Ip6b ~WFnCJyԴic~L|\MB /L/#gJDxqx_b;5XL?K5U*hID(Mz7$+Zy[^X}壅i(!t aw?hSr0,"Ķ ޲ < Ä`I-}bAd{0˹.y0 yG}WKg9:=֨wrIᗄWo}ԺUī¹Wt? sDі2EH1w U'PK mJkQs^B}. Y@>9]ޑ4d A͐s ^l"*IrV؅ C`xۏkgd(m)3 k:6(!D8]DgϵSj-ʒdB;`I7O"J|`:./Z*0L!Y7 ލ.ҌM95J;0~[T\hxa"d m}rXieġyyϜB"pNEU}6e&XB-WGYS  D' 9FYPz%dO27|Xc[9 0 jOMk/o;k=V`XYn'Crb >f_)^\PN K_IDᢐ`u8yߔ֔Y5O%%XnKțXJiZM=JE?  y˸Ga/q'ˆ(د#N6%^) Md,(,`0>y8#x(p3-YXL )f/ m*3Q ;(H/l&Ij)1SQ7qIQr ϫegN(rW\oVm^cKT:^p |8OIRx(HkicUX;t'?2wrwopX7M{g(Ho:3n'8Z" ]:%}Y:z8˔ּ=4^c@)N5: ܤ1B%oXTF82XR6DnvνDլ>MۥL!N 0{萰!ZEOkE]ge"=q:(͒9xXCoԞ|JrV!;..io@t-u^:1Uo?E}}v#0,2#SX~E@0σ9txbkvFwX%Hf+>1LBA1wQ4RIǾ7aV}Ge3rK^&<MF)=PtIb{ O.p)>U6Ԩԯ_C5@S৵,s Y@ ]\A:yR7>/rdM=hkr pC@kБ!>bĵ\}@':O #8x au *e ^nbaOz{P2wtWo 'K^g#;L5N _-oaKkRDj7gs`mf)g$ErC:ny{sKqfSFl>W13Y^S$.1#I,xrIl*HAO(ưK>f$"5F(3q{SB <:>xU mf;0tf1,v 뙣\<}&z?r](}1`,D8`@2-Ԡ6N#?_聍p_ls H֝zNrs& #.4 sE&,اyp)4T 骅/ZOHXz7G?(͎Jge* 3|ڛ:Xw}uM}S2Z>VjybB/P]W_AkμӀϙ"'zny;AϵRZg~6N|ۋDX{Yix`a4$a6,_ӫ4F? vJkbLxzK[W'~Jxt`cts{R qUM&01x#Arǝ/sqˀ5UW];T$YQ,*&[`jY2LѾ~g5t$9^6zXc˝F|{"׭CRwU_.l}Y阃n׈)x,>T evx9"v1}l,B%~bQ_m5W 5ߋu 4 =ᒯ6$/f>QPxӤ(CKM+W?+> ic5TG0_Yd]+$VDuiѪ^w mq]k,?5 ^-HPڋ-MZi]ɠSvֽ>W]\Wʩ9cH>^`bOnص]:Qmލ&h ܆/ْiHTCy!$#lLav{!X!m7Ba,'k} w㝱ڒ$2&"rH +e]c^Bg˛Էx=N9wjAUx$ `9Xo^cӟS١ȅ?w FHg]h-Z{b5BҸfl`|K>\pߣRVZF "@!/eد1LLwrC<<0LE雷*|! uo qGV˛r_|?YIwC4z%l6iYS t _Хߥо\j?Ύ LZzoT 72=b))e4[ɱ_USxJqvo%[ȗݿ"S8y+̈́>ĩޅvV l? y$"t.:߲`k3bW#ЈH5ݽ K7}߻=#7R=SLRBtV^jh+:{ks=:#4K_VJe8].̖Ⳅ^A히IeѬ<! P< 1굇Vf;-׋ |c 9̇vIAS1O][;D}SC4? *ԛYY+=(T⏹20i.S$:ׇn-{6*P? j:=/g}CyUבy7ZlwW%F>P=^Q 1L\{IS9n!I|BH@Xh˓Hԁu9>+9N{ޓFߡTYyZ; Qn 1JYqƗ1؀tKِ'۽qvMKS~xp켙jjM5\N(& @l8Z\K)j58SAc1ʔ 8.N etT e}'iѳzs5hp<Of&F7Mc2Ļ36EKdF{W&BWep_uxTF;/0>iYApzuGjߋbVlq䯨 KEi7c9+ b6% b[Vp^<_١x|FsuWXi?|YuKJ.S-e{Tk'ˢ_fqEy}*q)FsYwG\ JW'b]֠9E;3 +  IKj0AC`{.c$ <#"µ& (Ֆq%ܻgxHz/*Z|=]I%1|Ke!,"$Ý@kNEFɰ3kns2*mZv.8NgjntDPc"p8;@{0IXcB&T$Pݬ:9H rNTvl8+ah2>v*u=Yԟfm~x|l^6^iCS"sůx.1A/#uC<>) <=Ns/;ZιEr^*t:XY{\7R}Gech@@UHot 'XH T?`P ZNp1m(?"iR)XNG^]"}Qw)G/jǑ:1'meHߎ|*dGٰxn`P;a3[((&6:$jdmL^ji>轣s) nrǥPz6͍1Ġ3pM1ĤF!#[0 +eՉ/0 9cA+R::*Oiz1'YH΁I~gx`4G̣ W"@N 6Tn׳Uշ(D7δAO4-sUcw̩*s&#胐B)6h8:¢EPS`ȭlɆY靨omZEOW+ҩR])r۬1*cX쳈^4L+_ {-T fG@D;SYprNq>Z\ݮ&!UZv 0 ^}DIAx<\S2q^Z]{ʽ:P;9{# =O+qoop']jd4F2Dj`pJ*Xp$^)Tv_;#Y-{v κppIm"wމuF+s^Jw]P'8_"SH+{ZPpx;wQq+M!yCTM҇A~°\Z차l,H4= ;X. )bνa}9l5dg>ҕ/m¹i 2!76 eHuAsq8Ky2OWK$ ˘Jkǧ*$$~yxMAdˆ%7l2ȑ}f/. ؛c} I'!Mp,*UrŏC9SFKɢ&]s_~7zU ;"s;@+E|K=4|WwrL/a#4G%d×JVJŝ?mԓ $v]h^q L^DHKۂE\udbGAR׶i;iO]ͦ!##d.AU{d\I/u8||coSQ^84~f{]WЋgVIzPM#*PWXν|WȘqѼc]vMAjOEMHSiSgbm=7cQbHIZL3p-f̮2ґ2-AH\4>[Ƈ׻q.itT~q~]xE$V>ˮ; 7ɰ[v-x ͸okPgiZRK@(M*>ygH[.0'np !X s"75f_yS1XPU:IRJwo˟'44(<_ykJա閘s=N_jR_FTa)U&'3g$n( 5ϷQV ?H!Cm B;\z72N5ďAB\>6ww/MA7wEE]au?_`B5>k5hAg[޸Sm>/tc;ͦڮɟZ+ ==W6"c(qp E$sJu?@58M̢HϭXBF - Zf^=H΋JLPnEpvtJִ C K"[,_ǔ0gjo0u{ l_] }!+gnחĄ=7":Qe'=QzRʃw“sK?Jі\/> 5p# HT/IueL*_8FBώ]DP !ІI6$ퟆo|YI]ʯvOrI9 ]cXj#NЛM[uԻUd#~HL>3U( 3cm_zՌ oAAeEq!ReUY^A2J[ wq8ub>OJajY Ąq% (v)Li3#Y"We³ ͊ c X-ߊAҽ{rsL*/wFK55C?An'Qe)ҭ.V"3nI]$vƅh<~ k;Y-#<5Ǧ|gQ>P<: offjE j4^./N$ÿf.*UsӃ5J;ٻAz0 kLlto*e)sX'6sWO/5af+=PzޟGRTe J:rWRxDiִ_O4Hw6Mqmʞ6f%؝؈ C]>CZƍ I#Es4[W\ZYpuԾ.pBjT?U")M(ԟQK$֬q1d7;Âp#zlN-=b7fIeA/^pl˒yT(UUN4fZ+ѶFLqfe-څ[P Q|25-~=Lwy^S$][p<_L:tR!Z^m:9ˮ%99|ŵ1 3WwJ@G>%到!$3rI_XK [#q̋a6{#: "1D""US,` c(¹{̋HX:LLPяnEL@*1dxS+,iOd/Zm ,ZQd"F6Z:Cs:@D!! 4 k<{U:Y[̷쀤{i_!r Qy8A/XZi\ߖɿz*ɋTbG"m.<$)Zn&Nf+B(cc̠= rfZIhޙ'%?N4y>%ܖE\ɠ]{di ߵlg;bH PdU3\Ԡ`a~~9:V bKx"r7cq2ﱼsZ 7/¢8}\jC&}Wiy/4jdx;ORr^m[7Y/_sQncDx_#6kTi JmBPw*_î~O4RWwc{ $(T;Tk1)nI[I4yJ> %R jkB7סT9+̣wl{:A?+ z7w Е0j0U?4>1ko$(`}ntTy8IN`PhI1W.+ @*g)+f@GH²FcN@A83WM^l`Y0*E&R2I3vAµ@rh[ 7&HNNJUҺmFAP}ϳK7HFuj$@in~1@d]ChDRY2O#ݖ@܀MƜe`m꧗=I]6Ra׏"J?QsI$%>퀓c["{ KF#1@+ <./2o yI|=5R1b1e7= Oh-S|F߃6(O4m-S/HВlKD6e9p <7lBg>7zϾClfE0{?LȷΘcܓN~'?daUKD~tTȪ;wfDm@lI QQTĀ_q; BXTAЕ1B$CT8 ?3M/s]z>:F`6+tOJ[b1͡Q :I|F5B%)N@<6Vvnsu6;}i_&|+wBa%s`Ҳp1f]W \&"ͮ]PvTś9I*SԖXrY{֫#9?~d }뙺DcN8Q+<]3]YEa+3S!z[Px.yutWcw}G/2"99Ϋ[e" ky2]T_WnVZX= 7ʨH;$9  >n;ڏ:A>g~7h1"ҸpJw(QfW J!1"smg6dBSY7ˈ%{т!2no9bt.*>&H$"N[ L&L[BW-}SE`eO!]2ig[ w#myz+ a=4Qrr /`o]ćhmڙhkT_G&~kL~2IZ`Bڋ{2ȥK'#y}?Ù\^U k$оڬ#,qNuP  vT !?e~V ? w{ :=6ï!e3uϟ{ȏ UE;6΋ŧb[nLkGr+&xIwzWF~cgBũܳ>؛/?c,Zi6:1*>:H|`Y۳Uw0osJ~J.A$NUʧLdia$2t1O|Ҟ2-^ vzbҌD0Q{p:FAK"/FUKVEh&Ko/gV?3Id$>1gch kBjr96NTҫfw$zoTB ǣp z^)]4JmC V"z%Yk.,6E+e.ӛ(o6F35kF+ njB UYIEȰJm^^wZ%x +X g stA[CЙffF3jL 6i%֥eAl.eʳrIK>kC#ho, Lи".[y9C9 j:Dr~O+#0eL cI(sxv%&8$Ʃij ?as=@^ ?n@[s9WF…dXm%I/qs(m^:S|S&DcnYR#^/hK;={씰NEͶ [L a)"D-m-XӬ)tiċ,0q~ߨbax[)tN%Jeg0aYwyVQg jU4~~0=:`J Ư!O{J];&SVCMg%%~n B3lO[<,`!iijeMy[a꾻Y*Lǔ!4y];8T~Dԏ\5 vFc9Fx 쩅r"lxQKanיnGY5%)BqS79if&K)Vx مI3 }%⏘%Wl`bNe }ʔ6([ȓg׫+8x(ZAcc]ʊ3C!PC$6nVl\FiU'{8<{/ۊ')KQik7}9|I"ZC?dXſ;1Nx:%ĊY^e4b̛&.9EH|%&:+DWJMx?K͌%Nh5% EsLۃ5f{xm4i.W~C 3 ~X\{c#E8iC᥋:*M1| IHn폭UCrL;>yNc2iҟOT th@WZb0h]YRVSp&t[ zV 0 ,alf՘%S@ʃ,{*"U+cS˅dp9E~2P?~73 #}I.&,.&OMV"ŢCtg"·m u(&eZ.g<8-AEMA'9{(W71ie]E戕h-[}ɺ8ھL#b\yc#JO>\dKנ2iGl̠IL^gfmuXNzp!NW× $&q IU*du)pNߧ[T;a]\qRمiɐ$1ڧ9aڪ W m JAc7.21烰+& ;:!<-U4sƉ3hUkoYPƜV!|(L\o8XXfV=Ly(8D<gRO_ײ_| e| ݗ2i9HEa1+IQ߫BK=,tqʏuW N'3їIa, 9Hs(eD@f&VI ?O/"k̰ SxBh*;0Fe-e_˘J 4["Ao^415,s blo٫܊ *joe5hXP\x5v2+LwIY~/K ]#S;I#3EoZK`D\(]Oyi%W(SF^N,]>)ĸr-ӀzVzd Q) U;DSZ\d%x3ǚ9k0LIYMka*Q ft;jGC_e4RFV5$'MCQQjy\5%Z8M4uG۷e1ZuPߓC*xgNWt)PATHï>]yZOޞ X}J 5BlyWcDDl4a'Z)\ȱ]tm"Pma*J'&$8B^8R\/c/ș:‡%mzR_7[Lȥ tB2WNbaln][5fF('zkG׹960+"ȜU !%QX6A&e^蔌Jf]z:]Aa¸K3R`W(y>3+vb&s$p U@pʠ_4߆ *2g5$Q?RG1dU\R͂m7H҆`NF= T۴a W.݇p;euFD9/ UuZהolLkѕվ3 N27O4\݊N[\*vL kjX_Տ'*#?ֺM!76 h1YxJincaݮb?疁':U6~twwKB`>OߐCü~p?^"ɿY@)Gw^52\uvÜޕJ25]b2v>+Bq>v I] s6\dm{@4$cӉGfY0YƘĨ}":Lr!K_clf_•kؓ 1Ωla'*+ tg׀-xUd>*mPTDثH䓔n,^葯3SEltSV:{fF x(bhQ[&ZDPe fh"wA߆b [^~+EL˳͉KD /wՃHChh+P1ݤX_ЬWD#X7n,)kwX1,_Z6cjut/!eZ؝WHK yN,}BGfNd@0t1NdT}Jvƹ/,ǜVAaB8L7N[4w2͜Gi?~P 2 Y7&#ٺQ%d99GK/SIh$ TEb /hB kFws<᳑6kdR^xecH̳o5kV5ν6ؿZ$"bԲt]$Mײ飐 տjLˏaqbbmNDUS\TicelB8vGa'}\Vz ;R)$r|<243Ϧ:9[@vJE_(A/L&G4]eunjNC3gWQLa?ڋ2 .uKI`{7~^E P,1iX28h\<1؏϶L^СU^qd&G{[VPXGľ>#[3tc|kbtlOE_%s6oX4`?=Zqi5݌Id|Zׂݫʗd ;B6ӈhtr'";G8`nI]>|0IÍx!۽s8Ss gP%EJ?D@s^;wc{G ǛXY:7B6hCڼ "քz~Q?. *pCT}+&}:{abN\Qs}K˦AR9\~޼?y1= :Oej'[wpD 1cB) b|=43wjl3|w!S&,%2M,8[eQ0JWz:g) mC3K'^Ѐ&D !ipPu6[c?O&X=r4NB{eB3ߦPVG.gEpBE G%^#0R7QS, ;'D+Eٓ2U 1iެ嫦 <SREw%NYyJ)RDetȪf2;]|OUMē è  r{yf |ǸKQix- <v`!;VDh Jà =6R=l$B*&$Y!yhBq>9:W酻("aԚvVj<dq+Tщ|z?<cY8eBvsUP6/y(vJŮ(A:Esᘗcϼ_ts+QPwn;W-Mdrk[.~hx(pN '-3?2{#C!1ĆF`QPqNWGԞB,fj?=a0Jط:A~j ] *Vʰ%>r`Ҏ~Q_tEo}vָFǻ6ZP`*`Zp_ԓjfC! [ `={`$пʒ5or LЄr,wm\/0T;[Q󷻘J6LFV߸UsU,"?RR 5{$!*W{{iU:C +.NG,Gl\F݇ALs(7Lv35J&w؜,)`^eUL7Ļ8cS%@G'Q)?&sI]]52R?)wƚI@;ݕ" :8ՂkYt;lǘ+Ij}衎oOBjj$i H24-˄NDDgp@yG/HSiyp`5̤J#Q _.Q=-+ڜr.}8<⿥_0FYZ7%Hf3p]rmFVqa`3qȘ9B4&*S#`ceW*0zYׂp?12y]ITJd& ߖ`AUEg k YV~@)s1z-L b{91VԪo0vwqHǵ0v v^,^4،d:Qv|2ow 1W Kwk-A;WR/[G]SQڎPtP p!PەTYlᲴ,}~C%̱KW:暼MۼR $QtU}Ry?Kczw6) $r/yK͇ǙUMƨj[sG (2ZE)XgHuJ(pn Ctߣgn325nUN)B2pi-hxXgqƨ*;[Ż\4F8LTs9R-EnK$MܓpX^me*` yBpsҒH' 4/yBi,@EGjxzΌ/Vm)4T烴RW0 PZk5{LJG^yK㹒Èwg hWgX+}\*{~[ӵXޒQތ}t ׏'),Jxӵ桦;f;ihl\) zdf|."n$/EU J5!D}b@O8$lc54A/:tR@n\R:7 !Ǖ8VVV9}Sf#1+=܈qҺ Ҭx4 0T L7fm]QuB \u)?68xlojӴ{\`Ԏ~F,1˷4d}֗(=I1㰗q ?ZY#ܫ;89roiC8Q0VǥF ߟ% xN~m'&zZfLZ,4a2d)x#p2i4 2MN9y'UkAt [z%.ʉhF2~2P'Lgۧ*\§;*!9IYCsC$m]%ܵs)j??< J "[oѹlm"߿w*%"ÅPY*9~?]3jS|l!B}LIZn?2DJͶi#/@!F纮 McѐW;'SfL+lB/H&E#"8&y<=^a y" xK JP;9jkQAC#5U4jDl]עlEkY4Kcr#A&I]iАit%-"Ԟ;0LpѸ EK |he:;t%e8qKS7-"uOW:Ie%>%G!l*N0pYM' !9]WTo@-涀j*U(iǭ 1]0ycTay^0)fo֝_qk-/s[:?tsuDHU)`G=~ V!+>7i=j/,~)r}/adNA.2R<• {]j},FAL(;t$w69lV )VQ[1և9\cTB|d oϷ?6ʻ Էq~Z,6h#ȓη,H՟Y}{zv(k4Y i?  {5ŷu6x^d>>dP(WU\80lX0NXhl V%y Xϥ鼊S|V]&!cEnJz*_϶d>"#R"S7ڀS*sD_q:UOiuadCiy$%&ai0=w=f.]sL҃fжh fVLa>?{4evd ^绗1CsB{&A`I^ib~Om[<;mXAQ/v4{ne3 ۱.q<3fU #p;q ^g`nOC,Z<0ܟ?1I N(1zg7+P5Ц\svtض=8 mWž O$'$$1z#<6J@1G=[(tf Ҁl*1BH%Ƥ" w-PLv}'T NNӸUD u<]%Cx 9%RT>A .' 6rJ{h etT B!\Gf`\[4K1 G Gg,IT#3[#;}j>R{(] ʊiƙ8^R='~2*cG&ᄿiq}>q{Ѭ#cNDDp#)vp1'9©9q 4}e<4wTceА:kA7.MX*K[Nâ1oH̬]`vtg}pJsY@K̋-=+K!bů@^U3_j;?[(!́[rq2g!|S ;fJ.p vjGaɥzBDjd2 Ux"t[x.S<:5 gq&6, 0'iK×WʓD\ HPòKtX7o\E6y9ڸw9E٪R35k6ȃ s$&aqO걨UtAZ=e],`g\Ic qQQS a֖oC|'b;uUN^1Bu,&5 F!ހ _gP }%a7bb~/X<#bg+|4AM=- 6kY*&d r0L#uZЫ \Sy1Nm|Z"2!6y[Wo@;J&8>fG:(zPfì< H\ Jx}R>Ch`K$CxMh]jך*zu7X4[g]Jw. $(v̿&Qɹ{Z1kv4X~]sTܯzdq@ B /kC j[TAܲV^_d~C˭v∝ $2.`ޡ8>濁*BUPX=c<Ĭy3W+eһ |Nu YNș;3QOj',@hJ- [n8Wh^DqgK'Sm8/5#ܺ~qJ݃F= UU6IJGMt}ܪIHT6lU5f8lEHbq];o{ I؍M"ZfrSD*nEׄ/. 92&KDJtmiH5ofW0QjȲaeV?HiRBe$ϙm0 }$X"nfAb{5(1m3KWW:Xo:يpr99v,-@f/FvAȬ|buo+EK Bkgq-Fx;?B'ϕ֠cvEChzGiLJ0pxy(P<|4R8UdiS|n u_ 2x { Ujڣo~@Jgt؟<վw>E:MCvKGVg--@d-Xj; |mjzሠOQ|ONM$yti3SPZwX 6F-.L>Gn!W3zq/*L2˱0Cܿ3%U:Mj:3т6"Ϫ8wZ?%]X(!ξgeYд# :d4hsQP }%Tv}a! k2:df@]5 -mWIa:wN8N'4M?XOh:6S !ߩ/Xj{+7ި-YPo'5G M~<wx-E"E;g1XצBKN [ڴ7T<7l._2[BiSٯuH[{vA:Sº -YU8tZo )`?9* ӵD&ue$M^mh&p .pa7(CʧV=0ID0 /ʰ811K !b)V@aw?S NH_8PO;L1!bVT2&N0W;Ge2ua0!*oEB>,OkgFoԼ|S\10@Յ]rFՠxDM*BϭSa:p kYKZJ"k~ԩ $B޻&R4B֧ (fy|_@D-*w :qKűxҝw/(3oƑ9C*y#Kj7[f {c.ߧkeզ5U]3~ukFl6ԲYV.M>^ujLF׸/1W!vhb]jX"DCva/; cPS@UDaӟ"&.ȯMr|٧8)Yd򙷻{[yN➾E˖0ƼۭpsTNf0 NDS%)=Dљtvoߴaוì n< +]cA[AA y%xlR~ТB jyCZ3$j,+ ,csR&r@LJil?#,,nq;H=?p.5 _A> Yt4ah_KoJ_l&=mUltX0sX0:k1pw:]1S'IJdˆTRϊ ꎢᩇb?M g?"pA/:8ɡ/#m]c9 /ifRpGzxFafr'QHQܱYqizVJ;Uk!bcf?̸*t= ٤}^W T*CP8L%0`jM:{ʕP1jya4cdF&A/ViVne))" P eiE73QP\NU8L "#N!ɓϟ/ k ḫ\).ZmMϋRVzreLUwj#hOMq WI$>sɤ,rmՖg%[0|1I]G$pMH9vk`0kJ삥u77y>SG#:;=37n9˭@* #*$J0ųo<gG) ]#G<=>AnPΠ):mY8RajqwYS-ka%yEMpEKT|%Z-8U@%i :lG"3aU5Uidax$@!̂:Y1a<> _"̚1 MIADՂms󱯹Tae$rʄ-: @nS 'S@Wu*x;΄W/tPD2º TӰ|L{z=&ٷzHwH,A=wzJ> 8Ӝ ?,ۚ}!Ug_NrHmX#ӈmK" _XUC;(u\4C}ML}'] x *pVN>p na Xkqܠ|(\- 'Ϸn-82[^=Axs΀5kpR-O-Ruމ.(Dў2R 'Rҹld@JqUT ndEJ-L4P6~ 'w *{yўu: ds`0TFͮ1 X<=]2dK4 hYi6=bz;{1>~IGg2s*7*,+J/X+2t?VJgf)أM6_d`NM./Φ9̙Vm W hT-WIe3гh@W59?,b7 .܈̃DYQ2W QqMI0TeAWYvG|o.BJKS[ ;E! f#|F$2YO},g<15A] Uꃓ*tndjF89F'ñ`X趾3[aR^9s% yIiohr<ϯ\QY-d쓍Ūg1#r/V24[U/MIF[uQFDI @pwz.CFG1r„^ pRRC H=8NWƌwmtJ|hH 8 o垖*A=Y+?~ph s~;m/N[ k^*<L^]Vx,Er,MкEBƐ?2޲w4?4x>M9@ D &%18=^fVRMJ Zc_f$*]{GVHH@Ct>N3YRrhԴn,{>vV`dhUOK ydBbKZ@$ő M4YLjG˞[|w6`H¹eG PR*g3vBm7Fv pߑ+1l߻FD,]I-'lk{اoYoc;IڕK_8oCជzD#љ* ExG\>&QjXk"m0x[ #/D "mҬ|[9-a3aviN\HZYr)Rٳqx@T;AN5P2PNAI9>1T0#*\`W ,\Tjŝ>*/ A2STGk%eS:DR65/9ɓs\aK]OT'Ӄ7;7J.o@ )T d뢔@ Vmwtǚ el\]T;ۗ"s;s;mޭD gt'G?8c8dP'Yz\."級ӯ\vLQhgQϭź:ٽJH)w#taB֛7w6jkwwʔf~c|dlrjmD.i ﹏UfrO %` .Vgt`d=rPO [Uws`m.STɜJJWyZF\ 0MǑJ<)4-TErX3 3D۱r/: Mzmli"EX+/  qlL3*.6bKo`/0+!%\%p>HHfh-I,#.(C3謤 :bIqH ,$vƟЂFv}Yi*KoM^V>^8?@`jo²7]ONY- -?Ǡ& ۝Yb0g,4إ6aNmi>d,늱h.aSfoFl9V֘,dnԳ1\ `߫,#ߕfVELXCu\+lGt04]2>+>sܸ%l1vqN3xCtI ?-x;r9*21?FD+|XWG,uYtL 5!!y >P`^.s!x0}1g `dǯ $3(ZbV,N#bboǥ9xJy ORVO|%G μ4's-7sM6ghben(QF(aR AHWTX1wL[CN^Kif ݉ձ<b=n6m|+ 9$>y֍kv ǖ12>|܏cb\:"߽xr\jٖO/2 saX{E*Rq'i[:薈'Q]""|lAcZ$@O}b ϔS9OVf5( ,G{>0EJ8k>O3yATY˜:^l+˚Ow`>nI#wo546E^M7̂O5U#)&&+ xNzu`am݋ W!+i6m{_Q~5%KO 5g?c\2b_AA]?IS9.= eK/G U2g@ϞSE4tšꌿYN/BA-ge&/YPށ%„ozD150au`Hk^EW)z">e5V(ert +yI)ײnY|e.،ȑ,B5 ::͚(- $љڦr&3[sťHysQGï|vK*|t 9qJ'Sp$PI޷ ‹3 OvxO8h:[LEVVk>&5"A*(/{0Do(g C!?A)H>-s}@Q6;xc(': y->3}rƬmmlUaܗ5E׺,V$~c"N:!rAsT:N~|x ,x|C#a9֖%`E#)8ttP8ȩNQYIͷ*cA2д$L@0w qB^)/@SJGMf*m gg\u oUff^',j)uOt$;C &f`IKx:XGrppؿ2_ @ xUx].x}{PGnWiʣMsHh 8ㅵ<ҹԗC8P3ROtF+t$Hqm;RἭcaXɍIQm7N|>.(77i :sh*IƝc$aPa8uu fb#Y@iBUh &w?0zr1.)9ƅX(OE6 0%`e,[<c~Sŵ&,{Vvµ6zEzKP7F.M,$+NWn.F=~OMBіp{b2{mCF!z>2~^dMQ_62zoyX`sݍBH \W_vg8݃iB; xŒL[N Nf7>8?)r{kU]}Nm;rv0Rx u0gM<{݉S ~!l6,Jtt #]1Hmf~ez78lJP]_tYƑ !Z.v:&Ro_,t1gfNtrni>4U廎 jڷڟ>ZlF Q~)^ʃϖё-8ϕmYBo> }zm.:FSlN}蹪.r"KQfC6eɎT3Oq q4.elBZja*6+{m3V {BKF^}ٹ'%:9> 4bJڥM<Ŋ&/n= [AΕ>4$[5U‰f-CFKI 6qJRb2?-52+TP ӜTce1 q8CצNVzq^.`y8{ <%kҡlS <$iڼE8_U|MU@ jI'?a5] n-5@6&OCQ9ddtzN;/45e[xJx}Ӄ쇳9kF݇Ѭ]E 蠛CO^fIW$qOVs ?1 +$eg>C;üf bHNX#Ae A&%^@w J.IyVZ[NVVqG xJã(H;uUӺrP}TyR~ pso 1e຾Wg! D<hҳ4: f<n,0S$D2B\n84lxżaϡX'ؠ9#W.0vW4NO5A WD8ڴe5³rAlM2=2䲺ނ6> p4\AEM(K^'78 ؏]`}|%O ) Kh"B9 !u=qy栔iiZűAZ "g'& o?v,uX*foQ:qj2מ퉲:3$$@ X^p!#0'1k p %1( nu/ENꙪމgѽf9.U3x$lAgwvq>dI+M%ݬ3 {R`!|{6[wSl&q<47(x&XutS o,9]#kI2ZN ?oCm4:$jEp~?ӼD{/.&o;"uC)ͺJJ_\Mu|3,ZkW9>&ſXHA#hΙVS";+-:Pu兂ĵ]H< UKRj#u׷ n1ņ_L@N#V%t2R̺GmbԻ4DsuE~Xy<߇k)Y)1UYwf f2sjXqL(ʍ<墱҆JB5 ^{= $.3!\&Y\}h-D4QsQeP)K k((d:\[i [|S(nxxI+q0q $Әc_Η|(s.@=Y+PM%0K60$٨=41H 8X3j!l ߫!*uƹT15.@buVV8ȄsQ7"0@,Oa.*`eD(B@ 7/GxR[?zKf]X&HwEHC5D404v# E恲v'v ba-^LrZߘ4$}SAjtizf]遲 oGd`e1:C5p>ˣćam8&X5d6+] ·IZEӣ&@l`ULo>5 ! E~Mtq-`$5y"@<7sC$Fu6s? 5su3F.}dQh:o-ث@AaOF?oH " uA W. -Sgׁmڳqc]^Oؾ;sT%2R;}RW7ԛ1g ik Ł.qZn@>3 .KIXӨY^un= 3~pz]jҏVik;p$p:Pջz//<֤SKJq̸s8?U j8}5|{䗫GYOt]'K6QK"z˝j0kHkn ЪdH0$Y W@e֜ûzZPc,X"ŤI=HRnim#_ V/p`Dc_kG@#Wٝ,*[Ɔ Jks1" D&dC2U 3 ew5rV6iM2sR+ +H[c{3*?K#\6iFcӋFoT[}*JDN Gh5n| El$ט%qc 1/pyE:Ek SW@GC@}k &tW)"aյ=ۧdd_fg|l)@V=Œ]UYP.^^tUd?ϲM:~)凎} UC*Z]hLՃ 4YC\ v&*%EB~Nr\㨵 ݔ?'ȡVq(o%(niW.[@ O׻YHRuX{:{3b>e2h^Hea SJxb6n_J 7ДHs(8d;Z}/5uwksHOnr܊y֘>Yx##"4>7b 亍 s*,oPK WO"?x΋ո(=?_)=wzT: !IGDƄC3bKU38ūe_.39 σ㉯OZաޖZZ]a,{+Y34-;DsهѫS#@LUYQIe02pպXD\Sj('&( ϶W+ Q;/PvIU [%^jA6xWgqA8? 7+ŕN5dwck|<~^ J05=3٢ЅcdO L!CU8 CJ4 6wBrB IXXibɂ]WnN$ zX_ Zvch`ݖ9)NYK#S@+"?Qkλȓ-wq֔Ĩr€zh^O? աlGLȖ-7 I" \B0(BO#~0v>PQK7~=M=Ujw)+Zq 6S [7s 0T !bńZUbY F|6cgUlٚ[ c'XMȝ|qp٘!TXu;e[FC[ G"z2:'bW7獉6Nu:u~!4Z )9־5EтVs:CJ/\l /j\:zє&ݝḍ,șWlN2`Z5Ӷr[W(`8 >&+^X@y.O^G U"TlkgeFz$\U3 gmC*]b{ Xt؅@/zouX୧Hqt2w+&5 %4!ϟS/s (R|c+~IHxoZ}uW:*P) $^~ UOmJ)yOG~~TKw@4Q }ݺp>iOU=!i=ZL+,GIڿ乊E(r~jpwB$ O#ew~ !g*>vב**Femd?H}%x g:Pby5Z *b Gr uDixK c?0rscO2FCf###o}>Ldy@kVSKlAҎBZ\NA,+^L/uq/ƱC׈B.@1geyzϏgުrrRi+ff,*G΃`o:'&PީR 907g>5S^}K]W{u"ǩt67ԩGTmp=6~ 簍z4XjZu&FUmo8a_hoR*(CF'xRLP`g07ff3"GevD#̃v :\f }D=dQ'C6mgmhX^r,&/gPg4|!<Fsw)z/+PW3`w$auÖ8թÄUoeroI sKR[N.R F]'A 4|Y?6 ?a7i$辕憊)E(;2 Pߗ}nƼ54%J:.$8r+&#٦Џ0jȠZj^$gŠ*ץ(Tr4 @R,"QRr{OɚѼpG:WӬPz֮ w{tӎfA)shv(攽o:oԙG=@}ң kE{jIfC*5p}*_K|YmЋ.ay2[ToK#X!Ə)rn0~~e8/,9 XAbd"S1|C6,V% y*mHI4.. }T$WOSr\~^됐 .h_ZV9%=rP(()ʰX0FkD4?S J9.qIu|"b13]kÐZ!}nx2IS*Fy7UmP\ro"g0~߸5kϣi!bGWO܉5 xbJ S6&#׈LdC_Abq.$}ǹ0'2$%F%0Pk pGf3"Z#͊`5LV7lM!> /.|<9YN3`5Uݘ޷OFYx.*=l/wրT؇y8OQ( qYeY:ЍC6W J^$Kb øi-M?-o4d!}+Mpx_i6-)K w_$;]Io*.p~*NozS UGR?UA~q4h|Nv͡JB!in;kT\51f!ђU\ߜzp@61\)㶈<{2nrTU҇ZvXl44.^"-tW 8Fj&@5$l$D)Rccw3Ԣ>$5yR}IxE"rd~(t ƄB/Z[t:B(Y1:LgR\Xʼ!sCtga9) s"I8-EjUYNh),R5* Șޗ'+;ĞezJ곂;a d Ԏ3=}#+U\b'ثqˋQ|iKC)%.le,q$Oa3y=*Tg hmhU2*є6ڦlrx=<3P$ֲ#yjBjbWIQsNf6a\ m14|OyZw5†j퉏Uk~t8_ғ8Ťvft$jl$H"w;>¦K:,و@).`cO[qE-g*9Sgh10l6=vʘ{˜vGHPf/sC^ P۞m{4v"%J+L*v}:K!tyC2Uз68Xfݏ_/s!1}.>q%*N6KB"Wo3i\"kZOJ3uu$,{Ѓ\frhUDF QuQrB3KI -(;Dlkzf }'鰈c:3>]*ާ+ QRfS]g=!'sTĬXMTB}1oekuNr'{/ yt}(z8OEAKM/Q 5iss'h,RJ82Gm͛2LP"}}gG4VH J៩`.PٵSQRYk:g]p=l`Ϝpa$B7N֨M 6Cxm͡# wP5֡ |L_]Hr )ldni1m#ܚ}+6磦X^e+Ta.TT#@s3kG(E0~ 例ċiϾ̷ȇ Vdq (jbay`LaȳaRi+G]%\&)Pϒ9!S;kx@pVMEo yZV<6ɨ5)}`Tl 'rm?]9 ܠ-c;@؊@(QTW@qaJ^'w͂ ͕FCkSCwD6 L9$.RfT-`ѲB dOWN4mk 1(bp2Vw$/Fb~&A.xh%gTDSL: q,Lr J›Bmup;=s턌Y;yu殟4|cI9TFo?4+16'Jm*ߺPQ P,$)ׅ{ܪ E6 7Yvt˪t^;ٵkب#$Vg)%0WQBad t}% 8>Cm6 $n؅q(ƘGLQqha ]@"ZQHv&W\E1^EeV+9[':gMSȩĄ="n &ˉ^ 7#(Yc{toO*ryMF׆NsҤUltDu ~oqf]Uu F ,I _nhuYA;?iz٫k'0\_Vm` v < {PèɴFudŨI:#C KrBQ` N|LJWL3= 3в\b Gn;z%9n,]Bړ[xUִ'H709V"b&/}_CQ߹'"cQ\m`wۦK!ڈu'I2-.3 FV/@aBMެ6I99 f3CYYX=7̙8sM/(,MWjWt i|>{nF]^#Ulwy^WJ۬x-!*OAI8 na(MB], :X 4<:oȑ#؎Ą)} \ hкSR(xx҇LH.9EC,|?Ϟ# b_i@2>,_[5~.=gttt3{b;)\x%B稑=jgCp^:v KT2mA2l `vV4V @֧3!*/8 \@k4bڙ/뛿>9}hI8*CWC_+n* .+9DU/9{=Tiޙ"?{~C,O뉋gw3bp1͚K[dto^9a3GUټ'uD_^Dy[=y㤃 rZ)m | UW^0 ȮT Xu8ݨJ4pA'~ ZI;tHca(IMk/"MqrǶ>Lx+ ly  #"thtਫVWeIw+vOv }N).%$rhFСf=\]T1+(71׹ A=2u&x@eu+lq KGǠ­^g e>Y[&M=Hc4;vIץI'|V. HX[ЩlX u$X&ʴs*ѫ<`^K>Q;  .CǶjUw35?]'6]Wg.JB@Zp-%Ωsb䊤Vo DC3BڵM< @~:h! $cۃSjkd0rF8FP{_ 9=&e/6<9w%̝>sM][3qAf# )Jf:4ƾ"Sy%Y#J%츊mj{8n~V#˱lb'0;Ӯ4QRU*?s4SH9|XRxVQ2krR ݃/Wׅ!FKܞ $$7D5jG4R훗 Oa(QtdQasͧ#dXI>"CP% jNVQ¤r=~( ];?]' sYo0Wl۷u&VhB  ՟13BQHEW< %[!44SvR%ǯ}߻ r:35 to YD_Hf'H*۞q7X K? wUB.|eV)2-axqAȽ|@EN} ZY1.sGxdм@|*sT0K(fNob3o=G s zvNMADNq\>֥ͥ6\BYPRN, RgǦ6!xbQɃW/V5V AݴS{wOa@QvKՔRF4$bDӃJa8u7SwBsʠU.ݗAY&vJ_"-K7p}w/aim)9qYz೉x.b(PQE?z]_w!,5WXC]H mQt~ b#,pp]D/|4)आV9 _z"jmqֹVnrO 2t;Ӵϫ@ˁgdF޿M(Ho+oKgObrl6PV`-»8P G͜C?@K3Ֆ5\9e *"cӖ,.SQU+ws #d[qeOkXe.hU26AMܐ_Aq"gDȳ;\b{;M ǡy.ts8qMhXWMI7qU. eƦ[113z#=&ڷ2薃7,^%g#tNPjOT%]8eF"y1:{թjPc}UV4=O2H\v?u .DP굿ˠWL!q҃E٥\Ib~2]S$ Jn3 aKwUxԈ'bj‹–rgY;Cv`s;/*/piIp!v2AJBDnrWee %bX{ꕔ f Y}r5%@8ܓ[`uF!)[~v撼vOVSuV,0uiB/2Tad@W؉AʣBWސA֬xc6G 7w}IE#‘ 1rb?g&r`cj9A2robCcx2m zBm/Ғ7)FVd(;wTx^2n%/l}<)A#‹2[b70ǥmGut8+.fCeYVuZڟNR\<xVPsE3\p V>/bpɁ[|H"ǕZJxWa VHf"f{Wi1N@ù@t">182M%_0By{Aé|ܔqDh2/'CP3]w~l52,{esQ3Y&yZ$ jDevsWOt4ĔܰEPiFmm*b'Y0(Al›c桽"$ĕ+xs$h4U#7dU>C`Ք@*\]ҽ 22\hvܝQ8EY`4 _1r 27@Ŗy%1c),bOXpYk+bbvC?sp+C-R"j;EI{S~Lu)qT-HpHQ8x,NZڵTe2w6xK4|$ 7)rEp*:c2xz]daΔ:rܴHz7(o 2/Ke PӫzwU+F\=Z @ KS!gъFI1@EVh#j$;[nDcr .+M-apF"~meu3}L:7Vs@R=VC OwM%6+rM!g<~j%jb ;LEϜn{"<9|tvcWlL i]al } (ߓ AØчM\s[t)N(D7YqYFk8S{$UV׶Ekztfz;|*[ih߄J=8X+M>AcD?q~ p~4nb"V[ml|ZK6) t +|%-Ge6[,5w1! d.:XCfG%B<A0i(Cw!+D=A¼כJ~j.e R6菮}L&VşAAQ푖 Hڴ{c=-tI%4ӆ%kiBo+ʣ8~D\4r K(= zm*wftUX< "7i‚Ѭ$YSLIͨ"Sfk$4UqcֽWe(YFVz=6YX.k-IHS< YRs.թwvFP؄o7CE! 1 %^'x,W(t|û|r`#ʪ2X>9((_fz{ yZBpF0H(/ڂ8)zGC%]'l(8OsςBG',.ytY7*u=3Wd5SLզ5L,zĸ6<<5e-k\Y+Dc˗An]5ČRB>:KnϦӦPnSZF֕3ih Sg/O|<KvࢲIJ/ cxYdcs28K e֠VVjHFwk$b`mOFLsΕCѕ/5QsݪL7Q]yͭg/n-.֚Ԟa?UѰ3r2VҤ?L-.닊Gis Aq\}ճS@bP|3MS?n^>jz('N=O#˧D%E"""(hoٖ>1ͥ9y3 ;bWM4pESiLpIl}\r=@\7={ 1 .YVִc0uLqJZRX7].9#b0: f'-1 Tgw<;r; Mk+T!98_ 鳱|%ΰr/k,A*f?A u/biw*$[|Xl3 .uPS /z68'(>1ߛ= 3\BNZwk,X8)hsM,UeqmW,4G+:ԢW' G ԕx شI>pٖ7p~u1S>W]Q,K*,iyڍZQ|&\۶ғ^Z$ȺIL )t"')V2bGxjȺo/) #UI<9{O%p'sh{78*fCH (TEfVT$(`ScD֓@-K;a#v~`h=@ub|ӌ_Y J>u$8<q]/@~^(sU]VH֒JpU{, ED ^ .-p{?at7fbDGβGiԁĀ7(x8U0̶ LMҌvI/ӊ?0C7=J 4f qwD.l]Kd(Nʥ`*3Bjܲ,rhG,~Iڗs>jN8wVxd#^0+Kա۩{ h1MI#WH>b z8-$bWӯη;h)eGm^ahD6>51|+̓N語X9 {͜}ܙp*/ݣ+&W$I8s3@|0 2U|.SI~ 6R!(B\i$`4<uT VFސ+&oR3Ohu0vNX~"wIAH9AՐ:l‚3͘ӻ $B5UƃfNkg-0AXXYœ{'sHjڬkP~'>k\F27}K%`Gln4Uqcə_Nug>'[B ߴWֶ8@'ӞKM9sEr=9.^h\4 ÷)"r 1эki57#3aKZ(:48P[΃IXfR"R(6橨ZU!4p~Հ+\SmA/"tTs0 vYDUf3|bAӍaPiQWVnƲ1]2=8SNtm$0?NA@X4G FM!g3S$&?2Y$"AV~adWӈ0 Dg>«ғ>2ådq|ˏad1 !fDXZKI$*qh$SZ#'2cX5匀(h7GC6E ;Gm2rⰡSdi`$~&L'^#Wv/U:3Y#Nzk,$vZڍzGLԜ6Dw-x,CaO4m4\x Cl~iXo. fJiUi^5Dz׀>k?|*^#V(]1bml|8Q#eJU]EL2nTo~<6ݗ%g8%!.'>vT'[QTzrZbgÃɳA7̓۵z] 'ZW"2k],`5W2 P9t@-@o9h۝J W.vSËlx8_3*ΙI`B=eV.S}# ~-|OQ\S|H/kXL76>(P1 G;jB[6J!np̖$ҿz 7<3s 0G%Ɇ\K>!,:g۷FZif?S䂳` y̳4Wf`IY,O8`I`SblAH@+\ro Jnq3YqJF#Z_!00F/' $m XnT@:zZ Cy*GjW\r[C ~lզZRA&Ÿ4ҞZ_T-eEȁ@AHq6J<,yLqY0'2,?GL ߷LMDX?g "\"uj#D(Uw~5Dd#Όc{'c2;:'VpPԬg*[ p-sfQv0@>`R_.IFqׇp k+iW<3Ltn^7'jٞss;dȆ t%X~Fu:`&W]W"SS?[0nVDU!?%o+{øm*`,!ɖ&-@O8n >wd#X}/: -9+Uȇ}1ƒwQL99rQ%mxdLuY$Zu"29Eh{W/M!H]Ja2Z,qP6X؊5q%AlrO !- zա[/7H*$4Wz.sgES+~G7_QZԋ2 k&?\[ "ܲ4QR]whF%R9)}og:itYޑ[7s8A]Y^VfKۡaރʟEttcUзkv}UT}u|)o%bps{K|iIȤg+rBQ7'Q8QZxFo j|+%Qxt]YenYQy[\AYgIVn@ uZr-䔦"TXxdS,rnk )10ҔlAq|l=zon*GHHL,[c9尃Td^R(Ʒ5nUƑ [AT$P~M'-^ {eͮv?Wd1 7l[ -@iE궩Sך&|>sgӱU'ꇔ\(<`۬%x%8S5^| $5 ^u&=M۷~XLݟd"wWC1܇pbe:+t) K(R@չv AGθZ3 BږqgI,B/Fګ"./[R)mxU3^l04R>A>)bj(ͥ|DLjiOW㨫i?v*3ܔYe^ž=a?fhJ+[rY}{kwsg3cwIA #I3PK/0/.eNx@0>|V>YbҬZr{$鲋*Qe][mk5u{JW@2zD̓$-FGx&%D(.z-}QTk1ѳm̮63SV_޽k6FMR -Gny0}ٿw]} Mf8mр`b).,nbpz+!^ee}!'c[3J9mr$0{$@b&qR/bk}gT19<^IȎi-7]B1L6рºcv&'تM}][T I*/c%73ۼKWT|! !LobfQ)Ò\V ?g"IdY*r3s: 0A٬ëg_ˍڭ.`|}D_ ags٬:#1= zQF c' q5 Ԋo8*{}PyX:n$12m`S ˜KaWi;m7̽M;X>}Cqӂ |rH9 O_hkS9G# r4V6H ›ŌDR~0lt }X6B $`35ᱞgFGd[VT;<:2Q$S) bҠlF0v%,I Fi_£`L1U& ס Wb"YkTGr%WH#sWZX4li|~JjD xl CAϵ]nZTZs[x}']h03*Їxb}@EA!6s:}<+??nmc⎁/`m7y[OVX{qC191xh?!{,a?ci:KG =Imk/2@ia*ۡl" ?Iw"ӢXxF)Xs?2*Ӎtk@Yo<xG2Wʢ{/92gnzq1ᖶOY3.}^@]} REڿ*;#_# ESd].UՐGsB#} [rF5mm-`]!:?j`d7QEx:kIB^[`1P/8\;GQ4u4X3lt ̔r1ER@u+ P_ 7J+$'wt0D kѧ>A $s#6 V!l %GvQ 2w23]m9_ c s|F+͛7&0Uk[!T8+,-ُ  rhH?W@`u"'dOcZ!v}%tAԸyt,Y}݇2o,.qwz-i*IٝRL!Z_EJ63yVe\)&[IJ!Me5L-[3pV [xLP$;[ȒRq(բ3v }a Stmr4J!壗B*K X<&vSÐuZýH ˟a4?+#Wlbpd@Gejtu;IG15Zٽs6ˬ]aGުhip|a#%E~&L)uep6TJE9庨7\֬#mg/m?<\WLTn5;%=Z̠GqZ?E$j%k=Jk5C⹤j>4ڽ*ToZk]=Vo;eLzxqTYҌ_ (Z8ԭRx}fL2R>~ }!|oU5o_/kn<D?v twajm<-sߋD7]L7dDF 콑rޣ-]z ╄PbJ:g 8<*ͫqJɣsƣ!lt:tyjr3Dw\0awv&X:Gi}&4D#Bxsk37c4J + oJdlf OYSV&XnBsL%Jݛִ:φC}=BmJ\3#txDڼ!Rix|5A ?5!e\Y+fV)$6)Q&<_(O(m(aY|! ' x9{ي{NNj!J:}ptޖeӼǗiLt²1t㰵Rӡ~s[3`.ܖ*Oi!24u1 o$ҘW cNKIu@Tzmn817\ep .>@I7FR1G.\4$P8V:LX7،Y`mO#h DCuy!t% R3gfhECEw"`.hUA,(#hjHDj`2^îA3bS@~!=7o8/G\`x(FzD\֊і* Oy=*f!NFm3& ̮i0Me_yXDv1>S>, kRjr'ֳ!0fvrDDiu \]6 pYZɁ78`;04%`{rO4Dkʎ?C5i)22X\I`ܛyBḠyPmU'f&\9.i9fϏ[}n{ԞSYkseeeJ yNԫ Y曤zO'68 fA4_#İs [X2ey Ɛjs$s&?c˟j`>%fypVQ8CJ;SpF`.!1qؒR<0U˩Q2"#B1"F '/M}}r{{ _ sQx;Wyű(Bİx I>l5tB ԓ7׃+gMsTnDz&ƮzxOwX-Bu\PD!ֲ:,U:Tˑ!ٸJnZ)mC3BjyAXC'A8Tg>o)YkvCq ٪9|}#uM=2 3fe8CX;`L,^T1]_Q#2 oYL =_'GZsh V:DnI>CɇGߌHqA>O8Q<Uzp0;&xp+F#.mBeR$K .?v.r]Ga?qP :0ZЗuvjj,4иQwO3;D=P+-ܮsf@O2dvMdJČ|!T<4H'-zfwDF\HA#K+M7R]Z}ԽxOO+ʞ@5# k::%(6nj<$tٴ~5YۃALM)49ٷƃhZjӴ= |^Et/2BXpơ* SSףBG֩ sj6*a$k"9E>Fh,0ܪc4tbڅL~7=:t ]*1 | 㶮@@1:vuD>ii`),aX܊*OylJ#hQZIArœgWgg1%+T^/Wch>5@z `e8Z/ rD L 鬻-U:;ߌ+~rna:~kY#׹h@vT[E/zz}GlJ_|W69". YwĊے/4IID$s->}cCsU |ۈkQnF{D6E +tz>B4I\Հ )r-y"GIk%LFbxj晐n?߷+TiGo&6Xf! {Բï#7Yrt~2i78~QQ'-t!}.-~:.Yhd7 2U_՞+Ѹ)PSOi:AKN$he? `ے>l@&;)QdiE€ }~Q+ DLqd Wμ?֨ ݟJ&9AVXJ'|ᗐ*rbE21t `ye+!*I^}W fY 6@|4r`PJa6't>K u{SK zBS㢿Qz@鲽h]l'Ǘ7(}VUh|C`@V ~1fDLe,q2Gp'>z6 I*Hĺ" # VU]EG< Fy˼i`eFX'Y fN?D~xѭ!_.ۄ/Bh%/wYw*{'I%?l*ZG[ߢnv$&$,̉`u%ʏ38+8_ 7NjJ6HͰX'1$ycRx#QJ/Dž}Ʌ!~}뵜HuRup̨(_d}*Q׏2$dߊ0"$\Dh2j$ssiyeXeF{%*FOpJ^_g&X ~³m 4"%LNT?2-[+j'xi ڲ|~ aěFMx6sVB 9l^^{)7f#!TO{Hqs/Ҷ;+IGK-%rH"UK` ~H_f)ݙ jǎ#D_wK r3{//̐i+l89. !!:95IEf /QQ1SЬJg /3=׭K0\q>u3D2!O)%'z, nsi[`"»ή31(_)b#P wfRt|c s aa }xbڤk %XW@*6y'^swħhފ7 њr>(.p/ $u=]D|fNT.v0nx):4)gJ(ѳyy?O;Qocڙ$ $gC@>gx- 3yt*na|\&i(G|Qw.!g} o&4[T9JK=|R,{2׫"OOxֳąZ6X]'`W&e @޹qoVHښrj> B/?eSh}eyQϳe5:j@̻hf4P'l裏%#k9KJztF-2 VhfKR?ُ@5e@318ҋ%C Iu27| 4NP=3یQD>3xI0y=s,Le`g_iϾA\dObEmG QCݟT N.T4dfn(CXU^Rrn .t*Q;)[X zOH;XXX~1Epgb6n,6Fn.c {rGO# wA\Ǝҹ b %#ediaFx\"dm3uk4LsJM&-tDzȨc# ]VN?̳sȇ*)Ϸ2bBp vo`s@}w ц/ƒM-tF F#~S7I–;x@Eɽtg:6/4ž*. :*uj~Cg:VV5Fů7{#hyn"ھyؕ$HʵD qH]Ǧy*6#UՒ. 3p`Xx,&?(ѻB6ٿĭ6*{-o\_vt#L`)Ǽ(Y;oxk!3Q!8_Q76?xYYfPoGe\h3Ћ+koqL(3ۙnql 57s "׿-q̯wDnJ[PbKWEr1%d8{+X?5+(6֍* N"Az0#f@E((&%`X:_0s?{`wO ] IpW%53^d@J+Q'rH@BM@1aMA>*0@LѸ)bʴ=ZTh_XQ&i*K&ZdV31*FƉ&Wxl Epw][GE:$C7j1 Z|R}|1nzjNzt(^3e1[=yD%!+p ?RZ-1 ~ԺHXp{;emM䱑nZk uk@FOY9>峢Y*1|<=Hwh*m͖!I~pS)%9<\H p5͙16 94.;1r`4 EjʏQ2 w$jH˂M$r ; ZeCHd>Wߛoâ~t]V:>HW!7jN9(.idPۊ² e韷X*4Љ.e_ѥD1oKAY44vQگ2H~qoZx̜Y_ 3e<OuB14Cū9L6s6+Th BНɽ (|fGUݬoM 5AaG;˰jvh?2bӣtLPO[9-r=Ҷ*Y 2{ @`e̦,<")+nbR(Bk4]K:C̔OFoT;u@Ko62ehxS>E5V@n'yxO])$?ZpQoḣͿ3ᣟ;eᣙ 'jiUKP9%(<==nBj{]rUvoVtYK8.Xy4tVCpV1S}nɏgݴSv䛤_Qu9&Fcu.F?H!A"ۙ  2O˂BU1?ouy"R0Ϋ?TqS;*$AcWB?Jݞu8jsϜ=T9ř)ZCג^r:^vD-KM_P.l5_`e^v{f]0`r?Vzܬ76P7.6#aEHrIW8+|U+>N1jި@V @YU$c[tK?E2gZo&:;׷s/t0/-}9k&|WK8/.*0nhE]9y:@B[7q' Ѯיo/1ԅ 1t)}JvᘥcE>tV u[Bz7=RTR/{v+S5@bن\lYת"6vD4nh9K݀֯8^Rbj(媹#_v, @R/Vl ݸwDbjkf[cKc쬏eP451@uxK֞TRs$=a-$n^b{Nf8hr=geRd!FjŗK~e$/ۻһMe&}J7wT$QB$մk)2LQqtѯ`E— 7vCBA`yf`KeYlS`EBa"&aMc/f b֙"//ltW+d̺pF̔2?&zj@?CJ ~FLy4&v0Qt[2~'ypDU?۲!5Epon4"C>P:120-tb.~u@H>JqWgOC7ǽm|$ڱglNa%)tw36;o͵pqm! ͡Vl;gՒE:җ3v9P&BJ<6`ܬ/Ȫ(@"L$JL `{yΥ]]#u>|.0EwQ.eWËE+g ]3ߑh崍,5M?9co_w9PRt+L0  ╄Η-F˺jrwbAVss[\w6In =|TGDУ"lUn]7Wf5a|P@׬IΎ6}8DЙf 8X}yXu,'Bk6SL&^_[Ҕ2BAң{o)m6D{tjzqypy|K.cZ _} gd5OζX 3JF6a$80zak:d#1B1Bh')[Zs]gXGgJXD?(7d<]|L_ZlB{q|zSA) +~lv2O4Ⱥ2E݊}Twwur O/@Q+yZ#9p;^Y rZ&"S0ms2QjzO!B,ܲٱYLS\nqw]/}݆lTY0&1hEOdNXDP^3<"Xh$&? ~\r;%0!-` b59S.*ύz{5!m.#l\fTA6腙"})<)&tnmsˉubΥ)c':Wx:jCe*2!ys9WoC@%*{)Ϩ}G1'WF9O۷8>6 -߬Φ nx蜾yZ>(~Yx/`LJǼ<4)< |:Zؔ/&:`H3(?G-Nh_iV[ q(2'Ye 6aR+qܵ(b~y?Zmc8ᶛlsSX? tY=|U2.FDMWƕ\ %QgAq?zCz' RjR#Zn%F h(rki4Uw0 y:0;vm=T[֎[O:-ď]󉐓\/ 2g͆$ 8Z6]6fT0@@sIv*JƠTYxS$yʕF3>k_lyfꍐi|i|f8`")W@0g*]ұW|>{y dFbō}9u}QE1ܔJtZTCLlB1B|$l{/g8 #QfޖnzY nNnb H^>Tڎe9Ƕ%ܿ/\ )Qy]nZ'#{. sMI\rSU [ֻgt5=wr9ӠquVr=n[ :)$ja$&I. bY؅d2:ijSM[j>FOPQMܚy \zrq߆ dzO}Ԕ5ҏؿdDLI s?h΀ú>‰bo7)}~U O‚MkYl8*#kosovgM &]qڇ Z:_z@JlicJ&O},o*w?xuo=:Q -ncr?Hyӌ&8S_}*Rtcn4.]޲cR9]ε`[s%Y3}i@۟cm"oξ}Eldt͂~Aɖʞ)K21[On GT$OX{ xB-JЙ5}WAX:F(bɞuGxAijT@=X_q+'mZVȈA(LCZVId\YUB~r+rpڬ.{g'wl-k?1d%1Ebc0m7dE0;Ṑ :IdB<7E$X=u>>UU R; y sqv.w]i:!1ԦWLƝf'#_OH(ϽfmJoR <!x (@Y!:TU~ts苃[֓^et>Ls7<~m3z{;U"^ ~;*A7&ߜ_-~#$unm܁HLi .)\-&~;9edgӯ#wc,%O3:Üc0[}aƷ(UOs֮Y\CF CZهFO w_JlR4k̅qOo|g1c]Pu̲73=S5D3fOU8<;v+6H)h`uծo$kF|ӂhl%:6eu7YwAu#pt>Zk ?2zɁhr@3+w;9jZ9wDr_`_Z;InœS^+f6ʌ˜|RgOGenOZ+8o6^l;=M.glLzٴ_]R0\VQ73z>UleecKs׈Re뢯U*H.t4Mq'd)7Vhni*k 3ڃŶEJADLDqKhnyh289:%T'd1T?M;o'3K V?(}8 D㪏^H I8ysdži]ڱRz|N.p[X${-d STE{ #?;@J,/k:X˳^ع/@tv'vͳ#Bu\@R+/eZyUxC_6»!Թ4aaxG 69A׍yiӝo ;=#Y"V}=nDP-q'Ev0Lgb=2)P߿|KZ Y.:t4x㝥GlRk=uwc_EpWI& VuZ.p:~˒kXgPS9!ӷO^ gT)t\=U+JAgM/뗃ۤ6O/->*ԑK2AÒ]j`87`u8kbT=xCT]!k.ۯp`pq bX3E>WqeD!ם6åV_AWՠ2n_n7p!ήҠs?IgLq3GˣqI.*5,S~ 卄?WBԭa [^JFQm?榸W)VNB[d[N֬Vjagx2?#"(2b0ҿ2S큷-(pMAd몵9[E+4|U<%2K1"2tب"Q0A+̀9qX|dʟvJ䝑.ל ΐ'~ܦwM>]E6/2S@%7FH?DQ4FL&:4aزVDE+iuQx^F ks'pa9c-CHiV:`HkE#qGa]Pi>4u!(fJ/]!xIQ| $tvT4}`=E0?L1g_HfüW8`&NZ3W"ɚ8RН*q\J% ҢKj*|mxs@ijYT<3]5q8flB).ZxzW"gD9P- 'D.e.H{$4M]RѮRƯɫfHo pR\!M(*<r^t,Ju<TY/fa[#aWmV5y0B{/ȗ_gu4`%);gRJPN以*7cx.ӎFwM *kƜBO wMb٭{|yB8Fb* }>?taDf(!8f`izDS>OVtͮ>yqnjJXo.eml@ߝ{8=φ_g|Z:W% Nt 5e kLzrk7R0l˔6@K!*$Cpb< !#C>%;ن~_{M}Xu!ɓo{$W"^!p x+hc\<686o&VZa ~[ \9``o*MWbnw+[̠4sTe+Nn^mBc=A$&rM[ilsƼ[f <ˍwt]@A;V*~'D"g0qN%`Rpa9urL- oră!t]%V`VX&SHaN6žUE,'xa>ƫ9&+AI˙RbZ|yd":-F۾!=4hs'op%cG@ fj%^^H-25 cC0r^hCٰG4*'+dq1{_2 z/5[@]6H-n- ۞[Ԏ_ReB/3hϷDz|R S0(PJ0@i, f3̈*1/-,ufm)(pooYD#1̆[ P/\.JMK7,Ʋ'sGK^T`}ܡ7!4>T;V vQLg֞6BX0V)-1g@tD'[$ORpЦM*}cj+6 WK۴+<^Y,B*^RxXmċ5L-uRn 7MY("!Y1ZEIc!5xQS@nygm ?\-gAiޜ;>{ޫչ gc#H g([^>$y;#.NWȃiԗA$K.y(1EjɱCc׬q, E?swhlfƌ\A#G}5x6ƅ8TU6 #8߮)p+Ϊyen(ISN.,brR"  nVwQ͇[nF0-=AϏZ|y+{\xY -[WX5 KĶ\ܳ0h <6$2݃yPS`R hi:2>&V lC[)Lv_6yͨt2VTi;l/m!P["șYJRN1YKzuMJHdsxV<ZC%`|R[Yv "є1cAr\V卮tU+'z1Fsm6a0KzA5zdBJZEgS0 ,-77׆bFBJWt-jvo a8a}ZtI^|GFJfU u0΢ηG؋e\ze2I0z@v9>^Qvp౮;[zT6TcITNӫ'a _k)|hL  =OEH# m1qEsPm*oOˀ4Q3LrŶd`ĨU `kj7j} pD4Y\~-bE9l&|*Zk@P 29a/%.,:gH-fD.Qb|T &%6 LAJ i $$니e4.[_}]^'wRj0dZ.PoLzJWL99*(ղEvckLu4[%Yƒ4 /l:EٌDBѯ(O(jqG&9 Lbx21U&=D95`..:u/ UMG7IƷsU-W~*]wG 7n(^aڅa)l8C{z+Ocp 6n&5?UYeݭʰ؀)#=|.f\[c:SY'K m^ćGw;/YL*CQ gۧݼkUճөξ!G!wX^kNeFCj#u+O8:=[KbTgx<;N/aBɓ]jSJjbܨ8>gѳy2wMtY4&OθHvT7aGbd*TgAx2)^Gw Uibe]GAS씡q٫]'F;{oqn_ w&ev[!=l;L./K2T'd2YTJh0? 3kn{HrvmGbJX\.u 8KX.6[΢|a! m-e8XYatK'X+Jk{~S ?k^fp{8SVfBlTX٨Vi>s>_ShڕtBF;tF`l%!ND. #Q6zml"NH]Ky6Ɋa[BhIr$!3<à\?ίiHRʉAeNc4eD}GìH5b&mG}Bgp5}#~Y(k-,co[5Y0r Œ~旂H9CxFKg/bh5u-%e]qrMz;G:n\-ïvUy.Xm51^" Dsug#"nbFUvW~āekQ. |d W%M]A_͂|4}'fܔT瑃yJC3@t Ѽ(5@$J܀#fKC)1Rkޱ 0\֤#wDs\WVE^kY0;vwh={$B ѯWtQ>g$M&f w+7ȵ d )ʶM5 E4bRBOx,s%Ѓ !ѣċ 5RY Q,8æu紌'KD׶ SumFx@ `_tcEi$l&0zmmmoj+˘YGRp%&'>^*XeYn `Ck3 \f u2 |eԨ(WVBw!JQ6+WWueCoKnh; =o ]<7z7z 4q~@#%D^SA|[uK2ߧ#fd5?#g%l^O B6XN,atE ϣ7QNGܭ1ޡs-XQ)lL=u[Il,s!eO2z[f7&P,k%bH{e[BҰ8]zU ˝fH2 Xc隤ݝ܊%A6ݾz]l Eu6wN@anO\y&Xq[s%iִ@ҭ[HɅCbY7:!k1SϿ%|IL#I*؄|•Qo(|2#3{=I*[0[$SϼGAÇn=sݞƓSh=sX7 xF41;uQ^oC5Ϳ޲Y:G<*cDFl54?r8`ē> ȴy੩L(% DnlsLx><7GO|FFyy*i=4()#-oN!..}g[2?=[ 'QI0(.Ph_y: תfY$,d-Iz(יJ$5d ^8"k2.hCJtG-1@2>NimX>?sۺ&6.?I)Kن]4#r|S\MU1:֬T+XT?2$ӝstP8bGj;y$U~Pvm*<(/]7.5yM/EQEjȁf.܋9TDa"ZXp ˻';J!Y(J#ol$xc.nuEI!l3W˄mX ct瀕alNc>.yA}/{JΊP$YeʢbYnNVuX0^Ŗx |qcLkL\vXNz|51" 6!"}~?X뭋!1h1S#gC>hx@Za9|8˴gLMAO77">|e(UxU\=(Y:hf>'Qn|Ľ8 #ئĪ7o2GVt)HL>va=5̼< 8a43z1|eU-TX%-+|&]Q|] gZXO8SМ>{C0 A-4>L>Xp8=E*M_ #ۚH`)bCԯqږ1dǦ:C=̹t(GBVJn:*>w>uxvلP8'rز@6.qnC힨)pƑ9 ]KMvР 7BC yе"._Nv Ć,' dޅV(UF|2' =&ְ*sM֎Q/%/ʅ%6bTwsY- OBQ R>`sϧpvJl}g,%i#TK "O){8Tم,d@Kt]}nJ!cRTfYZ),bNCKz,P*Hu2Ỡ6rKCyYj͆lE6}Fr ]20o~[h?OEqAWz VD8lVx4x`/9)$Hl4w+CbDf&zg}1##p)ՏYC"R?Q [Ic#&Ȃ~]NОbn4%<}i#7\g2f<:Ob)t9ULt>8@Ïo=v3&+)>Khu28A(܏o4)a٭xMl')]v\M.;n MwCl<gpjY{AюjC%be&rkk]"qo3U@ƾWq#P`UAC!(NU^鷂+ \0͂ B\ {p]]6vݸw?2|U[$!՜Fb%I1#׀Nǁ1XBT{v0eJ)"H$X͉/,蜯Gbňjʽ)Fm/|e/ s*@5~}921 SZ5E;-8?Emo8 G?q7ZsؤZ^pBԱ,f+#^/L㏳O.n5! k]GR梞l5G I(gk: вarb0t513S$b|?=Q0h[8e`Ⱦ/6p⿑UxlrѪlK-.GuE}jEB?IgJy! ^ot.pTZ9'mD7?Umj&6`Tfxx oܥC*7{~Zfba(.MK! 9i#u)b{ J~Ra,0`>0vlpjp?a/7Yp4.3̛K>fʀ߁L˝~,DXI$IU5]^y϶"?YIn |ד߱ȣG\aMH+-9D`PUw Z* IBHm #:Q:T%;ZDl(#H~2[R# lOfZW۸E-#jct"$N:TL^4_ȯԊZ,h*w4BVE~sbh-ڜ1-fX/.Z3IםQETvIwֶd! -v1.O#C2o`roO_җ|.%՗sd2L.F o[Sn  cyeJ.*/ 9 v#,#s+K%> Pϟ ;"%<Eplb0'}672^,)T`1,IMG*}rU58d ѡ~[07 ۮ919{ h- |6>p,DϫRqS!%^G&ƾ5O.H3mU?>A-^"Hۙwf9afsZxfCY?,*Gba9D%H =y3Dz`$S:r(:aXc^]/]e9$I`t;LO6ddK"Ot΅l"|jOmYA4]NԤƋ|Pi~@.xXE6X?D}]a n(+SXe^Ưyr}}մN<' sKtm`4QwϷ_;jn7Z4-Lg3R#$sv˗؊?DZW_uH5M8@Wߘ|<vwV3׉h`X-v: 53*J`ᣚ泮uDB *80ݶSg5_˚UE)=:lr?>'€8||`VCƙ+|$J֧ȴJ㩠Q.h#Z!}l6fw̨ף,R9ȗQ`B}"ׇ  A;{e6\ȷHR:$3,歷?8JRS,9ɲNVdő+(B%p2^'g& S}?7Cy y dxڬ_Mw# m_NbV|%;[qяrtt#{Zgppm.<Ҵfx{&wѫ#)]Q*mlf̮5W Gq*XhA_}*i yT.:0 /,.'h|oh5\2L]uEF [HFtXiׯf'Qk5ݨJ(b4,g.a/0p.N. ۔`ِ-̕iBn1~ ;B݆v v(9#WUA$XX +8#T$+r,ٶOukkAr^Xx% wlļڿx{x1"l+_ n4L !GCS侬INFfWc}{vIyJ2{X_PPeF3л$퓭q#i\'[ɽTZ2-,ws`(fț34QMu~a&) $h~Hi:V>YMe2$]!GMmQC%a4i/Y:ZUBK1sGP3G(r-Rz26Gqn4^ CثKiSo,:ւY$5| 0Ȇ=S3*LPf4~TrJբKy[S!ɀI *JdC nc~P_6s7fWad~|\mU;` 4>H*;!*arO>6v싋.'}]w5X8MLirDRω» r7r#F, VbTw5v|فk܇N3#h&;2zO)hE}xky 8ans!,=#Jj D\Sv{Sܑy+rl+]oʺ GZ=K!Ut#tY@^,s $*6暏A eg7Ce!d{GMƸbN+'U-~ጐ+d3=##yyV­IqbyH0gڲEY%FlIK-II=muv\ >o$)WprfҠOEp "aȤU)YPgY F+%e&RHߺ4QcwS \((";x.M#(4>j༈[ԹYE\@u8 foRDKGu" k#3Dkg]TpHP"˽Iw"ц5:ҏ~It=˨(UL/y@ɖY55.KΪtW⵹F,dŹ| ;q-_+]OyVڴ%RD{ :W,?d6=1c(9P7-Degfu&Gt5.ԧo/\;| J1p~) kWy;=!GUuB*m'iHlweDǻjXR&EIfu72u8)bI n[[\[Օ-ǫTSCz^z;ySOQC!s =E˅6L?Qvt{ }B,X̰ko"\ HO,?[CE1IP%$oPr'kSD%$(s"xg'ᇨo*Km?8y!tM 3C@ xe}G,՛c:vz6YdvYNj *P(DqBD<Y֫n=pODH.ы>D.(vOWOǀiiz'5@x!zX} 8{8\UE'J(KA'xdr.Mw4m#;vQan+f^47?~ bk"Hs+jV(.#A;͕9>愪rU{1C_0CA^ZtIpROq3K5i+ >7%߅Tj4E]>E:,wpY-C2:Fu aK0 )!8唠. kQROw^.#Nε/|WrmnRoaǚ]r^ƕSˆh3Occw[;ބDVl(A6M4j32Ed| P4k_[uZשrW%"1D2jKȾo J XI$(WBqBB ʱ@qs};|'2{tIPę (q-;oգ\mT07qP uTf,ds +"ܘb)g*@b80Zƨ #!ٮUd},P2;ܥ!-+ ~LKp 6?,}X'RAu= tDg[!F7(S 0 83  {1-,وWm^Zv! ]9n#k 2  [{C&BlB=+?) ڲJM=p#2%bLPbYveg."Ճu#_3Pq 5 8z?iv_pא A?5.7b~p@u|;XaG7sxTn˜Y2U39OY>+)`7`>;ǬZ\K^CL3P5b]M}שg?P(/fݹͣU#mC]fElh'm1ٟILTyr' &f-/H+UѸtę>(K8T4"Xe< PI^$^&8ѹ\#UkЗOC[FɼfZ Ť|ON*eš/G'rhyc}8>4'g0/H]q–>8 uF?{ PP@;2ISDcBJE//XJ49n8xUv,< ^͖%!qC].iX*|XDe<^un{yvݬmZr\nNAe|/yg SnE$A3jȎlqiyQK@(yC=]nܐa^ $ l5ӴW=H$'vNCK~26ԩo&`\"L6SlwGƱv*66e bQ?Gj 3q Z/d`2RH%x}-" 󈊺=@QT-oC#̇ODp[@BW }gD HdT,( 6hiշCx4mS9QG룄yPlA蚖iGE لF:O/1=SIO7X_;?Bx$an+be7h=G=,$c iu%),o?H^!be6׍<\[w;f6h̫{F6O6U s={]07EIKfUO$9 Q|n]$kiP2x10% ~GڭQAkCl05HRuge~9^Ēػԑct׶w\04MZv[1 z^ @pJXt_zK@4@vR`w8jh^#b~JS;X3["i>&.j"IgҞg~ZoHP#MYG*=WfnM5$;q?@\jN~ x&5Qc >ߵtW6umb#&/Y09ϤH3O)ɽZD4F5b%_#$~n^}5loke9=b"mkRvxJi<2rA&P7)=+Iic b@񺌉@.؇c08H8qh s euGsūä,rS]oƮ{|NjMZ4[o)3NBeDViDwOcxc Vrу2q㖛2Iibe4r6Ux-/Y3omeaizqxQq[pF3W K ajo!kZJ<DXHhn^sxWQ ]Z^:>q566vyf>J1@RvcZK'rD2yA1Uv1ѭ] # P `x B>@,rHI[|SZ:1sݡ|05堲OURj$%(\NT3T!Ҩ,T$ \Y:qV<ݙ5kpkY1rں4*;7EE 0\B*ш Ĥ,DVҽ0fn ^2z#k| 4 MPo5V7;!Ėg[QQX|ԕѡ` n;l>;t?*UD֮{.KNR65<1G 7e`O@̍HR<3Tw^!Exﺵk$tohzʩ = u|(gdO/wBgh|;lM';f;+A_坌rv ZUd%uv:=ˣ!*H{=m;TBmL{ /@"nbJ{_壞%D31hD,]C6Rb$Խ!~03Gɖxdks GכxUۺet ㅼ"Vܸ&b^89=iX|bjaEod{Rvd\-v=怓[~;=yAN8 ѩ,G5L /ܠk&z$ h)) [ĖNe ~LZ٥[ oruΌX! ;!ʫMaU;<15R~޸^dU 1/<l`r=zS]v?a !O5Zis=`R~&$Wkg , ﭛM\n6x vI: MSyJrÈ8l 'I>n0sD t._ڨoRɚwEȨnL.sQ.{{_Sֿ#-Fx+2`Xj;0 ֌ Ltjv[ ko`Ӄ.+KGYv5h:IDMbZn硔r򨖈HBgdn y}$g0Di+ԳX!+`;ES/PDJ4>h^H'3niX+-.o}YUZ9<:}^')'(kC@42GP־+A{76׸45-Gy-R^܎y%nxG85ڡ(bf\Ճچ/uz&S"?S!?K9z~PB4apu^.)3m5s"| yM-g^i/EXe4U4@> ׬J@ 5~FmpD#;r-W"3ovU%PX*Oui\Sgf"6> X'U= 7} o늫4 { )wj ʣ4\{JT#[:v a|Y7ߠ nTy_Y+'n'۳y;]ЀG} &ք>l"K2T>7NQ{?W*ہv 'P(U$/KK`܏j^b=|qL40[|Z\*֋"Ǘ^-Rц8sA--Ⱥ.fU]_!|1#+7MvN$]xjqv>TxK^sp?G'ab\$ut<܏y+~KRa)XYJi \7L#'LR"RZ;hĶJ4-'6?y[xȮ,-y3_ϔKuƤtr?j63:H'0R@1_i{jܦEn&=W t40oj?3'zc PҺ/PC3[4نd-;# -G(I`UEF7=YD~ơ="ty4ZO~Hpȳp2~@;G\- P/I gWLlC0KPzXio.[l0#nW"4tVߐKuPx{ÂrP,{4Չ'g8v -Rښb1j~A-7Εw*"=Ow!8܅[*xuP`GwӔum1qdNaD(0_ 0fiQ)^oHs}$lg*E@гҮ9xmu)9Iӕ$3zMY j);eT"[DG Ǚ)Ǚt5OTR9&&nDOMBֺ@9RV<RU {/_ 0E<a7#c,xCVfuz;TԴCʢR %vƌNx*cl6JT V峛^,fv^^ϾSbĬB(`l`,C;B=ңxӜ[4j,PL}!eTnѫCx$H$ld!ӐÊ,h !Gjt>IFc0VHdxPc<j%5eZ Ȁ퐽灀"1,y<5]K. &`tЦMnvm@ݔ60@PI150>b))$iP#a l*=Nkq2r*y;:o/|T#Lk̴S̿n:/ xRڪaƩ.oRQCTLo;\jÅzcQ1 1ថcdos:Һ0ҪϠW_:ϋ#o[eX/x=ޕxc"BF,X֖T&WS,~]X< _'} ZriI ĄbWXOs2Rbx틏R+*ztJ%?\ђ:lFyW:a\ǫRŁCWtKK.#/  I9Y:ՄB@e+/,"5GTekV\I3}R7 q}{Pr/ m>,Ee C]"E-}IOQ|mBM|]b^^fǞ/M̡*m HbxRq^B,vnY!~f V^}m!6 uI"u8չ Wv1(dr=0tUuܢR`bH:Var?&Օ2|1{8Jt\πbNrn\͎7/Z莸' |A1t aXus }^&Ѕv_![]d'763uC >`rwϡY0M"ՖzOs,A=ĐEЎ*N4 1HM\v(a6a򰠕quBōRRg< $Gm;S7'CVD|M<#!7r[@#^|~㡩*eNsТvaUAsiSN._wA缃{8{6g]ϕrkVE4=0%zbari [jԠ8Ҫ WN);%I:[?lu#1%:}q=R Vө3 9q|wOi Nj0^Z;%ᨈ֝\Z2mF'ʤDŽks.jDWMxa <-b;kk 덍=Va9w{ iJ2.?\\D>V;! 5vj4x1J8d$̅Q _ ts ?|Lẍ́QN.ۖV{Y4ʄ%K%zKU|Qq7to\Rg^$T_9,igG؁"UL̺y=bp $ )l',M^NL_CQY΍t%$_? Z8(QղT$R}E `[=_>tdo E0^;[V-S7e#wSA.>!"tU>-s110fG\K9$0YM 3I P YℛGY ]X̽SFs8*@0\j0Qes!K>lGU"wb$bne>4g,Y\]lZJ[1ntwr:W8xkl*~:0Ώ-x//kPczȃZ9I4]-`,ub"r„Ĥ 5JyaF,QS؎X3pYЬ?t}"csen!xtU:Dy:W􎐇،]ƽ BcTV2OI>=傪 C*im# z5a}s^Tbqhr䤿q`7R&<2/1zѹb*w|y7n M5V|^JgH@g'( kz~:$Kpfl7k޽VAZyW)e2qxv7p*[ ga{=$V!M+W7nwaX w]N3?t:w^qPyc-붨͖خ`.;:?[2Ays!2ޫVGR)1SAꝹN^2X,FNҌ&%خ7$NwK:۟ yl)Iвmq&:?cts"8ELP_Jx0d\8@C%jDK5Qa1{]zuampq)Frk*Kڊnw˕kO>%%ɩJq@xEO4:m/6@i`1E?Oskh~EEoUOSm-J4R&ڶPiklHO!G{f^xjoFZhdk9=zVٞC"SڂwAeݳ;:ZFwvJ*Z(^rCĠբ~vŻX]͵n,uT/Hp 8=9wpR} ߴ1>I(1SycgDixjVԧetc'kY kWyO/p .00yy3u/E f&&^舷-ptЇ/>A7ib t^%8*4`qz=D!?GØ^i v VvB^߮fMRnqM5F$ IS %8j h6YL3'b61yq Ȏ5Z]D,TuYIP^^RU 'C2{1Ոk'pC-u !;H(j}>|"[A3ӢSjAO$ T3Ö7-Y\PjwWvUDN1"b 0#4mvےM0A;E9< 0$s|Ա֣4UZ|VJXdq)$6~f'g}uK52 Rcw ` C&Ճ $+{8S ʒDZ\FSZžwj?XtH\K6x (@wjg+}֠u"# J@vXҩ4לC4TqΠ ,HT6q|-6_p$LlG}fXAc>wr&lFKD]=~BD5#\Táٱ137|G 0,S  yG(J԰UjEhtFr)M| ȝTJ%Xl砧NmPDan6>X"P۔a'JFP}9, I;x41Q6)i%ny؂wEdƝ6V#$ l.Z ~>krl$QP~p\dh' gs`Z' zsj"}tu!$5h;*5;0K |;}wn/ŠV$Sf-[0>GS3k_$&DaL3oQX X| عE4S~=:$UɰvsD {Mi|(-+3B>Lo o_%CYz>fS,?iEPVYm/X \vliCMr' ?ϩ3\SO10׋ׯIX&^2rKGUg̒\4EH[͎PM}oLmByZpgw(Xg؇]y1>;lOzoJa0]8 J\tC|FRCD}JwnU2~bMGǹ輶86, I,Ηklч+ceg)u }i\;[Ნ>o{E3d`T,@ %ݙNhԣQF&1J}X~L8ūO._] wXL!n/u7()9׵. 0#?C$Hy=i=xW<&Ar5Wa$: fs@@^:"d'D9. 8fEl_~ܮ19m˂ihSX-)hOR  gl3JA=꽪FfE&1zu(1?DO~֣yr*$_ȃM5Bx}Z+{5<+m(iYL u< ĸ4}<7bNu"h'#ce4LǨ[5Y_#!; |[7il7m41/:"X9 &b,銊%<%Ţ\m]jGQcEMm ʥv$uT͉)X͖z;@mpסa7@Rfy(@E #ϩ)au8VYAS4GdO/54{X;8 `G9WuSbpDgK?rCY廿Due~b8iG—LçMkE`;[lE VXb_ ߩ]5egtW}rBuy0f\ޗ^hsW,[̆;Qō)7js5&drs%G%7)K. b^g ^"bš@፶=@e1Zyoa]޿wD(\|% Q>@S9K< \=2c]~%QCs4OXNDvm{Ac[f@JKǴQ`*Xt}q !W)kAdNSJ[GZ}]4-bBaUGAAt3h=y[HŌހFr$ޖk]0{_ *vUE_z0 El Lrbg|dl2- w2FoI`xJܩB|ֿb9Yy<[7{i{>+ h=fL%t?u锠Jq_]PK^y= 1㫇hWb[f#ĽB8_>POWp.*W%ڐU۝ZM薊kL_^|lF-gC!.0}pqj'in/wv DxL])8+C_Ys_Oy: catN,sM3{;qkZ}Vas>a _pN 5mӻZmjr <0kzy ެu"|`$ujog{UG[&uB8BEF;<*|m$XJC_JGpB݁]<ΝUչ "h%轄*xQl (s ۶!O0X/$2ܭ6_tYةtX pVcKDQ~spF@ d*޹ڥeT@r||bb(pcˎ<^ZkA%KrBd~8E8m.+yK{Yzeјl;El5E ya6[UVnҍ# Re|Ct?~<5T/#czq$Ƥ800=>I6/F)F5id*C$F ]hyq Ѝa/Mt#LJ<8JXK?<aWdu*- { n(Ϣf' +nU;F"}͏ڰ\Aad>WȞy#h4Z ھbO[h8}#K2;IUsh^21ɹ䬸[6~[fSw%a@yiǦF7XB 7MU5Jr@◰ nsDXiLb 8`xX-HH ҩS}&Mf<+wxDum]Di@a;1~p6W9ZJ-$2=@|bBS@As+Y:hN(D@ dqmQO"(WqJFo~ N6Oы4=#4`)AX1T(Su 346 %׳:JY?2^q_ xdk/OkB` >k*<`.n!jp埭$ťT3T+Gw5ug~ްʤ үn $|y 59d^ǿ+a:sZL^\#ҁ;!N)s |uf?T0B& 7be'Iϗ/"Yu::@˦HTwAaYC'BcZfp{e]2ߖG"RH^;fH|&?YgDuٯG6:(P(NƴA~|fUwwj=ݣNE&s+3Ҟ+l<Q\P6=V7 S%5X'1l|]@4J/TK85 [EB\-{^8tU$=4!. b>eE"uFh)RBsmwr3dğUe+sjւͥILJkH-*Sfs8ʊb0I$GzYԨ(//!Q}vmYA3]V0e9~?+ܒY8,Tex/&@k|A:;b?r 7}#ܴrOl& 1N/Y AʼnH-} @VPEh|6ыy(q #p_Pul%-bM-&TM~néʹugt~(&1GwHAI~j 2 MSvLj Ki;8ҡBh'0٤!TLeCgM <,-*s97']׬b>;zQ%^/\?(BE.fR !.֐Mri̒K[M dst uY`k,eܳZ)յ)Q6L"iE2؏DnhM^r2@((AJ"@d' ~B/1r3p">MbY7T2!nDzP``fDK驑v?cO:JiaocHQ>zxnu'UV#PfЄ:(l9Iye&_(VۋJ "=qPA2ҴqexNSB6 YI:M-SR(tii#uK˛[:L"Bd DNȎ;$Rq{_,q8v&#^aLP5Ѝy@j$Vy|#:A7j9mxW}7a@mgz~:GCo,+/o)9(I1:Gꥰy#deR`FE].NPk)^l#K{?lGNK+֣ҥf64 $ b%vo/*& @HQq|MD3|2Ru*:.>4xOE9No6Hk+ [Á ڧJk[cdae#5*B1x{/I] F*DСXI|ׯ,4,\\RHvw)-PG m?O'! N o$x:x:B':xM~Ǘ3Ly\Q[W\GgRzmt/Zp~E4B?o-\]q*JX-im8br6. X*֦]F ca*Z|nBlm/apZdHA=Ta5O哀SfD}r\JI͟zٽ_]jŚqt C,P#4vHSuxPHD*}?8֤wI=`>0z r}m*TkPHYWX_VlMeu.x|_(3Ci^wߪů!bSnprbEhtD.6)x *MfV驗,3 <y_QزxThE>&E)m*(]}/gHKƈ6. Q0a--pbM.:ViڲL?f{P˳Um>6Y#ci|=pXܠS$Pa[a")x-o1tcPkJ惫x(KD[\])-AaxRgIZh06xcԾy(i=/qA*X?NLUjLy[4hh畝hICMwUtIJAG^Bor% &y:'י"LՃ!C_5q ϋ6|}Ws"\RP/Zn[U4 ƥ$gHv,u5}pfdr/"2xvgm5]Ll]mC_nh_l3A@ƿ &ȱ I&c!4?+\W> $yޠ xEY1.rB𙛵IӘ< bd[/$$w:;#KR8cv u8Ii(ÕE[-2J_zhET2[ 5ro)恃=7@boO< LO[Mt^ kNPYU2e\3bP}e9f8E7ovy%Q[Bc Y?J]kk#_>s%eQ@I?>*,Ùd\x,d{CgJaR)Nl\مo'{=- #3;U{^{ טGE7 x}c 5(҉HU4_bu47%udG5j[*N/{prOB]? S+2ar`bmaG WF34Arrr3Ws 6E"wڽ;fśgnlhҪ @#mʒ!)`ẑz>L@I#T/|Dxm-+s }a z ,(Q_=(=\9 ~D͟EH7uulx;AhL]o(PW(lޫ~V^=c;~U/efs(5; HX+H]3i.\'K*{d ;=C\գFK y'6_HYI_цro/xq*PXT׷p%1$1jRBn(kS< 9typ1꿲rEqmLx0+ZaU?9#o4pțFj_Ǖߠ_^7JioIBw//bDzQwp92jG(yDm88CڐWS]l7> zfA՗ =X-&Ʒp!vf)"xnQ 礿g!/6@+@#X4i{C,*Om7Hz]ɧ`!'AJ*T 8 BqG{Y:;ڃc(3 -,ҙ㩦 /U{'I:`":OYꒊ3&YB|Q1Bj~]Z4uJD.,Os;"s4ղid/GM]RAqglRxbAvR܂Hb-8Bsݎri|ъPuۄTwU8:i YanԭDuMPX_I $8({g!cKʎЇLk%^(O\~~s+8N͒D4 %_/buv/%j~!lC"o] :z fyvjtR } YBE?BzʇNᐺN='wVi5C"ߡpIOk l-2u,*Ԍچ>buC.aW?\^Z~#h+ZxHYCKM m)n=vJ3jS3Uܔ$QUc¤W1AnFi5: $onIT͟)E>)zO7ۭ PX.'I2VH&/p4y~A-?vpnzGs$v1S2_2tWUvreE}!r~M>Y4r/4eS?]am@DVVD;#G&Z61wۡF+E+C섉 cF}Tp  ]siϷ/,d9?X gQipߕa= *s\<ɴܘkPnexjk]F^Lsx" s~8>wHhz(P}͕nwZm [=VFutжZ앥ξյ?!bmITz4Ht-X2Egn L&0'M/7 +b)r^9JNoC º$Z}2K}j{b I%t+^H5PّtKisw`MI #Ok*LE7HHe0SUxӍmJw uU9XW z&-uH.n.2@T3(6U7r N,(d?3X vaIĖjAr3|:~cu2V2vO0r sѿ'2, [˸y9YVTeHT9,.?Y8}h},3ԩ%ub ~.,=yh%Y}%|h= 'Q1TVxSV>d8d#:ǔMwL`.COyl2hJ,AR=eiP(nkv` i8M.YߗĶ2c;L72"6Ar:W:̓3韤Cц8M5hn # N٥eTEbL,OkA5 k jYe=@y/F}x19]>zвr3 D W a uQFPș2]cLjPϦR hH@m"PrYix=ɉ |dpYy<\qaBL'rϡgwB+!7uNP>(f g!yD@?6܁!^P6Q 6 tD{.X/7@+ePB,.%6)V/Wm\KQN\#z;î鿻&EKo]pSa[ T2}*]Ӵ\qѤ.m8pVFHr.Ѧ. %BP(X| uXߠH3 ?ŝ=T/UOAFx$2XiXy*/j }Ҕr'dPcle߻ޝFה%ҨXQ$*NaG,ˌH}Y:ި4~gQON"gCdjz^uᙸ~ 䡢1֦*5=2/j1mbȢי0U eGqX-`'{j,D),=mthkME9}?Ic͎ (.y=.YQJb狥Uk ?w+ElBxV6A8'B P~sIYBoR|Wi.Shfpv7%f[!Ku)M &=13zPV\xsE:i5"GeM9hHgUeO|U}W l?4|5Xx5 ۉKI #d~.) (~n_yExEz. Gp^<%.fax"na0pp/6q'x(`oeh e-i}`cgJJiHr։C6β + D-Rs~˓iY5HxaTUVNO/Ӛ6&jla6pm!y)3$[wUEuyd(S9:eupb|AR3W>fC+u]\"% F$jM8oH$:3r{a (veեe_dǟ#Ft:A@oVwoRZa΢fm8`wuջԠtBj|m1US[ڜ| P0 k euelSWV 3"LQ#򻘟* T"RKsG\ 1FqQ}!qwmsGa>OhxzOq͹VQ7A~!`|[=Ϻ#{xRga$j`HZ_yG^<{DZP M”$?? .눒+;8ҮSYx,r2$h zYQrA&RWȿ"b4P$QwS870 8\`)KlI+6Db {`%NTɁpoi.f{RIMm)-W*Wꈽ+V;).W:ƶ'ri,5[nl -yZ5Ve>B+ib8PIRݲqHgjҟ/,`_:Km(WLM'yɌL+'La]ƨ([f R8G>9!iXLɕ?nUH11pީ; 5jEeif$_ xÑ}P!ΛfK D*. ɾ&q0,Q"O:(iKLh4S}h?!f;8aX*?f>7Y5R, \k-G ->], .RA"=#3IM_/IZg Z.KO[xXEZlF2 2p ~M%wO%xQ'2r3idާ/`8ÐeI't,~,yN:&!=OF؂WG]W.n%%`Уg+I;ZBÖj jYgjՔS,(= S2 4䗀'Lu "<82JY >^kmII}><&R3P9Ս?pleܒR!K瞒 OiCh8~WJ+Z68A޺-?bbTqy<4y)ŘS%4A} Lp|٪|[wZ_Pv]3Cl=ۡq OnBV2l35]Ҏmޝ\MnU0ꠤ@H'x 327?x˼&鰢fq4`JA_1{;ycbGmjڵ>a3X($' | hiq*[^?f8aA>VfLPG?rPQ`LF %1?!]\&ʨЎ4jL\>!;>̫5*[-hk}kfn[FLqNa7#Z0xzl/\7bf.6d)&|ίdM7#CBLBRF+ ļܪ"Q-NJ*~U;9#k֝d ŭ|Lǀt$[- kSflb6ZY~Lj`%~vc܎jq(>eQkVJ;E')) ELYa(;1`<Ş<A'#~ւ;4DtObW W* Elqb+zG 6CB0XyŀO |q!;湺*R+i?-Wlt/[H*.}`|5#|ۅ/Bs,N8ܱ `RN'~*aegE&ҸC{ɄOAQrghAj^=q& Ph7GƬ_?)[o(7ܞ*h~~ǐVgRРEudC`y cRQ0~izujW.j&'I>-WQ:'xU"EqĀĨRiFW4@(98Ҫ a'4T q?fٌy/W~B}Ur{JRwW[a(U󄘽61+[ b4Zwj{Kfp9V% m2귃c v'OW*x8T9$FXU'Z-M=18@L"1cPJ`s}MFAD E ]NeI K;Sy`^x΢q +2X~Njb4I*KW3rpH- >uK`; b,3x"P4WS/C cXe[3[ wK^e5f7Jz1`93U KfsE+|VXAQ?QH-B A+x֨ƧvH6wjc Y XhƝ/lvI}J3VBS*WG텱,x(x唀JrfeWR@x̐%0 [20]HBrd 𲧞)&5w U\(f~s/(chO&D>1Lw=&~g_ Z۲3~.S<#J.V/=SW&P)ֳV2-M'mVvǔ#eX$ $+$jyE4o3-ȴyRa[kŠ7ަ(7Sa r* &g)9LYPҸ]o;ykLN%5_ܛѽ"EoK&mE.,5 w3. gժp%)\MW'6v4o428pZ_Hz8JuɻUCy3“|s6Ae&!s1EǏ5[ }])crl)R5ܣϜTApvN<)]𨳏DvQNN2Jl#p4mw>ص@v{wҦ6W4.ێ?Nc}_-D f*j2oL B3*EGWCv y͠81mMohXۯHS$5b`a}(3CKoe'x #K&GZ?A jSm 7^볶'3u65 4]kFZ=-ax(iℾ!摆#of7Cu1ۼt;޸yǀ:2,mwUcKZxXޛ'XݒQ 5 *=C׶;G[VaP#Kx,Bd8G[6QqsV_~'jշ-s:3Hojy"Z0_Թ i9(#OC q9AiОtL0.1M'"%"^ҺBdHS~`EL ? hQ&1׍𣠦IjH :'nm8u-li ._P 5v+&Lt&#Q XVA#(˻v715i!ȶr'Ֆq^uCQѤUE'>(L%=gB=`Dw .kl KS{kvTk0)aJ.cX"VSZ{d8̊7+MLYR{̸ѩ5I]Oy:]<͈tV`hMUZ#zclz[i,~SɆȟ7߳..6=ᢔu] K6I1e-?FHck$c7B5 PͰ쾻]3m9@IjH*gS>P`=+GH-[&Դ?oꇇ7sx><,FhqH{A${|W(QXl}vζ/b9wR@E-lt 2EJgDw6>`\?,v:^af xȓ }B k3 2;;zӛ9aA(i bV ḙ̆}:"0{:?TNVABm wdœT׮E< '+`&)1Ph >̽`WId(B[(x! g.8ο ߅7-M2=3s] 3Y)F;ӌjA: \77D cb\Huk:Bڶ~G7*ލ5XlHxjF DaYp<{%Ɛ ]MȤ(ܢy>qzH-M2'K{g5ƪe ^?$xc\yMm6"R@n9J: [; ~cs?jX!V cN6#GpHDS1j*@.n 2OB]P5;3"fk3CdƴwbAZYWR;դK^e};HVHeZ̽2-J=EuxBRQ渟>Wr{-E`-dgD}1}n&Oum#Xrv(scYKP@?7xFf~#T"W,?FLB~iP:5[a)KiƝ';@wvLLmr/k_̲Q.69F=\rn@W=>4dVF'?Ix&BaqSMdQ C..BpUb_QE3k{+F⛖L`$iH=bm{?L6-0(--3q:ku&{D-䜚gn.̿)c =D%'Lv"vLz挢ǧSUO-Vܕ7;uulMgd@sZAyOs._l{ bkTqINj"&X;ӗLBy׈Ͼ/ 9{Q Cfy}f(աQ7h""49s&FY`S)2E="2\Kgu)&.웆`:h7o6Frn"iZ=vL[ 44#4]va.K{2|:d u ngʍɁhRgJ^6 -~6qWDK3"ٍ=zz}WQ{IQe`IT/dݿwCT݉7^czUKjD-9'޷^nJ|+HN\kL|*?ӒaJ`a7Z+z5(kPډӿ 0US,ykPERBVaB\T~f .yO0DeXQ`zvE$ؕbϠ _є߀5(?4%ډ 蘖BQ݁ NA@$ ~@/\eOR}S=NEae]3Yޣ4>C4b[Kq0WWf,Ml5DR3@a] X#vjɀ'kI+bJ)Rs_q'^k/2E(5$Ţ(3 Vѫ\lI.LʉXTҵ + (&Wr#*C?x_>M ^/'-t4#=D2tz^8$4jbPغ=$|kdBI  ^dS+GߵV3a}{LP٣|J)i!T &lQ l,G qhm3ra|ٻu 'rNb9QCq-?ZIQ״cvxSö+*"mYUCu x"Ĺ8@h=B]lx|è>X^{_\-$&7-džydkXsw܎r寧 U0VyKM,3Fo9gq˴ʚL6Vf bn)`tV9#Z{wKde'?+7!E.k O< _+8?>.X/9ayaoDV"H,}C#m̫-'sہu]ԇG: Uknvloc-q ٥а M{(sWf/S!|°牝UBs{Y1?wz'Y"cMH$n#5h\bڣF_* %K莀^_/HƣD}4O6ârjQ (3)A07aݭ#5dP6͢wؐFq-1-r?Icm t݃~嘙U,=We֯#IUf":l_XG̮}:-ӫ"ڶ(2&i }͏4/]O53DrXJFkmi$S7Qd[|8Sǣ9 N15ј`gW6:4r w x8mnxB+Go_jtb/{;moGX߶Xnو ۈ-}= &qT8" K!;]}J1}`E3oܟ>% jsQm\ z-(HV}V, @ezWD\65Neَg`9ɢ#J &feo{S*k2ȇ2P(mjpJLڬs+@eaQ߫zkz.vT965.H:}NGsTYq:HWCY-gIU,7{u޽Ae#rh3d'۶X Q|٬u OA$`vxk+ez}K؏/90Q(I%Vbi3 Xe&K*qCH&%ӆ) G@d, ^Q>-zJm1@->0>]ca.z~-?MPB0U'mfe)ta;)#-T# u@Iq m0@mOK\ߟv\VA@Mki-mY<҅ F#:F[qKhܷ|*pTHэ&P{sa0; DzS |ԽE-F(0x<6n;tl|{ƭp\vCVЬ6sp2؍wޓ@|Sw-e l\S xWxl>#cstH̱p\a强\ކ-Fdۿ,mO&aƴh ʐQxwKiDʭТeL .@0d5#yI{GOFkw;soʏ򣫜4T"Cg$y12B0uH]or5N.='*'لxw_ @?ni2xc*vT;G'Խ(c>08 +N3=yZK/Dq)9pѰuM$~XұO׆Y poY;HQ0yT0Wd5,eECD5RnFўX@> ;*"AfItzy"RO"چ\Q_5#Kx&?` -'$ HS᜝}~ I,7][k^W^`+F3'',~Pwj1D4=D"*I8Ūm܉M~dFzJ*",r8mf(&ѤmIh~wIhFiѕJ}Iگ6W%Q:ߖ:@4ןL-qIXXtUj&svI;j}N!$|`l6g_jݭC"EgHfߒ@F4us,U-8w2DBWȕ}O>a gTt >m09 \DdTCuHJi=<9+$brCK$&5tZOym±_L{`61Q>d[ a<)ѵ ۇئhXql=}پ4lEjx{E|^x=f3*񶗅:1#!п2a\G;\ם!+uCV cy&`2$ fL: +-M \8-%NGYHT( 4B +(yY?߬2gr4FN܆!9vʝ#ţa2];6җh}xsXLr^OyWjGԑƺP{/8er]'ds|b.WZk=tIU`Q6 %C%aImϋ% }Y­9u)X@o{Ԃ^^ΟkX+9mM T//JK(Ԁ[QS[qd}h"jH\O"3®O{ gܘCp'D<.bvmr?[|ņm|MW49xlq3oGv+'@'CuMLA,6 -f\>ujśf@d6Afh-%|a@C8·*Zjvܨ",>e=t69iC\7EQ PLa6aj{_; qV̰o\WKt-!_| at_02%@Ⴇ%0[lo #n] 4!3)O"JF =/bŁKJ$ض2X:|(l2z$TK0v 3Z"3ȓ e)43nľQO} VsjNʴ~DȢhIН( /mĻX1{LRV%-˹`a]O>0؎azX$08kOQ!I.AfGDl#:\eW6t]Ӱ@X{.Vk.Nʨʓpb,#`d?hI_RS?K>2Ax"{@<  vvYbo6~Ֆ/ _Kj}t6@kz|G̍8}%QA.Rif"k`EzjWz\k,y>n4ht? d“ f٭ F.97bK|dN5nN^V>#E^G詩xߕa~ǧam dl  m#L"/Q{Dpf-1^p-,[Aq9nhB`:s7QG,2>9ڦ&[`z Z'!`@2FCv2LvZ7 $Tk'%SџUF9DyviT [ZcWsMȴ$S%E;mih 1 FNv [x ~t8D0^nakυ".Ʋ" ce'_g+ۀ$̃%tYAZ1RX fm7$~>嗲_q3lP`̵HKY:ӮC$Hz+M .zVTzG_b`~O^P/Jqףdr-xn:X"ճ F{;9q3~z!ú01<-} H\ -Q\yqX"CU8 c"& I-#rExo+!2tCYP?e,.bZkk3\$*;FŊSI k: WܺzxQ >F d[֌d(bl}ᓋ^ ƾaOј -`0XTV'w YHfb,6BJծ;E3 7GUb<}(F?o|.fS0!&m? PK'n\s0A#gG=poJPK? f6|OmKW/f혡a21}]so9Цlʖ_Aaz<#'~B$'F_H)%ՁSܕ}+A'R&dd9*S9wV@dH_r&TrqƋK̇˜\($TPso&yc,<~|1cc2~ ;6,gBg+(eEwd#qiG |\гiSvC,(տS.vFNGI{95 V3zNL\i!ND*ZYs) GF4A$¦D.0uibgxaB IRCA7Ƶ -*j;<@ ٞ9k`?ɪ C,΂J6/v/0_;[pL><DݷQXYNBtAtoZޔq&C" YN=Ih|Ϡ?BS"UNDzS'?JbN.% aҳreΘufQh7ndʚK1Z!t8wH t'UPOʐWqCՊsõ8ࣿI4S,̇̔ՋjرC DeD-CE - 3eMHHҹ&7`ɯ$hs$]Gv]'1^O524ޯPU%d Z CK!ۇFrWr-'-%B?ҭTںG(\\lr2^W|];qU{ IwD4;&"XKD\fۆUat">GH^5EjvC3 =jr3)=2ƗnVzIJF}}ҋ.AzdmLAiZJĖB^S1gNb/ޮvacm~}שY0{c9/F_Nn`:L_/sXt?q.1U H Wd|$͍olr&PrQe-rvW>J龮./"D+^u`*$GIlBޝ'|ʌxGHx$BR/h$(V QjƨlȰd'r >ɩZ1Yg&*`#T6J,#A;`=زx0R@p,#$]mݤfn7·z34ݭvZ!` MwpeɛμR&O~?C}<e`bY n30|ږẴv.Mͤ냟m+c0vIPQĊZlT( Z?R 4Mpӂ>*o 5K`|>5w@L#쎺s\֠5L =dĶejն>&[C#.-QuʍgEv-ۖ\쎹Y- z>0M *|)lB[kIXYq!ӁZǕh2W<Я|510h\JFcqE_jh*:D u!1刐7FY\)U#j')N/sꦬq*Q^B#'7*͛?~*!\K&vx̔51;FSW|=pnG-f &u%fi3G˰#Q 'a9CEܜIjB+v\;`߇za#>B68tpJ"'Gѹa$1tF=mA6epJ RM*2S~: ;O+sg@Z2 x⿽nc9j4@t) ;#&#ރ#~MQ+ub{k<bOWT$Dqg#CB1a{?ƨڛ3YJd/:`6 8KT1!elO]~IyxPORv& }ҿ\h ZjuZ\n$H9a@s` he3&CZRN#zs+,YfˡD5BΒjN2iH笺ovj3@FvFۂ*Q<Ů6HY4Pf3y}!F\Ԝ\ {S4򭃍rd9y)eGƞ^C|pba5%11,Kw H;(DN5 %-/Yȿv#=#k##_j Ѱ|=B6;}P賭;rc뀔rykݥ CuJ@JGuFEN ۠J"p8KOYV?i֙rLY}T%zdGAjhtDzw &w5ӂH ^ێߩX!Y5 nE%e1aB'{%.5|Zģ=7dAѹT+ҸED3B󿚀q.n4͍ Ky~}cZX_<oõL)l(15A1dZOnIw8[ Pu²;v%Mu U˗Wк)g6`KӬuN|6Aٚ GPf3թ& @wW2d;hi|`D@iyݰ!K]X"_04(E ݇[/fJL)؛Ŀ>]|7تC6"wqiUq[O v(8m_6 jLg.(4HDXa@r6}=*Į/u+9Nxo " &@Ӿj0LNB<:dE^ ٢G6 ^ %^zFtг,L(kOuUf7e_kM_zadTRDU׏*4U}{7) 12%Ut3҆d%ٽė{A٣"=ߨx'2١(KNm$T %KjTӠ FFd0=w_2QeTjJeG!niLI-? 9<:.JҎN"6Lwi"f =%+#QJ9]lˋZ\~}kSa,w +BۇKuU H/vk2,+ɽ `W6s 7lvgzHaIXi=QçrGCH-3)!g!Y濵g:_ЃZ+Iv>[B^b挿tY\DJS/0 \E%9,R?W^kojo'At ju>µ:Ÿ>T(/FYJ:lUe!y(p>+Œ93YJMpvhMֽƇ#tuhVr֑{"7 ~ƓSUwsx75 [(|ɹz3-:/~E!:ZNe"NJR*Vc3? 2`hdwΞ=ŕgQ}-~!Cmv@/k7%OEY|m 3F9΀\Da?Sjܴj] z.dƢўI wĦ)kWccHS]1͂ PETxGMUmߞ{zT=D -y'.cux$ /]*Hd1'IP̕ʐXMu9?SσDͭkiV2 vH q #zzf|NvoF݋1LOH<'TcyTө5H֑; r?U@rp; kObOZлerx*#܈kpj"(߭U3o%S`&BI7! yX&_T|Uz/i.cs[v*o-tMǴhDS z9 W2`񍳺;0-} ؆(s$(=x'FVM7j3$-[; wؤ|[V0ɏ XP]H/SA2|y>U->Q(scRe$Bvu}Vp4rG`6Ezy3& {-c1^\V5w6U0+w6GA$QNt-K&M&^!/#\(h揚UګwC;&i`"HԨK5 X'=.P/X(A/µx I}fB (^| ijmGVwᰪkQ@- gP.0 N~qF)3\s ̼q jUQ>T?Α}5~{qB& ҝG5 xx<=l0)BkaU)ow:r6Rc6h7uz?Eк$5lڭ7o&琑jĒf/u=9B#0<(tї䉎 (<ݙϏN|۩ux!Tb-pRF"s EyD&'#<pē3G $P{7p ESˢηٞӞ'K fXC6$rp2pӎP1؈~W]KƔ3bg}٥$1,Iq-Dvp9Yqb^$O5*_x|̭TdܣO] 9+P,pV/Sj4<JHGμb([p7 \vCuٴLg(Jnu`:W1k RpR2a5;X3M͆/]28qЋe7T7APt\Qk=[7SߟI;ɽ !Z$'@pkc#bAi˅>ԜPZ.R1gDik!~A^E(0բmKǖLQF4ԄrX<↊(bu8ȖJ djbp 彄Ujgۋ"&H |` h|\Fv *SD2 ^W >NQ*e"UR~d%׶9ZVRU3 \rz9αY6au `AYNK;E,q<̩i3d9}Jo ?SeXmuD螷G,}ѝ0`sLCR_VG-rWU17g8hc@0 cd.S^X)DvTyݶ&Al0s&[twɟ] K^( n*2ށBx]#ճ+" ۋ.hPJbc*mRx%]➁(j4XoeN;} =v:wϠeϤ Ra[Ɉ IU'U\PLe]چ@I>~|D+̲dO>"RY;]v/g&MOJhv_ fkn6Z沑vBiKޏ{J ߻}pBǠ2½qr9"!7ag_HĂVi|0u  c8mZ DOꊓJf v-7 qїJTa*T`jȬ`@95j0]DrHS׌38 o~$R>]$f2޸Q\܇kz M&`=5>gaUm Gr9<_2O rTHjM !mJRPM1n``ֽ1 t_CR)8cD)&wygk:4h3mjnj953 ė_ b~pLYαz ZbcOzJƌUYD@.t( Jדh#Et5+'[s (p~˫+~fo3?pf_ AV`,~utfe֡wdn LL/)Sa2PkW2˳O)sNgj|K4:oeQd2bُ(_H&K=ig*ӗSt8E: ֙[DM2y^,*,(7H3ˡ \$7]:X|4+\Gh`_(va>?K M*͸<`?,WFmhHU6aJ\Gӡa|JH}]&v5@ 8G(v7~5˥0PGŕx֬> a=ܹGi~c7H@9V*=epCց`۷#,*&w;,$)wSEnl^OsG8hBNz},=bO9 h]Rs9!٧3'K 0΀~=+NR;B>j^wӈՆAؿ5nYu2ljaj(;敍̧4;y*!ֿC1xuتq1 NLiƩiU˟v !c@ T@o'ĭyXpmĄs}c Ȕ~80X]WL!6nZgxIx RF@l@[ k :C:wZv+UUBis8dKD\l!5.A TK+rܔX@htU%-:QʩA|5!=l g\=3֫hcCRr`.*7$}Xt#[+#|u>(JisE@1H y5x`?&%ѕ;ZD{CV4lq fۣo  s )t3!ǁ0)EW =^ 7CuDAwa PJ*W"3 ܥooG.cگP9ω |+x3=['h%ͷk@҆ҸcP78>T;'STlUCNt~y_vF pʹHY}edcQ(Zw㫻=|X7ҙ@aNĮ~jU| 7ʬj>ե'1m='b]w ,ɭ!A+Ph+s,Nq힮;'t:Wm(rN?2LM}/-ĕ7\Zˉ&u#EYJ82 aFe?7h`Ipў w$D=vHΛ~hB.~|;j% 2.@7AjE~x-?!z|U[(]4 "F`RP6—Ű֗Sy'Ƕջ^+skDO[aWl?All WJSW2=F:)%'ZbK1v% Yt>TJg`w0|T0+PnGD/ׇ򮣯>AF)E SrmC`D0_Fend2c[#NK$,};vL-Є.;4tljoS-*ZU-\6pI)%{"UY ( tܒW *=0´&c =^ %jw̬(J'1!'z8Pu'{9 k!, h(&^-b䧎JDxOj]MqToD2 vvg`T^ɷ;iT L_. @#,G'bDlSk-d8YL -+v>ʱ1q0GH}WAaj5@G^Uf rhdU hLEPTXٸ8dȈ 3!|\}1PFQӽ]`pl)wy3*(9 Vi(|C?Fƒ1lltuoe9y`8UHI)MGniV՘uf{4V[0oE:7'O; E:B{V^77א g>?[+:ŚQыc2EW0 cr'yM _|V&=r٫9aՀ LO}tGAD2oNJ\C2I񈌻^_iWRTY*znI agC[rA] #8@6'ʥٱW8tPx~[mHlԍ!ASH0wsd䗓;pɖ/|qQ8 p!Hlt2qޔ!CgV%9W'H} `B,1^ >|7wQ;OPLk5c"o`I,S`&ۋ*} sys/yƮ{=32dKH?,Ս&o^qSy(2ǽ,s>ud":z)r̿}Axc1Ʈn@BQ`;LTBHBdb(?/ρwR)ƈ /C-hN ۩NG(XlGM( TI\I&PK{ &\3tLT s}rkև uu' EY& 7mVRu-xִ(3a-6EٛɫHәaM%z44B2j)P THAZ^ NR}\heiaA-PwI @J,=%.x/ݙeL$<ֻyHjhʴV8%(üABI$C{Eޅl:PIMδ+w61r H]ZwtCu1]xط~A$K*=^:88xg*^ J[by %x9 qYՃM}z^٘p ~=VꄐEã!U7PnHe\e1ht/<7jIeT7ģdO\lB܊#vF@A?lEoh7ށq9 ܳW()|0l]=u]mM'wn*r d5S6W˼ KxgI sFj &FU{UT Q4dRUn1ZKCmBDc_V(3O;0x<PAWL(QP  w1ZKAxB5EwC֩Ql^HR穨pCߴݡ%5C{Vz(&Ol~{VU9q}VahT6XR5-o?')|*_5x ]{d!Wg.M' D aFQҖƢkG!MӨ-ph9+{m})υjoty |nM%3-qm1 U06]NG$Lz`.w w{bpo1TMI;`;*Lb10:PVEYGx\ޙ$t@mQ&'Pj [zn_hz9AJmK ~V724Eጓ|>Ql]veS uӣ@d:Y8^UO%:)i1<ͫ.y?mPO)gTټox0'6Bqh+;]hx'E yt=HDk*9Hϖ0_s_PݷqEEt3^zINvZhNl]HAS$Z4bS8/vMWv[iw1#Ѥ͞|FG*TiBbĖ *VN#nFׅ&,mr@>1zZa%ua 5~d~6 qSxo@|-TvΛy&s [PSA542z~u(!g0h,4ߡ944Bw*N~tY"gZXgV9Py)A68Cңyn%|kֱ62WS[ ߀= *uEX} *ndrF=pjj7ERc1I2z9;$2V@ ߯"+.$`m ŚW'֡\J կB|"D\d Rhp𦖰CSU^Ƈ8ƕ~3FIs}DZ޸gH>L>;w֐Υϲ1x}ĵ*0/ 3o-Hj iTAP)W&lӈK;]R` -hFhJ-cƅ Z?Hk gĴЩ`whJ]i]MS /M:,D;,|\hEwo0t40rѪC$tipWmfNOP(H,3Cpvm 6%Ba6%ָۄ8KIZ'OPc" E/cԐŎoRki]9;< ].rq<"H oIA(S/)WKRV8S遃w^}Aߌ:pI`L m\y@tB UH"mrXm5~uNmgA[f6#6V`/ Q^l }gQzoc3W2Ry`e[@)M ބe1. {2MrK_ʦOQs-+QhmEo|%Qgg0vm64S i ,p_S!aBr_䑗B'LX62T=yns*wN;$t7+3B/}䆉%[r7sJpIH6zUCH0q%ĥ([mCy׫KoH~ _ZkXPDޔs&=JxgwH*sã}n5.Nƕi9+"֨###Z蟁NvMVxA17|c=ؽ44q$D?hV* b'My enQI`Ӕ7+BaM/{nyiFԤ5~p ,, JL~W~K݉+m Z;X"Nҟ*,cI/'-PL+@NW?/: ^ F&*~c%N&Fv?HGm}<|T&H(ʈۨ`"Q[ /`-R-;ԡHbEHP#!QNkÆ8vX `AfĶ|i-ѧye(pxn5Op͍e-16*9)j|$9=o$0x2-r y{e47rZKnP#$oH@+d@5zE%)뢾׀y 2)'@Y..`\Xc|) U ʽ;ڥ9Ք 8 %?UkcNeRM>>^E?!K,bqɧ-1[mqvclpBH_B:mIf[ O耝fJܪJ(Rd, FF}W d}l]#ۋX$SH7WE6_וOpEipe0OHѦrbw`0˱ox3=O HdP3,P"vO4{Yz'tSCF<2轏PL>AE &,$\ ۿ㌊?cֵ; `p2.S!Jz͸ (VVG+g8@VQ˯qx@M7'Q,Kl@:~"DI(/{DdUaaQogżՙ[Z#1X5z.752e4f ՔBa1.;=Zx ,i؏"'_Ӌ~n  Gz'ZaiEp\y1ِsZI5A{X2Et_yk0y]F2 !ue) n7N{+i(zކΘ'W3mYE-ن8 Y>|t2VTx@mZ~R&@V-և1]CnU c޽$+%\?qyߙ:Sl;S"3 w b7TJ6$BWgV6K'yȴ9B%F6Oj-*YZY/H^&*&aG?|ߒB.1 $F]I\g 5ؘڬ:\ q+C{3"*x;![HS!6z=Z3ǶD/cP1Vc@%-M%$̎uj-: (tyvf, ]nx%RF!q>SR(]hCK?γF]fK'>D.Te}*:͹rgoIe:z?iAlB6-[tjy5d5%5kRr\ԫ\l5HH}>dZ?q˥7l&vo frS!IL}@FktWX=¶h_f+V~k{S yH*-n芭ڷ8n&86qE&9q_N&×C1*QB*}d`58FŕQ"x+h@Ł))deh9I>W;6O2Gfc^L36ue&aAw/'u˝wf 3O,p]%9զ:*~+FSol1*د:hO @hM3) B)' Bf ,Te/Z!MbfʞbYfGt=eϾ~78 j mOh{LZsw*/ޫvk!/3OHx5Hֆ֒\̧ϊbH* oZeaآ\oJ3}Fٺ3 3nTXI׼d>dzf8cF/IV 4dagMB1o|sMu\xe6cT!JXs‡f,Q~I1yN]"=H; s}FDg+q6gA߫|M5epI?Vt@1_[[<}󠪠MoJGuup/&cW{zmg ZC%(驖7if [joA\pC BLYCt/O:Ѐ"o'-l;]_kNG5,ueXH8Y%RtY14KF&q?Ŏ>k<Ѐ܉+HOB5Wb4Zـ?@صAosٕD͎Qy~b}} }W9|=拔EGڣ/;NX_?uն,5;1 HkEcYu-K Rw0(1qt{F[3\Tyhya/Hhv?]:LIIC쮧_8 wR0 R- l Q[NqŇEw %?AbX¯`Ɵ8r4o"m mF1[.:y]4`|M8P)P@ ' VZkW@ꄡjTYӎױMų>V$N9!f3/IyAX'.? ){^;>|y5M:yk~ԑͻ|8CW5G)NX3hv[_c⍤!tlW_dԌTOEWfXFrEꧨɨB,MTSEi8z"Bxg v "֛+5b&p{evd p /DU\dsz*t*$\ |@N>1a΃M?;8xd_A%!4FBL[6ѕoJy"\ѬduoYYѪ,L<r_bvVlAƏ%s?O=llO 170FSC[ 4w|JƊ8HJ M$ltc]_l̕JvZBb ,+Kct&v\3⇲>BTWZ|*s&E:ݗU 2* LO4F/K鸍3jQSjc Y'IDTWӱNAj򍕬8tG;L@N zŌ ؄pjsN4ߘ՗EԴ2]8ښw~;"@Dý%.#:^C$#ҐuFW9vJ!ޤ"=0{e҆M )Ψ\4]jl5ifkdXԖvu^&f"GTT'v&_mryo9uŴWPDlٌ-#vI䚏ʐU*Ֆot ΎEP~|3?D: \5I䨌I 𬨤 % [kV|QS;t1m`Ӈ lʱ`}Bbmh l?#,5@Y/Ay`;_,!A14!t&^Pc1ҳ%~Zg4#w4~0*dP%x^ 2fibwʰ 7^=]]Z$˺,NSTNt$bۤ:\NPH8' ӨMeذ*&t9Z^v@.s_r8ΦQ8eW}L9k$񽳎 bT)gh`.jv$. ⎝:=&; )]_ 8%cjmXɺ&6hU5ɈFkrBbV}+ЕV[crB@>xDhT졥x&̜yeCo x cg0>dssj˜X*v 596yJdhBbbG^hg$|bVK+0:| r}dYme .{bE# f+҇'ށ"zGCJ|~Q4t=aoYQy┰>)S\ bT5,%AMSTUјI~$/8k'ڸqɱ[9sil7T@G8gRnbs#'F 9w)mm]dEc&64䱛T?ڵdh)r!)zL'; TM1W}O1'9WfbgE:fLdYbuf8 wLI'm{ `X"7E1f.KbbvF-]ޞX";BcUE*P4}vVe<Ɗvel@\LmQH{\`S)ƺwVMgZ`kYET௭= D *Vggu\9 hnҍD6 M9뷕\WdI}ܔ;c7)$R6E~Lѿ:>NeUz!t@=e#6#QˍtM{T{kϵܓ|7Fkq)V1*U8njmkQ2)w=|+7wQyށiSdLﴹ4B$ے,iwS'v4 m{]1z _u(^\cIiGbc:j5z 97(\9?}jhg=$㕊\*iRXAe̺Q**˳t&M؞Ύ.`F˓Ԏc8(,r[E(Y`YDƺ1a#/k*&}et|v5O鉨g?v]T5A%E)!*qLJ@>%:EV[N؝X+Ӂa;jްdJ FPq)V%5h@ @6 ʳkw]>COgq,r{?[1l*YsA2S?kQGD Goy*];S\Cw/DٜE;|VsFF_ ,ԃLLܼ '2lL: vQtv F(:>g3NP`M.hFJ)Yku4*4̴ {NajNl?iquz.j 8=~Q~JP7W()~˿~Ux pTQO!HOi{7bG9u/4_)_!2*Mxg !KQo@Zs &Xq f{5I +M1Ms7=d,΃ yl;,(z,qLOǠ0Qō+uNKҎ!Mvz,$?~3¤埍#oێa졥Mk7QfrT[)OnF|%~f~r+,!rp جy#cvd~?X u#Af&oj@–5&M:5*~O- (ֽ|/5q%IF*GW_<]\b"3̋xGDZS &QJcE"d pzwFyRt.:V4'P_SĀgq[ 0'ff"5T8YΆx`PSsTeX0c[ń,O> 9cWS X厗:c/OND &`E]ՆA=x$q5KT,jZLJû\;%K̳XכFq J̝y`֟{ ÍҶE/:9uy{ "NHw-l+4hGdno Lj +^v( Wx KA]<(kf.iArⰿe$un[+QߐI82)E?#?51=0= AHvHdbx(;̢CjL@%菊z/mv6qպ= ~ =`Q H㖵jȘIV {ic +/OȺT &PeZv|8CU׳,ܬd`aV3!8z3$A2΁ u+O W2Hй,*HLA[7 b!رF8QR̊Dy?̃iECv6v3iZ*YTA~/λ6,^M ɸ84"!31 +K?;&bRWQkQgA&yiYm,bVQ`j< ,w5>L. .ЪbThM?XỎo. *-u}#Xn=Xu {h7/^^"]œ0SRjJ/l >?{J>tg0uOMƒ/Hep/ɝ$pZ?."0֨D|~eR-lIIPW-TC+T:Y&P>MIYCDJ\lvv({!֮zjW8v4,䐻וq׼Ae^vЦTk)4s";>#/o*k`.Dx2m^s#Ko9$ RyAKh1 _XD{MUgoM|Tu׳c'FS"ZzE]-A7ocH9'ǎth.~3"; X@8q`%k Gu6 U24i  םʱ8>47Wea +??~?n~odD6ǃMˆ tySLq@ňiޑOl){6K4qΧGH ö$m纁 6Bى%hy2}ƛ츽x޾[J8Y \0~*3 +j"1=xjR:xp_^FndΡYw?唰Gl*⻻ҙ G*|)NQ\3[( 5R[8ApnTxfw&Mԋ$A( Y9Ewz13VۖځKW:<9z|ף]vro N9ZQc02/[cwD`2IJ i*eeo+ʼSxedXzᲽWe8!%dSEEf7RƼ@EMZ@kCEU2t9J*iż 63<  FѮ$g3e=)dڕL~=.#~*gpMq܌?I@AAnV2ڌP"9FFmL~:Iֈ/Z]1 ,u:/pD?)$gBUQSuнqp2c0"ROCbլb;r9O浆-77%H䇃k 1XK>hw,IInJzGPhHU9-Ug)7_P{'z ?P/0 ilor9gļ9[͚>/Ӻ~Hm[' f\eO-Wm<.\J}3^rU07%Đd_@|G 1I m}8cr= `NVѹ0sf(6E}`4\$A>)8s.ςCqES+R׿$8'S=T1GlJ^XA e{Eo{g<_;p]"FCp&89aE-̆YnhI kݦv kw%HH/ 3WD pC3W QQ!!B[i{[ ` FiSH/HgezMW ֶBчXĂ8Z-˰ypwY= qԔOmK1kacJ̚Wb/wWHuߛ/]rAVof!9=Uu[HJm(q٩7sٲ{RF6CwN4:%?Kl|aG7M˲27蛌vv? 麍r۲5yOߛ7DlEBݛC)%0Hq J'jPg4lυ}?k㢁;o8!0?\fn>>Ȱ3*BtbW]uP!4| W>(zp{hnuڛqih\R^ˡ0 αY|5U#'Йkp+Ŝ*~ =jO"t|Πs%nyZe^?Ĉ k.FKѯ 46ü,37Ղ) ? r%7^_~bC(>Ϗ .NT]$]4^jL^G]5iL5<+%sʍWkGCd'061&[ Z,!׽ܾ~"dM{_}3Ly{4XhmO 񸉤5\MeхŽXq=ɽ^E|tE۲aGBCW'Z |v(J^Ȟ|NˈofYοwkt"ZIP;Ǹ2iglzYhٳqW!iS3SE-9h^Y,}k\_J{i0rCա #ENgrZP,sSJw&!{Ka 5'|Ѕ%a˽4#=*œھ Rg ]1,qtUCBV"1%KM(.-:CJGXfBmi`gۨ0$dDV~%_AkrB~'* ƻ)R?jc 'V#(`MAe)GWn*''NW[6إ0)b. ։IZt|:rNڼ% P(5Mdǚ@=xyڻb"%W?=AfMϸX4u@2mT0BZJ4r! ,U;=܁T|g)4DwCLAhS5y#-p{DҤf+RDmpa ģNs景N8:jʘFT6WJ態s(co?L vG4dF?{.@W==Fj-uF1:`8XF ^5 `}/euy hE B23*XS :ěF7 j6blN}y16mXkeq![29ER;y2 uvOt@\^5;o9(̦bzoA Jq?^m$ljضɭpe -vMY̒,ي ܀Džu 9)(Poc`q^`^ٌ3IZ* a^@#}W+'rXFx$?g[k3Z^5$ g.:0_ #.Jtұ. RZKRK_xm08^Y3lV-y7n68=H:& Aefŝ5osA0q l{O1<"UIZOͺS4SD.,'5lp;pbSZ9ܔwzqdSе0sFW锏04%յ@2g{>9H"OcS-Zt(*AU$p8yRQ[KXJ P 1{w <}~^DoPp- C/%=!(FZ>s͝1_Ȏy ŇP Cߩ}Vl9z̡F ߍ \6Z<5! @dwWtEJ3cl}.K zBU|=wy:)`rfYS(n>j*Pe(0|xiZW&0%bP]:f_`l}6AmVA-G`KnVNXvjtKjՖZv%Uݧ;w`ӷ}c bLWbiZ:6h|X b]ȍ)xtɮ!8VXm^yՁJOͰ>%YǙtX-A0"iwoTnkn[/ X" 6U!MϽFa1_,HNB]>hE1N+G&q+:fح 7q,qxfxD)k5V(0#@Qͧ $SQW6]kӨѓʲ\H'#(ͫoP޲1WD 2I{'nf7 䖦"un]ppxuϏm{DB6ZNh =0!*=%5|kXeX8fgz?byӁy{U%pj_5FD\ok z\jl}3,FJaiO_qtt{wlVH@.q e1uO%apvVb{0OS;fo]C^X^y T"$L "}߭uT>bHWS姻֚$ɨQZNL n*2ފM{/{oUC6^>^VŖ?ϙ}ri:XvtH4`2Z!3Euz #e*kd6?t[ݒ l]Җr3Vސ OLAͼ^`u ,?c"M`q ?ckhĈyg[- *)l$/ c?SS3Z…f[Z4\Xn%12v?:]/ony.^gŏ+ץOtPiNL|W$<ϰP(ʩBqVhQbȟT'#r>oY.!{5@avŅ?(AaM LMa4 >JoxS7%)aEV. 'VIJ5^+b}q\X:pIj8BVquO0">CdAՂ~0XލS:q_]DƃFaʑJ)78mJeA#2.W>(SL*+fc kPFhtsjm-;^8}w Ửq:4tIq2>h0Bn0vSإeH`;/fY .W6B0u9i{ߚtp8@3"ئn)`lz&)s'@x`:L%u^3qd7=e*UWIhl 2X Xz9瑺(< t-6 |0CMeq_ nb[㼉gch/ҰV53tBhml% B;VG>YtНǍ쀿~7& 0E"WhUk8KѺmIk*d~sܸH$Kn-o&Ҿjv2NZ߂/dr#kF]n>KAL4*վP)/LCOY,/ DG؂xxNT4/(?IR-~3|^@ҹ\`\H1T)Ӧ5*I?A#+ ~NȊN%d;̽?q@RSJ;/ؓOoTzJMVA{pǒDz-F9Cj' nc0OUЭGiQOMN3U7FOMܚ#;W 0=Y}D݄lGQ1# lPFO a"ZEm2C X yT[kw!&8@T+ʗ:b-ƥa/彨{\* a@>H]jġz =c@ JNFk3ƨhJl@+KxuJE _ԃXP)5̸դ G> XX nv:NIbFt*/?O 99,=SGk0`tQid⍲?aWpykts(oޠ^q (%4X++Ošod2&-@]¬UG6hk"Bo N?Kj A4p<.r9/CE`(̷!gt ~\ %j%vf*I DJ6cU+yXsM#ݙsXdorztPͤ?[5†%[LSN&̯Jb9lCKfxMlQO~T8 EFފri-)LSAUlʶN~燦wRݖ^|;Hp;aD`.$i6Peh9g9 LDM~&`":ck!c1<кՂKORkt vY_".J5~t4oviYNEA1>)LxJk qr}οk M@|-"u'hwr0 ۣf؏jF@8ԗT[zc (]5_NFٳ[^~ KFЭ䁝^Tn7x] {4ȍ]5CQc3kGcB"غ b7%3AWU8-þ8+c۔Y9Z8#ڢh1-Ȑn*odCJH//DݵSI/9yܲ:[ʐ\AvG--/u4NQpւm1y;H{K--`"@`Ru6\ Z1;e(US :-0 l)$doVAWNP\_ [rЏ53N1O_sW`ZCx>vX_{/Z0u`ߢbIZ#Uk#5F& Iy=_:LQ\]r'۫m8Ps}f̼ kgZ4=orHa٢:6a7ǟ`;Һnikg"ϋS eSN膩_sl8I3k>1)]>1= !;F 8[뭏-+  Չ?ϲ"/.#*4x؀M}A;y 1b KP#4n'3w]E`c!ۿYvuMjw !PNҮEI~ ˡIel FVv uĔx Jr. {n$*>C7:LmOL>cZ`O:tzfdW9H0BZ4d (h"nfn |Ilo:h(V#6Z;/M< ڣxL:G]HWcHpUq#ۥ}Xxubad 5O>TaYk778:s+-$暏iVgahSBAºD\bIMqh-\qJ]!51k+|J1UiI`[l4aY k|kt4¿|m$97aȱI\/8w%o,.P1J4Ȉ?Tt?|_\P;pS%3LVM@ wgVrқ5F#!(weӖ,%ȯ+iRé`x,gB)6_ d:nK?}Gt.Oi$&JeGD׮S/+O#WIu$ԁy?`mS/ڷ8Z=!H1[tŵ#Z%s 4**IیVJСTX9ܬTL|jF|(XKw-oꆺ aވe)ZdqҁX;cg OqKh|`rꁗLR:d60UBFmݶ)_nLM9=>R0f4*tCXlg%kEN0-hAWQVt)`"\Q.VKNo,S-z&/ͤ`{c_]юn5va ~ՊjF 6L3Jwy`+nG=b^bxW2hpɣgvYֻG]1t͖1-1)M|՘sŮ0MN_ueP FV:ˌHlxGc|ZZev1l}w04Z;RaXɚpz1#EzfNi1cYF*}B\6٭D74F|hmɒ" F 4b nIiߑn΄8c>y''w@JO2:|mrj# +2 xvP o _ B|QZSnNQ(d[SǴ>_[Oʈuf^c P팧z1fsA U/Fe|s5~uGbfO&3+jw8^`S Trֳ)2I'bҡxv]+%U,* +n{DE bf4[%e@'ޣhQ0!a+K͌:&YX6J,Iș#ܭm .0bR 1Z*^+<6봨ܝb!wjL7/zOm7``7| MF 8ryRY ;w[&I@jݺk:rWrʾG Ѯu}/?J0ZU!rUT{L<*#>qZ$9;D3toܧ|l6Ȼ vjηB@DO_Rej+[i3hQc+0waC R8eI_H두n7@%!l MӉDyKCB:ԪE,O-e'&Vs|=>qY(bYm82KyAw<=a#=K-oOPjN/u_xRގd! 1@!6y[2A{3A2jNqp!L60Mr-_k&|:VGv&;a'Dꐌ_r:DwHr>yg*/5o @|r ɔe`{4=!]eslX\X"2S#IGX‰i,g ꐖ=Mx<_A*o6{VG4^+{h.O3cg Q cʟT0ZXJ<`{8]Q#lbp^{6s 21k L<ط9m0ʭ=aVaK>C8S2g f;y2X. R$?rG{B~0ˤ|tµGZ]EÛ>>PQ0x^42,Fb'йp[9p6d 9]xfx AY8d#ME>۩C^j;"cr]' T%H~X^ ^Nd}9%jr[ h@a"ty'Dߔc~,w]lV}b)l؀3ufWUAOx%q-P^8UaM v_2dS]ە]ցa;:z9kT[n5>t~ KŵwvƧ [n.ܳ&_C8u1q1EIp tdW3 4%},($l+ UIBH9|8lltֈH}e jcnm =ƾ.+B N†V_8Z};Z !E.@ _༹h=tXmB9A?HV Z\I|G'B > gpC +2\,u6nj9N,71+(a!Yh}\, ކEFA|%btlױ^1C>/x=2x6hk& >n15!RHqu4ܣ1`.LUvtޏ1-yYd8" ڢ|ߝ$'Kە9CҺ̪;0|4#}=E[f|%\{m[)(Q t|حѝ9RN {o{sjuz~Tt~!7/3n4mGam0='Ζ\ ,r5xw?bR(/T%)˜AprȢm?m&;^Do{dpYբib;)v*8}0GULJգxkz쫥uO+<\Rؽ-jS?9wfi:d* 8H;`hQjy,o:oN\?ː)Q@+F][PeUGRQœ%9&k7o B l| 4}_)2"&ڎeLY0K!Ctԏ6yM | FKѡJr.lNDr5 mg|QAs,>gA44zhXAJ0N knH¬uD APEYگ .KU<,HXB,>QA1I_cuW %l]'̤Λlq+!K1h [ I-\ Ri8܀!iUy(]*OS#eÅoX4GB=:~|1ω߄*U5ڶxM*Sz"+)P )=-C3 -I ,柼0!D f_w v cUSo?[$E<'0hK8;87lAX=,w?=ZӀEuǖd>3 }, .Qt }"]\r2[tП= *DJZnxEsC77Ty@{*9 ֒V0:Jt ֫bx5lت@9)3*1F\V{Nj7RG2Vg,[w G; &֏7<$Z-CR<{+OMB2 }$uGex6ZUVrb§݃zNo 72<7hP~iOFfOCG)rl uyaD8 ~j2Ö^~UcRNDc1p 4!UķW^"3} */Wv]4e4l D<[.voHʟMy%'Ҿ- X{< |P;eF(H"n߮qRG<ϙkW eQY^0qh.a0oY\ <2)?W)RmT1^ 9B3(>3+twc6? !T53&VrW2b0y|^*| ?ha?Z({>^-g&smoEPa~9Ljf qV;>eE3=ݴon[Ej$?`g`I_#tjV=za>2mW-6/ BF MkrZ ^kػNWȖf_^ءI\s16i16{o<Mix1Ȭ5tdZnAA]rS-dZǠzv-RPWCmU{ڮS,O2 +o4_S;DO{z:g';ym)YA Rj6Cs'v p[MgVmt [XP :TγgV02d"Q;ya.,4=rҐRlR5y|zD}HH~\gXU]꠬'tܪEx_v,wKaaj@^d-@5_ҍE(J#f.~W ,^}nū2i_' 㲹fIf!]R2ǽNY&A$29hw-ОٯM]Jg.LMB-DV'HΠ{@*!}W=*2qQgU9$+cePdy*T$lCMdC^Y֢ :q|5EI}\!{LHDn^{Sgr,:/5렋ͩP<?a+SK&^fb )vl-3)O4 >d3r3<9oA4؋a>NFVl!M܍dbxEm@4f+ImiqRn&/J7Z}3 90Q* >|~.LY YMv"9B~?Nvrwc{EL#e0fTSiY/j k7gjO#ۚ$l%v+lm/NVj٥UzH +UP~ŻUMd _$C|̢vVian?FWKkKB {`ĜO}"ݪhu^C-Nu 1vv>?(R;'#c K*?FjΈrB' MqA*:Kj/8HOEnQ@,$)RBMB)J76QR~ :/ⲋ\}}ʗqj7M\{6$az`Ns%5n3B㎿噻]4f qvVW*ç@BP_:׀]8敲K&d \ aG=ڍ;REǷoME,$6A{Se rezɵ3Ink\5%~f=?B~ 73Gnكb=R=q(u @'B"XB _:gS9ƼF8-UlX.$j*\PA+ Rsl("Z`-Capv϶T窺)p E@ps,3Eo9qy "̓{ʧ)fJJNf E0-$v,dŨK5BXP˟݄G.ʂJ.â]‚? @(2!pN1Pe^D8"md IP|< /a.$=Shd0GN%V^ʠU8)-|& ̙0!iݒA渀`NJ zZ2Uo/It%pQ&o@(sE./P) nG|ÿ(K찄4|hY1flցhZ1@f^ĞQIiۭT)OI]Zzơ}zZ}?ܤ #Fu3$_"JxMʮQf15O=Kuj/b,c v=Ӟ k.;)c:b~E`Y%TӦi/[ǠfO C^2-DҨS =6ٔ$qW:g'<~4Ty?f \ٍo}t9UF&býQwu`J̤t4s E=4AZDJGQnO,LSWM:&[` Wx/:qC 4k(O֠qZBCHq5vCua%lW}"_hhwKJޖũ͊opJӬ'6ț13\"*&Ͻ 4ɓpkG{bHBܢ=7Üm3Q3tjŹecWSD9KF%5r}YY{A+|,$@]7; :zȗ{$m#7ƴ1֨w%L RUqCjsdo!ʫR:+gԹ%p["άLrBmwiz\Nbp.JCvnBq(# @ D/MӢ'~',g@ZrpcXt$eQGܡa)a)z@|ՆMW v8?@ \6S'ڠrby$ɗ_3|e>Y ks$'?O &jùOZ<`%VյU1 xc_"j mֵw7zs +'>q#Ir9EU}(:glxL,CڡR9'mΐUr-?]%~/q~5,`u]IEE%nt= x|r] 5KpGd֨im{GܖTFލ _kj1W-Lܛc i v?#1M8mur)Kg ';ly5S'$PH;T P&I30ErANi7ɳ}9kҹsJGnwa=,H癝y̙6/"ީ^Թ4}1A|.⛹4VL>J6cߎ>6)$XQkIޗ*r4IJ:E{w-欕yLlJX @$V8UXzV_J%L:;e}Y-k# SpZ u"-줚8vLX _l92"ra9\peR_,`10O2(`CDC vCwq_mʓTqzCۅxeьsyչ$"x41UL }YBPT0O49ƹrD`T= =o,OJ? 4 =u{πnJ72Uב4 Q w~umes>8]-(2Th=̵qHդmZل!{'wKL7Tpִ[Ac|PТE}rgyv;ʒ+?r'o. r6q]>kApS!HPN{h6ZzCl 8IBVz1^gnm'P3DJ' Yh̐o%+%EKX(R }5΁h*ӕ8_WS&"je[08YTEm/sQ!+^Lq,p D:ՠizX|cƥ=O2jURg@v4*C5nk:kCuMI- =,HPaZBsG[]N&@ųQ J[z䜶b{@3d$ְ>B 98§-.䷟axkBXʌ۰DO@zq#"FN+Y>$v7C~iJck`P]u=C֫L1^i0fOz'Y(Yr`m1Vx)QJSt^}~袉CWy/Jg@ Jm/PńH"Ԋ, (^V̶ g tֵKN#ƕ~drRٳci+ضgE$-$Y&­pT,rn<Hv 7Yy4Y731Cbhlm|. Aᷨ\x5EcR3}\ɔl`͢?:v+3ܙi5$6B0Z(#X1b4IT+im37=({%l&M l&Rlx7?(HG']9]Qz`r38c@he aУ#bldʊW19!Rh?l:Xzᇩ*i zJmm6N{2+:<[ЖI+.9(ҾІj`Y(Mz"w8 n6UQ;VzQ`rЖ=> c52۔fBioasuytuqgf";?-WxflWat/(%W|̈ը\փ 먨aQjXFh_:h+PmM2ؾ{ ~16yqS8Qw.1f|sQBc B'/<fڊ *nj6cv(Kb.8/耈>0[nQ\AHWMBVuBa{ Bw_Q ߘ {I.ay tlc2%m3lO9yT_'.{z;bf.H#C{KCx u.}tTa?ѝ;!c1Eauird;8sMMz>YLNek|3mR¼j"2# &MHD6iF`@+KYmIj882[0c|w25?6ɸrR6v7+Jq^Vpa9фz|i&b= LM%)YR)p*a=|rdL]3i)dLuR޻0r {ƙbb^>_'WaשýYWw mr33xcxRtIlΨȦP00H+{zg֒&gfZTId*kNt4m~ۃ7xKPw-EvATеj_ʦiK pl+lbp < \m4r. Sc>?EERk\Ulw/Vc2ZPd90OI0/W0r?[ս1X QWC<͕0" 0V "˲)$HBÐ^ǰ5@lZ0ǴIݿ`%E ܸ|"fz9 !6g2-(^zht3Y[oܞČZ_ 5c2*EL C5Bz|vzޏWF*Y'vУJu3> Bʕip|hfpyĽ0kPڞUs:BcP@ZR|߸8a[ET"pbs$%x'9 ˕}_2!1N\`\d{SpjNl 4)|O1HW@yB+^-.xBi]u—YQ^"36;IF%oXtw"],+4^E _f K1@(I"Z|{z_!?ӱv ŁmPM'ޯ-La(b4sL^,f`a(4>"׹cEuķ`ݥBoDT ?)c-PqB/bX~gDՈPs= .{̘'T.G,3lk-4xyo]D2Vnpyd)eU`JxφoMglwzx2o!=G]N P09 \pn(hϓ`N.){]3 8V?b$:ntJNޛB+aÛ~p ~u9B6<{YB׌Eĭ,\ uIn:ęRw*Eq@;`_rca>M^̸ϊp`y}h3/k (ATL_mWmrI><3^1[jЬVR17Vi1Y$mF=l;fY;b?G8}VF< ]+![,i ?s~RMNt K* *s8FSGr%,9N5*wYwOf;s3ツ|X@Ysfs^Tԕ wVb>'8,.\lPgojd+dE#-R is+270n7-&o!}s[+ Os:e@YAY%DHJ NtsF yTh:T[Iv ϕ_VekS йxdP >^*]K0EA17MfSHKEi}jrF+_^QoꮫsD]\VGq;v8!{^Bj ϗ7).]BљHYT]>!%ex OޗKk,D9rHx`ʻ_Z9=zT|w֝F^1qx47$o#9Ԋ>+(n9K7-z%p ;˓2Hq- r* )r7{& U@f 2Sj'Rp!|z2({1K;`>BjP^s၀teI1~]S$WX%[A Zr*e0B^b}։CXͲ$Q) M|-5~vمƍ L\@':E{U-B ਢ8w6ǰM}X}GUD ibzxn !}|\|Jh%Sv; ňslŭdpf {-oyo*:Z=elQCJBK8 ?UI#GP@?x[_A$ K8rYFvjo{r=.y.<= vhfg@#)8,NxQ Wc_Ihs-6T^x*<ɤQ@%sJ=76r }jJ9"a7I Zz"KL1w< txdv^. (d 7 'f kvX79q-o6K "l#b8J6x9fw)f(fM>Nkx$>}n1,˺MM>=tl؂6GiD5*f _FÉKw:` SN ZyJcIwEi/7J5C[V'*paj!x<8dޙEkRrAGF*kyGHU~16||_xVu*ɴg[V'sݷόmg yEx:Sx69g[̈́M"G}Z3Hkq̕lպIngN/rڛ S{anImdvU2>nZڝ K,WQkzƇj8zr>S) Myۏ4\,~38Ш} _l|2> W-"/Ы6)ЁH8O6Tnt %(i#Y η0 Y|"a5I> "ҹ.u:ɮ%lev:XoQ>5J)6([ DM} d5m<\ԝoTlb+#Ҝk8 E)Tn)8ЬZo[!؝z}N]ʁ".v]LP4pU^-\. 2p)3^+t TrU,OUL`aG.]8n_a90F Њ ){ѭ8f85y2㪲XY??yKQ,r4He޵3Jn,Z dFo~?8` ]΂XMPɪWH 2'ɺ,oH4TMYAHa[~RΧ0`p3up4m;j"i?\smJ#tн#9'xvf?pʶ7^BTu[] + lrdQ\EdNV3q?', k*3ҳb!S;U =R~iaA$62/an)ś3rnx&KѭDYGi`YfFLh8iݍo|a~fLː4}Cmd>6=5}W^r.WzC.#b?ln6b8*0MFB ``r]ay+|mCgS1(@-v5{6Sj'֏}԰$ly@ERh#mPfh>>yֆwlYb;,uFȰ |LK:ޭEP\ # iAi ukƭ]LVVͨ t-!fH5H}x=}F+y>[i1^"QQ1 ^uSuTcC؃¯!fuGi_}'UI[mCfiWąV@(ěяX3h#ejY3.,֟o] -Jc7OM;@1%_[4mp@|ZB Hj 36RJ.36[j;q&ܬ8@e}S\ N kObGv6yM2؂M%:Hn}[-5)h:lAPS}f&)ۡ2%^/tNEtVA5bjA&z hAk c#xga(v$b]mzCňE1)*A4NjL` ]@ng-7͉C<glPsWn@XÝJ= ( %D_y*Fu|:/R3Z8k$^?n[,&[/_pwhA8[0%$1!/QZhlyd+;=MBPO2сQmq7U 0]an23D:Y "K{Gv+ <[v:I zC :5{zy@eBj%%@UP6Q ~6rQ?{#|4g0& kT2.\ 3'>mHpsށp}kCpsקLxt /2}I$AOذn^~dI]XvR!c5\ iԲ/,(Ƭo#aJm,Q9ۃEᯍ4\׎$za_ Ɔ~iRD+u5M[>?(Q։0kTO,.첏<_aBi{Ql/f'DMvtMꥶڤOdxm||!*&/ӔU}(4/dQ ~]zFg°EpY MN k]tb7 ne7 HW˷ ~r#UX&-y+dggy䀈#Ӣ.G ]L{cW/c/x8+(PppD3_z{  %ʸJ')Ukjƶ&Ϛ}I$۵[ gjz5ʾf,}D9dk 7 ].rC6XHsŠ-oGWvvЋjR"-?nLGJa\#n"C__/5}ծgEr&Ln:u7!˾c,jTL`dpv;:b_DqR(4قLF i:#ڛWpks.yR!iq?[W(~Aq q{*x OO8gW3s )'MY7Z'*ep+FţggWe2/irAq< S/5Ͱwe~bb6 Ċ#줇&nO!ZvTCp4]DŽoīn~և}Vr̮VwD׉gF\9 iئ8 c/es~;!0'6esZt()6Ҍ^2?(p6:lYߒpg Z̈́fyESRW2As<60q7x6 Qu#=UJ' 31^q>|\D}ư~@vI|ްa6*K1 QCM3 ϯAy9k_6&Q,uk<#Ihi].fִLaCL7/.=,tHP+ ^v'_ҟjW"BG7A2MI&G ("Y1ïRLD;QpHڠ!LsAޡ%8̐N2p*FEh'OcdOwP9G4QOD5 =iGx#}Ԍ E^΄b b#Q_esxVcMP?7z〹$]5Vz/;<"Znaж*(+p^2[gt;|ңK%%m 7pp/L;3LS[l#P{,Vť܇d h:\3ZNrIyjϪħVDrJ:( $ӫO A2d k覒(P@aTDȮcLCnsOjsW:>)x}Z/lc(eSKO/UMȮh(OR3IG|iǚ#7=&|&} Hh8whw3cWLЧ'RdxO]/v#3>UAgTlenq[UqHۙO$Ϝs"Otw<㍼HGƐg[BGAi:YE %C*qJ4Uɏ'gDHUUHpt~տ8 r4`SU,^L tG5x;SC]jy3z=tGGWQ] 0U):T3]4[HilμKU_807^,p'8 ںwτHk;B'&QUHV̮8d07jh~d_lNeMFys3F\Yۀ׃"NZb^ƈ/Vظʀ5ӑ ǡa8s/F xA7U \a6-;f 12[j y&t?;Јؤ#^L Zɚ .jdQwpNd1w\)~^B8ǃ*c(Jzx >2(AKvBkbS7#`@$=FE {)6_Ps$qXg\Mн,&64!}.8emʆ4rԱfKjwsԕ4lPj_0Ke-%ә~| `̦B/[l\ l-UF?$*%wZ2ҏVņ^S<3.TáLrld;RBxi/+g9cِgjLc /g`< %(:5ljƲtM?. &F\G"%X<1BIxi3C3gݚ<" M`>~UT~ V %j${b[95q\Ę X^[c:V(Xe,cP@q?ibpdtb' ѵn^FoRT'4@GanR_'*&fnAY+`y30 8euY9IЀfjk&bN//WFn{YDIPpN6+93Di:V< .hAfL#pyl"g+'ߜudsG);*֐ב\b qŰ(mΠRkha"@.~j؁C`Š^[Q4C}rdn665"D7J 6蹯8,<Η3Uq߰t]݌oj!*%.TZzA$f8_7Jr S&&jK%Ei|;E[]>9:fPhWS Oc<^\3f,Ҍ旎3[*OW0[}٤2}CRUxSEXWcw,|.X۶L`\t{IO7r;f Ʊb˹ },RsPpەA%ك+tH'е](#̊7ڂ~̺WA0Yؒ]\)VR+BMY=:Qфb7 p(ٴdBaz R|乇7js'c!fi'jNmp82pMH˂FT_܉J%ϰ|.@RxkDU5tZڋ A5 8̲Y}Q InȢy/^5 7_}7߽tB XA\e?&^Q8|>jF)ɦ{q[~.{>ZG`SJݱe\>,ˠ_խeC/Kng %FG@L (yJBSNdG~cUyrBd_4+Fx0j:kyȜp )*},Pdi/ZB ` wZ/l%N}]ϱ}WʱN@')3bˇ#7ԁNe9V$%\]PV 9T5Ym%d ?8~)V U-/S=ꍄRHinW5ɫ=ƓpgV^kG32%7xcMcl/q(Ka;euIC@ {qJdi2NÞZ S%yo̘q]yGI =Ii6K?LY2^K10v.6oZOtޠ:)AU~gqҨ%@sjeIՂ0; AgAL8`ztM[9ߣCm6Ѡ`4y'(œn- -"_]^/\W,AwU6sろ26."O=9[8>n#ȭ*.p aSJv\\E-p;ΈG˶h}f# l ,1KYWŰ(PрF~Ia/zƷ-Lq!3](\T`Qcw5a7Oűe>3@n K)Xa$%KeORP"Y?'1nޯ:XOraF][]eWY YO'KRĨϜ/^TVl! ",UO[/=~r‚˟0ˁlrߞ-S BܷFmxɜm2LREA8f Ȍnƍ*>rbخ0,ȳ Bˉ6(Y/z3imbyr7b İ#|ynUgN(±"= \޷B}wk.h+M?⾹00Pf ;ںb_Q9k owEVE6ed0u/U)I8+yʺqٕСrTrs xfjlibcl~i 6O1tP36|WW: #+}@|Up!!qA\!⫞e7<=Tz#F >gkJ:=F+t?리uYbC 2rm{KCv҉LWXL'℡*Ⱘ] K\WupֱafKʍO[!DYd b&&C4,F|2 4EךfBRC“SO}ڣX$oeEZN~jenUG^<Ĕ4[5'Qvc*yr /W9;~YMK~ %:4Il)͊'8ύXXd8EqPq?KF]DChJ൷Š7r|#/`Ū8P9% )u(r&KrABٱְM%vǪ >5Fûw\!{Lw(UGMƠߠ|6+5f'#cB.6-ED 92D)Gyp#´ӞKrfB0%Gn 7Kv(` ߓF9sZs3n>)B>;"Cevpg )KO^ us@GImjC:K cAoJ>Nl%[B<"1C0CEnŚ iRٲZcLfX`_a`sT-.ə}r#-HLIs}yBsG1Fv=KR!?`;E(]?AA*~X[Ʉ3=gc YK+}jciSry.6&'$qz "SDd}.ʿ@À~]03_ /og/6|`/Z20'DX1 9V.7ƃ=d5 mҸ'9K4% 7L5֮YJA`wS3^{62y3?߽E"P>hX4hVַv\ œs8kq#+E1Gep]AIZ4pf M:7ɞ0TjsB-\cC:U'_pZ9]:He$QE[C xCif>}OuKs\mj1G *rےc\p6*^7Q,4.*,u~]]gr= _>V؟6zsk_s3;;خ.1/13ǑaRefo$+}ϊ[.ڏ/)B'@<'F-ݮv6uw ֠E0"MZ~{;abnuL4}#`$FŢ]25xFe\#aCRןnxYLcXJҤbcŐ2/U!1رzŋkE*(tw>>k80l- ;oN7K="ѥWGvL{E㮟PGY#?\C nЩdӬF 5K8B@6/ȹ#/0=P%Eq[@_G;|o44p!%oSf.OEhc7X-ۯj ]D)_ٌWXL <_i#0geIS;5έ,rE=Dug[ Ob/?}QLdDޛzd-4\y&P[~g{BT5GHr&n#sQ43F]O9yPk1Y@XƺtTxLֻO>#]<"`Kb+ s"@Hܵ>GBM?;<*aC-]>%)Y1৙1&Ls@Rz19%θPK8Z=.pw)g/P{s# yuUh̡H̃MעY[Mbei jd-D뫌8SM3 D)pFe_Ȫ,cvqPA NnH0HG4}$G߫EjsZp(U㴀oY(bʇ0G1OB.p\M=n xPnçE)? , $~#teaסD@[%^;U \B!HB(Z ~ 8KHwG? dWRH&'"-.V]h0Awr-)+st $j>D pFilȓF҉cWrD8EU,`*:a_3Tϴ8h]`xϚ"T0dzH#zdS]|a0(ɝ*'ehZ ," »Iiߊ{mMU Mcf:YYݷ:I{y!#1E֔`x}6Ԃ:So_cBu{t0l+dDV5`u|u,MwN)ji73 EyG!\Ո V 7orqiiZ3`Ô$sa'Kt#(x8*LVjZ"}59ٰ]Wto . O+^v̠IBǴ"=3aboJH$9e4wJ]Wj%A6G޾x6XkES 3A:Oc<*=zSg9x|MYCPjv4WD(.2eL 8I!_xM-#ZpMa`zfKQg̼+$ɑb28cEbh7q&ށo/ifq\ԉ1%]n9 Hw'@|a\TkIR$Tv<_Jv`AU%5\*T\ki%w⁣M%(\ʮ:WXPQ'j83:HQG- qfZ :[R^9zM=OaLaPmK@v*vԇuA1ܧއ@0) N?oDž`KWdKdC9o՗'`s^7hHҐ6M?MDjNf|)@ [Δu/#p\Q(˩ﱺC8X<ު6-[#5tӃXn urC1 [Q!Tw_+s} '{x˝Q3S+ տ͈>5Y#I`9j8Y&)yU 9Kz~){\P4xABtVvږ%#ْ>9rӒI.;$7B`tzZ08 " N0"R R湾JZΝZ09b2?YԖ*`Wm/Г%8` "'g`ҬI2\S__ 햱7۰ ۍ_O {CK@LD DOpc@M$=U+ aW7Nң I7% /9ƫ,ol.;o H/ߒjY<[@#Z%v0T"PHz'9c& B|ZkJ~9U xU9*0+J6֒sIx/ Y|6maiuE oYnh2k4tGѮg w< mdVZ>uZB a?n{T/](4=o1\qrmvZXر[Ԧ9#VAa6No铍duW) Dfۧ?3gxJxIӛSG~`.Z4m BĤQ]OIXOLLA)qBbpQu_hP>?Gzn7d|$j#42h1hɹQ;K[P.KoO(FJ-Vp9A$tYSiiV(uN6n-"a۴e*@#R\0d/ |m6N(BgLܗ$9k8KXMcW_U`%jU O ZFㄆS)'Myӫ W}ɝ{Ԧ5'bcJvxB@:Nl5}=`ENwD88 FԸ@N_ܼWFH˨VU_}k8WpJDVRZ·3GPظ1٤2WpgKWɑE 9Kꁈ'+)RI vdž~XF@lr\@ PfĬh]K4ץ!<  SxAPp !M14focfH0"@ 44uf o',0]ܤs^إh`g<'D0+%IRc;ξnK,Έ^C /iuVxMn|vbUŊ+pw/<,ޘ->ɔ1W]n!ot?9 "_4NK5_# 5~LϤTofC=YI4#Ú+3q!?&Ψ p_Vψd1NBMI?dNGd;8몾YY]uZ9+h~N#'8prs+O4 ydAMD | y7}Gop|-l0V\0r 4z\+7HɑtcMBR(+>5-:w| Bb)z[/4^~[>Lgz<^4Mkzt;$b~Zw2r^8tI퀰Wz2 ݍ@5/NYF#ـsD/)T\8Ā_$cPx.:20gFg=%Z}ur+C`!k5S}n[pc`IQH".덮25亂I.P9J >`rk|YXgvDiPw .(nX`Fst<p.Zp TL wSXr9r(gT ;;[>{[1< oYIVl.^3mAuqS(^u")+= j,ݟh]b6A"vػC:3'WƹŒڡ'XX-J"dW¦T9I?MM ]ŶWw7x]g8f'#6؊J?rH|)܈-9?]-$cA'.N~G$~$ Y+soL'e#ϲ'@2?l-䜍.Cg oKYJ@ Rx3(]%!>FZI_ufF)=)DzFI+ hcHx HDKjnzldX4[ Gjәqqx?"P."Ca[BMs\Ut^S3]XN1,y_].̶ShL؉/шzGWa*Eesyuݛ~ͩU!1g]cC;aɻ]j2\4檈'K:0f Ԥ.JY3e?C.ßY1MP ;Ax+rvRM#7Jakd\pkK8gQJY ]JP=YvuUKn?56'6:;ej~̕ _kn {. [&'lB<17w| `vѻ W34@l?Qc)9fZC'˚#TP]-@lo@,f01ȡ^WUXG9L:pr Gu]ѣ=Π/!"T3*g㴡@+{*WBdai0RndC.Q"@adq/ SX K8&lޥ. H9vo|rHIarvIgʥv0d 10IOv@Cq7RMg=S^NhzT-$6S&`VVN#f0WDy=e*$y?F 4[:D{k^zY&&i\i~~t -Z/P5SQ(E`]W萉VYE.XqN$.+1G\KK䴾}j?"`(2aM,LS8@glʱՈjOu.z:G/t l5 &לÍe u4`Զ]Q]_A] e!I h0J: -r@/6QovD^i  F޺Cu3ZE],Y.TW_!GYo&)Bp䳸۞6J@@٫wҔ?_{*=Y肋F6k_g*_ qէ0SX;4+dwHW Gv`7h>A-"2uXp\X)p-8DV~Ah KbzRrqhd iܐq^4u [ k2b)B^!hK/]QfG#O滱R~S)Ύ.M 1Iޛ$SDhj`,6|cV̂+oZ=nc:QwR74`damG]nTe Y"e`D>`bM- #)`zcy|b-p]Gl GߜJR%6t=V^D>ƕ_NX$][,]%'BX٩&Nǖސ|oqKzTSMקiVVaKgQ${ܝ.T(dʳEx᝘[SF+5}"Ɖ3zٳcwd)B^pVUl/T/Aו)2#|Ţw00w՜Sۯg:'8E_E0+K'~|R@KIzߤ M`ꎅ ArdJ$jWτr=N锵>s/%[yRD24ed.T%tNjIGMә1+̙lXQeAv2jf E$ CFzڨc(BL A*3UP & Zʪ}4+v;ox=أ:z6$B1Cd~n̿ ԐU)fMG"@4himvۈ"'ZUF#zMF^qD"t\rȢnOBCF3_vE-7'!<ԺGT $s ۊh75'7:̊0S.JrsO]ly- 5].5.Jw3lZ3tDgF,7{R\mK-'\W!,#NӃN==|-Dk<Djj B%aJ6YuE&>"(hTV_Nc2 ],~k杌{-cEa# iv4ٯopG aqRtR5gHu5\^ =*m).=n`ٻIHM?*b7]JB?'jzs=<NX׬~)AcaSt!BfHىG'&8P>q%*sGګPby圜<&|7apM̨D*@q^KFtdD[z>L ˎW}Ӽ裐7 1a"T:j1VSG}4WUN_/G&^wuL>=3H9sɣy~oDk@ܺR кmq Wyh&(%t!2XS&AC8&ɄLyv4JMZm*E {YxF~FVν]&* {0P%I qA;,-wuqm0rPlx;=|({t Uv8)ޯ3;nT욭}r9ȕz@ ѷHחgā]:⨜!]8z吔Q|b"o04L*bǍbC G AٱϙWkqJه.NMcɗbf{aTY.nIXXX%5 p 8('Rf`x֝t .Q8{dA#%Siq߶Qr0A9ւׇQ dq (IwRG4'ّ0C9v'Wq 9\ccAvz_`6fP".ٖ¥kGZ̓jN cY}ׅຉ=!^5cHu8@z2Uώ C>E3π,%Kj,(L啽s8]!Mx}]TuB\1j[~^7.] _ĕj Nt;4~ p:Y1{[)#8 ϕ$gNJU`R:y(0H0=cq;guرbѐ`;4h*Dk;,եCy+JM[ G x#TU:nPmZB |*R{qj60 ]ދlpqlT={E^ c28el #Vq^LrŃW6ϸhK@31f@5j'c%yWa)^ 8~k@DzqAN }~h^ x8;t\ Ұ]:ۀy/5~= ~1ɴD:04Jn6LT) 焍z&k%ʊOJiqXk'.9(ʶr_i^fB=?FMQ_ 8LZv,l_\LdN80*ƽfi|ե2p|$L~մkˋ| Fa.?APlMޤ`Y7{oh=Yf"4n"ܘ9R0I&ևJM&0n'/;AlY> > MĽ>fo߯:q0zϙغ#,'OxLc_r"as똰&l`<#'{^=%\#a9uoT}t:6k3ʀeQDċ;M:g_ގ-y,hPZj7] uf|z02mjl0Y-f.2f#0TIh_+{/LJK~.`%~&o]=)H wc_$dzOtmJ2>jJ_4,-WcvEݯj +㜻*@9 o|[#BJLg 4ʹw35=? Wh}.~sFuqWp%3BJ X+h^kꡣlkGRbu- t#8VPJ.L?24Z#b8:*qKlkM"\2HKqxN;[cڞki.S`ߪ+Y0=ofYsVye5~6چ!=ݛa LJrhŘ+dbe{(Ɇ$P1EVϦ-+yoyч9jRk̨הvMOYgAT[&E(e0U2FX]NJ3M}P3Wםj&/WܝЂ̐5f][VƷ"һVЄ@+q #W(TN l$dqRgBjsk+VrxkFyj"Hz9- XhU4 Ec9g;މ7|X|ԪHI!w(5]]CM* tEHw6 1ʈ\CK~GZ9 .z"  %HP㹧T~a4zdO, RB!Ebs4 Y~F ,ap;]}qSJ\i`Vo43r(-^$vm:[[ᬍWaҲIZ0'>xW=bq7L;W3%2UM+Ňɋ!'`ߌLuP X?[Z18 /i;`]UY"F0P J #^Gx&smk`|ٸYVA" 757F8G8)<7TszhX󓉥P/Ʈ QM#`"H:@k{*^::4}٪YRhf9ݲaT 9AbDO l_Ց?:dp[+*gwSMuͳsL[8Γ]? ڴ`"4]Vsv$eXJG!9j[iMR)jHa  2[9&33їxpԡQ|:pE.>nOYR8/d \.(Tgscb_.˦Rg18amVdSpQ3(&pЙg͊͏H]#s,|i@kp*l{y(Ia6.!ڐyJwnY;Y*LV\v!ecSSr0ȧQ%A#Kښ-D?i]Wf~~W`N5IL|"z/喤R7yjQw3ΟE`KP0sHU JԪ@o4Ba{~nX=e0C̸q{ ,@2֘e I$ɐ.Ju7f¿-}Ąs"n~~/Oxv#{+e+8HF,=^2NZ Aҥ#S>j6m1JclH3<#2P콞e]7ޫX[?8+3Va6'JOQrZ0lS\`yQǀ3%  2Y7i#^lgn| _E6TT 8<33r.H*j"Kk(NȘmGMZ4LnuM p6sS'褢js8D7yKp;e}S`;b͐ȧ9炈N|"]fg iu!+:T bpz]^eOR̀cG : h8& B?蜩@g"WvO^bOcƍHj5SDͱ.c7 t6D\!p VG:k`_[+YA|_;]!rFb>8U} ģ`Z['Z 's+e=*Є~ԯ LhI>Zl3HI sE[ 5EV 1MĄQBlDE0{o`^3Fw̘Df郷.O-⭒)C(84 D|fXz+4vw 0L $6ܗ?-|\i`4,p{v;J!2܏'H@KE^.oĞ-bM7*iq.ZN$s\[ {vO~gU˰!GxZ 3UN{i1UCt!rn6O !joՉ4^.rT Cgg9(C_<"R 0$lDtX^RNRNN a%HLz!'f-KCFY+5TeED/DE9 (W9^lKњ!<řF ?+$5:_un|홁ؚj<[ e5YgJ^A~pk.LH@:[j^BT}'V#&9 cVj>bD9HYOvq2|[ 1 #W^ p$"/nltی6Euy>EN~jו)SbdPT۞h*%iLrArv7d?l9WY}tޢ<Π-: 5C =v Z1uv$=c@K鶨K G@.yd)'RI_.mh\ԍ' \}7… MyV_Z~Gi,y4̨pq"V;ر2I[k @o$6pݼ2ۊu ID%)cղD˿,S$N1C_3dAW3?`wXoGn=_luMA,x\~зAmYiQqA^b/n #m $HJS?U5$ Bn(|5jW Dz gIrGNx,wH9:yM({4nDcNQG~%'$NȉE]xZm@/O~@ҹ@jEJłԜd#n/WdzJ)UL"4naЀOvK=5-~h嵛?ģ7yiP_@xt?o<4j2~iHyi~FP<wK]%Kdza90 \\;q-J gњݶ9W@tLTpwxi :% 1B}$|@0)(VAhhɻJ@Rk\W=5, g~<-H,Ŀȇumy LecMUo|Mb*Ir:=]a[7fZ8F}'nLj׼(a+-0Jl!>-1Q%]ěqz>>.ƚu/^d6cޝ! $K$gF֞u)Vl,Be{vO0%%뿿[i?o@LX}hpII1V#tTΰ4?kjO:{ckH+menLR0L'*$Ti= 6aߗVg07[?DA3hzve`EԳm_9~K@ -^ZD3xQ9דb#͵N֓Ž=0vSo~.+67R3{i{hZq<;-r1wKH[}IDl1Mq9 3"$t կm9Zy+1`! !3Am] AFZluaXRK>mm+q1YYZhTd%Ѳ1m<(# m _1\ڈuFİ 9 qW [K ˓cIQ Qev]EwLq)/ɳ gtÊ3} 0v$XgJ.58K^{/P x_D-1y,r9&{@ig~?{ xc``V:Ibz3oy`slƌT1&ijx͇tHr/K$u?L;MJ$: V`SF*ݲ$%cK^ԝR׺A30'uv[?T4 89bc]cYz#yЧ[WgMEX7tXpMA q#:i WG_,߈̉*&׭B_mmW௾U=h6E<2XϤ56QíTc8zׯ& /K|$Ce=U-C&bf6L)G0Т=e6Ԝ-L-˛X6$OAr=[8O=95'偟n84%dUhq&aD499`"9pX=e ]4@E&N ZwM $ꃐ\Hr.~]Zs VcM( -%>E-'^6_ bk P\i$UE%F9.h*H[]Z$T9}xz ?5v扽^Z> 28_&_g>8К֥C`fSAGX8D9ֳ(GKo!`)Ny:Ju3}AV xdH0]x)TrbW Ӎc$؀RMnnWMlѸF==&\ d(L]qI7YK&ݭWIPkJj:o{ࣵp߳t:a#G[LR(PR%踈WÚMDh)0x..KH[s3fEuײ<--t y< `d'!_Y 2.Jnldv)VDe_I$'~eM+'lLбhb{c^SQbN(VN1r8@-RAJR4d4֔XAO\ZgE#О|i9+ZXp}߅`$? V';k^UrQ 5RS{{s-6RGXSԟ}q=%GFR2L†XЍjX6=Uz=QP/l\ZeBZCsHx͚170,7Wи5aY?FITTw_fFJ7S;2RVFH_monMYާ qvr7.2 <"!f(rg<RsrpXqm  qucYKW7 1&ܘͼ#ixz1;J|N=kƲ:0En$ )V#-$HHU|>߄)aH *x2tm)Pi+)93ꋛ ODEU;ݖEJ^4'?,6ڀ]BdzjTKڧ[/AndQT\h7!v7}iZO&dfgni'dxqtitƘPglGUQiݽV CG̺g x"kP66pPFqo[g-vɑ'\dm!P*X Ԙ5&B|a&̬)jG}ϳq5o8vyfwWbjcBiEiȴ= ' fbCB022'bJ|ڙS!LaGw/_.k<1XL䤖SQ6!^C ޒۃZIO(6s\Y.N8<1؋֣Ï>Yk֫ q4uU|P~zk)>Ki -N*nwPs"Mj `EY 4w1;fnFw8LCPÙ9XSHc]_ ,-:ׄ:X&94L:HUp)g7뒃1>u*Dcť)c{{0I 23nBBhvgܾx ZX:RP!_[6Ž\ s ifi6gU+ߜgJ';&2Ǫzzu IO-DK ˓.h>4$ݣ)'WgoC1E_{}d9,80QVCvQ&D]e_ <*:ŏ*fX ;l\!9CaC96DCp5AtQoESߗ:QĈߌ|#$ڃ-kzHΣXm_cLjILuWd Tu1==fhM}6h&].HIşZCz^Us1A,fW@-LF1ic[5f<\mtA)OHF8(ܨ(LXɴH_'4f +(N=[2)D.nIzA[8}ϗS>(1 ZSL|бahiVsCGD,LXT k{o*yVW:qR{Q*+x1M+;8!KEꣅ{db8,7(9q15uMckp`ݲuW}5r '.]MC XʺZ3Ţse>RC]#=hm-#o9lRC4ѱPP_Y{‰Ս?,&I@r :]gd\$:F(&Ī狆Bͼ]E(lR5Cg!Ifg.`I!٪4nKD7)7Յ7 BHS'^ ֙h}rź+< `kY>o#?hƯYL%3 :ުƯAeڋ~22]-zajNhW jD[)-?e%bF2Al7c]2\[c0v׿`NN mxQzs}sv4Yb +;qe,1@{Iwn(VԬMt˃ 馩eG8'(M ?7TY"K1j46z~֚ÿ.fe^i\ pѫoe bb9ڴ+FVgb}P0͂)Z]m 7b}(D^Z'V" m FQ?{!߯u҆z~=u/k-W9Z,*D'1h30 ?ُ$5bS-R#"&]=?~##_ )/&)nÍԛtW?WQ^J%sΓE;/QXHrgLhO{JYkg,ȏG,}fP^[5 g"riS~#/]JWQA؛&*LϭF#GJ`}. L =NgjϮw^Wˀ\&R21(ۿ]{Tɫbi*cޗdVtǶ:…0#D#Hw_>;j@)&7oYUH؃ 2oP07Zf9M`cZ2k\uW1_"@G/(,J#/@)~)ʪUfD7j:!5|7j91M\:K!=5җoELX;tFr C$G~HAϭKlŕKmvsuhQ5*'x"YHt3!P&uXNE !*b0ǁU~k' mo<ڂ:\zgpGGnJ[Q!+T4-@&P 6_b%Ih4]URG/oUcmF*Qc$}@>z:ٮ<]9*Q.f0앆u.NHͿ1."iP>v6u/ꘇ._ woy00X+X)gd~07ae)&b\rj?ݩ%<LQxע f 6j"Nw"=F-kat"/V8Tc. 5bsJD[A,ȐbJWXeQ+@b `#Mg .I 脀5R ƪ=6 9zKskxe''RՅOcpܵI?wȍJu ,3L})%Srfhx4}S$MZ[Ã_KRˋL|`{EkKS$Bp@2D= Mk5W=U[[?J-Szb*IYzטI 4۔8]آMS0)iJLHC5Z E)?ecR3t#go`F`VJAk1eu,B=h3'^PXSZx6_1lTԑtA-friTUk:Sۑf9 q4ٛq Red*UBti2,c<\cB'oPN>aܾR+_X>ɧzyHK*+_eu\@- \yy;{&GEJQ|0.d8f33sMhEUcn:apR˭,]|Pԙ)ف! b( _wu{5<j!ў5B{l9(f=d\m֞0P$ 976cpwCVM+8Z@# ꌝg.:6+%L b;fv|={:a\?יv* |G>WPXc\Z'\^]JRhxQ#8Oͦ*\t._>jmt]711/RCgkAӭL 1d#, j,嘡K-K/!KL\-6XXW{g#*DodȶnQG._t07EDPp@@-=*&E[o-!`E]R3ڳsl+JR'GԩK8PqTC.A@)爏AB-1lP)~i=dz: 3e'.\xWuioP+lGK^Nf:=g*T5?cuj 芬>~Hշ=e֒ծ2^d//LTVBQ枟+1yI}E G"j"kط f솋 Ue6!B~ K#Z ]W"|邰fZ8[B .2~ U/G~4z #(辖{'/bn_'ў|EUetpqvb|H2dQ<[j jZSt7k4) G P8XoB \s@X&q!lJP qbTϒ7΂nEuSh٨ ~Љ(}?567hf&s?e}bņOHpRݠ5h>E`{j ]v[ɩD>P}j(qQТ2l-Me&A)33"y /<ԉkuQLk؛w- *1YÌ&5UcęWxv# Ig {DNbCEb= a5@R&_讫7`=K;n=ZSj6YMrԿs!4 #wD-_xY4Ld ̠"/ѤN,G $_^`2)ϲWh1y-!_b(2/ZƈAOA\7f&&wPJϊ3;#E&lx -@72ꗣ~C窲6sTŸz,.#U^;=;'o.zz>)괚Ֆi.B =oŌӹW`9|j( $hf8Ņ3&hBĂl fciIN[.mdo^Sh}{Y)9]ޙ$|0a\:̤b^hƠ_,B' :zy(υXuu(B @K$J mCg(i?HƬa~l<8qD}T5Fktչ\e=ذD\ӫX!4j LU>JC = s(`;g nI5# j9"׮$G^fW 'SS5+CUUb@$F:7֨U}I6AGQ7 S4B3Li~ejb.G8^Oebbw gہ#oQٽ)F 4nvqd@O@ql~\68# :I qŻHS8X{m,/Q*E~B`;kgRL5,A,no-Qلg 20*|c¤!oJg#FK?{;kF}xV-p`g^G"My8ֿ\~.>!5Ԟx֪$cjex9^axo9r1ӼOdcЇBHs1iC]s}A,y9Ø5\j&JDZG? X[V]~[.s,5)7b<,XnF(u+]ܵeBƨjƹu=e+b&W43S2+k/Mlq0Gb70n 1 a7&%pL].oF]߻KQR={}Q(ot PÛtvS`&o 0ort@|,-ߣhnLj;򉹴”l}~ y #i_pU^ݢ$TWu uk=P2^gXK c5,8qYf|k6X߁N`U)T~$ޜj SlOT~weE+aQƁ9&So_`%ޑ}*aE3O2(ި(u!|F\ 8wRfDTZ}8qCӆE%(>=?rFQ z6IE/_ >͞hߵXQ]o HLr[sЌl_GнE ]֊ԳV54`ytuM6n5PP 'g 9&p} N$ĮfcYhdbfTёqm_BN8޺.UE ^|$K,0" &Tڬ [[L&>BR2_tg VDd :iû FzZp6k_}w"Tbaɂ:qPG- Q2uٗKۓh%GCk?VVR9=9>.t{Fp@wT~f{jtزv#f'E>Z,rܡY͙¹h =9󽋥,>30y+T[?pG= '7dq)aW5qϨS|J34i%Ҩ2ԋO%M} JΘHσb̞VIz3`v[\xyJٿ)qf"'>:vqIvM2-b%苲4P2!+fv"1g&Y=;f"mmX5Kucl㥏R=G755ᆙ; 6؉3u_)r dIp8W$?b1˲ (\T?FosK !MrvlQoeIY '&O'{9=17ڇ!L"BJI4A mIfBַ{sRW1(\h" xUH7 z4 8Wȥ)D=+RJ>KxUs|RDhf HJ-.>lgfmUU@B.õAA 5vt2 `E boʂ3{8î.8J gMήy)g#&WJbRx_k;O.m팱P5nZ^6Xdl?*a#KӓyzkP7ybݦ qc>8r L<ݫ}~OئY}"W\ .գ:V*0lܙRo٠H%F i7tTۣi 6){|+/˪c!xƒQRmV!XPȞhnI+M}n7-j/-m΢ULK=Z\f-Auث_tGB4z 7Mf$|]'Tȗ,jCoh| \áڏ@D8YkY l^[ ]yQva d?~@٢j|Ycis\p7P/taNe\aJ_ß;v9z:Kvgsu+<NnSzyzKz) }8Cr}:9x߁Sڲ쁋rܡ оI6Qͼʽ\DGGs[]LTߛPf}? +h [5FmrDk WhVq.*l+qCp<ܓMijz6IAZ<5YetA 0FW_Aȩp hdTH$+)2k ` >lFF"D.ٖCnݞ9bUVY vN/yiC!QQ`F\fл64'5cz_oQ (:h+&SviـqС5ٿzG} [nZT8\i6ÄSBoDòUiw*31a..9iACD@m=A2/OX9-Wims-iHW<#I{/xa-f0T*qr>3]Wz.-!!y}TÔ9i ( 0t2As[y`,hF-? )PtWVj2Q3nSY.S81f!`"}.nRkOlh#BUpdXӿ4ாu5d)|Yh1#P Y>vt[ YRc`,3e40z8@`K [nļZ[";’괿l;MƟ( gf(JOL5#>.`( ϩE l`@}N>i4ywV/?P$lbԼ|D'WStlOR;Y1v3?ci7u޸f1S④ ^E[dX(c,ܤ셔]P9ފp+_QL8דB~.Z#DE /R =&Ҏ8ɨ tPI5(\7oX3RK۝\vWCsɗ;-/B^R)L⵶y)}[g(6{n4[~Č*gͧƇZe;gIy7+1+oh8P/m\qgbwTk6&gaU㸓M=6|=Ym`~[ՆC|E:i7qy+vlL.ZZlb ;*33^2,M  OHBJYr!>YSLc`ԑwTgeQ_'_2؈1bBp̒`eՙ YDxȣچs~Qռmtedۈ lqo}w ؅gijB J99Zw򊔁Wb“5 ~"~jZcئUu_⭀;kOŻ &)MZt BK90(Y(Υ8k;ixOfZ~?;"И(b{R s29s|y{)\'D)U[J/^ 3CdWG y9dZB_:8&nmaQE^>qa\4# Ggȴr%>G:9]2#>i|%:ɛ=lMN=cCҶ $طZ3 P>cw4^]L!y~ Cl=9uhxpj4'@mOT~ya!n?IVg)$:`k'`t`;Jg̾J%%THKe&;gxJ Ǻǡ H/S|N)E4* &@Tñ":Y·A%(^0o'pp~8kw\Ӡ'sJDd"Z6k70>_:U0A&1)s&.G۲X |Э Jg1i8~5n*h"Ml+Z"9a4`6[Zidvtlm$Z[hK@iR/t :E. aG"6l o5M$«[y_OU.a:BPY&52;l@oʛZGGƱЖă6|yϴL.'a/"{3bY~F~>Q[U m^: 291 V\}F:7'42P,lC#1Op^PMս",!H:1d3I "J Ѽ[3M>[E8 F3H(e6h6'=[u(5b-hOv7_HlȁԻkQ4kiD5äjNfD䪄l2,!%!)|~; 3'4{o]i#Gs\J%](6C: Qqx'C+eu9O:u , QM*.G(hu<t7fyKEhʩqć<otFsRo AWL^E3~e$o)7IG(7[ 8"4~sӜkr%hJ1`+]yN4fFR][h V/īX:T]xOho[yZ|sQw4f)!3ٷ5Z{ͤR7|50̡]uߩGk߿I] O13CyQKrtuAhD!JXĦt6u ܛJg]Uˌej#*Ht]89Wbּ.PRCl}ze(#/2z?jOFt=`q%3dHTmv/K$_aimՍk5k!AP^j ew#^qiI{?{7cHWmkPMѭS[ygd@ȆBN6eAqG6]Q , FѳD줢]‚MظM(pY>0b`_Jr5T+ )/T=B0slvܳUBBTˇ$Q'4ytix5ZH4л^9'UJ*E[A՚uC|#4L;n^7* 9gC8\ 0~:GAlGekJ?|Јt &bZze+7b ▍W$,>MGiB?P84Vk٣ĥw,\BzƠ4G@qw!LǤ='udmYs40C I jOgcQ1& R8dq'~cn09!E!~M )oI}U\!XֱDms9/zawҋE $"@l{[S!F{턨6)n V _mK'_QFz+]~_}hVl&[$H, 17Ƙ\6:(c;#E8>B!lP߹Jn,䓤HD˟I 6u{-MŖ I5wpOټIr0 &A^ܸPseD1I92 YVC Q@,p6Jȝ;E,L@ ;EK00DwUu\n6iZ,Εvӊ8m8ʀrpW"W 7r+Q'_ ]4E ܁#M}@@Ԁήܛ*D 6bxKF/{ Y3;xW/ 4kEj},&j2y~9bqA5AzBPxw>K邥eJ=|@B4 tK}w2ћpYlvi£7 Ӏ~ K>,p'cfv0k ӊw  }a8QzSM,VQt+$zUÄ=s(wXOƘm~!nN @%XKp:. ;f i:!kQu/"kͲKzo&<КrUWu?յ$pkQʔ*1/BMϭh΍$)_}P6){:))K _j'{$4٤j0-{YsΰfTflH"Z]8*(GtH\tʏ3۩mr ό{&T?WYD9ݝ?3P5YqRYޢs# r=9.iǙRqUrMBN)LlU ы(bAaᵊd`KT 4V87QT@Qٺy6x#\g]* yDvIpⶫϐPs`ŚoUBR%?ƕrwP1}q8⡔~;^+ɐQ.NٽsH7(֕3=x`g #AXW48qKt_0yr[zx.'evAD`~rM/' /<6T1B $ _|m3J m\5̾ mvWXV4 >/8!9=B_SEQv_FdLzTˊ4׎iuoD\kHnuaŻ:*̣̓[>d5>WT ad[hC| F1*a!f\dKJCT%I`0DGh ϡkql+Rj .vh[=r(=Mܑ4OX̥XV8tXi[Sk]0}_csQ?F7B%b5z g^]z-ߡ&e_n(ECA9ehCJKbz|b1yo종,Wͯ@nGQ'. G)vbUIp;&U5e04|mkQmW`ڍD2t4}Z䣽g/hFdB -MC]\*2tB(W#>zN?u" b0<5ER3)RM9.<|9gK`wt"cfTi.y-Q$V%bKÔOe a2S6n55Kѱ~@J[J.Y]RĬ3N{=Dygk_ ?H&fyr£\`oR$ s:8>.r 0U7S,qi(#p>,TZ,u6}~0Ot+q.H *z :P0l x~xU/ 1=ґYgHݗgA$dPW \7E cGl4mu3\ѫMJ(`< ;ŋ=wѮMƶn(P!y%R [U͔j!{ys6JD:(Ft C>\1o4X/BGb)y6A99IAZ7W޿εhL< $~ҪRIƱ~ϹHpSUUE۬-ZX0 =8WReU̺[?GuuP ճlՕ-&K_%Ә׋G|o+$cx7'eͯ|Oo5k#,6Tvm=49*;'3QHy?:Yx-.hp}O M#eD-6`g /j1]?N*lH21 g9mMUdN$V11!{!5ӧIkgg; AУ,xf'#|pVk\7cp'Q|5tvSmls>#Nhr8VN|RR^?$ٽ8Ռot% E~o.f{d+A(WH ^l>_Նa:T_ e4v Y')|kRGF84'JΘ>i& A)CiN~qHx lOs$-q) cA ayOy*_,@ F|-FlFk7'44U r0%g(%x p'Z3+:t3dxgg3m7> K/pwXq-4.l3&=A\ ~y7i]PMZ> AGovd+|УüqسD}$.4Fx׀uD}yL&XG 2.VdrwL1k\-R.\@bueW- U;K/iY yVVQ*vS!qiwcR6p,,P@.w#yV#@2Qz9\ZEƟg θCN +߬c ;|NwBGmTMm#vC/ Ԕ&bjY~7MIF,.E{ñ;~jX C${yFE:9i$9|d32.~lH590,* Dʓ} ?'tTW\yVy{/ 20[RQ)yROrmY +ȘO6ҖN<. =nʓOת^0A}qb/4K 2{by|@4P.<Q>uqe3E})C0Oe,yЄA4(!8+=/5ьx~t&ϯ P~eEbR8*|3o3µXKd+mv&)ŪtOplG]}顿_.ڰIQ%6 )Y{T iilޯȇy>Iu&:î]ƿb@~]2lDe%[D: n;-uTVbaev$ tJ36Mw..fϵ3'~w7GjvVyػ4q^]+فrJEg!(1NZugօ4Шr}ޘCTE J%kK,B.):%}Vs ,ʛİ̅(vvzLH!>IOLR*},cAW02j87A T> qt$N@y]| $}{W@遤:CU.V\ MIy 6< i2-"sbA{sCG*W^L?ߘƆM&3.L.isבvf,ltK2@ Q.%e'{n<9q+k]E݆l#|_B_4QaKLۢrd5fb yz4*m8.aVnI_/}h(>\] >&}u6|@*i#zÝ6Fi@4ݫ{T~P@lɒٟaP8-:ݥIZv}Y|i-iټ름On_jEK KCͤ2k5g#s&yi,gU4`[g|Ӝ"fWG!́nBݲ%-g?[sAL-JHkx$LUg}]z!<4E|$}>u(Bw{IɻD3(ϖՇ#]hNFX;NggBˬ;NzH-DY]]EEsҜal^gKէdcTyi3aӷsXKpJ׆#UvM伶SK2.nzOΑWqV]e5LM [XvHchmtjtAT/Ԙ?Kd_Ab.5U|v=7@0l3c;ж>Ze @i&ZmIuEf8w`#Tl$Y:ݛ8k]ژ[2ϸ44OZ0_|n@2D%Y5,Ku?d T]8$\ ɽG1:Zg9~ ^}/ܘdiY𞛔,peI\cP&rU Ń9JzcHtܖml%}@N'~(`&Ug~Vf y u ږ1+R=$>۴4N@$&3 3d*~W`Ĩ0. wUL{uWXkMod?)X|QB92 @"NHHe;pvπ`5Y0KO=ԪW:MEᅵPA׳I>ɦP3ocL^:~[OR4J T='@os8Q!)hҸ"oi+k>YU.mJav.q)XYycoF}oI}bQ4u 6>Xa%I4YҰHPؖ/ETT0sz_:O5تr(1 TDY܌t QcGTw**/!S@I!;`|„r {7t ?UZdW)Nm.B35a)3a c7$mW6 X6$Y'6 _=16'6;ਸNwQ6cVw n$]t[Cp} =E<}YKF>IsoMO%X}Bɽ&&^ B{$˔9\K=a7RۇVJ(~.͡QacG"uדMU4u4u mR5:,ī(ҴzJ^=.u6v*k𢘺2^[9mH N[}Ĕ?LْfX BfG҇5wNjX&{eLԥI )Î/8MWUݛeWo9尟di @ɣK`9_v t1N`+_*ke "QC5Vfe{:И^"GݵOԽG QfM8kZQ,9HDJ J5Z :2|L8qW8P-*ZNXR> Mı2ƕz>EO~6,|k!o".$'1gv{/ Sxք֙@ ?3eqK 4ܡ,2¿%(pME|t+T$r3ā35/b9AWP?_0[L <,8vBM,9 ͊~-lrlf7π+pL\W` 3$ R!s%R Pbۄv셀 .M`]㟣[}%_x((pDaX7]# V!HY8zVN1Rek3cPl]h Co$}8mCb1:vM-cKHԟ.MT01s/N{l0 m1&[;B?LR`N<"@Iz oϙp- LQ3d#\Գ'odfv0>2\Qգ7b4~!5p b/a>ni;M5g$r-WwQU8FWQ;}4ؤݛ n+}0S$=Zf֫5xӋ)/_WP{f~zG < GDbŪwu0zC-@R  6t+"P@!Jr఑ث[w .e 1v11]K ? O),RT UL#*)+zMp#W6J^m|#&ᴹgYn =*0(eT][o~ o[܁cQQr9,[vJb)O#v/ A,!/!ZY4oGl@hBoe3"GQZ[ċ?^nF1Fȗi./o$Jv*མgf~3,P>)pjxbܭZ&e],0VrL#A4 <۱ÿH[FdA],3耷\IH.op)UR*ǚ % AG{"'M%+LOs8:^ ٯr Vy.-Ҥ "dAk(V&J@]\jc<s*T̒ EHԬuK֨8tD h? h;ĐzI0tϵfE&=r٥Cɜgl'D/R}ZsGt' շ75 CBۯrr̶ܾCK&zhӠɰYyꐀr1ךJkshHPuZy5 K[IW F=yL, Tt%:ϢuhzKi+CalD1@h7hnj5\tSɏ:ED6zlHIp&:cnZ$:OZx]fJqU`߂lB\k*ڣOq~u?Pa}URb`FPZՓֺHyv{ |܇Z. @P[6' ¾j%>B]nJo^8a/E?\ǿe(yQa+"_38+1֜\k}#ʬz(:QƐeksTl5ƒs]ND%+)zԌPǽܲ%܈F PlQ`;t%A/ԢQ+-Y zA(D2o;/n0 uwU81 \s:cȬ; C97;iltB=iJ?9A@qS$"en-th.2k\35oUuH&y|jA@jOVwNp{߶ {22{Q`KΕs1,[^@rN,K=󎜓kcED#s[ akۃĝ6m)6ӊ{5ԁ5r\C}\찖ǭ[u c:n>2eBe2T-&Y*ҭ m0# ˇQbg2ފ-bHic~t'^$@Bheb!X!WfkHk:*st'ȓp&:KG1P+'gFws V!qPt8L)j[% WI yGTcT7y*PwPjÖVP]r3Ox1I4$O*i5ŬS|V>ҭ Q`{c=6{i*mۣ(椆ZŷOߩȺ89N0Y\7n29_ d[m(btqВ#YBxyl?[RZϦp;;9JC%Gq4P& j2y7 r8}j8<0 Oڰ똳NʾxdƘEZԩg7}mEI92jA=+C_HFO OEn n.;ooIVhClk45d0wrĿmȹ UrKۧFE#(SC:èCfA^&s*~.ΨB2$9K,? :Xw9;4JwI:H*ӉkrfjIb AyW".o+qP >48MG ΃USM Iʙo[_UDs>9B߶Q,~ $qe_ۘq,wjK϶:]aLk^5B,ۡ()DQq֡h4/ Bt7#6!zɔC&|Ol*6+JSCϰK.5VO-&]Q)}Ę`WR+$YcSmnyN>LTN(8hV(xU4wBjJMezK a$kT;k1 'Ӵe foHhf~%`߀^=;;?Mԩuk.q\9I6Do2FC7ag Ő_i|,i RJjXzqC>K؉# ЀSϬJKЛsI:?ٖn)!HosE k™rB&LF5^F^PMs9ͷcΣ*?!V/B+}}HY/”cP,5 2̙B wWNX~խW©IFk]NHqXɀ^[MCct4 =G. jvFx7\QL./s4MrZZy~dCX~nR8^1d ]7vFVEX4oP Gu߷vFcn@ ٢4mmsȭWlSrc-tX-#dEMQ(M;jS7j $^iAFZ6Ӆf$.̦|Éd!2m7܃y6SYbF;n+BՁEWì!^^Z={;֊/)?y, Z7@lvY&W5x<936Mބ;%)ڛ*P<z]P; ?`M64Y3 u}k5Aɸ cP.zyp1 qJEDv\MT},(H'bZ#D]m[KF\g4F1ž;#iDs"iMK/'Jv)u5dP _p`bl0UiY}Gp 3h/T boF4T(t­S"Sfjx/Ϳ7!Y̵>pAÀaIqng&0>,(~0đm> Z4^c}:ΰ%&z7ae'U_M6`FΟ9my1Toy4G D^L sN(\]T=c8po'0{@Yֲ}T* c[S"rvdXC$8ljwSC0d2wG{ Y,FᣊPw)[9 5Tw(^;iA `K[iutT#/Gr6j|5Q=/Z UUj@,k/V~*>ZBHș>4:HN::.KD_2`h)QYG <u!^Y}liJؤ&[ }عκiX%VbBZ^1"//WblFt'չd 5* LjgUVGn}rzé9%h*GD ;qx8ԅ\E`5m 8ꓡ=đNwfbU Yԁyv6K/H=eX7&JIύ+\LuSKN,O13/jNK;b FIfA N,`-f$lgs<{-oAL{T# 13okݗ2v@LwLk5+͒#NJI&5*?14';G% ժ/K`iyu5 守|Y"ݸ&ڷ( 2Γ)g=/`J p\LG ܆KvOW SDmdd 4I/޴k u;cm{TSTuG2zgo=7ue28Ej6fig_}U71g{M(SЬI]Vg(9P8ZdGT3}}Yh+ռ(FXp?/?$ho.9йlWڤ9{}Hmc$.e$duӇ ?'. zML_|(p2˰H%АQ:-ihlF0$1GxvAnrsW;|Zĺ 2ҙ= ѾI@-+Kh^So`F3_9  ǡqV@#& |AdUIX#ZsDo=!,Dj¨/ ը9Ђ,'V)N-S7ZG:0 pp\ ikH$5wGH#*])p,pŭ5CвQR+dngWK#ᤅ5 .TqLjvK  1!L Y(K\vNc_~Q[:Lm[z,a6-;6c3HkJV6MJXo3]#-y cn9Yb!@P 2 qZ0H*8[j+,}h0H`̹Nͽ>| 9Tu^R.5_z0+p7 y WE<1SMf @` ;fU)~ei(0u)\H3 I<ɔ#΢/NW+NDmn늺E{C>>AR_`ḞyL({|}-ss@gfnj'B3dK1iu [7ל)fc&Tv/!&X{lu*}/dтGtעKQ?m|elV%a+"܅1$[tCTu4Ճ:3HpJ}u"sʿUn)=ш@Zk)ko70Q0, ä沆#7a洁:G:gUx'apu}x:x^n:b[x20Q:Z< Y&EV24oƑ^(g ڹ(1s0>Gb\;; ie=ƨ$Oәʿ/ydNn?3KTB& h#nZ=8z'-vqǐ S` ~.q`6hH^hmU "lYSg[HLz@f1ώO$r( w.%XL 3l`"{âP))V&oWdk)ٔ*gb)V%УfIO)1Q .l X:' !sQSnOo`_z 5_aBhws5Vt k1Fq$3B&]}t &n-?^e`#n:nj ڶ'jwD~qNOƸSLyl&kQ'xc֭˸4 \~U0_V_|ί΀VJmN4k1K.՛7 O#\`N>q40f*>>UC\@QӜxH RXт9ā9n:M|:ut6rſv~M;"'x*5%O/.2u_avrqm\x6.×l\ueC~qwSs?c ^>м}9jک5w#kU`#-(l-T"w5Ep7ƇwFXJ3UiGMcG>9zί=pl䧵豫;B:J:\˽ΨCP.4;2Q59ropPǽ!70̡}20XLl]s1ޏB P_/yO@)|>^un,H8FWҠp{ lj̲#KjNd,u:j)NN3IkHʬT]6|I,җ "w͌(!`WFh!бI g;ksxV `8m@!ShUky?.Z{9ωG$c}@*xߊCsmg$<57)$^(BAGW )ϘFwAKh(Ndjfd} %qa6[NhRIM'}/Qetzn RF zീ S9BH;*tA9@dήgB_'iaƎ[oL+!Na ӺY(:qW&"^Hti)vy^'HFAPw٭%Ӏ~͛iOW)Z+L#`"DM7@.6#ʃw|4Q][*(]r+R|#{1D)x%8wDsJ= dYnWĪ"Aմ*EXe9 ڝDA%;i G7Hp15=tX4KZ2Z':*}]]d fJ@O Ɩ5 jh%X7zl m }O.A>SgCW&.($ g 7i?{Do8Dݍ]tZb%ihږhqq[+W7T[08Ŝ!Py?C6o tw}EotJ~ @#8hO9<.m$ ^-ul`4>)%<\0߂;dXENtl]Ro1#^ޏ$/} >M!(D9*4#ofV/(c_:HwDhHRB*qnC4T@@2܋V8fK[n-|c7winқޔfLznSdi:RCOz4ȼ=ZfTp 9hqFa "uia|;({,#>IN0Vչ'w<03xAVh;jpbhjILD+޿1wyMk#Otld$`߆oըW,򿶗zӰrW}8JzV5sGj]tg WH BV,ŐDuK7GzWdKОYm_7ހo4D#'AC[hNCcPķzyO%݋Ԓ9S)5Anr h,QJO+Ҿ#oq+F:\^kzdZ@&: ^;^o g=ڛж4HL&!N.(/^c)ֲlJf^3k3< Mnۋ]\a}oZEQ+Vv+~wCBj[ ՁWs:w{o9aѮulgCS1i}D/ @nHlZoG)} h$-_v$BѯJӨH_82Y_=xq4cd3'%V$(Py7K !6TNu7@KHSa#{2yRjlJ>ߠ~GceN#_[=̛lbVMvDe>ss̵ .ECpqvEqku8djij#K(av'+d_ъ*m9\x0ϪE|,FUQ>ڽJOv*ijLjfe HK2 *}EW1$Ђg~C6 Z`Z`aJv~p.+i!tOCA rA&/Y4/j'8IY2Lp>л`B<sU2 a˭eu2<wɁ &  |Qɛcl&,D{!wyjDǥYm x;,,iL28qcAEہ:-$䊹^C/2u-ju^x?lv.vdi@lf.l= L!?ß'hi/) /`El{vwho 5H64x_P$JI/@Hg @A ]6 %ae.bf|SwaR,i?BْbאEB#He6uQiYPIDh$eK4cRpHq)n-PFV&ڗwp= bi9?s.Od\e* `?~)~f?@ /jk[mAң*7+VkUr+@Q IQ vzk"jjc6{yX9sA?:#%/0 -od7{[e\;d󈜑8U[$*\8Ch>#`ncGk C W߇VުokOqtZ5>xJgbffcBO |A[\\$U\ys/$ݘPFmIC5:vEO3mA; ٩Jp씌+v9r^S,UZ! qJfJMy^[҅o>~aG-b V`Lb짔ۻύObتH,P>ZŢ?*tIRG;G,fvۍG 6Fs%9n{๼Ӡ1s2XX!+ .0EqMu\/Ɣ |4Q"sV=g?W.bk&K>Ϥ.) c[뙧IJ 0# P.WG3&cʹVK_"߃Ι`+N!SlQ!|˙^12͑ ~?..h&k4!E<hlAUB E<7-m筈x$-)cC/Fz8,4~ dfF'YNɃ瞠A[>ӑ3D[uPc=y#W qvzhOşjF S`1I|;~GERjZWRe&aZ[ 1sI;Y"u`*g% }\&[D.}~S:IL:tߒYQלd)Pŏ_9QNg-_?{wiZTx;dbk0fﶊa09p`D ;TnLIG}F1`p7!Nɠ*|U 7O:WĬXq&&Y,+wb֩ĊQvS=)E88q*s 347OAǯW8 rUMvm(i b%}7x.S8FJ;uy{Q0dmW{cf ÃB;򛮩 ^Cj击m&~)Bkb"Wծ ScaVZ]<ŏdW'.x7VUR`YsqmgeAYIK`6p-ƌ={J>.tO3 ۶n:zH^ FRvnD)3rD3v1{LG0e -ytRo,*^~\KOm,>1Kccu ޡpIn(SN,evok h:E8LiiW+φ)~ GO KLFxp^My pZ X-{"ep7rAuzXbWKGԄHNTMjf_8_B ւ"kܳ+Ŷ(2 Ϗ-IZ`Z 7 u^mb*LܲsD"IzJy0 ykYӓm fS|@5J|+Ҏ*M֫J!Wٺy97YȔ^:9~]r̈t~t %*&B#.; Iy Aܰ9&u eLX B@jZ<5ǧeJҥFt{uN/܀uosOQ#20 iQSJ\s>"(i4)yhx7xf'WsX?eHXy}/\ US {;HWT*ژLty"eZkQZC!P˦4=/* P]6C ᱇gT:8T" Erd!PZ8K8UGo"*F\suɓX)Q[`eL_.0?'YrDpx%P;l;a:5'B+ƍ*ۭ {Y@ %t:e`6jr?ěz԰g&8ZQtĉK!r_H~"QiQ^DZw(B9+J]UTkgS-,mMKXr\![B6dyLLh\jwΚg-3E/HCb>ݢcH(-tp.gsY)u,in:I:,И>~zcZp}vZ$)%,ÑFu,kE<\pAG1ꆆY?eB v4 c6vΦpPz Pp^OƟ0FsWZ`~kJMvl+gsqfH_"\ _=Pwx@S?qk- mҤL0D 3kLZ0ؤ@[!$dC!ݙ>Rͼ*v6a~G֑EKYΥ\cJꖁ>x&BiNlnSDNC圅QwVbSk$Dw<$i&vxV{?&>wǹ[^B~sI4cjclvOMY}fFs~ c9fg1*j6Q(d8e @99FﯻCM^y.x' u6J׀˨ O|ӱiȟ %c&KQjB J;ගȬ>I]eS".YbiA7Hsqv q:nf '[T \*D,UKJn/dS~j,g$mW^ʟp!ڂR@ze븝ԃv8B-DvGyy/4a߶Tcw`746lJ kb_,LQ 7-"r'yry-E8rLV f9 `2}.wHҖjQT$ 'D! PAg gыZ(&JSgiʧ8UHm=uꭼWRtQ8Es9-_: G#c0&Q?L6*N˻RC]Kb1ٹld_tjr0uh^2"̙XYi[\rPCSGnV<}NhA>ͳmY;oVĖ?F*(41H<}\F16ډ. f KZ,d‚A/*5V őba\yyj'=@@V]>_nr3X) D10i%K%| "P t(efyBUrz`29sԋ6#nOhḴ.]C,OoO8hLZu1QBX/p-ϱ-v :dƎZQ"8þ]Cy*gMK:39A,,}~O*uNJX&IU;/T[Qك 5rl݂5lѲV6z^t2#qGxTBoAގ31P Ovl2D9EQΥaMi#G7dOA5ȨnI?JCa V%ҷ322r-XwTi? q0$0ڊF6- aԢ!Kf8oeٍ~{IJ2XNn0T\ѐJ83;B1:u^aSW7YԟoP9-kDLfS9>SGAgXj-ƺqkշ~+2T+.yu3hS Un,#DUPP]>VS~R!dȕnTx>MgBtq|S.oQ^"-7D׾FB֑*BpG>>!8X[qZ<-Ɗl"Df\XtT,Aա\Ĵ) vMWS}Jyƈ>J6; t*GWr/? By-,`(9' &ju!㣐uySr fR]^ɜ/ǚ'/<O (ʰcdJO4Ίz6z֋VNd9'I'-[QC, RbdZ%0" 4ҋPSY xq0IZX"sxrjr~DQ5ӔZǗhR,K`; alUB:*A\xSh4n%Sf8-_ g7{CR4P=:%H?/ V\Vn*m礬I@6۰ Goj {[יܰe6 Ȃrk]جWmL,ZKkU1,)V~}iSU,`kVM"f:}0.3Fuy}3W-3U;eCQCTqE(b7I_=ܴ~Gb 0uÂf8aݷ(> ^vM{Tס[\di@G\΁΍ݪɖ[yǟv#|`ژ[;HCYW nG!kΦ/!W+}^tlPkz&w~UWPҁZ6(P4G:D HJ}}&ͳYMLC䅈M-̘Fyg >QX A5GD_t RDи@p`hQYF jEґGĠQ[xAqg$xń4F"tMg@~<'n]׊ɃSYxq5`̌L VʎV9LQ>W{"k tR~0Gga'o K* V4XyI~_+&'m\ol\_VŐRZϊ& F"`=)_> }Mu6P/-idOݚ%OMS%axU(3q—{AӶP$~({35c`َ&sC"@8%2/z=O`N8,޹(Yz_(e °joVO*l?- 7)y4DVdfYQWՂ;8k>Au2Ձ{$c0K4`; 9_3Ig~akWOvA+-*2Vq$ׁQm4> < ys_Ы\_AݪbÅ+Qᵞ!9DOҋ6]! dGơK)Xc) 8F+є?}b2XҵR@)p"%AAB2ˠmagߧ 31^6U'I>.|aơ0U1c;x)@1[:Rk~cy૝cItXPksU R,^y,@εVI(qAXȴ."ra ZVL8RoCX[=AYuQJSIn:*I2cU_^Ff\Mi {㙟<,c[&5>LDq=o~2 uyydL/ê`#n@{Q.hɟ &H1F|Wgl NDo< hYK;)B.:TDEE#w [7ku/x7{J`8tfL& &;6 @\s `s!!B;#U,¢N3z0˓(h2_biYl K?ˎ:m jޞm}fnEʜNsF2o)?,[^#KUL]SO4yβ5D˹`$ B^kop1 145j9c1\;[Iѿ=x3pŀ+V)K•أ>n;J cLɅuHE^NqܺԻW]P;iXy2Ȧ%!v@<.w=u$Xr7 zyG~;}dԅZz$/d:(oQs\" ٷ]D{FdeZUhr'*wRv*]_W9X.Ygaaxo&kHжj'iI!R uiZ,w! t FQJ!܍1_եIZk2:GkՍ* AW]j8KU|Oj[8?;T/K5yKy%_<(j%wA6wc5@8.!yLHIXVP_o4 iҹ/тh2V`M]ݞ &H6UM6<+fP q0@E%"w=Ѝ*-I>Һm 0L 3iwgGm=v`+vӾ hfƳfS)~Bs᭠,0?Z} q95#l 6P"rE(G8^m8MU3?aQ~ؑWiᎲ7q5 ߈ v˜@NB%ᓤC'k.b-+}GAF9=ـaCiZn1I/W]}[볳/i.]nhnt`@sǻ{oƖWCd)6»R^UryC"BT8dߨml3I^w3k9wZY݆uF(N(~Yj&hdYp]+A+M..5f&L]~M%1rMd(Q>~ p^3!IW2yCFGgC},vll(H%[^_|e7R1 B5p|TႣ5Bd_ڮAPQgx!Zrjf@f<7 93ߟRo+r o%eėz`/ ^(zʹ~Wjjz hTV&&ޖ!rHیa|8Zykc(<_oҬWJ[vmh_Q*^טIup20lpЕm6qՑˆZ_CWju&cW_H4jg;A )WǩBǾ+Iaƚr'ߤނ Շcx3"~&CE%vF2d‡c /1ΧYb'X&Px#`ܙLx(7|1^y wb1"%c)CYjb)Qa=Fz,4ՠTм# ڢdZm};3=z[T5; S/Қtfd0whK[Ѯ FVY})HMfM-Ƌ[_^& 6e-2IyK 1f4!OR|rR+puB䟨7C^F0?/j;I.,fQ(] ay0kMr nOUv7z˰~E Nv8O5ގx~<0>ڝpF4wnw5+yN\d #~θWswM}rt `/^D5W̖*\ #)^oirywԧeI Y-)n&kڻL~e’oW H޹-ejjGW%D/~X(M'mι-ރţ |--Ekn1~ܾ~/B@QVϫd\Ju ýVz6l[d1phOx-^#r텢4^6êh4u>c$` *8yn'6ѢDSAil x Rѻqy)3砥 РZ\򛾛Tp%+wY_׋aOsBMH#j%VlY`f%Oϒ7):nnbݣWK)0+qUM]!)Ѭ|[*W:9VGx8`kt q>bNG=:5މ(GpT 6g+7Ԭ)TfAVC:o .Y*giτd4-cަ"˧ޣ|_'[QM|$ szy'9MD)+祊<Lcx:SagEmn!^"`)ҧ@CwZΫ^ G!b/hc+&%HTḆ;_1ԓ'ϼ'#>I$H!Qߐ?Z§(>q~« Q>-4 y;G5Ӻf&5%M.DOy->F(.` զ p g$QfSlM)Kw^4&Pr<8Nٹc7D:~d0{P^ʼRv4[yB[½㦙0L컱bQؗH2hnam2۶SJC1Vݲb\6\jR=jX0Q'J sDx׆j"ѡVǶ 𑴾͗@}*3FP fg)u%R ~_5$wo<Hؽ y5"M.!HPC/),U;d]aa?E^ qtR[8OtV($ۑ9Rg%*[`~L7΢_ ê%L( TkB#(mq"v*Ard(ijm 1:kWf >A ]<$Ӂ"dfS5gl |Os+?jn,Vu\9ϠsR9Mx|3I;ȷ'Lڊ3ޢ$I|MSgqowh3 EgΦ#y#7vZvC_ U (xh~_A0W%KςN6CI98RB]l37o< -̼n:dG'vPʏur'O`XƻNFF/^VH; KↂFmsk8f͗3f9VJB4O=wE7]4aaъv^m  nJt{dʋ(qv3_Fȁt s#W`xe0bJ. Ŏ9+ʋ  IU&1lc ∄ɻ6Vm~5X/ tl#x7=QoV|VNl2-o/2Ż4fٻҘ2N騢 i0ړ;J(_Ѳѣh'Ǡ=3LxM% Qf[6~~oX;7@ǧ$frܽ]قۋ/pxD! Qd粥T,rVSM7mn,Ռ^aY~g$Tu)c##1Wn%4SʱܾRi#Y VZ/{Q1V!!D)r_э4L!$PK;А~C Y@) Gz'G& '@,g|Gz^Gj¹ 6b>u> E@ +fSjhFϮMQdc")Xoknp0j"K f:)~5<egl2QtXN_h%XzPT;TAÝWT9-p@rKV>T"! j ލ -^nDhbl|G1Y,қ# fonܟmS ;\]/&k4% V3G.Ah0ɓ)e:!-u^y,S,'߸ʵo-gUr =./=5 &J/P MzQœ4x lZ6|r"+mL/rp&4H8SzI)Z &׵>ɰb.~)w_5bbxKW=+%-]wLQ㚒-|d$')~Q5 wCe٠Pq+ȕ醗62"X=K^)_.nLŠ7ASJQ#E0tdw+ʑr91/zZu4ю~JjE L6_'#[hSMٖ-NN-pa <98΃}R>jI-?k%{{kڽo=KC_}ڟ 8v턯b_Vc CmUm3פ;V+KO ~IaLNomF䴩?EX4}sC!8N, )fk#l i(30a=na4Y! Yƫk+`l $3f靋<]F VٿLd11wHE.@{[&eyHN$N9B i} 'o;]ܺz 3K]9Hȓ!am62a%ju0[/Ayݮ_„ٮv8:74~xBdìn'ߧfSKif"ߓNeߟ*j_Gz:9ȨYF[Jj$B 3Z}F_ӳEMz ì⮔~ Nx+5w ֞`<Cwaoڶ! !`Aƕul%@̖r^B4R湳#3ˬA`~)f2yzb#iIp(tjqqԕ6_g5\RC LՌ̒s+ Wˈ%*Ħ:%G.C,.OI%哿z> ƓEy$M*IN@ yFZΞF!@(e}(\?&0hbÏ=湭}ʘ߽5PSʌlæ]';` ٍСG#<gBqx6}!Q&0y`u#isv?~AƨI==)26d_2L\3xsn5ʪ2/kq#tJпi&a GpY7h~_ .ܒO{Wܴx a+ >X'eiЈ:`N0,ddzoaK)$gvl,1QBPcg%U58sH3r!_z]\vĉ.RKDi5~J䐏~obT1ݹF0(PS2ɗW˥F=kڻ(EI .eF>{`ƴNu&i-_<>"z?ʼiho괻ykFR CUu,#S)Xڧ'.GܥLu , _苬  FoʰkN )ֽ_T_9m=ao8kv=V`Qץ[R/V?5}2 DZhcs3؎"B'R(Q'yÈ-%0ﳶK1'HdF`:t6K/\5e>ޔ$nd3y/>$y|xf,bs2WZS=eH'm0|P;^> _ g< |BC$ x;V'ol{yʔ7j41TEô,-M;H}7OE֠' c#oL94ElB8Ԃu%(!js5PFB60ԣi~{<6珙ciB O [F LO^cK)*ᝎɶp]訫1ɰ׆ ~еdǴT ux{Tf ~d[?\.\ WCa7H.hzʨ$|RbLXRqwlUv]HςaH#$QѲCcwXC\!hl6ٛmQ~sqٿuD*=)|jU4W@㜬= %aҖ8\jaE1)2S pCzwR I@$?P\%1|* s!:%,E wɨRx =rjʝngN~MJ06:m!̣PH?n״8# _cXk85=0 0$CfF_| j\dוhΘ))1+D E׏\a'jkNrL$TKW;c-/X<tV/f&':NIW4"l f[gi!b/y0(U Jx:5tC-SL0Z &f8U'xo&D—h4g$9'g ʓtQ6s(: /PXǨ4Wot\ M\㘟ikl}]zR]+ Կ?--X^XB+ ~O6\cO-ʆ'%oPj-kwHnjzې$۽ !kz@$FIЇ^1"X#k^ kǩSF)G "nW7P[NgԜ e;-q6p[ Te\Q?_.c.>OЬ^Eb|R _~˹Q{['g VE_YkI_STtW\3Evm7204R_<.j 1Th= j٫qp0Hb%H2˿ I߃PpLTAoxzc-biÔÉ8cC|KT##ຢ[;,+$56qȳ{&xvL7 ݍ2RΉ '4ZYۭ`_k]FփrSi]Ycu/Jݑu{tyt4)Tmk"_ a q_Mȥ -$Qe2{5]t9NEF3)y޳&*qH2Hy0eNrYq]̫"̭2kR'AIz g2o>z$b>E}~h[P ˈP0X *JFر, $ e"Hfo1HȊc7,'.9Y^}-w(]m! V=vqtƺN{dRϟ)jWӀɯP2ʚ˧ +p655yZDMa;EfʹnAàץ?ԃ/(Kп -b5B.7<5םBl8ѓ*g;p?&HCz,_Ҫ:×! yjQNƫʔ!1fl%d,jʦi6/6TZ(kB)J"rF\ݫ82! >nv?RkW~J/4~ t u<1?꣤VXEz}>n:kD憩^0p)U/sRi*Y:Z#[ ".glH Ux+h֜r_g&Br.X]w R7&iz1אi&\f9iu^%lIhߚP"gƀV@PSXJ-*(5.vj,8/OS} %']B͹<&њ?&>ɚG`rY†Ww/ Uka&JL=no#Qr&RT% Sei/XW㾆mCiWo58,C;I1n5Q!1,&$LDYB+dOQlX16X۷z?I>=`p׶A㖻hZQlu/f2' 3;*hjYj|x+&.t]/˔kӥ:ntr:W]k!ĢCyJV79u,rsMye8fXwf1V%NIQ}װ@(wK 65Ûy-ݔ:Q/PeShԱKlQK=C}XdHw&1ߌ'3w)Gkz󩿥Gv6HXaOzlYLnyWJ>lH75 ;(հSefq =҇%?Uh3ޡ;xdW|moۄF]*ڸauH2@_F]&,x$* "YJbI ~xc-۝z,1bg{[wLɔ%a) Y_BQR8~Xq~q62#sZ-@C_Xgڜ/3g@Ru!LQ>p62]}@U .[ށGYrLēGu%"T= w6L] o<"`a95"Hv-Zⶳ`˃~Pvuw8<6= VDr`cqڿk@Tž&]菤ņh8l,oRqa%"p=`syU#4̲Is.C<7 GUEe$CTvv:fDl?/Q϶ 숪XJ}h?cי&ovޥ?k0cgB >B8%#[vS;(@1m01*] 1K̇/$-g.CM,,Uxֶ&I7\; g>]1CJPdB )XMdEu|'KAlv(9|^S$s`ggJ?q)R;7aB|ZUa~E*0/UPMP+2yx hv↤P{d[2*fsn71Z17+ kdYr+ǔt_HHQ/2{DyY3a8-JEp^Xnܻ{.7/21ٖmSD % bKR50S}K6L+@aq>15{ Z[ a~ ŗy`7iCkD~4TFW'Xd`9`$Y]bj;ețڎX~r,s` k.o9DN f]gk&*x#3Ҿk4' J294fm24R2O(Hݨx\ViiEreEHi&A9_LeYzޜZ~~K9 9/L6A/QdpuSKGԀN1(0ei4QͣZp 9㣈e]\gYV'#an;|:16mj"55(mvdg&ek#‰O3UU`$gsiJ&3_|MZ ZNYa1-bQJCL #ѸXF:ZpVP(jҦ,PVrs,Z,eSEw߷$K`aumL!9E-UsT`>TߢR.gO)ycK4S.y]Nz>]Q&EsDLgؽ~.r30?:cH3h[n1\n u  "?Sk56^ *Tr0CYS2B]\p/и<,/l5WFԼ˶MZ>7|$ȶvA)]-> ګay!dnh(An=L:NZ(,CD8Jh &%h<m<8٩;>'8Li;(f1-0-M_::C/'@G&wE'%#Z2pQ2 (q A۰-L1α7Н HTMG{5(}"\#g</GrnI+r7Ӎ!eIGɾA_1[hFgf{ õcUGt0!sdLM*M,Wѝ;QrgTxL-a2$|_%Eƍw7b ~X^o5X)5.%SЃƖP:Q%$)R"Fwm>kdߞFX-.a1cΙNp[ 6cIWtHhCVOS0!N4MZόb3SgvETnzV|v] p[DKnNYĉ#"82$^qG6ma)q@rM JmL6GvOӝUQ9``JU 9U ʳZB,u3 +J9mrG;ci+>RVlœDRHAT8B9wT^uDĥ㓗' #)M?נ:>4op;X61ʎ= nߚgeKUăU V?S(Ӭ&_8ULɥZM}[-#լJkF^ 9n'TSmO ԭbЭ-ŵԐd3zZ*l?4172p++ fm뱂&]@ܥ7 KZVAIG(\-:^MD AcbN F/Sk oQңHNcl@`UoYV)<%Q:x[N&olVVaqۼlN<*TزUbCStWm)b|{/ۈ+ ׁ9[}Z0t,#XSδnaedOlU,cm uXNV-EurБ7X\F1˞pX^C pqg"b*%SdީeL[Δr} }Yk3xim~SsC9V6XqmO gaTT5Ytk:6޻R^ Rm_ O`6u8):~ @!ʸ ` 2EО65gp`kNBã<1뒺RI;J.5 XXN Uق٥w&J:D_Ɯ[cD:1oZt'L%_@)zЉe;T4%*^w[ f[~40)XULtAig[͠ )I|cOj!"^x\F;Fחijҕx~^;:gWM3N0V߻+(y A\sk Yd9kaA``HmHg ûK\PPk/YIm$Fп!Qq/*#? /Bj.jlY[ç{ԃm&FdTrSd`EaQ_>_$ P=Zo:g{BZF[ qgPo6$NqNa8 r[vn ȑ40 `aYPwTD*l@Vc+-Ab n~^^XN:R.f4l[r%²beWB(M!| `LѐQ+/p}༐ b{ r`[>=-S<^*Y,b{,ԕNɟc*x߷ [n/9rHp}7p<06R K] 13J_*yOUbS gR8eӏL7@#HO9nCc8O9f8\rx\._Aq[p\i Ɇ[auJ=n|Fjڦ(3@9K|: xy+(qY ;9 ?B4u:`]ia.a7^?IV@5Zk2sK! =NV6yig[ʦ~x M$cu!KŐ簒J\ĥW5P"%o!ʂHehǽ8I{ KT^z=T@z҆3,-~0c@ 4x $u(<:MێH&5aD}'|$oM?$c%Tyxw#g/\|?)b(;Uc|P>+2iJLUZ/[AUA {A k98{ilڿomo.)l:Jû"4B|;FI)oN8ldj&5;i=&<%Jgn~VD@9O@V K"  Y[x04$(CۧdaM_7UFT$)MƯdyB+4BUlF soO)09qXZ]tn"G~ UR< Mx{T$ɀAǧε5؇䵝Yz$CӒ[5?hN+\FL* K]nXD1~ly?U@,4cR/jBDUoQq'91EF G7xULPقna 褂 #4lHC_ 8j]N2WZF517 kaϸ[;tX]DHl2Qy6b=3ƬQƔxKM 6Y׺bqTܬ[M}D\kBd3rcŮJ p0dԐ@хo~Mal:#뎵Yd:y:9{|x ;ba2!g90ĮSws*-O,BcA9qqc;*c@T1.Gɛ5Rgb=' & Ds¤ɇ.6[V8*7 HcXְȓA׉T\K\v<Ң7+ӂ|m%/fi10}myPJ/pGK|BZþ°>Ba^"b,GdU5l1&=D#W -%^tj rQ<߅y^)eIMIke =>°q~ӬYJMVT'`eKC)}L,)[]z}Su>B> >9#L w?'}b8vT|k/ӡ Yڸ ځo7=NMA(TlhKi$mOSRudhx͘T~ YOk?*z 7m+V()En= I;Gk-%4`@3ivX&m6/Xr1yrމ|%gM:JMZ 1F$ӈeၤÒ$<J9_k00<\p Kj/:E~j#FO]q{-F`Dwc'5v7Xw>[ԤoL@(h`~ރYb7#Ms9jCP`L]D;Y)e9P $`K#_]tY|&uFDC&zX$Qԑ0z^(>*^ ϠQϪ ޥ֔w*sG$/g4k<_ BMR}'f 8_s0$6RfW6c B ڧ\$`^g4 ꂃڎ5O ! 4rV ]BL ޢB%)s|j5Kr{䪪V?c+.09p,– -6,Vd k;i+[ǖX{^xxOCI1?"] |J~~Q!q}IaNr,= @X*82 [a:$O. t^Rc~/C+dK<ʲk`~wFqCÝBw ,2Ԅuw"Uou W_4I9ӹ3w8): Pk,+д߼ Oۥ>&6Nr"?n>'_) [WϿ/|уjX=zu6t:,$8x;%L Pj~ o5&z:#.C, ' <|0w ޸tq4'ӁӴYv{Zaq!͐ӥ1q|<4ISY&=]ڣy,zHL磆pvf `$A驎ftsP1.K>yom E2٩2!/;QI'+8[( bDT \"/a>{U|k>Hy(u Q&>S]@&kkX i)򵛩1!̎+"kυF7KA8+6&mOiKzV!A+2Z:NŅCjE.TKLD|RlPX\-dm4r0FyP.mWkލKZ~'̈́fF|UdTZ~^ܰ#j5yWGmv(7 o*k2]Sxȟ1 a^nI H1Ur5E#W) C n Eݓ(oX9*|;fC6|ȣ}矗מB}/-X 0MQpNMX'aLZ[("DP=VǂIvEtkQNTĪF}a\H۫jN:FtԵ&[HSjx4?TZ-ݾGRl1On!Mer;Sm!*3'WvLti!_nwCdJ xV|K%G=H˂55_qs Ga<2U@E~w<[} 5cd|QT*b?ݗ5ztdNS#q?8&Xa˔g=" sj3j?\d>AU 0 -M:&4084c ;_K9GF"\O4œ +*;%~ %' ga1UꝞx^~٣*zuN)͑<%9 HU w8K`t U$ !FsF0߸ɺ} W#WwMŗ #8 Y| Cv$0Fڏ')=zL; &A_^*8)DBeݰU#*L; qv. N2S#3`U7 8u*cz%!MI[Ҋѿ"8.pGUK"Ьwlh]D=B9No-p3z{dy% EsN??nyC1|-?{#@!T Xӆ׬LCe2JH 4``cL_PX9d&uYZnJX2±f0.+!24bˬalN^S*ٔ{&W{?oQ?5 =`N٢yv |욭A;!>H_󙵗CfNp`|C/b=| b"qt^4Spdxz.ɒ$%|fNǔ.h-@`ϥ|qFBu Sw ovOYكd㘒 RU0zEb5 N6ʏsR}:(ah –$W9lĆ4$B ;6@՛t'h6hG-8K<"':6:ze>F`O +YDO+,:  GZ 7o#ڜ-Lm_6FYa 霡v6'&:<]Qe~r}n=E4ÒДzd(yibINbBΚJʫHs-J8OJ7FTr (T-KtB~&,C(r΢B:"A*egvsWsxݥ`u4rKԫ>AUPԸ>TjPNgߣPu5oU~Z\Y8_>Ҧ1 Jx:-.jF{S%{cm}v^ȯǍ;O5R#͸=j)h,9h[.Ch_+Bꫂ t}f2Pe>'S{y 75I>?pE6έw߂r몗+0N FzU|Q">A_O.z^Qw{K[9+4to:Ŭ$RvJ^7(\B}.ܓ'K iaجA%rZHe&yJ~ gSjBix%QNr!&(< |C|QW8)[qQca_,hޚ){w TgԆ+~P V}:Tdx$$4݅Dѻ_7hk3m8C[_,G(4,N2i~rOO&(c Y'#n$ $XemI{KrȠBPof>zdS4;|V ׀ 2>u@  i3Ux2+[Uoa@˻@~(G@;0˯jYz.bs{+WѐBz/)M {+4܋9V1?z4 ɗ.-۪뱢4e FX+%cH'/.7 6ڞ[moqaV[@D14-Np^ZC ߶y8I,!gL(}3lܛh9n "/f1&H9Raz(Xp9K^Jp"Y {&F4v=:v'׹V"#ozT_B؄ UY*X;;*J>\n*J_ȽҀGPO{w@.-n+RL[Q$D@qZZɞ,=Fc+K*gvP\Xnög_PDdu6D41ywm<9$:P:wn=WXt޸F8LoSlqq V5VO@VQ?ugq 6=:8ޔ{kruJ jEDڮ#`; N2҃bR/޷f3UylaE=t#Н$Vč(-*yzY=cG"ЋM؛k$1/rO(')cjAMf:C&gU&QEɜmxrD:3|ϖR?Ai r!miS#'@hסh |H#HWift .:.f`~'(9F W HdOdx6H@wo^ΟD 1q)lW^mhw=vP G{ \r"BE!@ga*KO/KT,)paC_Gb-AbU2⯢9MHUN_NI+L_ z{^\t)؉xĥ5|(pa_E:4FEoiwYXJFAouF#>i1wBr!vfO(s_Pk lE rRєmXpr ":4VB'(RSnkQB૘[xTXQ{, =lN!T1Xj[(Lu \P 3,NQ'PMVR2CkVjzVfcGHm;ɸc @ b[~$ p!Y*kh)ۜ .S 3U}^䅷řc=;9lO].Oڲ0r9;Dw/Fd ZMh߻4] KOsMRZs]X?rP=BOc\Uz`/5Nz?)7!%7aEA}ymB"!ѢǝXj<mNu o&!I#dF(Ҏ1K(}}iŞMɜa&p9Ge~;!/evkAi+j]L##7CNT~\&5*`z%Qr77RRƇ.R@07"J~W1 9Mą6|LF 9|h6HR2Qn6:yǤ3)tc):-e]Yh;!'z }-%nC!aت&@b?{B?}z$'K؛[921vigo@ۢ2Lvb.8,i_ncLb5r}v A:[ 竗&AYQ[SD,t\NF-`0iXsCCVuu|P~W#[-u?B6GuqR,-cy;5t׽JTG~R/,5VMiM[>:7ȆZQ[vvJV#Յ1!qҷaC]k黙΀pt? :l ~9[l6VyHpđe/v2%ZH3})v_ &b. dSEʮ-EQvT*1E8kYuzCV F^a̻W@TA̒=- cg]Y7ԑrY9C/Ub'Ss\cA_Cwf1/؇nqU_?H~+ l2rХ:leR< `R2S͝ZU4zpab$UΧ1w WjhIsnn. ䷦ "/듻UճLF^0`D )@%¢@>CV eW=ngcGh.(Q􊏭/@9 &4^}n5rg0Q eW'w¨j N7EK!Yh\: clWQP&y-МXױK?~EJc0 ڒ2OeuV%NuXh|¦DN) 37/ M5ΖIq"}RUFu""Gekvu0^#O_1#x2oҸ 0;#+f<^i>JDQU _|pɔLUN VuQ` \" fT`#kAXK~0|^opJuMi,WA^3gvO%m\B'Mz$em҄L w{ }Z($dXW-~[4 Fmogۑ22?Ly,ew q +>J@EG~b!FVR1(*{T2ءz]Nl4]rXM%ˮo+ʡUHѸ{ߓ1*N##v$< GpX\ V}=9P`[z4pTCTi)x?mm{8@/Z ъHiAbWJVT@nDdYX=?-0e}xF~3A !/:]S]PLݼ{BZx~ĂO*#3ɤJz8c9J LNnLUu v|{6VV%W4D-ֶ>$Љ}6}Rh]ieS(JZF 4XΰmZ#5yA,[O-F "oÆp 7ܱw3kDè#T ![+%{2-,hap[R+#-/7ՁwQG r[>iĔ<~`V'rbm`Ii^c߀ItV" *qa݌85H Ϛ*@4P\+Y6_]qZMu $Rcú4&hSDj*/(T,f=E}^Εq[E5<n}惫]m}K9+ ^CFrLphL〼:8%6F>l-;ԍÄ~#~$뜺%[u[`5|IXI]L+[qs[\FxC: 38y߾F?.KsPT܇*D|0ӖLO@a&&QFǾs2O)*=TFb[b,0(/SF"kv0f:͏%[CpK_|cV/6ήC[sw WT*vZ_)$ڧQ8OFƖ<]&+`N}g4 q_T_ 8B.Ţ\Q)>>o[?e'ǽzU֪h$pIe^;IyMe57J` ,ߖ)y'͗ JU$>Ds}1k<)9whyFsu qc:Q, w]a2rl^/ʞ?͖qo=N|rrEW3g4Yܖ BZPFmb΀wDq6l^@6(@yB @0J.QN`J"4}QyBp (rkZV)Q ]&KS ~9 ȳl#sU{葉}<]~%}06X:Y8t,cs15,ۈWNvoR:jDxVگ<+FAOmZLl*G, T*&8\ihrY$%  ʸV*o+?ڞ XH<X숟;eAie/ I|퇰X[U*xC21(j|Kʐ3oD,/5eaQ{ϗK C\7o\u󍼷%DTܠ vqHM6Slɪ6N(h=!wDgO&jIw`9k$mRT i YdVY[;MdƵSٔV"nJ&eI<džQ=t `2O^]_ 't t3RYESqHZ0yHP;"އhnϴ,@5>6ײF $pL }G-/) + yٽJ51Q-ۗ a9nnd`nvX`k<*o'RzV1xz3xZK2ޥYlO%3 ~scN꣫KX&?8Otް gԸ~AƣG+ƨ\w>gA >(kh%*-p %%"zSRc|4}ޱ4b,"}Y}CYTi S4ii!~~ǝ҇@s:|NɶٓDgڂp">;Ay dP:ZkjIa/G瀆` ]_~|AP3]/"]$<C- u8b<оP'u-f;ٟ Zdĭ!F`UqBZ~$UAq+}$o|U8_uJD3VDli 9øͭڳfM3t?KZ}҆_xaeWhNîRKswmfL= P ^iy|/LՋp#pwڼG.ZЙոѾ} JlXҰ rApY:2ߌ;մg OE.eU:.xA@u0WOVěx]&S6j3!'[0^rc+ɇ!Nwݏ hhVSznRmM+ Z`XN]WwAz%nxڼx5iڏZxBL$Q)g%mL<=(dQoK MOB`s5dz7M1߿QΝn H'gVm7qk{z І-isO|h{ᠾ YWl0,??ӊ}biM\yp٘Hx*?> ݙtY E| `gg=>ρ4 W`^ {2!01 J̘y)pew0ʢmc1 P ƙ70 Nic)uKK-P߹Tu/w =;c`Iθљu rӀsȱ6:GYY>geufj>!vhx (?se1-:F-h;0# !R2W :@v+o $+,.15?1;lޞm1[yQ|s~+m\g+T@[KDWd(,g7RXh |[>ɻ3>mB/ '&L8?dJq7/;OP[!bkw{2_ക OwUKՉ~_+)ENPn*HID#< A_!ԚĚ'sapI f;- RN|()Š7_cGWR%I L p.wR7&TZ=G,Svj̩X m5]1 ӇF!Ѭ>Eט{ >Sr2MRݜ* 3QWi^y 9YCgmKŖɾD{ ɬ2 mAOHtw.݊=3q,/#:eVl߾ӈ]vȿ% =1Mo#7H >ŒǾ((`f G]lWdj5v`ΥGHRC7#/RLŬ`D7paRY  e33!L0˚^E{HI;F-;RxWῚڈ!،0տN.>a0=+ ߻blU/= ;=\kQ5s9΍zpӚcqa^r%V4h6L٫',I ~VU*G[˸4͘~ MpV 򛉷 ',eFs)&H#_oW+ƓCY@@"#NXӫå_~0A'7/OVtv/9uW1mq<kLK#<63yyψ ʫ2!HkA " ¸'h'}~cqP%vaQ+C((1jDu'i>eMzFIM MZ58n0%Ni>ǭ,0)6I ,5?#\_eTuz p=8mx|vwF]b pQfQXH|M߿;76^ɸ؆K]qC{n0Fn~]ώGP9'D .>ߴT #?ZyG@:> &]I6 b0JoS*fC@.́Ok_FY//v]K#D+1ڕv[p0(M!HOZMnC9KY(G3;V`G ++<baK{dȂ%gt?{@ |D(c1EA(qJnsdYmG-͙OX1{sbGJv %haC(#9x:ӦAC 9fԽÕ%yn皻(oGC qdɀTq6 R;Ɠ}Ӊf׎*iy2b*ΰ1Ic"҈k! FKwЋ_Z[KBDx N.DׅٙݮYb Y.S\%Us$%U؈ջt 7R{zR}Cl*h^Ge %2ʺȗ֜r?Nu|!lkFt~yo<>ƪp| [{\ʱyĂu{4({3Oc 4Q}JhMoĚs|40T/FuzP BwvVDQv=}$8>KTLc6MGl,8I&X>#4ץ21 븰+~x4%?ԥ9Y%ÿOۻEطͬ#q A7 j8'%18rk Pp|Gv,< 4s%q5%j0M;2f q  xfy_%f+VW +sX^p1<~nx6ԓSg ++]{N߈+Pv_6gRش*3+cP~t#]dvEKlY){ʱ5I%+,zX-wDnK+OPͻW} ۥ$^(e ٗwJR5 !,XQtc1YF gZX  sJ+<á~м;B~ >/Q%}GAt A Tn!ezTUE/U=? c?}< 0^B8ޮҋ$ٿdܝJOibꘊ },{ I©JsW2BJZ(̷#w%4crWY݀/HANZ4 7<w@nM$OMwv ڣ_6) ?-01mLLbࣞV7x(t5)BMhџK'o2QMw磢= >ýmԢy'B* zjK0ycqO[Q,LӤz~@eFUj H~RS@bԚfZYݸ@RU_ ejڠ֥`DSX*#nc*öyt-lk3mO*;!9 2z7j\q?u|X( !A~s2ogT+$ %eCacsu=BwJXN)S٘u'vJ(g/8ʞ 78T򜳄۾ M3GV -HW+AޚK&JS{u)f7LX1;@wƦ³~3^ڧ_i#`J5GWjPWgW|\M+?ZlJ\)5R~2~yN)e>XGX{]VM1]WK뫿vIlՑ+q2,gk'u%BkЫ,_j_U|UQOB 뽐alrxx0h.$)Ded޽2o?LmD1*i z m2g,I^>p1*!uy{ U/fӄ2۱1JKqpZ*% y*$LtCM@ ]CkyxI"n@wjZ'8MBTe7ľ0-H\e"d˽2w,`C1-GtHS9iiCUAh\ kzS]rpGkk'ӌlm3BJ'!Ic] |KG!R1/޸6ur{v,7\-8 1eV^JgLm{: eZ>6V6V)R]j"I>HpeS>MsȎWrZh5^n iOvqxb ˢۚlZ9< U9[\,ŽwܐlŰIīpv<aB\ *Np`:OT22>wM c我bϣ> Qnz㸃ȄD9~N%7"Tuf?pȔ,DVRסǹnȘ%@zk|1eZ#;{Ր>(G1a̦Yʂ>W3=L7ۻP  #"O<*Mk%yNBcCRc83U M`,0L!_?7`tH g&?0 [Ie$wĸ|&Q Svr)OEs|%@Xʙ\)3VZ0ˠAo6{O:9 ?sU,6\?byˁ܍v ZE6aF@J1.W7pĘ3n]+܉Zr^u̾҃% !1tcC.IP5APzh6qBrVqhBOO;0qdDmMي N@fVdLej4=ғ7͒+YBCEMr*>aޗ'ƢI?C_k7i/kj,zQ}-+KvSH_@|^3U3+d@BM~ L. fo4K`f07)=a J \ZHY?r!Tg a"%'t{vXXm(\1aW$K1fSؒsn/ʧ[H閘-r -7A±CawԂ$7XfݥVPZ^W2ًje( rÅ% Nƛ8A84t)T|3X/S6+~OQ"U^EDž4EOvlo a,_c#(^^uF}&K1jjo%]&bPJND& (֭yhoF|=NI ~R5Ŏռ<|Vֲlt|2bwSf&},voyTuq8\zfvpQn!ze5G(ub71l1\}r`F08ޔD!$ yzQn䊐/t6_PVZ vZ2M.NZ-eJg$j@@\HN*x63DI. ld̔i]}8;_.OِI7Kv^PWZ^{=q72GK(sc硓; /YSNҙJ+AG!Sú Ws)/ei[Gf@ay]x*3}cS"GUG&U4W&5ciWxFEo!Yp0e~k VX(%~lϼ {U5Vh?nMNO`$hQn^W~'<-i[*lrrĈEYyhVN ܺ̕qDe.d"|,U0\QKX s[ 4Sr_R$Pm Dq5eFs#{y9 wLelXFjopU⪶=ηU8g&S$AM:*ߺJ&B@[jAYnx3{ TN[?]*o:3cO>o^fZťڪs(͇v9iZS{+\u*,eHBNHMP hag&fyITY)F}ǐ%Sx"9\X*K85l f-\H$So 02Qe}Bt<})" e~i`|`Y<fzӚ!A%jU u7_ FlK"UJKfo@8R1BrV7t:XI$)z^7Q#쯵f5Y [NK‹!u$6)+ÇD%S%̕HR\JB!SfܹjFs-SiBۤ$G)G,F"$ki7}I)87u~v +B IEТ9]"a7#V,Kl@m4IZ;# lF!_:Xf‰tYFZy(i Q86-ҙ9ju-][y>M;/1-}A6nNTkgW-KXI mzv( i`mKYe)_("γ;, TOfS[pD EGW2j^(5 >G=?BM7ֵմ$9kg#.@|7>ccF -d4 .ڸ,n/IPX}Թ~6 5;Q8!CO[ ?[b:pAgLw`=\TL0iQ?YT_z@Q_ј}%@E|怸75ٛbG2k/>4EDSL ʆyCԐ0z-CJߘSS phY['.v`F >*u  n,D{F^~?﹤j/G 1_OґAR(H>79@~( (*aESfQ"/7 79orӍ.&8m,ȇ ӄ~cʒ=:8K2qeoFqZq9Tq\qЫ2xQNbxD3`NALk}m9%Fdx3zBce-^ H93;SP1jjTuyGΓYO^N[jn_$_ut#$Q&]1Ɇ%K{.JYh]1ʞջءՐ>Qsv:j.d([kOtJX9FZp1,_Kf{ !Hֹr OlZf#m2d]pU);'a H^ Zs.A)VX;* W4'dB\.> hXDT۹Qrf`qcp 0?2KӾ}d ˬU,rQ.@6 >V;>Lӊ:a#Ym[); 8e}cRޯ9Y7D,ˏ 16dXf0Y> #>EKwXZ(rCmOtA"`ϟK n59ª PJa8.<[/00#Q<`TbC(%XkpجV'[>l8 Pi\Ƿ"ҭU3QxYG8U |%T(FpKp9[U8,Ӛqx"ӡ'ʹDHˆދwŤl9i_W+ˉfhr'cW=xLDžjp7dKqA(KQJGoKc eWƪ ĴøQC˓{J}R"|$ښ;{0O+!%s{[aYH%X[^Z)M phjڙ3f(9Kc392;:{Z5Wjg%K\J sȪ&U60=Sl:t01Faj1ώlXoVz !tz; u^Wr71Px)U<G-pTOfÜr۽54 W6bIL*@&&vۥr; WwJ/LΈ7\VT r> ο~9#ۓV,x7@>0۔E.Z {R` x1eF 4%Resab0f%{6ilV{W:Ƴ%"Ϡ`Sxp)OIr8+3߹"MI +#[ ]hnjvR e sSrv%YXnqss(MX,{,}!ST.˹F{nACSL0ZHBn(/2&n]3D DiҕQ0 @yVy/rHpnqp?s0=Xp>'mV icee4I `Ie2^t%b~ #eZVʺZ$^7{Lc^Ȓ]& 3y)>0yWj e7eK9~DIKЊ@|hG׿ktwpdq$>Yٌ{s9c$/8!qL wB8W9v>]+)sm)X2V퇧E*H\Z} &l=xn[NF%31׹; vV?ʈ3.a͋+ͦS|i68x!L˳5zgEd@(,ŏ 0FG;_> !Z; 2}M\//E0sk{#ӆʂA[ d5H:H {PU 袧 ZIn1PëSoMaTЋW,n(( ګo$0-CU|/ovr0!}!^NlxJ|/:vXGnOuH9o C#,L/~ ]X-.~Xk[[n|c]*>iGiǁ}K72>хL1\=iSׅQd gi9ɣ / ] ^_>;CH\ pmmOăN E%l-t'}g+9{$炪[aVErQ!3* ՛ 2K˶wL}IDo{pP\_$mbj#5lH)Ϧ[|zWQ |n[- (@x2bEYÖ>*Gpl$ϝ]%S(ANc>4MeEmN\S2t?#A /?iږ*eIZ@SL"]֍1Msr%}0u1xqͬ}X^Wb#fu kA,F-FC`h0oKE\%Q1rlk@8@ !lժQ=B(Nܣb7ԝ,l̮73aZ^!yuJmdrMnA=EВi3.BѤ&#F@k RYLCԮH9ԟzS[{j7s/o"L_+fƝqYA[)иa# h9$K`d.y/r0 '6Ԁ^Ο%mk8&r-cπQ&[~|9>Y*#tYm H"`Se~:r%.L)0I:黝PlX.I%Hc::h=qBy$ B;]"= c۠%U:k3 .J[<6bcynxk 5bӕ:5QHoxgf QѷG!@\i=S3cXpkFWޥ泻Tu#vҐ/qx&s ! yWe#VG(:}Uo*:D9\!™6|}F6"%#8]ҟmVBO&yɟR)vbK׬~WMt!bP~U?1@qu ~ 4 ; gT 6,5^//I;%gxD6^*K}ݠ2Iϫ a793BC.G=Dwپ?2%&33 cG}r' ,+2=Xl8{ZY"rH)$$yV?"efg(!u1WQ0'dH-f] bˤ^UsQ.Jt-IoԒrЊ[hh6? ~𳫟6/,ǏZ1nOa@%}X'kOT!EA RWy>[bDU9O)w-}S_Y|r_pWQ3Zۘ\EZ)ԋ6;9!)zvQ`iz*.ͧx+uմ4ܹ@KNᲪXh2th% NG789 9:)i?8i M z sEJ6fH|!uL֎`7JkϬBYrBW{+CC8J2If{xi>(-S[W41/$9rlJNyԵy^uG+g(d"'YG-e럡0 ܓw9,&?Tu..!Wٝ ‰6x#]#-L.kZZn\0<9  +OneNޞ*~CYL7]8a =kƇJV@{ӻ[OQk&\kߋ&@):"0w+j *fe[TzYfGK VKka|ov?N6xz~0TJU~o Fu v[biA<b -?;GG^xs, i%H)~!&Zu_jbv@7[Z^^sgvrͱ|$`H'b3h*Q2Q^-}mkuQ/&SGҶ_(h˼$U'Th' qv;G&lq`n&ߛtvQl1F+/><2df\ؿs* Ti1/i2>ڭnŧ0ˆJie)nUi@2x3tuOR/*HxoͨAg#R:N~Ӓ@RGU+ՐX_XGew}ȱi.)J#VYm ZXzx:=6m,dzSٕO!\] rS 0| CѿZ_MooKj5Ԅw$("e ]H3X1Iս)[A9.ˌ"篃9EVfJ~V8QNI0SXZSF\S҄|μ{-&R], GsH=aQ3m@sL詫(Mx#W=m! o88;CKֿ<ޒ<?Y؝7Ϊ,%& 2lfIId[U0#'\d>N IEhgR]"'ܜa cN쐭40켥66FZ3 S 攩=`or ^]E:uR@@GsiUA{@C4 '-sJe wX{dqrq_F7œP$dq=/>%vh$LUӗg˰1/;?T` rO>RÃn1<./ -;>-ec[.gn](X32E3:zҠ:6.h3d(VX riQ,b$$3\, 8v# F^c{_gY3oܦF/<9'"갏I*?7.Ul:ݤGL_)CYgÝc 1껦jp9ع\瘯Arne»]V' ֜vCa6p ?nM :x ck: O3ɋі^&_ETA-z2<\b5e K#Qx-)P򽄕zg=u6>҂_!:Ou:!M&GϤ#SyM*[oԠvkڣoqz-DRkl!BzB9YTo.5!KS8!ڡ(^b%Vঌh3vxqtMB-) rm yY4;M hS& $f)a`Yuɷ;ߟ /BD:dKQAZ$(% 44Nt<֙+PT^ӧT9ht5~n]~nTcADv3gNpzm~!nM/{ɡtZl)0S7Q-sRu[GŜҽ@/_$OjF>јnhdQNjpGn{,cؽrp uk of\3̩O7-S "~RYjK[tdSy9* %2=f29%QƔ ܇%ՑXCY; "^BLz7S4o vlRtv7  | rõ96봝ڸcP*yU$َ;/F#M6GC;";mnǮK7CLtC OM+H<8OU5 yD;dNwI_Zb0mSG̍ƣ˄3|pojL2#DJp+$<8>;@hx11Sʮx*қὖo_1SڌN{ 0!#I=V)Ds k \Fl/U4 #j˩+$E3-jhe'S'3Z^ ]TYHԻvoH XBVlw?6y<]-!P&La9d>e%oA 3 9PLBӘ깭ؘe+n葡K2OEFn:TzgBc*0~)Qs;m+<:|N hE.3<ޫ?D{bSb&D m "~^~.ʡD~>@{^]3cRlGar1Cu@,*%H.p#r´QQwm],M4}tʬ =޾EWsw XZw$l4deUȞ}GYc 1!^-EQFB/jW(pFǤ09zzz HᏳAo)Ag:{.P JܻٺXyhbM*{W}ʫy[oRbF!YY<ӓD>WWoYfBx.[Ovhortr~)\LƸ Vƍdr:}96Bݛ^ϝ:%3?593lip e-5N`V4g.N)h`*hͲlɺ y0nDswq."\ ]H xk(G\֬W'N愙k bnB1/d^o@^`oĴ}Y*@۽I6*h}l0zZJ#3*,ndf6^$exVѺp"M!Io-.njl0u=TIѫ?:d}Y)z_o&efk"G݃n644fSp~!zw4nG^&:I.5P}-7/ pK<-Ƅ(7e_{>$}L[@*?ֻH6×z3%11=RE*2q~+)dk*jsO>wJHw(w贑|b Yw{\UD*:eu7k6:.E&+!ZR,șnq=*4՟f1{[$rJji#љ_-xsO.p5Z^1.+kq^pl.5oT 5ߨ- -Χćkuuqe͈hU_VuN450EWy0s.SmϙaS֯/$){NBj'0ye2.ycУKX0kĽ P=ǰnhk+4o{V_~ѢaUbI?,L>O1`Aa ɢj>TKT̩qJXcZ<1A,H7&WU g!t|gq>Q|EҚa^_[Cd,Bz g z7mT)X jx ½Ş( k!ڨ?.C!~wQE܀u W\Hö$sϧhldH5oHj#g~8w]ZvEݾ cN`ZPlSTUurWNeI'%41dD?D!,ݼp Y$yRACdoZnn `r\qT}2~nIjڛ(;|?|Б VOЪp v^9u_ja-ػ$lNҨAr)ݛZd+5..Ʌ-7.$Axy;eV̓|*)m}X.M"9- r R\)l4q3&aC#]%ƧuM /,mJ 3Sx(JQi=+nM `VS9GCkx71HAK^Ʋ) JOQIĖ'C( <֕iZOn* 0[cMB^@a57xm0˭991ϩkX*jUzń, aeGy.F![!#G!}eX4<%3+< ̌~rj0[ls0lV _n,*;Jo{Yyq;%c%X""-[8BKZ.8[٦;?Ua 1mEtT.\/L= ojNleM:#FwjVIð{nuSgo@Pny%-#*`'ǭH5M(XhO~h u!70_#L!H OpS|u%o-tMx,fn4Qf]3#1ݑu6jҚyz&RezIg"OB[e-wѢnuR9t 0c(XT7HCaZ'VjwKm@/A?Sv=%pF6 [K;L34b Nm d7&Diž/_Np.C`EXB):~'AIhq@ȏ-B^UcF&xS`-0F~z gg ZCPxp8&˧Q[ї.-^MmRt鄐Ew}J+PM QU[2H=ރz>quC0XDr7RHҜ+?[1"]w?\;R`PQ To6NlYpEȂy]FflEYUG)ƅ %ޫZz#-GȝR-*j]c*WxvȨb$h{S1 tw $Pn I8dϔk<Mk,_}(D](\q{?jHVywIz=қ$ۦ/ +6A(ǀ]I_JbAKbNɁC!HN)cL˦O^nv#sA𳽑y3S.M]ìa>a:Rӈ ȰZ oU̓s jFsJ*F ^@oaV N61Ԅ(\u1`6 !9E DVSLRPS5Pߖ1_fNw# %Ẵ~:|зU73+bZ>w;0'YM랶1IJLH%[QOSJds/]ՙԌJGMfޚ2=D.g ԙ) 9zu<iH aݱQִӟ@ȧjCܻ 2( dvbKnbnQpx$7VZ@Cғμ~lf 7 CRTeMep1yi('-Qt.D/DR2R:xe9'󪪿WȆ1=92в+C"o^ó*a08bh|έE-*HIn..j>`pnnxEIL1_VVWnPJ*\}q)D s<ʄ=̆7TCw"VQ?́+B#u>ݺRw#>lk>99x+:H&/([[#/l/Z*߼/I#p3g}@Nf":oڏ;[e)."N#{ 3ɦRĔSZn`m/~V-;[ >n;9ϝi wp7eL?g=N0-2B~' }o>y)̏⩎m5[dCf1 #DUJY8lɛDI4`yl9np5pflؿgXo1CzzrO_62Ә#4n80@}ArckPɳzS G\[v%CNCyC M}2G/zqw8ĔpJ>40> ~y\ HǗfPhJiR3Z} \ZD%1L#GM-p)6 PQb_7 l59 bC@*=0=d]`Sz1b=o>Jc;;7x>PQ{"h啋) g1; ;a a+o Hbheetq c=,(1{b%Wq\qfY~woplTr'ヌ鮜{)-I;@I EbeBҗUK ')i93r8w!iq#wa R Xvwo/(NU4w3o7.o+G ʕf KRyYRUe`A@pyqȘk2OB;G\)83pJ04R= Qx QVE΋wym1RכX.aZY,cLMx(D %CODTAbP/4 pQ%CRS.d]oL_@/NhO,=z#.#-cD-SOE1|,"Jkq&BAPk[Vṵ*bp25ȕ.;.7 iASY4T`1bOAu-KYN߮^eEmTbt-gCA 6'Zqj(Y)ؤim7N$z#b$o9b'!RFw>}u\ ;s5f!Cʧ!~^IJ~ @+i;FHzm)~[ @>?<0}t̖I {DKnPrpy"{Лr 1/ V$|WnY/|QKVyͤ0RNK7ecqfexA$]yrᇃyeq85SM{8%f ce^$.W{kW`=B5{D ^¡GynG?d]ʬH}:$Ů;> &aȨl8ڛᡜIԇ+u| 2noz %R|:'uR* WUgjSF1(xB\9['wE3/G/#VʧydSpnG{ ?g:`M%>A\q8:BI mĹFY-506q8DT)\"M*E(#SP~N 'jIpMD ͓ЮJ+oi)pt2Hc]&'#pE=>p6#o Kb'Vu3 L:5>#ś!; EUOx gJV-!]yz*LYvXq vKԀ>?"E+V%cEz|sN,iRD:>ɽdq/ox~%KJz&^L>r0,(@+R'{\g[Dz_55Iy_n?4EHTJi@̒j.dں/6D4(⽊072H{΅I]=!W]O4wwWqSɈr%ʹ{_=TwQrܩyf9rJ`YK9;".t6gfnݘЂbۇ)vT$# 89OpFP!ݮ] DaJ Y.&Pfׄ<xBr.'\D&7 ox[2,}b`.d:ZZq+^D/S&bej p$36F 0wr留*Ĭ?u~GL?a? aam,#`>ֹK\^#%4ztq*X;,nVI&EXy$67b?XD?&9t>TI"g 66&`hR>B6S̏ W E@CTuZ,o2zQy ΔW!gε U/,ҋukVd޳Qb.]ϽQ h JL[t^ͻT&"|&^6'B" 4v+I^ <'.0 %zir@@=TWy\৞vQ0!B#gegh|)-I%Z5adZ%ΐم_f&.#{pT&{.hlX  %t4yQbl#\2}zo V?pZy4ܥD]P9IIu @ 躂Oݓ;ş wE4Doң$EVDKl Slzha1 n>U0'eQpjS>7Y~m'WUm8+ܠFMXP&7HFDmX*nY57fJkE? .Z柵%M4Eesq aBPK5ꓢ՝\ ._~DM g.ڐӫz'O (XjZ/xTPֳe6b$ݖ^N&+eIB>tc(8²MȵVCp` !e BSΪ>'kԜtI KǗ]P=? &гzN6Q)m, xʕpE/.g$ SNP[AO:1ZHT?`eB]i(} Y/q(4(I?Ѡ]cUn!vD j= Ê7F=fRk$Ќ"@3ABúx"aT:⯈E8[e-|ݿ*u$~\ ~5ݰWJe%0N(i!dĝ~N\R51J'۔0Rzw•6Uj[g19/d[{nWmxcAba33ZBv=WomgFwI$u3;s)AÌpV/0Ck6AC %8Tr+جus0I5%+;z0:}Nn,"e> C]R- Jπdϼ-9;}`=~] 1,?'B-t( A牽*'mpⳋ3׳NIB/vm!}cmҼAF1=)*0$3 ҿB{isn~ }iH֡Nl Z#B93\O δ 6?Y϶6Zvh8!Ӵx.*l2Ë},ql9¤Kbq:6$`hF0j$sӧF&ב,89<]}q^Fqw _10;e#j~٤cQ6loe|AVϷ] Aifjj|U yV(]#Yg)lӇHJ&1['b?-ge~(O呉Ol9'(2١`oOԃA948Ɲ|r bM%;݃/7l|4!w]q(wkvr=Anɟ +cpEHg[K$XL\2h0*-dJtb:~,Q0j-bj-_gw90wv0ۊ(`#R<@[d1|j%,: JEn.Q\ ,^4]—qb"*#EiJ]\"myE[EHR R f3c=W:iZRE^X`()7GoԚi 7Ʒ52F'gvh,.>'+yG׵WX=A'4.yzFxT76塵Jb8՘tY@j/',KW%t9J8,Ygs.w@ V. I>:3|r,']Ĺ#+i‰忪oCz|/)6v_k-ž:O&cBr 0zqF^N`yniahAV{ p"j\X @JDŽJT{$ypJ &o?H=.]~#ZҐ? SV~Lt`!zI4uOXQ-[xBژfpPqG=)`ZZs*iZi+ia(hɳڰSbtqtRtifb+؍pb1>0}~n< @xϪ+^K?\0RA>g|8912b>ȟ0?V-VlLJyRo$i"?@`bwYaYwM# { XY{B|8]Ƚrwo[Jqkuo,2h폓 x厀R:b院(▿5,,[daz.0\ސfL$u - TmA>(8%_(3!wZxgb'BbēM*{\%zl/:ŴGZ#ܰ m4]A玵Ef1ܖ25iGEi1z&V%z Qs1|P`H&>#x`op6]9 TU2nu %1:~JW\- ڙeݿC j0vܯ58EݓX"B2q:{;T̬MyTMMwGG@ir.URO4ym"ٲvn ԔZ.*G;?3kuž-w4~0|܋%!pktw[;u|WsĆ,VIh\kSr5<@#CɈj{n,8w3+V|UFs ∨RN0Oȏ:*}Ar֯_WC)ք1LzcUWM"Osa9S ޓ\>HC qW!;qAFN Gyg#=J\sSֲs"z$DZ^cY"y eZvYxٽ4撹zVODM4mcRdG :)v-ZzŮhJJS{5% 9Uې MϓLe6vU(qdC{ "w*%r0(؇=LT;ϘԸ@?@wmD<ҙĿ gE㑽|O(h _Q#X:ٯ&i=+ކ@8}-T׍QA1 t*/%d54ڂZ:[Z`xsg%k:RTfCxx E`>92^Tĥ8u}F^ 闪(+n!zf>?n1ȱ[  }gE}ƼED!,v]X׵9uaQ_:5Qõ@]mg=^?7Č`֘ȷ(Q_s<;#ٙ'4Q7Kx9ȷ&>w5:Zk~Z*ZL24Ex:4jy&~9/cU&Y!(CI^B˩k/_,y1o~_bqw pbHEz_'v6+H݈3 `LJrS: <@h3[6ʲ4KzHDPlFWt.:<ַ&S󺷻3PLΉ3Í/4G:~k ^zDVFnXRv廭 W@>JhެvumЗ>MAu>dL: O:2I*TD&|M<nKW+)h. #mm5VLj\XcUqŝ؇-w~-C44ZȞQU;˛?w˳E-% cOl'WhbkأߟO$Ek<ˬ:6 f`9OWrPٚ^F e|t*M6zLpۢ?݇?u#ֳPDqbǝw; QIB'۬*6f;m`2?, $ĝvps̯Mivc`3ι̺DHƨz59.i+;}![!Fȑ(#"FxscuObT? h8 gQQd?H~!y )p>ڀ_t)|UR,<=Pҕ_ETor<갢um5-\Q3jzWE2eE k3O&Iض PHu@g4דy# )ì|X8MpP:ň)>'[Rk*GXk.6؛܅LBv޴I@F0[RYeT2>̰{G(Vsx?JZv$>'#ˬ(&ruaeB Ÿ|sr3H.3.WUX]CKʹfW-1~=P>鐺nME~*N  #VgG W6*AoN]']aF> 3h4ѼA'7n+J#MT{e/9y\KCLK{͎%т6:nW7d6~ 4bCF!`}ݖ27ͱ^cuEߔL]`8l sîc<1~x="ˬp@i-;p44}Cvw-P*e`AHJ0 +CbPiNܝ)VV9K\@`{wʇ}_3LZLDJxf@20 |Dnx?kfe,1G7V?Qj/㏻;C&YXOe7e_Y 3:8Q[&FbZ)6ȖfF㸨>veba6#eͅ<8Hɢ\8D8lWyIѤ~s`!@oN`̴5=wO 44"_Q}Fg2YItM]pQk|VU_g"Dik\&^ olg JI0TɢVw[q,Bv\WaE;&K|ʺK4ۀ=Zc<'/wF;#-`kOu q=JkIBYzF:pF||컀=NsdFXh#$?.'8,Ǟ?y9bh8R!PyD/iieX`g4C(&@ͧ䦜c=e>Y2y߫c+NzVMI(ݿnlԎ--RNUV" isXbшVyb"\xZ6f8:q&Kc2jArG'pyj;0R1LAnT .a!1pUn_µ(n45͠ĕvj<|#>YIxTy8[Q?GDt08zF-=rt ;[$ç0>! 6cFyb` mwqx28RKTf'Bs"mlTy !3ᦘgw_G/[WI^)0-h2wJaE֪! BʤE\FSgmwK ^VuL-"t[)vjR;~:TV̋bq`\_nTS~sh~|GԸy|I~&"Hy<\p0* mcG秤Қg#T[.~~qߎ2CqF>=&tP~0 Xld]9鱬yI464iCh/q>I} q4-jkEW  f{7lf|qj-?X]=yB:@2|UCWE`=WwP*>["+";j+#QHwi8RQq;& }z">{BtGƐ/NjdY_*qv瑩=si]T"8-o3$0ˮ+uΒG4bӿ_xjZ dEP bqfUDV{ V!ڽ{،^g4Z\mdR={J/ȑжnJ[zʲ;>۹O:DlCA>u 5q5;U% &h#|4&=)%L}4Лjf# [zu AºI=\̨AbynGٲ Tv.:/N&q;'+n"aC H̃p'-i0`-5JKхC )Kuf*nWܛYR%7~C:8ʄJ osKˎN`7s;~:;H8%17"㩑o>7e-(&&JG-&]xʅJahM~| QlեEzxԘs +*K:I70z%_T<,kqԐshnX'A `s?ˠ] + ޠ'Oc]OJ{Ia zRLbq~rk/P'kh~hS= D$VЖnu>L@ϔ'! 4(rxO>;,Q BS j1mB~oA˵8xࣵP2if88ynS[ eڴi$PSHp1'sϖy+mT8V XZ?> ҷXv¤л"J(m ,5x,OoOu%cԾJX1{Mo%};[!mj&NAN}]& }13TKPOmyN̬B%s֘grt+s.:(q@O8)rㅛEa8} ܚJX,cI'W1p'_Z_f_&uNZ3<@gߣ2Їp`Qw9rap6A݌PP#Rp"oִoJњj͐҅xVھPl[L[z^Zſ}bKOԛs-0;{ob,cpN59 bWz(z}lG۷;@6TԒ.~ bNnkĶaGQnB<104\Ҵb7[`_Nu9Ra!DJ 倥XI3"ڻFόL%F-*K @3'ǰx`>A*(BR ݯ0p\Em4O̲Ԙԉ<ɚ&6Ѡ)L1\_EP([*aCjQ7H EuQukFũ6 S@#YCߪ~; aQ, Tlùj fCbs=ΩdeCwa*"KBx}d4_ lm1ߜhq%q׵ro[_cI#e ɉtB0U4~׋J ;c}̼Q_Un/Pc B}PZǼ-ej_ȳ9aaЊ1a+WjqkN:qPU1^WFфDI7s#;lJP߀Q*[e0 |McqkXx\IX?XD%8%1ctLy. s5\pYQŕ)KOˆQI%B&U9נsEFCtXkXy3t %~PuWPu]*_!1tJG˻; <$̰de׈S<}} {?/#䐖^]ߵXh}+<{@kuX%]P$=jӄ$Oxl k K mC*#,-ϩ{X7~g *!cĢ[Z91pZhtENӧؔ%NUD ޞeCy>O$8kp#ha]uPF9 [ӧWVZ'|eOrcWe&Ϩ9C~vX/ ƍ[`5vzEbOx2=LIߌ/0T[L !P Ԍag!a,W] -.}bF(_~b",s tZo4 %%Fz5:]ު9plij $ JYD%d4$ _~xzIN0ŢQJ2v_dء1٢n32|!rfy[A8 y' `KV"l_L0>'rVz{;ڙM;`Pבq=8Q 7oKZ5R[hb:u&D9순*o5C~u+[^:(P.TK-.Jr\ViOe6Yz:f}'dK"b&Yr";lx*/J+6pRAnmJo;F5QvXdQt[me`e ~lVv n r}[>XuRKEnpEr` L >@YAVe.R_Key2S}sZe1pHqt)s*(ڣz o4iu}zM:1>%VM5cr&)WD%dXMጬ>v]:E![w%uKQJ(mx Q_L/Җ a0f!Mo:%2B7hwBQɥ.`|JT['4&.usџ6u@Cn8pdܬn0ۨpѼBl{ǖM"%=tPIMtL'<j&IӮWS#h/zq`5ľ`4)z*= bT JUm.qE{~Nz N7K^8.q Ϻ2_"< +ĩy}A>qd,V&:mgtdܮxe4"ӣ|OnRT$UمDGx6)!Ńv&ytO,lӛsڋŮ7:6mq=?W|ءJ!}::Ǔ}׬ӌAb}v63(%{:N>0QVez?Fdb.ާ}g%&?mEp'KV?k[ԋ.Q7^5mj3KAN = ZEdjID3\np.ŮF"ULpZ.Zz`fu}} yliB&T',.,w)~zIvT*<>qb׷#_AF V>A͹>:=R {WZ33Y']OU^*aIϏ-TP0()Vy1J!YjAbІN =(*1؍1~8 r6h??*CO׍~@HZ<=ǐjnth6R?S bPy'b֕ᒅ7A/:M ,#ZuP]z~s[ND] q*4}/$ԫ )\D\ 75 FQ,ANX5fnU]<]xTNyA äؿ rXQ˭ȋ[Jh7CR"-gS\4|m$m?pSoXidh:XBjn^8.6qOHp 0|X`_Q3AUǕ vߡ%l_\Fqn]A <"Hlѭp4-_(IxtlUSQԼ6-fmCH_K tzVC:"8HGL|M,7g6s91JI꧁Cے~iK&2=1KTwȅ@c,P݂dI2|>v; )X\k95+3%os'brJ1p6sZVg!Ql}< PMv g,>D5\₨0``zw9|E7GaY՜G=iLc2X¨юX#g>4· 2p2< q&,F>W)D<3k &OVcc'^vTj Sп1y,^u\ZīfJ)F9)i/)Nx|gj>|2p&>&+lAu4P0#t.IŞ B[k iy;\G)G`|&eK F+rB>p!V/h {JAjҒ3qy/@vZZnO#?>'9Ϟ^w!)RxM=3%Ftg®([5paqꓥq$j"1QT(p&Xz::O|n[ <򴚎C=%`A =i^Ϋ?x0eno&ZAlA\zM1h9Z.q915L)6scG (qtFABW|O鰎7+ n.P#abԱFY[[}dn׺r[Ldк1zp}|R956| Ӹ,pyWE%n}grw^z}GkbpoX{jl-/T=@m\LlBFoԀ3 x(1ڸ/eZw r(]xj9 V'Y @lBvpj  mӔiAv|4T1ݜZoEk7;L+a a^Y9>K eˮd8 eoʱZm#^F*[v(O9碾#2.IG-?(ـ3*ĵVNZ1ӔI)QVVUУO{6Pb\15ҧ$%HZؾP^gc2BI~лLn |9|(E ?sMi„5xbP02+6*s/WJ74:TWd!F1DL=x(90ڗ^mƊIm-I|-DuSԎ (z{ewH nu]$3 \K6XehyHh%WeA1trr4fSg;Nv43X)&p)l&z%o?@|"U%,lK4G'3#pQY._;MA{e2nz“GClEߌa9uH:se:E D ԉ/zsuź})Er(<{qۏ9?8m:Zu9,Jݘ)=+5^HڊUj PQrRcCKsUƹ =IL﵋  -1r2%^KptMSUd3Djg]PaZzZ'sp5O'x$>(^Ck v[w^vxkr_{@4R)5$8N|h7FWB,eu$4M*))  :##㌢^^P%tK<ˇ!$$ItVf hiDc+#w4~G`%7ue-[dJT{yDq {IHVa?jb3xJ=Ķ{% zs3&KY[`h[+WcY+ 6^Ya@ D?}EU8}YT*X9 x<~`V3@GEhk ۳/~ܛ6>aKD""g.L:DDGdL/+,[dۅzzEܿ/2sd(f-H7l iyvR>I㊵VyQtpۇzR/H+Qzh_ƙt,#{/P7mUaN€akT^߅98z|,` 4h*$Tv6rt9 F'Ν)ڠyM Sav6qg FA!vʫ'Io{57?~z5(.f9ĘM$}MuG \qiC݃d^g]ؑ-M8 `vjuyvG*&(Vl+۲@A/+<\HŽ#le,Ih9Qst[}^9gQwdtc%3}ŹFv1 ! b/O+`HA/ Γk<9 BjKlSASE n}k \0n&U}K9L@͖O6@^=ÎvFI;$nr+j7=F kN6Q1wӦK[NxqO!7Q*;I]7/)]:J$g z>hU;>//a8H+,&t d^ж6>;˽,3s27ą7ktuOZ=wѻ>#c%Wږן)h ϙ+&, b$jɰ٘B@!!OoG=),7kҠw,1&&4VװSPqǪ,4O:*%PW ?_8\_ݘ|?Un:B:,h/CFC0uG8z~1QGdzl¸zŽ@j!:v7ј_95<4nOes&Cy! $7b|Ʉ:7Ӈ[ДZbnقz7*NB͙jI'piZp0"è/X[Z8%w;S-\sϞ2q's;!#xe3b,? w!+ lԬ]WRDІ L:5Y*؁CˁQÃ"cZh4 OccsF.;E7 SicQu--rFB9z6UاXQs@ rHX,tl FXp .0wͲ-I5+m\{-(?Mp㡋ad إrxo,,,zSlP=ZE&Ryg 3'Λ e'U)T敖O+xPIsY8út!b} PjHVQ.: 1?Z: ! (\r5 DZAM'~"a)'\M]M3\@ mXd'?JeJm{g([-z z5dFM-nMì0F=mwy.0I#K%`tA n8zjsrQ1yu9ʁmR-6<Վ!rH;쪣"9ڎ2XaqeZdNbx!=#}³ę0|Kq6}I1 \AvRR'^aVEZDӒq$^=Z 0  p7 `"_M.0Y)̦kaӣ[Y WBұ4#J]"BKl``cb'!u{V=g5b$A,Ew"!Mmpv_\x-ѽӀV`&"ܻh1Hh@-`\Ӱ%m `H%ˤSD&45˔Gm# (( ;f&&/aP8|M >~,#%̣]?DŽxiMfE-sl B2DT0w1AM#Y1V;߃CoCQ`m[ZK GA:3CB !ۧ9(4X ɞڲC 8!xgxx,G"th Tɭ <-M|c-f*-HB5(ܮz$*ě2Wӈpu0nOXU<)1IauJ/6\1HHhXzNnd4j u|z]# EUdU] -VxJe}R.]M1/nL7 LC|907 9]rW^W\9PK,uOJ>?)?[zfQ5+ܜS?U|AalYbCv!͹m@~*Vg`w0M N`*ED>?ICfdԣFJ )‚#ҫkBcVqp#}7i{Q%Eގ`B8AXS54%H88w ;i jCVDBbwI/[i~j,Ai$ F&TG4c жNuCd ݁hG] ͼU3xd݈n(ŧ |>B8Âjgv0+&3QahAv Z+"xށssK.Ze&IdžadDíĎXr\h$}}>k㮚jv:hxԪcceFMJf>ꐱ$Է>ؗp4Ҥ"~9BIb˰-ϞAb#{&LZNfS͸FN /(FSaDPo {QI$vN"~:y eD#ˌ4I`l#>-jgI>66l'xH;SA]xNnظY nez,ƪ`r1hV -(Y(|guʨA>9}ȻP9o&Ohc @^L}i,crj8%V#`Vc{e *DviIzK +1@(\vp.1RDZ RDprJR7ɂ'Z*`d5N Dl۟;K.}߅p9~x^#bbwѤdDaI4̜M\$UĂKƒ"a5xˮ TX) QzBx&[ L;G Q):yWM&g-'Q?W?#0^ݦ?[޼o}ӸM=Wnf[Q-cA&mC`/{[6n~>AZ$s[kyO 3mG+]]U"ҞƎ'O&ߗi.?L-F𳢎i_d=DWzKR0ɒ&D̸1ql}XR2_b=^w>4@E$(\uVrEn(&?}.ȐeI TiJ)BoH;EJ PTĐT?5N.1SATgÑg#{W>  xνӗUt'Q eI]j?!"p_4 0!8$Ft ľ(&ѿ$0](:ۼEM;>jO$[u,MվE7,ERJ8iĚb\-dhNW3\( ugF=a)K[y]VxǁC$ 쟄@۽;.b֔s G*l:$QVNu3׼- LBl'kWkm˧qhƜ.NTm=Zۣ'!W]|0ߴ✂ĭPuQjt18NlxZ zqn'&U 3{o|LAn * }L#%A>wG?01mo5N.2UJh/z(bǕ6i~7g^^yF! 0=QɌąfTXg-e(kI'J0'CAٷEp T$amY]Ԧ5A1ěc~śrx8H\vY%0kurRY4@a >YGQ~%3DcXQP"GxPॖ_ߜ(k*AOY]m.A_&7LY1e|-A3;(hHq^J\vc"2+<#=9ABJWBHR'G}\Oqxu9 ⸬Q Jxot#4IOwZH}XҸ,(a++ $ܻgӜK6 >wvP Zd3+n]ɽ^U)" :EaYpu]wzTLaG$rIbv 9`9 *X@v= jV&;KOաI}Gh_0}4 [h8@}󚙓6?OSױehOk -O=xF-<1)*䀮^鄔T3>f kx-O=Ե_w^;8sdz 9&lX4v,j1 7*+ }S;%|%[ DBSh[4dz C-Qfyz;. INy߶~;i5Cldx ȽIrt Vw%mQ0i~tA2̀:#䷗4(ǃ U -nynR0Q{;dl%7?C`7מːe <ӁL*IqApi/_(ܾm,M*ѐN z0ɡܖ|xPboe}t μQVȚHmŏc%g>t;aO =L8ڼNw^yY74& r V)KW9;8Г3lXa3dAj,Ϫڋ;~ٖ[b/J"=%Dz&毑̀%Mޚ갲֫bF! RZ/ LFrthѾ1JKc#PfmsJ>rYwcV_HE{g;g5p~ڔ9ZWP܍P05;`9Vxtr3>$n}9_ d.RpUWUR~2SvD_H}pJAظo GXEJL-W;AU"1aPcHLHc}%8.wmufwz! V/y8r^yÖG|hS9N`Gע&$X)g%egVJ8d?࡮Ln= ׊8+lp..RGOdccò@u2~Id̔H_4%1!ze欬gV˝+*TհIz `Tf9 <*21-= ]+C\ d&}-"'<hZڷ%w ZWmP|5ISW3i"9&X#v01s#9hxU\\#I66Qa[IJ1}w TCqC¤kHw Gk~qR8'zu%!ٰyk JI|#$_q< o92$. :~Rր{6SZ5Z@vq28qn-J]ی* _U}N08YY)I5$vg1`0"KB"yknRD5lB*JCZxxQmᩮW(h!vҜo*GZ~=$nΪ͍3/Hgr+ ڃQ.7^P{I3ߒ\5g*DZPcɠ^Gl5:KcQaC=2Lqp1˨JJ-?WɏپWRvq of'/y}F@uxO Iuv}n֠ldؕxWFkSDrD4;ٞ5vߚ3Զ1?I)R8=A(0mGy Jʈ΁!" &w uImw'px}smhgsv'( \P@b-փ<"sfb@{8+ Y{dL۩FO~}9!krKo|$e   _;x^u:[fB/Ȇ_2ѭC;~Tz28/?Dؕ: sL"*,di~*tbBF]{ɹx bw3u[G%A"Tˬ/6]cgU(Xc#BCA"u2U7̒4>QiA5 7*Z})쀐1óO+U'꣫Ȃū}P02te|an'P ܰݰ:rHԉ.tZSCӚ@qGϵ4#1:Ngrֵ<k,*I,RulE6A/~:%'3N{Cc߁AJAYm0oAe:]0qRrusI|gFJ l-(ol# 6[.@(?Z}iAVOD-(O|^}IėtAC@NX&֢PH΅ҜpMb e̥ P)!GK9H/~SZbgO+x3 !M "OzQ׏ xmPԨ#/e3=dVzt92I ?oh3$YOjG :-i$UWj`~RC'E/"gD7|<-4Pilv%Z7+B&CJ'~% ^'&C4n'#~VCpMs 6rx[z^ pʮ1`I:o2Q묝\ O ZZti?24?1̭S#o ?P 3#7^Ga3 ˒iɗKĚ.(4P\pw"5{j| +2oL ƀD.ta a™W ^ӎwbB?TbTTOBR~ށ$Ԟֈ}tj퐯}?gݹ1&0?ڏ1RFy@-_4 !tM4Vuh;f}څ+hF+ -mVZl3 <'>+՛| bd//mOd~ p9."A N[&uv;@|f']G]DQiXM2*⾢6MG <=,0q>>渘__҈Aa2lYDkY!xQFW5?rT{H]/=ʃIF}%0m&ew i-.gxDM(ƍ 1uߘfbSRWd O=4jQ24YbABpM+9LvD+|1Opкk4^ኅ;Bj2ypPn F]mʑR!ŔbsWYXG#8pZ {ih}W]6hASя> B~| ]GtRev&}67\)n@>yF8.\W(%n +'%($zɛ{e٣mnک fH\< G"_դ̯a"Xu(mD#5?V4pw8 JW7-͎cx#=#=bEc ў W|n5[ yL㺑لlsQ ڥ-+Rg2i#L%hcME=2i{\us2DŽ#e‰K6&N nLl]$.HM/pmhtQ6⮔hv&SW9=1Lڞj\lB '`GP#uzX_:#a]LNg>wS[^ߕqS+z1j\-< cCs51QP# wB'~;xfL[Ct)䩐}(YS:t+fTF*+XXVɨLP˧υpY5B`* :R<|ҦNeIvCao'79ʦWM,V2w;*19 dx@E,dh,HyՑ\vS`:,-ӽioY6fQ ROFM@AFR6lӠC  dSMbneA{{G;K)|azhZ8KϏ_AR9VMը3{y\*!:*pL*4/ 8KWnKڻĕtSjqvuA>q6 1$ $\\B `yGngVWrp+r1=,;4P|Յ,ˮPdJ褠Оe/B,Q]ꦮ} \:fMuWj8/E]&![9 .#4̓F KqU-a޹.F=$OTqܞc)2rv@E Xh8 xcm0|9٦ n-xoA_Rn]& ͦ,>N]H1A>R=koțƊ~' (]TcN*_^eJNڻ7)3򀵈CP fux ƣ**޼189֌b{/ka*Pٱ9DRFO{Mt,2> "oBe,48$y5eм As;m;=t魇29Cf7lq2_qUc8[.eL!;|[HIBEdz6dlk~|Ɠ4͎=PL_*/$+/{$ix7A:[H `@OPU\fGQ\?$+e, JKEk^M7Ytп]t}cD/ WQ|xb!!]p<4 Rx ?^?D~\GNpkKHf57aEu -<[;\=hA9MucK*䝛o&ÛͪeÊCdeGd'ٿ}@F1hOp7da$)R\xzЙVLuPT!Ԯrk:}vjUZڞJ=ud]xIQܼՏٯc\Y53R@x=1FFq씺4'h5쟖^Go(hF}sM9p6VUJ5_jS}*/h(β_ޠmc+dI+vC O2 IciYqm_CjQ0s_](%Hܳ^t&P:m+04V'R+4mZgb@܈6ψt+jftI~3XB#5lM܈ۅAD+}~>/BT.Ab;Gu@{I7-r]=N_AZZ"ZBiv ʃ .#. Tu7e}eiWM&TWz 뇮n*^ݤ{fJwҋ"dn-[_W$4%}9)}+ޑYyZtL3ᅻS/ `EOxߚ*Xic;!`T݂y. `Z,QvJˆ)UH giuzC`0RŔ<™W u۪ik'0zz.\nzhDߣ_uʿEl6.`PGSB2PRʑz>I2p1,{`+LEa'k( Q^Edcm=n撑XD}uۜcX̵U!p u^SQIV_Xj픎b mr,A_VIX@~u*ݩab hNި˅Q۔䴖sdsRkڞ݇Tb]x;6]yQٴ\t $&G?vUigUR(^G&֜ T ]GB!AE6Fi)*3VvA=z~BOvAi`M:4TC /pI ,~d!L\n9[;+s)~@-dcwгtr]kh5QX/!%, Y(cm'&r^VYi3L7fHsh2AZ DA)9 MktQ6$c2\NDML2ґs1D/(7`nǷ $?Uecml$0 W@`g(*Mr&p l_WI*xyNX@7,ݟ"mXS)HƱͣ0<cuɔД4wWl&?ǩ˸ml*5;Μ2e'ođG,Gw{VOm#2зk +~5Y($ ]kq83so8_*fӊq*A>t- UJ GM"9dѝPЀ0'_)ɂsFi0P 9!ro(]eceM3ˈ5}nNU4òCG[xM-(b9;+դNj&v61MEڽ(ŧ/(x;VܛeLvj+1[xJ޺}/L|vkKCU}_O/'+ɓO  CVU|N"T.0,!D@ϨW8""۰Սzi c`sϤHby.jU3吿|'q3 fI)d=/%0O;ۨylIS -(svz\ wVQގ/R+u$LI2n$,bJ-KӾV/,FC]u_z*2& ʉ.9R~ȫUύ%Ԝ|(aa^sxzthˉt,bqTVj+Pq,x^@#FCJgTc$$BuX,2Ax/_ZWpEi?Oi 㪂FSR/qi)ˁL9mpd$ ʚ;YwnT5]-Tcp PvYN)kHoυ7ֺ$# Ps'F/QZA>vd΁) nU3QŜ~,#/O,4TxXcd7` 4dușKsLG=ۮm~|ވ~tJ|)t= ,3rlu {w x#g f냗vx F~znm!*Y8QVW .n8OrLkp=. (CNulckGz6Q9:UHV&̷1@a}*1l{xYJ^eZ+ITKM>27ms+g:@Cz~\pC F'  fϜG/5LP wŗMA=B$N!N!% +Pc=~% ӓJG̲h8WRK,Q+cXpgPWMc0 @5Ï/6MDX?, Ek|+MH }+\ DK|P@=_HS U<22[:zןg:&r{7集ngj?QbąZx$|\.oZ$6EZ-ȧ]P[$n4,d}4 wLѼIh Sp0QnEȃ^s~o6P@0Z0$M4M +,H"I]Vy <(^%vM X5%EzhtzPN/1&$)JKɳ3KH%/A3%ݵ1azL',#s`cp'T҈.{gUٷR6dd {g,X.) J[vTZcni%&v<*m׎Ya(>tf+yΜz8i@p 6^vwbőȞ z"yig0?{9@lA"/q87.)p߈ d(ՠ |ĵ希Hjd:CvGa*"$DW*V8(>MdjŠLUzJ>boÁZ9kD`-dɎL8 5SfG r 1픔 eg[: Rpe9DL3u24Y, ޽ ~Oyp]&|B#{* O>zU% hpk{ =0Zy~*ѱߘ论WcδAWZHx^|1x0-P ^OMg^y7*JlfRH4NZȴZ)2U0Ċ SbK!҂8=%oRRfշ}!^m#}%oY-WB: xCvYnil :6h(PN& 0:y-PņlpKcefE4\ZC, L`ܓF/荽%ʙn w|̟I gܛF}MM1mC̩j /DzU & Vl轺pDfvN6 fEeJ]:UWBe{wnu6X\deZpopOQ MB_gvCQ{O:-:2<`s/T_&o87 n8k4ZMS掭 $ YۣKxpa} g\#BVYK^e/ǘ(,{,&jL/6tL-ۚ*R5 #K.R;ugUj,lcaZLDb(5O! Y}uC|p >U~tѲK(  w l3vo1aYW8sՙO.]3&B#P!ŢߩpD>?'DcL@lzΝq/v+6D@\%=aۑ)Bӹ5o˟mASka#{HB"G6X/Az=u:m" pk=G3'ϳo[<]`Ka%!!"H 4Q5T2ud75@mފA>6j8jEm]J)+pXw7ϱ%M-QLFlq},[R+*d&`Hf EuRZ< 8}Vt}lN)YCpԊdMj<I-v%Č?V>t"LjcݸOgeHIR<(ri2 FHHkeV$).\^ 6Uʔ( /;h},NlWScH$\_wFDžǎ( or+YnR*[v[a#v5SզB%VN9^T})~I{C~-2<"56w&q8ÑI(SxpC|xθ/ \8: /Kk &ߧ'dҒN/gĩ(r:!r O֡BE ^f9o&'ʓVuo>؜ A;UL=Q ,+0mDG>9tP6\J o-jpp@,ҍ*sk}åduuUhsy=?VܥLE8ݠeB| w-gslP}"`^Ъ]'ʸJ5^B*4PmAju7$WX=)x$OIuї_z[詖֧\z&3oe&- 6 e]=ߎRy͋Z\.wXv OG1H?˙9?_- ?A s~i1w0B8ƣeˍvD>}/X.H^m+kػz2­) GpX06w). Mګ9[id1`)u<-;z YaT.ה 8>d;H9]Q,EﲕPPHhz^sf5|?\ų 9R/w(h&b/uO[a E &o)bXR6_ d7(o6vk#ޓ&e96m&=2>p'F;)xnȑ\-Q]۔Rk):4E:ۆ<(ݴ|\jMED?J9r~ 31R}$^.9 qQi:YR*rbI]52S]b[w&pM!HCS+Yk+nf~VYJ;b7 PFsQY%%vBwݿG~=|%,pCtko']1ap{vB*ڙCcCmD$=j!T'|ƿѹU71B0Pv'q"]x HLMv>-c3K,U&8\(y-Mb-ތ1:kL!;!NqtudosQ/tr12RCU@4{x%vAe&Vd[O Qo,"L' uGWZx sr?]Q=K'SF3,b uCxlD8Xt;N"d޳xgx|q:ǩ$It0ݱJK8ԟ֦tfwD ]m;ڗwtV]\v@xWbAvb)] -tF4qӜw.ȆxUHb]?-V+AnUOnLs~Pٳ"NW`p{1?SYۯtt1մ@H-D^D6&::GûM$A{NnJZ9;Ѐ}"H6Ǚ#R-COzc&JDb9'vp_BzEH3&J>6dG|C-L =GjkT7NV$@[!Єl u>L€#zsnx8 :7׳tTGᾇa/ocI^NiS<-~iQ@b'ro͌4°D(:a\p #0[fxݟԃN%kM]vӦ! 6 V--P6U->h;>;DN!;4k"Ⓞȁz"bb_N[r*W+g\] azZ9+'(pB`ٯCr DƱrb+.fII u/rld a3BT<~4<3 rB*,bB;We8vυA%aoQ$lt1FŊ\-C]8(<'[@Rf術5u/w .5iHޜCtJdb`́.87fqaV1˥B|sJm,e&j{Tޜ+?F 1g_ 9*rR}gin rr|c.?@)Q>{LJLpɚ1b*IpO )t?ޕ@ͧ:3uֻ6Tq~56"sE. xo@Jޠ* J]k0>pCW%4e'=TULYKԽt[u6uoѪҍT1`!We&]I@lRZ_ wnx@R<=|H⽴$Ƹ;5ˊJX{5r,]2(N#BHCb9=zNSڂo@뽇s5);|N[2yIyw.LicMYڠDhCR)@9QFU@ҿos eVXE`q\Կ$D|-uWK:.8J >w=!&J|"w `&2l5AmMKY|zgmw {s hqHEv1=ߜ"M8rҮ{uq߾`<09BO<)*Nj𔜙o@Dc*pEQϊAsRޝsE 7Trr0xUTfXV,~* Y|QXOh]Vl =HwOf`Y8s!=nkN{Kr}hا W907iٝ\ [eH+h(ZpBυg2g:VTL䴧E&c$* Ū6/"C3c1*N `i?=%'0XzǟfD2\’[Dž_Rʁzd>3Y֫le-p(*ŋ>SEk8SPAfnhd)"9=iy ^܈-Y2"q.i+TnYWXq>5B燆q2~}'[ڢ@ck@r]G4z¢]%[!V|l _=.QY}`N_pLȞ8ח"DY;J)(:Pnh+6X+{wmPl$C3RYFij:o09-z+) !z%g) u-Cdb#^3S4~AFDˮ6yŶp R|p*VV|:睷h۔?/fMl6|L}#D<$>܏!45-DyeT+[ܨzKflOf vI??Ț5'$f>Rð!sY`%Z<7!|Y? ]=|I׋am n=MvUհt|twJ鶖$8+>0Ք(4~" auw[f|PUw8">Cw\rqkk;xpZȷ7O)&ż @A(X%+}:+RUE&ȖB4§h=zk9d!~q-EUd}34Y;rY kͺZ}.twGjA`n3Yo/vj3 |Bw pB_)Tֺ9th(ws4e|'[{r쎺kb6(_ru`p R}ؓv[z wܳGgo*4$̍w]y O?@ sxGV;yO`E:XOgt/8f5͞X`mo{5A1W '^n *^^U cFi%{,OSUՅ|ewZ3WV ( N y%k.,yRjzWj(:N~#&RN;`r{ƚ@~e5Z^zc~yUw 6g,mk8&7Gn \W8 )Q^pߏI~60ݶc9ŁxKTTqrt Oq ڜC;cRB6Uoٽ ?ʧ>Ly4N #k785lڲS?_Yq8"+Vi|}o KJj^-)vaJ+ԧYxN3C0Ke"vI,ɑԱ $lҼA /S] bwXHCy$}Epsk6 ViXxQ#v*PE"ɺ 1EL,ؿͲ_Q|V" \_)mS9/!;ίi7[2ѲvVNog=e+ 7PZ얧=lɶ9<>,"yi\^b.KcJ*u-seaGTְzn۠QkU3]/]9ɵ_ݥ|zGyb|/i3CqV}Lgk(a"u\,#:E}/ e}-Kd^} ҪS]r%Uf}TXRrbf2:w>]hn+J0a5 5±Q5Yئ%=b 15 g5h0Biٰ<7ϸ)KnVu+B[JĻ/N|y,_{ZGu\ZI؇bp]SHoui TT#7mP‘S> E]TH+减:#%}ՆtCvNF`e^ؚݡBedzL/2/Qi0}cMa6~ !1|^-yR!ě>Xj{@+wAԍl8;">P-*C|f7sWF~h#;31 Ǫjy?@"o*61֍DS yԾ ׍@/Ea@*XJMQPgPi JkK~%6ZW l'@)%M [yļ[O)k-֍L(an?4w4:BO5$awU-}Ixq꜏uqf,c4'>r$g{\)"`xESXq4O>z~s0 -ܰoVBع P"vvM?]%q 6 ,d "aFƒ;RBNH1ڟixSf,&bQmޥ \ ɷ{$.ZHAaﶞ:j tkQƫQFc-;BjEFژL\ut=xvmXgYcHw=!ߚ@xk%EJc<_ JR8pZTW675O]o<ɱ Jzހ!44z Vݺ-ъ":IgZ,4]䙥r85GvbEh4Ma$AL&,>  _\~ ' <**7uk`~x-o[9 .m[0wH˄H5ԟ \€H:r oon o,JLWbؐoc"V/ LA PPUFkviCI}A5Ƿ|.T.u!3JMپ!ݧ]f-nivJ`(!Mi 5gQi9Ϩ"%$ EPe$eRkE)E)=:HH? Vc$\$rTAIJbz^ԐyX՜Ŧ%SG?ClTֳ*,r޷6b~n܇T)#Z#6 :\| J.>77av\[beq8v797>f.Tm.&٢JݰԖBʻADUzkPs7y,~j.o؎Ɏb"l˔}'F|شԐҤvCNaqDo-ݗ)xII%ԔyV Pn$ir{[T3($z&mθ_ mJ6^sУ&E76$Ĭp+\ʣK9%gw`,.l=+?Sľ iP3kE[&Nw+O: {ڟn!luAe*&F&1B{Pӱ."k~?ЁXbwphxsHу 3r8Ė+T2xɣ $ *,g94uDŽ0nG)zVW~n|By%8!'Ook1>W0jrf[xy]e׼ƁfBuoXPOU+0UFHMl+7^}I 3qrlr^w:yAdh^ |RkK&(~SiXE3R%i}[abO=&FnUU9j(Tt=`K)Rd4}oKx&E6˿y @@ELWaoHtq86?9zǑACE4R/m- oϿ2Xt' meOYnBG3gׯBKo/FQMIς߼>ϜcB`6*B鐂/Vzƃ!xQ5I%ҨQ?s5kgO\0x p ^PLB0hE*&rj*fDfuN3pyh_KiZ_R'$MGw(rB%V?նlki8QϷm6WY@&i C]~[E:N|4@oU;`R%c#:vn/[ )^砡kF8^p#&mq.Èc+}{~YXv.܇!e++c!C0 GKECUۢ)­oiH%D٬uamVAu#SM|T!.w V#o.<;CRP¸m=?1ڲpגR:/f:V]IWu[[iRlSʆyę1dFJނ1'>reO Wg}Zbr]bܬiViEۢG]f{+ρ QеI3ezOcpfkI7=0'Өb# q .dBՉBTGuUa(]H1jKR@IԽmq S:3 lm #4`$6euԵ db8=ZhtSW3y+wѹ.ѭ#`*NHw/lTI<-L*h^\=!GZL]V f6d4*jyvprM%nI :Uէ; VczaʰސK+܈M3u(_Zj/\v0IΊ7d~&Z[ N_=1ܷjo{HQf1`ϤUB nvε7K{0WYQLxKBީh"tyt@T[R@bjn䞴 Y-ø%+@xf3A< gxNSJ=s 6ߒFKPpKHxBouJ^f.9Yc"۵h(s?fqއP_*nJB/nTCc'U qHA.p35ϮPCD;h saz93ʃ[F ?USpJL2 ♲K}AA[WS@OM­]"nqwnāG]4}ٗ(e cdd CT|"٘.(`?F^C̡߈q LH-DS}F3VZNt Β 2Z€/Oj?p=2N?Cw)sOl{&$gzW_rX1?Z3c'&K<=smq@4FJa?luJyĨ[lDNMe *mP0`g/yqltkxwU|hk)\mVS_4MͶoEnDֻ ѓ&q4Bp+ٔ[+0̅ BTvڲ~FY6ME*;"}]o@&g[Ja/(|Lk+4d@)(͚as~%W=8ꖪkƃ_p0&S%3zxY0gs<4Cf5gld`b3-W>L[8xYѥyQʄRƛt|}\OTӴ  kUԣ0NW p|OOa+O,][̫qer"Vꚦh豥/Dz_i3ϓm=K @°9tϳI opi;ˈ3Φv0iP?jΘ!U*+U؛6RKrX5 r"دxWh 7~ P`.)h b8@FPxTh !n޽.>d+cNo:_#ڇ̴U7$)1ϟq"!@oHpV`C)~1E=tCP a#0g*u"F=}NȀ:pJMr̋΢6~]6c 1kW1X5{$ ܼ˜ci0H  +GV~OkȺ0P-3f(E!']8@%қQ{Qb_,Y$YE`g֍w6|h[aԻfWe'L>ڼ[A_p$2XvUws}T4> #Npp; x9XeУA&ݯ}֟n.6&7{1Or͌ކ0((?oU&$E9 ߊ9g`QnG%&3A06<B"׹W`hץѡJ$ixC%@ף4&+/C5jCoebc;tccPztf2] <%jNOtֆ *‘j 0=^^[I~F|?@.hܪCgq_M46}Qi&~`G2s kؗ1E/]5wH<·]l :Mبh`u~Thmb'+Basۻu#s5/JdNidl.[@59I|<)ͧ/@Gz/"婡p=_Q4+Ɋmp)(6˚[jJ% I"Aܩ&CokC >J֡N^EAt'%Wtt=@ (:VDBg ar2G CѼ?ʡfvB4e^E>f,x Ds\M${Icn'R +?yPnAi cŨbi$GcQ<>4k 1yhJlJᖨ>9nPyZ8N`яUyB`96FdC8T0dPUPy1S7 fwNu#\VXt86$M!L~Byv.O_H8n[Saol|4L DAЋ{WTZ8@ *E&#{.OSX7x3Vِk2!3m0xz3±y%PPLgV v"OE(n#p8m.vLs^qzwѵeiDΏQa-yϽ*yx6:\[0R1"U\8DiApW:$E"N;_L/L'1\AGg~+:u5cK6]}&[?sR2">s-P[$[ %u? L s9{#^@?W]+%ڌP=ߔ{y_6 dBa[G%Jǵڨ9 c)XO((g^L>?Yޣ̅>JdY~ r#2"p(&!ZnDWl3C4Zt:a"v:Δc^𥤰LkqJ"Dka`c.Oʙv;S[+=qV{+N"I97}t! sCW*$2;Rt1О@ːI̲1' prW0mLCYULZXWJn]ޒ52ܟ 2C6Pn6]rnEĢ,J4duu} )cW{ LӷlJ'}ѢCSZ`u\AT>.*a^{V{ڄ7H+F0\yح$:Un5 T,ŊT8W/sVibV+z>iu7'춆8j247b5}AomlΧFJ? σx|^=MJ &Z'ԮiF/2><ٰG,8M]͢Nb1]v)1-˒/y|R#IT*i&/@[%EU2I?6pnk ~NX^֋>L!X[2I~RGE\j#ot8'y2\{盻ZP9)UFBiϹD~ءMm do_li%k_٫5+;5͋B[cj*R'( n$axgEy#z'gm<9|qKF(!b`r{xǸ0KP*=X5rxKߪ%[V. _Τc+ *^Zdq̥{x_T WrϑG»N!)vpT TW ]*(" rZj1MD)BC OO] e]ۢR0XQU̳/fRm%6mBˈƹw4 AW<Aͱe:(=a uik)2%|axQ(Z*5ou/ ꊑ`YڢaזN䇇"f/A d{S@ [T )쭚;w$Cigz@g&0oxEt`%Q@J(*"%"zmMWSf-'ۂR7yBAzݖ22fQo S!ol 5I\R&zTt|ʺ|ML:!f>~dـHn#hxBu \MmwX7UƼauC]$)طCM/<}m{^/vX醘 cwKfkQYJ=UWDz, rB]e/#\J ъk ('W /t71xx~K9]")fAX+XWI6D hlu |@xCQZ8ٱo^ptC<;a _9E&7k8 q8u\[ ^sQpnA8y~)⥆K& ݏW|@5Gi9G-8W}[I RJUzґi3b܈G&!t(Nvsaє$J%߯*~9+[&tlFX4M}:ׅBO1NO[p4dM/~^EΆo*@NOqg,'#ceo,cǛ?ş7ElWQ~zd8v)qVc;lh8aRMJ\]KKMʢ`xDӝ>gYK6=NM䒪k{XT*xwJAe6Č oA~Fwkޏ9ӏ//)Ř(xɳE[H7$V RgEJwz 8b] }'O"jPZJn?X'Zj{2` Q kq:MnDeaOJP.C|# ě:BYg7Hw=tޘNS+RZ.w4;O4z>aX*Y++;_A?SN3)fɈWcp#>ɀ#먩TW'r#PxZ$=رZc 3h\w~R(4l!"lrI ւ/e+@shpF$5V ќ$rw7ChFJF4"}+B=$\ àc}~'R#/4Oua\($%rdYӱLo*!}OD7mt}žM?xEk7 wކYʨz2Ag/DXX|񛠙 ~`L+q&{OJ4hNWvx+_8ʻLM {jĔ6 mW`Bhz\gBDG\9kHUyǮoH;a<~<*6ٴWzd؎ށ_vKP<| {1zo.,c\?an%vPQRghMfpe? S}iDx\lj3 S[e/aeVH,!=Ð7RX`/% gQ^h#L~u$j9jѷvi_W ,+t.gWoD_TmǠ‹ t3Ϡc dMr<Bݙ93ţweaQ;N;Xml50sD%[ژLq9mUbWV4=^R, Ζ-Zhԃl+S.X^yO+E/QE*䜱d!&["pւc@ 1r,O/w=0_\nA*ϚoXD.B_x@PƷ;Nf;4l$-}عZe=$XsKB2w7" M7\-9}/>jaE۸ۡjsJ(VuE}_PfI$ Y*e nLjO KڲE;ݴxm>^ޛT#+Ɉ L_OڳitB֣k5Bsk oe gPF QUN7#Ȓv")AɼouPwpo}ޮ,Hh@/7[)̘|[[¨4Ak )plBkf K*%x5QQ8J.$Էl6fr^ pT{H"pBl|FRRy'? J|W; cH)0+H-hyԕ;f%;qz;데k#wL^gR>%SXqG`)aC)OTbgܸ V t$:ಸ[C2 66 %-{ߔ\v@ě=Κ\}$ {0~DIl.h ?$5%FL{UYkCֵ5OL гW!RjSBF0J2(5ؓހ'=8, VT;]APK,%4¢nh%kvrkI72 ( z"O=^3q.?H4IG<hvzk0VHςơ{a9V:ۜۃD.G L(k wsRE =7 ld38 NP:3HesQơJgOX"6skUoT&c괎xQst$Av;s>Y&qwg2ip肸:)!MϕY7&>Hg&th6u78Ă)pMb ֵ'~xB!Vlz"++AG +߿qaq% kUIYhR/z)95C`Z%BXIKås7O['_ 3'6:ﭡgpwTΌ;!n[no cvxv g&"M8IߡW%#'n7bk"`(ȈSBnu֊lա 8?gh'8KUVc)2QAףZC7e?'q0M"3`-h qA /߬ݟ,B¢ܟ`,5 [GNrRύ".dСC<+, |+f#QJŔ0`]yt: K԰'i_s8H~fJc4j-@WEBhBtm^14g{'e\dM?gAN%ڨ(D[iH +fxQ)? $/峇Oc"4M65^7zC{hQ C3HGEod%_@p4YUvy(6XkM]A ҮZХ${*,A6$d$lP+\rpGxe!V4!ÕxuikYBIUcP2>߶uffRFArmhu Vhq%hw(U|~ݱhSEub2/+(5ZVXV{ ͛ 1/dGe7RkTҀ1,3 J֌Z+p3uἮwH}z!\|N\. 㺽,x la6"1(#⊓Crz|H^t .yvAt<^(NƯAb"'2q )Z 5|zg76 +hjfj%Oe!BM 7彰_(=1KDa(!E;lcf>TeH?Z)~LzR#k8Ţ\ 95D)%t%(ɢȿo~`=H#6q$j oQGOv〴Ӄ-ܹE?|DßwLlquˎsk8PLvVn$ ) CG鮸5rIp 5pU)Noį cWZu_ LdIº@/)/c42m?G߮( /rٷ"lk-]#&Cx7ߴ,pP aE)Oy:P)=v~?T'ZiԃnZ1cU~Xy):)hz:|411jē {LgxdxD͘ߙ3qBnWV PLA=c&bڽ #0\]#ETF01aO]2sܴ8KC஑,?W2G,:wb,M3 v]|6!wBU8 kg̝Nt rr7:fbf1+OZ79im }zIU+@F(B e?*N;Ax%ueFU=iP,S BEsaI9.JJ9Kir1`_ap*f(O^=WlùiAz`>Ri^<̅cQv000_*mgkA6ՀrBg[z %J谟ZK0)(yy.uQ;uqu+k\-mThJL۴)rK GgFVbwDU7_#ў"4in4-Xx}>Pͼ. K:Ss5wUpF})e9!N tBCr9$AS7ijP{tU]A(ɞ7,xck< .gEj$_mxU蔕ξK#OgQ*=oǪ;5-D@ihȺzkS/H&(B8C~j&}8K3?Td+D^MRSvb% ttC {e  -9PWz!^Uh69{.*v&ZtNK6!3m&}]eIa!HdxXBA0ְ1zXN!yT 5(nSЎ.cס.?\\ )h'+NC\ֵB(:%ᶋ K'4r}"CBeb Y3cGH͈m=4йPW@(v2<-XzTeًOS9 x^Mҏ2F IƆ-Ӆڷc81LzkMև%2a:D\1ҒLʝ^;Up7[փB&+t%>L҅[l閌pLT|#Cl<"Ԙ\"27{q8%f[i\RŇ}3J]/$b\X-pjB@"=q+>p0Aqbː+ɴ#DNJ̻~f#<4S%@S> !OP]lj=Z@o] ?j 2ØXKynp*v!y̳7ba1tlNkh(ןKT^͒8XCgxF tvT =U'x~ Ksä5[h֧H7q"tv}_"# :ؤE=G׃FLDVd۱1YҷΛt>B@be:SJ4i6ԨYxaBԢԂd WΡc=ο7ݥv!D4 s(pҲ,'9c[1̢iHXq8( #R#g߀MB`KgrwV %\fJR4*;OX#8vk{^~~!4opxyۂ+@ ӬJzkDf9 >ŭINF9^4\2(J5l8Ԟs@>YIBlq=DcZ#CԈ<뭝8u7:rKKY/@ф1HV@ֹF+jt=7wUrã\2Tf%$vN[#xyo,_F~/6h'ZJ~1D [N.=ԊYy&cOa9/'g#[񈩹kjcoot\ߍMA`u''Pd8J o}B< d<@ɮ>Z$!=տRໆ=)f 'Xj%DRPBeW|WMUZB8M"{MfZݖbO+evaD^f!HNtญq*hrnmNi,^t%U. fъtńB kGr]ʔ]{ )  8=IA{c-U=6`W5wZXKh$^ȉA+\/Va7?nN|DQΙ><2[QF"f0CFz)d3T"#=P7 %~J+)DJ>qs]Wk血m#l(5 X.fr?hz~9{C.4]N\ ] ՗ ,@ >.ޯ7c D IluU8WŒXwY =Pf10vdI$,Գ=5vnmH #T>>i괺M,ZSd.iobbrؖZ2Q8SN]h_#ϰd,j[&c*s'69Fɗ. wƷ_=0c Pq2N1kcԄPYym0mD1L/ňD52gzW% ߃&R7$@h䝖wų"Blrmr/ PY9e՘0;WxD'۠B(DȁKߢ}OrE!(%#X(vzd86N.Y!zG,b;# }&$wURd)?/zzu3c&=}ff|97w_E e^~ª! o(ufXb܎  ɟwҶC>;p@vk#AIVHt&0؀$,Eĸk{+jh$jj/u} C%}\·/" .mYTC_pݓ_/m &Zl!B;L[=\簔Fj I8 v;qc!N3O'fwHr'=+ஐe\Z-ӗ_&?@2l9 yKW5mH^ۻx 3G$\£Q

S",F~qgK e:^qԎ9-Ăk=3g5Z_BCC6*@L/ ()ZE!pw GQcr cfj к*=54Ch$QG\DSM7 xmXU*NXNYF_NX^N 04;OD38s(UTmhJL+;-pC:-^ge!oL?xذ("[; Ə뉊RҔ*;YW&Z[~H㔝 4`9"7h zHp;h:\07| ~19HBSԞED+ߒ%jh@:uD>-B'>ۄ}T.L.4%vߡP@܊?iڛRrV)f*RTLbQ1{Q:'CB!4A֗(9K8C #щ;јVS߸Fw܀)|4Dpw M-+Ijv=YZq#~^hRJ0ː)f%3S[$6j?ϯdI6*s޳&vBK싍Xuz"۠FW!F6!PQ@q7+"n-?B,d^2zt'8\]=ry`v#}8$i"b;B7lTF^~HS۟ PzRiX i\uKwj?X\h`GI-MS{t2ʕZf3\kD@lP) RzG(W GHt=+XO~jl?\ex86(E.Yhqb4a+Ju+p1xsQ0rz'>ٿ³J2R}T{Q2h l1 Pscy3a]k9ZKPt'+%Bc㰹.['$ag18pN*SinEʎ<<43j{l-OMӭQ&>yX`ܐD"]Wfn eb%1NA9HF!cp@qh=`qi^7y`(-N@ҮR_Gc|ɓyWݯ[~E:}XKΜ4b8Du{`J`ܛyN*y7W2\JQ/+Hu%UDslμ8`3{n\\'w}% 29jMP(F8}>i21ch Zj+!C^FP= h$ iGrXNԿ6t@L@IY;bmy#O(Y8zϕg}·P6{`MY-j]m5OWȜ&ye$r<|yo`u!r}z byWKaɑ/8L_AOӽVYfw<7BQ4pl:6v |7oPsNM*zm]z1A:Into#)K Wr$i} û[!!ȱ7HL1QWk(}㤳uO/4 fs).4 pJPVթBQ'tH/Ӊli)WPu:* ZΞ=ۥ1vئd}0=tNR '6BD>L+dg@?<}"9@27X G9 )P%W'fwĻiNЄ @~ s`V?""w)ӘRwգ.Jz SSxK6#"#^t&a|sh͔'%+MI^U GYKκ3!G7>B2H"zTC&O }sfvXlNAxx<0WEAc%B$Yݦ8/P]a3/LP03Uz)`)RZ, \%g-`z?_ZqG mŁkW0KpZ!{k[Lu~ p˔I t )ToKl>/: ']v\RG8_} «˃>v>z+1U gk9/9nY˯ [wǍCkXl>p£w G]<5cH4N=MqL);ݍHuAx`өs/4T|=j嚶˨~4E>i|^6F{R igf?VV. hS9q=| 2AT@?'gث~$ljA}GOWU~ݠ7l Jb:bZ"Ot7URd=zC0r!J˧BڸJa_ttr;gICe;ܚA)$-+QN^L_L|Rh:JLV(dg)\/9<‹^W.h b AJFV> 0Lc+za lQD>rtMFwx!㓶BXlۚaU;'y-P'tfh )LF0hj.Nk<^ m8ͫ0O3,@|g~C"jqvib}Idsn9(Cky|s>+򧸴͏[W$Wœ)f85h{cTI'#8[ }k㉙t0AksV4>ƞH3he`&kx tyiсL eGSAeAMi柰E+'Ç&= Ԗ;F +VR1+AA E=ģNNa ME_eΨ{B-OL9yI'0 >Wp,UIfìʥ2M 'i"LIx}+V¨]W>9VWuN'>}j!:QG@쩶Cw6F&@<_rB lI}&_~([ s4,IkT-j-Q8Mס zڻ R `Mu~!2Q'Ui0`7;T&+/*ߒ[ڮ$Fɱ~֟;@*ؙw({O?{C`#MMB )3qºu VescY.اJ5b&ߝulPHVq=D)+ʀ:o^5h]a0t%xP"D6oFuNA 5CsVJZS@U>J'4fwk_ʭȽt?aRI1ә^Bac[Dr~8=|,C0h<7&-_1-tUbi-$m=1kch?S!w!p##'zMąEap.Y\ݥl9 =/|v&Af} F&NT%SFq&ڗQwƥP<}3B:dpxMׇ$7̋1P GՁ E~V$mv3ZE.4;@-I`֜)ϬKEɇy!Qbu>ʭ]ͱ$ ˠEĜ4Mm"uDt#GXë}Ms|@ظ%||KkӪ&.c*AG 񨓷SlwEBT̛Qvc/nU OjQIzhBEVѯw}͒a&ARS2xiWKLV:&#a&T M>YVt!D)1fϯsʀK1k-meb鋇`GC]zկ:5㿄LnYvcåWߒM|@Dv;{Iq k.. 6u0mݚ-t[@ /%QRӁҮp Օ\\s`z'/^6Ɍo©I:r[MZ"={sHH!qc0'"|ɰugXu鱯=1nfT|VBqd'Dk/)qo|zCݖAT`In Q fv]qDŽvKD9DFk]'\Kgnz(թU:tXmr GK]^X+Sq; ,{&xvp)V؏_>(1 <@XNQLTjSP%RZ DL禵GG d]5j'TI_'W [^ݞ,m ̗XUIVxeݭU+a )|5/inE8(tڝj#a?Z]'Deh|+V$l;o^A? ĘЉX"g)qJ$QWV 7>m ~2jLescu; Ǭ()BX N܁bIWS"zr1kjqo}1]@^+V+3˘jĵ\E5h8;n&}Q }{iQ.f'}_yI,Dk@P%Vٕlh4B*Z珋_c_T;it((y1k\dzm$ G2 ZJDUCIe ŝ9FmH("t)6f++?rT*&eۚ{EK.[qSd"-HpāWßeY6|#w>jKPHu$JQ̌;I'Y Y@0|Ev^=>9glcD%O$,p hnԨmޤjQl=l< 3^3݄mR*5 =V>i< `fe]ᘛ-i.; Z@=2%̀P*~1-6 ڸ}?1ؐ!u.) j`y K;$S/ bG‘A|V ѽ]EwUChZ[Q_#dUKt%|^Q=Jk_l95n O/oIZ-녍b,"-)x Rd~( 6C49M0gUTĒw!mB5 R?P<.p pzrq\-]-|1Y)NMME tT@\IʗzAj^4Yb!22TI2zCm:Α Z1:EqXjS/ ܫ5)_a"d,HBU6Hbr2!+6:e:Tn+2;:`dP`p2婧:7=$Lc~-Nl]YqEMWdꔗ3ʩ6Qۚdpf-0T zɢE]xReʿ {Uͣvnr}W߰)C!h-"XfpR7@dDOkD#2Qm >ݴ"5XQ7& Sg,?gr 9gGjrm$.aТ&gk}HŞʟ ^Uz{Zk&򔲒 OX5?˺ǟR7xx,?DB9ewNFy[ss$3^ǨuZ7 kBݾ3W 7 =GFǁSky:_.+<PᱻP s Yu 8z=^CT }2ݽ]W?ln1't&5Y=Z{P:;h,޼yC1;ނtsmQCl }$QV@7I 9kFYV +͛hf`s9 fY|bPRVYaeKJC' ar t|O&;LV3uM U/ F}#'$?0!c6(`нu#|"UXAp+52)m);RqD%,ڊi#fؤ=G^)Yam*|@^^x/Oȍ!.ηX;"1pr^.㗨t3cH6}X; eHEcZVkQ멼u!6X*!kܹæJl.n%˺@Tݘ.-6;c eheAdHm jfv> U ݀j0,< K e\OY [ 6LE|N̴AS.=F=@p(4pʈ(;YL$jhff1]6H*/KlصNG,ff)-STS:-Ų„+y.N*9L[jkzY($ٓRzGgf5.kdk NGx*Yu߇)̓(K"h 3BI*#~@;_Vwxa>I 퓢ZCn3{n8VІ֠ MHSщ; ʯ''ݓ{d~n8p~|)x̕p~;Ʒ3xpO@WF0qA:>XsVZբ f7V;+"mvFO^]Me6w > ""m(7eWh} ä~#RB104+E.ɳ'E6_)@ՙMP+L P Bx~VuŸWTEYi7;/Dɉe_SNxKaJ{x:^g(8U(&t ZYûu1*U@f@t9 A˾זG+ [fO#t\>x4?B&39?QkP:X1e2,sm?lPCnwaHk\m)1Vrx u 1h84q\ > ~'jYSHAGs> #CSF'Xw/,y03\>4Կ߄Ts%Oq=`ᥡI6}*h0`>E1?h3u1r(Q:אBlkWμVb?صAdةH5#a䒟9{K t rzw2-Sr$)//2c\%k ic.s\"Fe&f ~_!x3_b0Rj} "+\|0Q1ׂBz<_ sP\*B85E,jhwz5{gD׷92NNHEɜzpNfwoAFEzࡊ`ߔ0|Z7y|/u*q{=|B~[aݭZ8ˣI$]E.[DH W ܁Uwm!9xt'''4{i zR+BЗnTLT@1̑gZКmӍ t4Z0y;fPVE|qʒ5M6[eSUрz3d-kbAQ]"}098TYaG[qEӵlpGkH}#RhƸw{ڗ+u!9f=~GZa9rlXTo^W%/¹._ŅH=-XZ "Ԫ³!Snl C0PA!xB&4 ޲!)hJg6FU f8*p-rf}Y27z-'"mJ oꄆ7R@%@x+ 7fY]^-_LP|d;bsj X?cR 8!p/EļlԖ_R8szOZZ HPIO 9Z38]eV50ۿVoY~)CâC[,e=\ 5Qy|I4XgB[3Ъ3}3ʾ3`jy}pKP+:*O?p%MķEIa+"%EMb.ؓI6oX6}[=DIR덠E@n8*/ Ư4ݟ]#$_y=ܳʚxzߥ9} 0m0ת1iu~=KPc^;~!DzU-;H5Q#7'HZ˃Ņ5EZ&-d;vaQߔ#%t^ e"ԋS4#@DԵ=?c߇1 *ʱ blpN9ty{t,(Q0C^dojq1l^d=8ᓣMl34-V­q mUX?G0|Tt =Q=< '8W% riOgW'eF4}j0)O%<5Iry`]IEb7{9R]RfpTHTWVgux2d^ nRE.=5ϺC ׵>>o s}ߊQ)*v?M(&D&CD} {/Oq+}Rl%8Q(7\ {֧*OpP@S}/^d]d€r&坁bVu쫿ی&3Z@ifSZxt[-Yz߭b/=}H}ǧkWwL[ϺHdIVt0pjmƴ٤x ;ףC ]MS@;DG!$9 nd}BCz/k?ϯT[钔pNCErai8$'[5f?W-Vv2gD ‡`_a8qᎣܻa YbV*xKKCP͞Š2C:]+ лBVt@@j@b 񻖯n-H#OYèBhf?k`oj`uaP8g>HnI`i7'i06_GԳȀ@>ӐQK}BȬ8T?_mNJ~#V,L;p `c3b>KL4pE~][YBR:©=+7PhӤAQ*lCʰ|qdd3o0HE$J1ڻGx kvI,`S-Jn2:1Lر]w4B(KȐ.m.dtfE상Go1k=@!Db?c  "-"b ROt*(J=@/rD,)?ru1&`XDiLA|`qDAD<{X[`CcV(D 鶃-z;*18ӫЩX idE0#!ɑdb#ay7CTnJ JIڈ0r{H2kW7KMlp ;`I{㠓EdFkPMLbszeJXp[nC=d,aC~tY]\ o6[gv!7ftmC9'#H!-ymWw~~jVT,Jƿ!jFxi0i²5h%{U{=qC(S3myy+7fyx"EB&9BenrR6x еoGx.,|(c ㋬cqTU|z˕w5Z8#{CvV1j?tdUW?< ɲM-ޫ O1 OWQ*w2mcE[Cetc3}N)m勢kK!ګy|7zq12AZe@ƱϪbn4-ϊc"Lkz?g'gBO̥">qď\_ijv3N幸%іaoyLD74b(#:`˯s#i !zC !?C2H%TY?w_6_jD^ʆZu;PVϑ&{*z*j5%\{(*XEoTh0 yƀ=Q᳓3m8jICΟ߆\NU l(t xuj>q JӱFNoh⃌mN9 n sQ-  Rgםp8NŻ's.,ŌY&cI1[*ӿ 6c2TO9go5b CM[4<2kdiR#<1d|#Ld'-,%n. m{{Y-. ~0VWBXk8R%Tm=X7?9N,n}[0fr7.P>|GVg Z$<zU×.gzn)`inB5ʜ Y{BMԉ͢E>U" Y:NvЙl҅!{ noJ'TB__d>2dK}bK,ǖOWsV3Xmņ l̹f]HQNz?*$Ț`=oX8bSgAʽY9—)tN gzu?wТ m2I䪚rw*V0f (lFu&V;??TRhHډ{&"Sz}*BxΝ%!QRU'WGWˆlӈ˰njԪ0S(傽66*R%0qҨ;9gBPy/Y)q}ky &`@CoPf˲c N롴(kOnV8%&qBmQU6tcT=jo !Lc(1*Vje\j" VZ ͪM$}a 2xJ[R1*3p.=8?!J-z/^d,5ehr4|p9(AR UH>iTi:Ű hYG =M[ iJk٥qN()Df`Q0DBRfp2Sb*& 0fM`BfuoٷRK!En$(AcjoȮ \$HNfEiSS !O CET* t6IKJEG_vo:dFM? 4U<=cAd66$ S3%g>/b-ܭ؛?X2_3)so%ѴE@|LVC1J,`ns/|>ֹِP^mEr:g==,)؞5鹆-h,#mgFAw=3asw6j1$ۮ k#LtaY/k̙ט$G ])]ƮqwzÐ X} jp)O^@TߞF=FB20_Obbѳ'^,a=yo"T\% ^(YD=(TXf/hU6(R߷>LlXkZ f+UȌ3+qI0L%S>):kk}xT0L}ݥdseۉ\T{ܷ_Ls" iNDݚ$ &r'R@߸7 7/*ۖUQ}ZGmz#ëOCc$2AcNjhއo3;4U5bѳ5(:Vt&MG[)h*iK๐; V[LPLF|COCAד%uVŅ_}ի5[sTlXjROyX@׭0/c^q檗xj h6|.Q|ʁG(ӺsGE儤Y\p =p޲5}*ȕ& ;R\'LRhb{%?[긶{Cy7ⲟIkT#rޗ0 ɲuu~~ ZdMbml*+͓ujdZ4ߛ)WܚFƥVsceu?'7I6Y1ώsbR!/x4@ ;~|wBuGǦxJ#]g!rǫ9 EDg+|mՉ#OU}Qd-uwb 7 k0 {1H?ZFe._X͊!՜xzT"쪻5y7O'?sYVg]Fy'([wCg!dq$ ␿bSc"{C[n\ \f+goCaoM4vWIҺGYߚ6iP.:G>cKñq˧hPL(;.ƏƣYkдVuPi^\ |-~1'wj!*l޳,M W6O!;os 0FBL,Fx]eI+N,MiT7a07׈LG7 "1p9Z&"AhHC|TH)h=>e8EY̩h4 V,Ϥ,x l h76ՊNiGc8?kAC~3t=*8rENfb Q-zZ`cs҅d,O'@#9n$XzcsnyCc/DL7BҺ[<+t4ؽcf͝(c@n f\gU B5ax,Cԓ$ ,M⫡wPHkXn1HFW'vRne)&j+9Gj*~3)Ĕ{dZuJ1eƤg _a%lՍm!+R7.h W+9LVIN;s f=D_=Od >"PLi~EJX[X2^`3L`(9Ae?J gDЙdvEv0}Y,~BPE:R Yt^BAXؚRK!eO˒u/8ig"U]K48k{뉴UP9Q=ϹEi֯e*!A,)}UL=ћ2cb&l6aߓ{XB %>'8J 'c[z`Jgo{2!+^ҏKūA#ޱ?md J,ޟ>S+rc'qI}S?b?I&GԆMnI)*5_h a`c-Fgk9g#Qt'r3FqڒfM8nD`[ii>WJb\ϟbm3MB72'.,|rGmAEv6N0S[M}:}LqP6NJemdN|YuHN"xؼ"99KSh:&7%۶誉"16k?&T𢧦L v%6>%6¾,`)by7bx{tPi~ ނUS'`ׅ My *uEԿ Sb-(!x  )żSQh%bt^s~ID][Wp2>J[,7)ihAB;ݜoF\~7/8tes>[P%lt*Q\'Ϥ.(Y uKCk`@ަ"ak:J*/"$.zmHBVd!}ȇYR8/wj ע2Gf.}'yRpį Dam9xnVd*B[k0%|(BHtI!j>jw+-9W?L%MԸ6z̹Zv.m/?V'}5;K4f< BjУ(GKi^mj8E\mZgI; l4л{P+Co3wjN؆'IWkuM: &#["cj-@_U ~l:/=^us~ Cd6LcWRa<6HȥRƘV4 e,!#֨6eac4¦uH}/L2֝k G3 g%@ :b㪰jj2Ex"&aV`Ei!֭h8L~85O"Ӳ6LHX=wjch;xk=$L6%H+{肱R}_Z١b@6oS^[:d p 0ÍI"W >9%-ze$mdh 0M B” s].X/H=^2]*m[0kg5 Ya4C/ iUOftv =sGCV~ОcC-47N:RՕj| #LiaXѝOl0av܉:cvUد}nj]#^w(UcW +ZW]q3Q ̟:$Dg\?f& ̧%6Z~b*lvaΟ` ~5NҎRKKª`pbc?6]M˗S^:[ +$wU޵w8'7]5-mjK#s8DfIg?wG*z.)da+#H[IBhB%i.tz&zgzkeNR;ջIT^D3y$w7& ZZjrPVeq@pdN.2Iڡu-z|@C~4+$6 `j 4\[{VUX!ҋY˅4ƲpMp;JF0z(0D` Qa0L0^sO8z8smǧSZsdbCZN ߡ>x,S99c >P1 ķ^| ^Sbs|_m4z4\ZUfvSE1}88*9coi$|1E[ȁ{*F=6KCd/,z i> QS_unsl!ݙ Hř<g)X}3ڵ Y8<5H|LLJp#!dfu_LUy@%<DW쉷smnZZBftՎǫ5Ii IUN'2 j"b`R{WtڧL-[r4co@d*E^.mTsYJٷʞׁXbM~QSiIVo0EfY] Wg\n;Lhweҟt>?'2Ȍ!_.~ca¶skvԤb鄆(QYZsjPD&'{7}"pE=ow\M$+E/p" Z#~,U|uY{zlA 7C{bZ dPG8 /nE~2"Dp[[šKМ չj=mmq;\*Y} K^X@/v.D?Ti2jt%R n8{Fun6s7N (2fVE ubǞt;b ]HjjD^UMqTy]]/c sl83!nJAkzW}쓒2,;͙$ұ@gEx)` ѓ-v.%ԜA ` Ѵ// T7\ P\~վX.ݮP"{QTv* :jQrʙAŵM/f*SPXey]@< *ape&.F0p>ʠf_ӛɶqFFsC ȅ{炡i2ږ[Gl8R|.,,(.tV?=0|J1-Bj19c2\1L |I.f;G$QQ%t Z!iYrax< lʔP02 񊈁0 ^3ݶЗz=s^J>{8?^L/ G=lSiыpy\q:APabʧw3<β&wJ;zHkLf[9$l2u\/GiP::0e%hM~ȳ9= Fʆ$3 z,4ZtJbӯ4躅 %!*nUq$ $Bd\zlc61hl*cf#d`|RA(꠯}T4kjƿ5R{2V$KKKƼkѰZҩhs$ͮܦ?}| " дf^\oEm|ŴsNYBNc0$ oN S&j*_#(pBzxLy[soN n8cpig38 `HE(M#0+QK?RPG/[LA)1*P{x6g!8T>MbD(DpmȲac{P*ޤeez WfM쑳9@˯Z&2cdI.9+/7W9^oTi 09 ,eUiD5O hjҕj(~+&p&G%d/^1˝8t2R\{PTR dÕ/ U|v%6rrG,  k:d\!!9F1^p67Qyz*Q9idVyx"-~ըoOf}+-z}}-vgK˱>*{V+)l'@'m`A}Y.:uz&ȃ ҷ]Gkvût\E7W'0sxpϲOQ?b,||ڬB08c~1X8w'YCr#ʯ[r "`4@د&/r)?|u6Rj R'0613r,}`dɓC\n_{m 气JV9 !"F^g%غB][﯇kł[_M±QHTZVŋ$&݋G+ ڳnY7dh~;ƲtCqwKhI-k׳)٢`q ˶ ?ɃE>(gMY)BNJ0Co1F=%+ɽN/깩ΎԪ&,NUQaG<^A:X-zE;imϿtz";%hj;ujvLywPk1o:E+k)JUCĉxqP8:1=vec: hY$#KmY_Ysjrhf"w+2T3=VDBt^}t(( qP8ӿ7nAR˯WgF*HD/4i߀_ӊzM59=Y1f F[ Е]ߕGq_:Urx%w33b#+X9[4 o|ԣp/oFj01߅Wݬ$Ժ,w ^  [(>/DBO;Tt'ptL,HgHu*Q"!ă,*TC _[E6h2J,॔?Xyu}&j蝄\diMQs}e: h:Gq*M7%2.-澁IWHEkq<ŶƋ_8|ؒS6/ 0/j0uyè̍ ƿqѰz$ {Bq/k T;|n1b#C,$ WmJ彉W3ؼƳd+'ΆC֏'⁇vQA9TCC x? y0Yuq5ɮw=SU#+%.GIz.Y%xo2)t @%94)kҮK|߄">"6 ?3skM9Tcoz3r}a&u[Rd~5o6z 0BW.Ĵyrr4m̈쨽XUO,7&`;Pku[=z7 ^@JY-LnAUOFxYqFmʲ!8 RG +!f4, Pܶ=0^  oea [s?3FIjb"_? #+ %81’{ī"*.57Z4>i/o`r^? [zA<=Z{&Ot*f,g&صCJ$Lh~.we{yMJiՏBIYRG1am-hr`ҏ Ǝ Gs3 /Zx9!p{ E-Tg-P *}Q`w9;Khqt5=ɀ3M"1QqNy{E2J>&ZU(2Z'FU٥bK~ #؋܂,`/,6jVf }ް<"],~B\ 3}Nr=M"Xorr w% s d&&FiʒY.*x^%쬛-im*8Y yLc.fjѥh!][zQ0- GHcQf ] mASWbM 87Ș \nק C\-{`U.I+ LJH' 'CR"MCv>@lk  6B% [6w&t A'I9 ?.,]7$y`EsMl"/.af-204C-[!.s L"a~u<}tjqr{WՈBݿ.S$ȁ3z8*=]ܳp^Z|鸊0y,7Tߑ{R)fE%#L=Xxm|.RzxY0-4$f/V9Opܚ`wSZWH9:.mP&<$1GYun%E$F踢^hH=-R]IB&zۥ&a Ώߕ)"+`;&kFؼm3w Y:6 (}gˢ/Qĺ"i6)jC9ey4Q) q^ uK}e߉'7rg .D-e 4#M]:n-ޭEJLRìmIy9\ 9t%d~t?=`` !l2!p7X4}[|nnb1{K2tH&ݽ* uT &ۣ^O6?|k{J6DhG)#(([c~ɱ hEWId_0 VH4Tpt,EryK7gaptZlM<.SM;;ry`Ovm3SϺڽ]8)q*RRxߙ=z9mȌ!xI% Om9g>68y-.tAnҭg7,T)x ?z f-gx_KP<ez$Qّ9rΙw[):ͪ'j>2z}8OrF9uԫW^s& (ܩf}{Hˢ"L_ֽ':Cͥu3Urȭ}vΌ@1w "1ˎߥcz@D~9 Z #K|@udosfgrV8NIGP4V)E36\td׼!̣JC߿@kzݚ o/k<$Փ<{9jmjp8qq)1SQ)Cu*% =qQ2 EZ򧓭VuȾ`E#ʙJKeV/X.Z*7(QP=ho!Ět2рXnǟv%5*(ݬ;KYL'y\&Zn= a{j?bkJ\(GM_E{VJKyVaJeU%zW13A!4FTfd?rkڪ2Z W'ڎr:* I8"fV'HwmsєǃWcN,lJ,P/m Epq*g>>*xG% lַėX)hc6_v)egrit}ORe!T݀Po^p rRH 2OYŤ82)7C䬯n࢈'С1 W.$;B,R;6KnblMXVCBS%aJnu(Ē-j StK__PQѸ a\qI7N0rNz"[rEqyEPn⭶ F}8?rnB(碯_eLqZTSŬԤcHR57'EO9U/}<ع^Pk6ؖ͂g :^h{&.RbǾ5ny?I8$#*ZAiHv7'lp^_Z7NdGQ6 k4}Ť y-dj\cK3*Uɚ!ggҐ =uq:g([Ѽw#س  ՜? i':ߏ 7PЭWBӶBoTM/-J;-^q!ǰ&?0A-:ķH強### a}4j.G'(gtjr qY\4< 4AR#겅|P+-~y4F)B-3~3AbJs1a16&V1*䶖dr>=R4C; ;0y:pIМ,YK9 pm@*֚hbk r/Rfʻ:Z4IEVU  :'{ $-T9nx9>T/s9 Wrs̢q9;-112S$ WΞq"jDUf} )GP9httP>SvԪa @`ç#Bqɔ?PBG<Ìq&1>`$-8XDl s M.3BVʛnq*隦B/JOε'$S!TY\8g_KOƓ?u|S9oIISk3bY+)(wխyI 1WU@rgbQOl2=r@IL2߾\k :'?(Q% GHSfPGzl:/gVb$ccPAl gd])%!dTU|0EF@`$D,t \FHIFŵbIPD0oF>d[KOU1k|/KS#(dٯOBTG6x%& M]da2_Pѻ"O2@-j ڈ8N+Ѥh|V "i-1d2\ BXO㵟 ]Ff4/bo!6@$b9ଜm] ^|븗~%'*'mJ<0+ۈ Ӱ7nd* ele94+>[ hjؐ}Uȱ-4.|P<r&'ݡpW1_Sb}!w_*Iۇ3|SyY23/Mp*1P^4_=Oo} ' P5=sgyVufmgWϏr$zxPkRܘ%!W041pJ} (V\,=% 曄ăBp `:"P |\50U15ZI(U8 CcS)&y u=eky #,9o5 A]ź}R}4Fie]J_HDf Ȩ;g-kM5HYxg){z'4s}8rMV ꨦI rZ;-3GWFaLphVG{5:LЅ5W]쓓oReXUzRYK1/8pfV|],ykufB r,s34w^>1Hڻ0p$ xX;`D4C^VA޵H~OµoZޱע)P9M\[kQS\McEZƼK*8CO3qTSi~%S?7ҩy_<73YE,KlsǧDSRSfjs)BϧQ{q&v"IІ3emnXvǖK7 m𚵒=yJ յ&RCR td_`a-MagHSEGf爦.~UQ’ ;VPzjY"_ge'.9y0'e.PD35n%6>ӎ҈Yy?tVĊ]\E~s~hEzt2MQ{vBM" ٴ&yo춠Wʭ1qc+nהm08eDDǘw:&(cvx|ڣ2T;"qR0% )uIڼ?ɴ_KRw靎8zcϻ A/qŶ@7O\Q&ܓ 8٤9+nt(4[IhᲳ J[NngpXtL#H]:>nr a 'e5~3€Sy$%s;s:w-h\hNejE^)w[D= >V~ըw7(?e f;Χ9=vi_%UgzgY\|f\+sQb H(LHC-P濈*#̂%}\tS 1tW24HUJa56\pVE*kuC m?#qd^$yI9o$.6;F ΖVR\u_p* 2W cPպ~`0Y~z M*Y^6"+Z>ط"ɂp˄?C$i6ۣ91D L? nN!Q&^NLo](;p夿,og u4eHtEn5\{6)-*`U慅mqSq99dzf']û·ډd[$Qְ~tgWY2zrP/ Lr9I@[ܿ/0k) q,6fO&-?2a6\JߔvFfx+l24B>I T~N2^.`;'W"MޒUyxX7qx~C 縜pXlV,M6MOADrk*B7<@ زwlh99Co*kQL՝_[i::o[D|nh_ɭx!?p'6 iDT I|GD7])tzaO`w܈O!kAGK<ǽNK! mq[jeL@f2on? EBőLK5Ds( &ɔ3I$ _aAvvދ\ryq"z\@0DGX 5G^ F21];ܚ؆DY[8Ffo-CJbۚv.х-I@7nêJ:' {IU !Okn{:aіltD#Ѱ,^ZG&I fTi&L/RŚJ.nYsv`SjkjN}U\Ehu K\ ~ ='ր1p-Xkg̖ts*30*]HhzeuŃB>;v;IO/P]]|:B'% /ggBHOXG5]En1Im^y$Z badC'@SKrOkWo$~y3ZLUlxiSw,9vNX9kevGQG٧.I;B": 7G?C[5mAF=˾$j򀥘u8\'O\wDo"s5R0? hܣ l$-DR&Qe2}g;X)$:+BK [ebpwtW>rPfpMZ k9DE3ҝ1ψG^4MZߙUUJQқD|w7Fu;Dg';u~;t 3d<OXStzT(Úɗ>[߶mV(6ɴIY:9MV9^T(#Z`2+ʵkkSҺ7׃)U4pܧfh7$7Kqo2f\ޭ &Q俗@{eIPSS'R'pHf{2&_ IWȦ{Prs=!96@76ɷZ 4Xָ}AG5eݕ36is٥ 8͗]&}_Y $s@s3L-y 2n2L* o8#0tv Quf}M|.DP9+^9iZ~&#Ej~?}{>O7ͮ@l\PɐOYwB9^p&bs{cnZKǯH+7]It س. 6rJ#8McbxNbTыC3D}R@r J&y r}ٽ}a{qR:9⩀,O [ RUS$oV鮤BOa|=7.dn+Nj\2H0)SOErU-N`'" 0̬W.M&I$H䧳io j;:J]C{+K;F 46vۑü.hhB ,F #C{qȔk37V~?]F01DZTf8ߢHgƮ#AA pP. y7Bs]`,hsc8kaNe|#ޠ=Hj$KZU=18ƱT!e,yX/gvhOT=l9y By@$#2b[ң޿*Yd-Β\/@kڸA-WGхyϵ/2-IFFAGur%|]Y}~Ҁډ'"J3Iz)A,~,&O2[덊I D4/EUNj<N+6}`տt=R-}KmqlNVrԂ4c{1vʀ6mFd r\r]D"AZJ6 $g:z W} (ShZH_ְOHC>8ɗ@XbGL>[Yym`!F6Ncmo\5JkfFFsNjOD7#d7Yb1Z|t9&щygꗷql!9+@h+s>%b+qvAZn<:yk6d+L:ܛouu ׹.υ!x)ft_?( 1hw|_xtg:ԥs> _fk&j'K4䡇83vv-N |-%õ/lH:3/%dm?- 2cs+u<%1aŽM:`o @ml` %'7P ;.U!K8tP)s+<"vc@@W11VmFlF6 H)K٤xkFb4$F)B̋bQ?ZcQ7DMB]0 EcUqM<oBr59sAdoojk: cy=Mغ>^=H&4;ҴmAl@dފ%" ;0SzyPʠr\w /v !!g(ط!nj)ƘA/|4jj(p$,93n@+Wވ ! <_{ /B wMI}6YKQj2{keu=Ɠn%Wc2W@nyUbϰ1?8WhmjibzvymR578N \X ȷBסpjLZ]Pp'[֯>Ϝ]WfbY:I-ՔLVysQ) [ It>1 @|lSyz1&QaYqv] )lKLE)Kdtl#^^v0 iӈv0>#:\T j\A/;1v,@)6&#w팛+Xg9"Ĭ$s54_IJu3W-ExIIy. >_J,i.vZ%U^A)"[Re ,ho5*[`akv;ʣ ֵ %|;ґh4xc?fc= z[$96sn&4%F=٥ē/V/(u#ʬXBs4$aO u`8=`I/qy2ã~1xRp)jwZ0>_9u}V$Ql7ߢj_0'XPUˋEv镚DuRbs!Nq ]9 ˁâjBJ}uQE|YD ߉4E1ԝ'ENs Ma\Bd6i;hG*)m."Ð:s{( Pʭs%GԊiބz1j0 1W5ema;06 )Ӓ hhw/K8E> 73tXJXwѲPruNj 4SMѤ2DDDdLG 32BZa6k]Ho"u!L,ȿ"Cֳ$] P6/ǧ }zי٪˺d\f {@m'P]*{g,\ԢeRv,뜲A9 H 9eWO6ƆV ?^1 yӼA) GL< vmPϊfK_:WvQ]X D2ޘ A2`*rxͅu-3ob2@7q>~eV6Ne:~5pQtN>>ȸ-!uހo(YbX՛s^WXJZ:y̹ "7$?' :we$mEjq8n#M 擁OΠ5(7khS6tH@8lhne-ٲ|֜ҩ3|;Bpƿ5 )BC7H ]ء1ׅH"CcENy<(NSw9lC1)Ǐ;bZ9uє!\-q65߉yTR'D1?DCk8e&kS0?rU *A [߬uft/@Gs_.ga|Qpꇰ⹅HPQ4tkuW* (6N~HSՁT=}bɕޥ@ĪՃ+4bC~#Lf{{o0F5|,v(3fm@Lgf<\^nHu?jȇ_,(Ye'Q6AÑ)Y22r~!q|G-ط)K8 +%"U 8ǵ^L֢x__ S7I=! J$sONIF^F{N3vmj5%̕kv.@D=)C2,E\aʜ0WD7-zKu2%i3@ӆ^bcY2SU5?.p)i7!@gnBko[ks2r#=meemOcVvƱcmHe bq4DK`x@U;(/Cq(x<3yw!i"W.O³byB7 )"2 H1m*Q8̴=@%u}bTi8M[4>ZIL @r`?ʴ~S=)g$%F B[K  7ɓs<,J`mjs\6I:I)J+"A |2>e4F\޹ֳ{;LC":dd;;-ӁOagacmjKThZK2`gxʨی'2"Z,EA 8.Nۺ z6M ~ݦ,1rkvYd܊rTAjIML'G0٤nӗ&X 7 fG=iE*9k%F_ψ1 (O8Y{"۟4֠~A0 cD:6rzKflŮ Şd$ȁk?C~-J@=~Q}mf7'+LKlVF+p ,m\,rR(v%f 1q1vsoB׮U*y6o,MK6qT5y& ehuzWu{[nT)r{gx~e{>|*`7lO~%mt3!XX*4_(+vo3o^)~s% H5!"L;3CAa%pߑq JR<~3YP( RqO߬[=m/li|Q=Lq'7?(*%}oufe]{@f'RHiƄtVVT=I:I@JYߤ:/1Yz԰0`*/ޞ ^V~ґo$y?,([VܿB>߀iUM\"p`9jZ8ۯ!.[ "7ϔmlY 1a/ӎY=JFq<51(Nr$mYvY+ |jotvr~H~(B]Tk3@w|(׫ؚ0k},GA Q6%Iޏ8-W\I4nVHaڞDi)mC N&NEg|r(~Am|eK}5 B,k|]~n1EJ"5}dMla+0:J\>(mz`x&V]J`PҤ{n[mmc|!;͆HG&LY*cKuVAj2-e)- CjCWft hAbVJI@ y⭬6Dʒ*#\& V7)j[OzC2-/hwr_Hlj&  肪EimqZ !]|' e"8)qSSQ:>'Mo&;X.dN2#K1cW+Bzi,_M%6j;QQ9\ $/ƱYe52+e*YhVWc_3mgWxײst%GdO-6ZL4 񺬣11=JWCKJ|ml'1(#)9e p$Y /&kX86S?TGiqq^T/" vǡ ~]c~kRV֬Y4{ryo{I} R {*ə*s| gOH šҞm061]X僨 a8ѷhZWS_%y@LF ଳa|ZQw`Ag tC[ :]ײؖCAnǖH uKaUx_wB<R&Kyz4&SŵK45 3=KfS,r^+II AИ_q<3cP h2)(? Ƚ8t/ 9Fl6duX%Kک(Yvo,VnؿKh:2[e{myDxg6r 츊2`w,=j've;/r*lCdy B[~zaz"#X6B02PoӤAU*oJϊ6@(HP"W/[id:zX-Qd^[`,7}NHUuЃ5qQa,Mʤ)2c=Q,H:ae|H[( O@,B6ęסedo\w.2=#`c~z!Q a _X@3mHN{mϵ~w5\2VN_{8u讅V$[|&e*;ƒZ][2_\}>~g 7"h}\ػ1zGPH ]My*W pD5Īb8TV>u 7I}'jԺ<l8cVB7> `HuRXMzrfa"FGtKOPM/C\֬Y3 =Z;spLU5r=^H6P€X,-CY:K@ oai8#F9agd%v'LJ tb P@(1:l? \p -DгG>@BꏅIfJU3}4Kp$/W^"yJExNj}mFUQdW`B;VJϯJ9y oJ*v6H:sVQ.j`*_/ ݴgLs{RU>7>z (q}ǔ,zo5wKGi xIm˱+#)zqSI8GcF95 ǝ*ͥs63(1| pȜwNТP9aqYL%YqZ+iTT {)y2`_F37Zo>1##vX5@ 9cO23ӵ'4Ɛ9LIUD+n4~Q@S0vZsXGi^K6dl;K%Hb~P=D1Q FEhX{d Pi9O@h ( iĹ.U~r#E,RPO#KD4݃5^PpLyIs߾ ܯPwX9:Ҵ%p2Y;21q~PkF_?J1Ӯ4!^EΔcxl.6T#U)RW*5iMN*=Iu_Mk\ *U}p;o:,T[).8 -B@zƧ갥q|o|Zsw^\ج4Y.RҠRLQǹv67&ej}ڿϜdnYY&,"#WaYJ(6&WZ૑:zFNvbdʙ?hN5 ,uЃ j-ViXHcn38(0@c}X;!֬٨0XM؛xynVS(Tb_{9H){}[F0~H2} xw1%҇v?lo&$̸<&y$'rec! f=ErR 2KM0( :i} 7뼉bΜ<lp?fX̅m?Dݎɯ&f9n~/.n)mڒ3u+}g5&apɯ6-vW)^1NRLdl+k6gȚhwTCGXPzu)Y[TL ûL ,יucggfj>  kWD*:EsLK:Z3=vv)J۷ h\Q<%~Q(T!qwf"FIC8^;O Kaϔ#\p{瘆+ە5NF1rRY '`X[OwUR|gXVS ".p/~#=z #!lmvkl|53lޠj`;As,G bQSb(Q=ҋ@:t t}]œ 9g{B~?ҳita*:Jvl @ii{߻7%OupJt6cDpVpJȓmaTj>%HMғr\]8ўXƯ2Π 0%?.8~ˉwY:W":D D*wlb> fEW/GԒZ#jӣz)T`E1mڐ%ݧ9C肂ɓSIΩdq␵>kk䅜)QTA㉗B1<:= Q=s$vsMƷ-Xhs,= l0RE Q?DkB@v`@:Nm;:jdk+Q1g΍DW6y}65ńz/]/(R8"R&"[%Ԉ730 sv/kTYDSMcw'!å6b;1JhEzyQ9ez>^Le> hISio)CRx<̉tyKQuݫ7!QtfhC\@rz"՜z~a= i Ϗ%NIȫǭ]pmzǞfpm%%|&;p=v{-)dv5|b~Q_>V\m19$_d ?d. aa#X](af7$/WDk^F$ sr7'*yA :%3}Dߋk):cxJY8] \lm> N,]&^ X4yxbaH=$\Gug2,)QL;|865&#leXN—vwҰ4MA56ZvbV4V!ޟ.d)G*}ѤEIIXYYc$krKw,¹w_Z!л-P9o4[f&u(s2gjH8UjŰb(Ђ p^ʩ,R1y Ediy_1_{67n&)Cn/ylUi qTQb~WjvzDLV/Z^&ZU-Rf[#8i`O^smqDۛJ?+x4#Nu>~x؝7rx>8OJ(􉔿T`,6$mj+)V3*hOt0{S`Q@l2"}# f5waHu|܆g+|?Ba5-Dνw{GO޻5Иa . y(לˣ]Ԋ'v];=ɒqLKX,Nc^o%c70 щv\YH%C2H 2åDcվ4;(l?c3gAj~(wzg~@Ԧd? ' ;L'ط5`}ٻRqYֹUA$[1f? sjF.<=<&p;-+tLwD,տ ;l_/^$4D#!QSgy;Jk:) '̠z!90q9 Ety̐X RGh9I` w86rFnIpS5}-I "S],N3?193~.H9yr(BvpPu5فlXkgV2V&? 1Hޱa- OTs}wjk@ݼih)O\DÏ\r4]8R $vU ;^3COvXɃx0Z9R*&w*8-x5 &5?kMꪼA-z]*3a;kLp^4_g 6T\]ejpK%j=$0C8glTL7B쥎px|hļ#iiI͞pԯߘ i4,{wBd͛-NŸE_ME;ë>MуybșgAWɴz6VeYscg35#z&XX~򴝗(d'N(>651)^I pLdh sj#{`_{W.a=?o_L 30/'YxO<¥+DcY f4T^aT4٘ */vRUanvN!? Qpoyv<4Y˕:f]R6EvW9s %jz{Eb(PǓwa{/kĿDJyN8]0* h9ܚ%E׍-c^(>Jn/C~H+a _͢d0O(!8_Fa H夢y1l6G}U$ųLΰ,a[% %a͌l6@ǜ8#b4"_C ®!kFrFMjKasx23B"WT AS|5⻐u|kCZ|A}[̜Vj coq&_A:^]49ތQșvM9Vq7xU<4:@.<jq0n7Җy]zV.zagдtp~lhXE XT(lH!y@$@T%b9BNcF@Kԧ1/fK|:t'#++VU%Ɋ,7_#KƁZ{0;S< 7tn6F.pt]m7>X4>x~@?qU#шT*So5sZ/0"^9}ITHH>H\rԎ! ̧ ǥ1O:1F'v#LB<-̥"={ i2X-:S=FiQzkrR)@>}X2&_L,im·=Co^?ģ_i=>nFI.h5+9l‡V`嶒 MLX#}0^89qىD|͈ni,l-LLE KL_4X_ 9GxZ1thDJNɄ%8S z<q>9ɣeJ}|Hkf.%zlquD8zO~-M(3Ui$T>F$fBM"ϦoCv80oQWQֱ#h`i,7L*aQwQQd4ş~Y_T7[ڮL?y/C8}y+:SU&fʁG6sCnQFQ~(}?/_b#c\G|_O.%k7!fihn-]eƭB%Ɋ;{?b$;r~50ud|B`Z(DZ\ǘIfBPl]}-BҧI7A˅Z^kp닳ģFF\!SOoW7=F% zm%&֏ǺF9Vcxcr`fHIE:u S=aƢno?mk;DT"d*Co%dgGwhi-R;R*? u.J-cL Ir44?Q4`n,ҫR=4eȻyv%HI!qDpڞcXN~̓䓁ZI%]!6USu>eH?} 焚6"B"Nvy!5L 4S0Jit0̓ Bl;;S;XskUWA^:3D{zgߦHRטU7|T?Ga!Ȁ:InSh^r2J%\ *'T3-j$ho^!k#wW/CuL, U~׆&&u?>kȅ;)1G܍R2b wOuVIЌ֒϶& pܿ*d _8`bBѕ-wdM$o+߱8Ehh!H6m?i -԰8JZm/0|9M^Bڷ{'FvWPD b+щ&P[uxu/ë"箾 dE >{SW ~=_ զ wksLL#pzqe~8A[K]rYˋY^%&JwskWggmӗ+`5m&Z=Oq% E(wjpGo겭]d{7Ҵs5LBy>/|u~pɹ`EFm"7:%P=TƵD5ą4H,aC}Mx\ޖO5(\\t#x/̲z ~EqInV+:-&'׽4ymի!Gq }+"i#NxC(ؘٗP͗g,B>an=s S?$rO$6Q]vP-Z,ɤة:'~(4Thצ;kՄzFEN%WP-c>S KAd*v92^bӜ־~ `a;{ldQI@mz~3sĈ=l32?:ka%Y'Kլͻ[ iDplEf쉓 QR;f[7U+pI?ꭏv:f"N}xL`pNQhVIZ1h˸Azqwd=; ~c':D@"_i΢|aӚ$_BgdYnƹvǐ4t<s| ksӒrrV"m,'sQː-Qv+_ \Έr:^WtjP6ڐQO.hZy(O63_D P]z(5Hxx|erIjH@G%4%7 [b<j$ kge󯉅id*}eqPyɢwi)?)x^%m,AN" Mo[R=5*^8>`K˘)x{mA[Kt [7$DJS"h[]_=Gԅ y*׭Z: 낒$ c >_ !2o]g nĻb].z֒U ovhLb堀Ԓ\AgS\+Fc|PwUV x`W!jHRrL34ډi۱ ȧK+!zo)Ֆl*6,x!t~$;}Gby_AdF͒47L\Ksp$X` ;k%QHAMT(Z)O[1>YURkڶ"j+wv%\.e$ztj,YIMŞXoΞv\6jÛ͌[anc0C)`8{^q<)o=1 n Pr҂PyJd$!~'U" GL0+^ cKQ(g pYmϣّ6jnԌY~uԝ< CN#$QvPL?i0ͷ-7>{A"꺩T:gH7}db;o(*ؠ3.Sb uAyβ.9}\۱}Ru}4$#<#|(,e>.-$q|fz*&U9?ItOm:57zaWݜEFӹ.q!=|@CV *CaV4 3줐( IkF)55^elB^lJ؅sc?i 9V7L-vq2q`HD4*& ?UŠڠ7  Ja"sF0زlzXupr'p?CQ=G=wj7!~aݞdjZ3dg׿Ŕ ]-YFUᦦX%iLW%c,biidOHCL8֫I)LDeJ+U^ąL0Γ}QMu|k1_0i:9[QVEh^FV0!>"ȳǟa6va9Ah{f[?;ՓIJ1މQ`-&B8ϫip7|zrBHn`l0λ<;{r(bE ZO'?Q`c@RSQ%Vv,K 9|F&M^?5kʺ,:!zƬ¦npzWǡ!&k Cc;hٕpEN'xۘDt5u%HEy2tY EƩh?=DspZJr;gI|1j?Ho8&d) c@lU,G5J — HȔZٵ_p7o-4  xv\zN^RLҧ2Or޹/;xb'#@X- b @!:Pp롶y^#MzYw܄XjEVx^3qD&2j"9xP[B@i l_5 3{R,׼:L ĶSr ΠTl5`,b4b3O9n/ͤ՚O!StQ%\$4x\L҅1B_"; ppE蟤.uWvN1U$G̺RLΗ;Ы,^aߪN4BG9fF?W]Y_~SQ{2B\a( /]q=Vf`.^ї l_) eem;v\d0."`:an) wf^^!'ECet)\oFNyI#2U| ZA͌iĊ}g:ņʎQi<'{904t|mq1j ;#9P,t3)I Ra_8r>W&,f:*$G`r\>3K1O pX[j$NVUQ^/Ҡo;XP[yhл );a+Qk@Hp+MW}cN}g(JCZlld/jq\[D˲P]9|M[0ŴJҴIrT.` nL:osu}s*gà 5A^qچ6|4@8PldR{FްtW+FS~PKM=@ܳv/BO>b>'ۇkj+$r/kV,wbʎb\hzNHe%!m ln@ڥH8C$0Ԥ*ކQD Gc4U"Ś.Z([O߸TA$ ~܈/ FOKd$Ąz/k1)H@'CD|ߊz~#jўV=y?)?+Zd8 =9XPS1fBո]8n ui@<"Y y?e;֫R=y*%4U^Z+}XbpZD'n['|[Zis'iՑn}MsSf4 YM^A)RРZ_^#*hzih:W@# 7XttF\$TqtXI^R]la{25_yE+.#{mj:d}$`[GDO B[*(lw^$?郥72U?nmxO7JUzjHcy`ȂK{j{PH=QNgMf5Rk\3K#] k@+jviߕ!AK*7fy४fT?U '©ߙ@ 2{Wy 5X7p춆.av `<:u&ժS$bgLz"zcbPlXL ; a>8ETٙFA;zb3;5^k1L)?P$zwY;eo lQ3=w bl,j׺>>mm^ӡ>.Y3҇Ii٢|Y.NS4T\)/I}:YGObldT^/H؇D'̻7$8 il X5L 'uя l; -d2GI,IU}|@j( [ SOz)s' K"`t7OnǦir VenT>.0Ut1%T:yZ&CJrC$Q9Is5>) e4VRn}o ` s:Kz:)G=W V'+ &L$Xe, >H)Ao (de8[ӹ-ix2_5ywu7N9I7&kH9hzz\nuN`Pe _-B%[!#'о/Cyo 7BG U0Mdd&fuע|pKdBZZSYpt۞\͛r=1[}_l4j;)Z^Uz05FXi!8BI% zՠwiC3HUPB@bƂ`ݢhԴ,?~i5Oq r`=v$|nWFREUdBpc[8>njw,WsHc.gA&rvq? oNԫ memG=VX|*m" "u-yc$Iu&`$}Z44"1*M [w,N͊2݉"24sS'o+CE ! ;@x]E,YIzCRk ]_^GR}m Ayz94 7Yg-EM\}I.dLbWt:+ϭ`ǥܳ1aLP󴸊HYA5%#=bϜ&郙%JbZvBtu#i1`k즽:-3g6Z 5\q~X@yI'!=ϡz]jLBlVnC\c@qT-rU)akSykVN l<3ctJ@)mFgQ\A!L #ݍ3,""mp 2wӆK-#lK{fGw[P=e:F=b@v㾌IMrDV9ܔnGȻ x |e7ҥJuБ;edρ;rV?{Pm%:/:%ە k"_'eCR' [ˢѡIsۮPw6v(x= if4 ˰s)26{Qeˬ} m?,ĭI?c̙{ :uJ8IY.(zHJ} Vƈh~h?֬"OPJ(PHToxKj&"YK%ҐDVh~=J^?X٭ZGQ/DshȜ$DZjy<Ř[ؗ#~b?Ii"z@Ԥ4l@c>,0 s(tzxvv*y-'ֲĊjM鳄-NJ;;]u9Ypc~>Z2!"ֶ'2QSot.4Vskhh$=mJ 4XFy,6BH0GbяƔ%nJC90aCh) #Y+MeAnE5)Vӛu|9ѻ"Xn K\C[I#[~ !9: 11qj oV߮6?qP}-RWLe/q䫒/xl23P{ٺ-h)`$Pk[Wk݃'(21e7m%]tGFE_ΑυŃu03"z}Mt;gpaԆ1hL:,AQ&ihjޭ1N75`Z숔&lrѴTo1@?IĆmL& H~6Z!zu]bf#Zu~Tv-WgT#/F pL~UCbq{Jfď|6)L)VnJRBA)>sJj'mNbqDDƺ}u9Y.KT/YA=LSVig9P';"mWyf$6߄&v!& 4DFE]ZwΕ'vj]s08a`*8Wo2EO6R,3y fF}I~chF&5#8 63!iRs+Nt% wG.=޾h`u6@)(2?39EZ^iʭqWhǕZM u*#R|~nwөunu? @(.#zY5$o/ӈ?VE #>kZ;LW_G`ٕ~yVH;#́5XL6U@Z y[W$osqqB҇e}W,1|`#q@VF.wݢ̟:l30c"a'w`T#nG˛ZR }a35&udVOC+MA.(_3U Hgۗ 1.ѭUOĭo (%"I&iCNϳ37(av/~(jw2=kd0pGza|TPZ'(suE1;j刢/ ؁HppnQ+8%Zy-HYjtNֺZPE<"tYD;~ Rr9~E$HNge^..qXp S!f8` Q)Q"SKџLd́xp[ňpe$,{[y~'ï儻ʎi>zQr%.0Ol`CKZ2s^TPS>Ԧ-B2k, -;iDZ$⨃BF)ͼt9z84mXܡ4KY&*ɂZgFc.%j2JDЁzG݊LBR͓QW %<#= E^[Ǿ >[)$7ސa{_G%F $/ *=ږ sq0GFk>RBj4ɽ{.lQ0>S=}bb$#jŸ%PG&W4,7:MJl@[iH3ZB>[J fa bv},".f8}N!x o~q}[J#3d f5XN=cd $4YY={8H ˺2"=6ybŬ^[,$`(-E܋ҾMfrnLEWˤ]jiIJY'_7P6N[+?nN^ U@[hV$s'`q:_Qxjm7eG9^Mq8KD9, K0 p9!ڐ xzHF8HGxM=$SHﭾQ(eLj(Hz? @6CC!FcفA0!Y觡܃AV<-:TV YyxyRzhևA!IW6P- Wol.荲/;MJnS*j{|b+UrLٓB?4mCq<8Ct8]C^n25$󲈲]w6:vݍ]@l ̹FJ8c^li^ӛKWN}Es3_P3EX~gy4r9ZrRjǔRN3)Cc؄~d*<\߶l$BIT?Ѽ‹I [ +t2?M?DE.>,rGI(Mb5A}n.VnWx0/o{l"q݌ 6qBrB!Qॳm>\lj3@mO>l5@fΆB$[)ކYV1l$Ar7Dڂ[ !ԅz <2v&Ve0-c1}gV{uv%7P c-v5*giCZx99\v n vQtvqo-HռWB=U(:CNG̠:moG\doYY+nV{A MVڕy_OwMPX~ɻAkTX|gwes)⊦߈]nϐ(Qj$ yA50HX\) Xg/_3+$Y_gyw_S;:9x:ˊ θJL&H/NBit Q#ICwBQ{HLe k& wh [rҘ=}9Tt$)|p?WN ;#K1Zj[LOsi_;rrdyDiB1oQzIt\-j&2e{ ^hyP EG?T!n] #O,bdc։ q6m@Щ]HVJBbP&A+;(`ڗޝ*I'IQi< VA"#r$\"L:BЂl,M>(cU1mH<6 bRbږqO3&V {g̹ﴖEJ1NҮDs) ӊ|##v~ j-z%qɫOB{?H̺0Vo0FǤMPgI6]w4=Z3f9˃R)& *H/!4 JշA@SHf?U$j 8N|-bUFv;ds2U9Ү]*4AA24>eޮN[Zv\YRxbQgmdq(x=WSJц@؀ vuB}j[caާ}R)WmRђkLthnMִF%t$&C3(#i?=.BF };?ݫMsGTj[U36h4Jm{p͜K{,*mfV y;],A ? /?IId7}y.U׉axV+h7?AJ. %z4 Ѝ(M/r/H8J˻R]vTN!KfepMxҫaƊrL*dZrsoM U%^㖺x7o,OQ1TZJ@+^Ś=x$1ڍA-ưOޮ+j }wwLuOk{slQ۵DTWBk*]s$~yG]?W(r KJGPKh\fm}lOBVIm/azdj/e0n^Gj$=?#[r|S|dž?]\S V8j|ܚ%'8nLQ8G zl9@Oo90 ﱬx 쾥@eA~w[awA2cs#F<$C5n9A]@^N:}⅟1Tj޲xNs%|7;@7!ftPG-'Ԧo)&TjI\ۘɧ9kįuI8Sܟ>FyTUΐCv>8ԁb~m0Vl&2%1鮾O@2nv U=|މ^h a$|ܥXd㎊zCRO R3'}\ oZaJ"N|z\UkUP/v%7YCI&gvJe?=~VUҚ&ڕ]z2ҽY괣Ro}\7 p5VKf5a8"h1sC'uFE}..!ᯕч:6D; ֊;ʟo5v"Mt2}bՒ_1چ=DIHK"I&_m/AF ['0n M⡖u%|hIe+8|_aq6\HYXMgK:F݆u5M-cZwD7b_141yGᓈ~gտ~+Gszj*]~Fg)1 Mp@WɾPwC5,F|5X~.Ks ˉz &GJ;ލOp!BA* ;hڔy3G7S785} sBfekEˣإLǠnXB@vRwunzՌh~5}L\*}^[Քr}Fs)ɪ5RpkmuW>dHF]:X s n @h+D1D>GUu*Pg ?r&Z:̯[aP-.B;ԞhE]JV$|m@rε$)GgA]?[_e‚JHX?qحWcʆuz{S]RA^I]8&ti{jH $e'8dImʊɩ ݪ5HuCZH>>? xG?)6/_3[۷VA4+ZODz  +E'~xgeWeN;8|5nAPHFγ,c/8]8M!, xEIz2W5o"j<ɰܤ{U~P Q֏SNv-g9S~v(`+V:s+KKa }*[U\]UT [I ?9YTg  2ǭ;;f2N(U2<_9]ŸV3MxK5j{C-^l@LnQAPpn= l}j|(cޚpNSyxa Le:^!XjZ fEV2P)g E7J/2ӆ.kca8V~J hm`|bUdքS`Hj0}vхx>$Ss V@)&h KʦpJ'x{ZjmOSZP#9aIpr?XMF0M >m'FoxCx͛-0~^辣Lf5G\ 2z# ®?)|iSY*Xu.,qX~3dfdD۪5eC G0/"RԪъ-TP7h`ՔdR̤JeЧk=i]IIKQ3 {EI~W k:##-8iHڿ 1?_b~qT.?14G\c$413Yȹ#Z|ԧ: 8'*&sP2pq-0,wo -Aɿ8,tx7i4DMk`z\&Ύ*Ȉ'xϣj'r>cx.6z؟\8!3"y*T߱Z M>)=)zb㑘j,uzoO _79Q~s )f1;e}cLCP: "70/ywZU?8jjc~V:VG9L(Կ5oTs(UB~,GH.^PDt)8$dcS*q"̱8mr;Q2%4x}<{rq2}_O}jkƠ<A<#AO{ډ@~PzFuq"6]FZOu vQ1%x#)/{I1\;XJfM兝ēCVL\E[3x.tivUkIkgd'Yqu=A"7^Neoӈ>qWv߃h_WF}uxU/  ǟb@bu9Qd^a%-ʼu^AYW ^|'b4!KXbLfU})|tkYw4zʃru0iY}Ԑuc1f["H/eA۟ o/.W)JWhv3E7bFm-P>>9J^otnRXTU J(v}8dQa$-DFRU6ˬpuAEmru!\Ų  !XD>^ a1 fd*khF;x_H컯9<J3VKÑSIB8z 3~1 iZ!p9reI^K+f>-O#Y6;V50#*U+v |>:zWP_Vt|駅_*5;)R6`BVԟ.'ʈc|22K[/Rk;±1Yٍ~i@DZ!_<7۬2f̴^)C#sq{qs0aE:=F* jYԇ*ÜTm~gp4 @e sa CCDg:k4W-'rh[ L,w8nJC+'؊/ PyM\|AD/C0ArSoH8 <: IR64zMeo鋿Gk19O_y¯3/:ME oEd->'ðYy? vt!b1tG@ Z+hޑ_m)UiņL&`@|Le3r0wa@nXnoהO==;߿0Rz$ONʊ&Ⱥ#GApհx"Ȳ78OGsi0;vǥC6|$nWlW',0юn/qܭ!g,[~u74OϏN*k?!܌J0.)۝9M;cqQLj0NKYCaD*ׄ94b1e᷆P)'CplGFJPK1:2l5-f~c~c]*\3ruO+`\[ dW~}1&?kxq {͂`(`GH#{.`*(T >~5UfX *zQob1C0b8 ,Tygc[t071!C[M(kAJw-S@Qr5,ggpDZAa<I}j_3M'dvD^D [ O2#oq׹1'>?p;zv9ϳk 04m}>ҚsZ䘕5DV2bc"֕z[ @OR&TSfE%(|E>{mkn'^o3mM ~Q[-_R1|)TVy^WB*DH`G.%M4LEmjsT@, GZ?[qO~@#y'1F tSE}YUab#"16VTRqNzA$35.q}&כPn> +! AԽWea'qw1bѡewDJ2_&Fkaf#,[5&.PtH&R {B8ke?)fZ'FL VYcp"VodH QK3ek=CdL5ᶛLþ"l<3y|YDY9_ Zmx 2J(>Vo  ڰ! +ѷ'0K f J5̦R3XYΪ=- GSzZZ{m(WL~w '*w62v;ԣ) b\,k*Nqx$'UPvfJ^J.{^>"e$Pb+Pݫ 8a;|*\#`?'m^gq8f%K-Q]b?CjX^RJL;h(@a}*(bw( -uIG;h4%&4W'v:|j@"L~һ:r_glYy0jc(o2};q">;^s¹.["l?5=xͱ[}bӪ'zb|+|JbX+]XWj||.._ƿT#u&i> B0s\to6&XRUq2)aH0 2S݇f(w i'HG>c9ns;F e| +x1uCX$ ts|^Qs}u@pxFHSZ` VOZ1Ŷ TVp)>P~kf1`M-a|U( d-*S詖l>7|7K׿<$ѡtb "6 s1}){+Oԍ@M?`OSO{plSZ:ď)䬬ڢnHt;S῟BH^ r|=y`+m_略T2_7<)S/= @Nw⭼Ց/!cX0|~",7o,L9 a(!u+r8xL:.b{yRy0kw]߾[l7hFp]KF+V(Px\k,g,銞"^Mu& "Kq7׫_լpl\-L?w/ qROJ.3`T}a8Q?) 1v@Gl$ luueOW"ԔkѶ҅dBd?Dˑ<Ľ˓c:y80SunemFޮZ.`)27:L¥֎jCpz.Ե<.B?[Mks~,+p D¤L D$9ۆ管][P"mwd^"?sD|sBrX?Pw,Q7rb.K@(}ѾP]چE14}RζͤZphiCq[ s֝W- l_gNt$vWi`k栲my3)PBjܓ&k˵ A2GY7qz 9;6 WprpGiYA+c(w)A>}kSchx'pi/P\? +F.iyGX80hyd@YB3>]`Ӭ5KZap^ NGh'MSv@Dw:4|x"i{A6Zk'M%BMeCz#6G]T1| ' n#=i^dn>#Nk++P5ߊQP{R/Gd>Oߛ8^S[vTޢVZ(PCZ,s::ANjq5@jdZ$1; m^~v0ԔL Rkh@%Y|f-]{+&vuGtoG%o gw@NjYU0ȇ&o6~PW/n7KJp&Pܰ&nNx4 ca2yq2IY&~dPI-HVg^`>1*/4%?R0.txkQh3 9 GiY~Fs0"%Sa}i Ol- FV*&pAj|)g6ƶ7lOt2BOfo7a")"s7R22$ӭ۞+y,RQ>$k}%/4Ͽp#6DcsJPC4(o J>.Ts]!!aMg)yMZ0ZQZGɹ4}OUȊ*q3ߨ:_YCҧʼn==2g4]')"E#x{um<(2uM8rO5aej!'yꈉwׇS;7~H_T=Vv㒞] `!Υw8^3{ha Dch~Mfk3hwU6ӂ}F[Bb,}t}P;loIpjQrLE^Sw'PX 9͑YH6RJ RCiZՌ*FAjCz yNi׉+6<6}.u^q;!;6 qAUp*ꠓ ><ڷ<[Ìjи:SsAݙ}&G4ko__>t/{⋼8#B WOt> " (li}T8d)2.Tw\>g=UK:0"ϿZkIGEZo:n" n|=Ҳ{1u!TOPa夶Cb`EBi2 C5u V<8qR *h 8oR A}o Im8GO4Q &'V `y pQ$ [9L1@#2 e}7fE~-eEq=.|QRԗ[գB'fq .,VO*4kwI}ʚ#R!u1o-Uuɣӱ峬`K%^c!xԈ,tvKхZo|P1s,xU!u*oh`т 3:֝ɳ5cL ڥT_:$SW <a(E45LҌ(g8;6`ON )gw*z0K:fPCQlȠ48[V:8;߄ o hЂVXSDkMK'~yaP D֚.`4˨PKBSl2mV3U-+#c’+N,[u?$ꐸVө{lg_ە^mebkPO $|h̏0kv%Ld1q9o0s8C],p! Oc*>KVǨҽk6-ܕ)>SO+d~LH簞1]b;*dVIIӫ^xI׻@L {Si4gXŜ@Z!vZ!# 9Ʀ:v{n&ouYh!;$7ǎqx@i)`.tdں m˾Wgmߘ @|Xh=Hg;t^!cX ͱyL N0U/֨Q!#bHqKm//:8ȅ-OVtoP膘6"{ܹ lTGD]#ZNcL9?ܔUbCG#SayJ@, Y=[`mW͔` yFw)uӉkq*m$`yi7Xp/6eL߉{p0n|.U7oqoqTycWLbX[Uyw2[DĬ@e/8 :1IC?1 1]F}uXFV\?!)<>!UTD;QY(a?U3x3{\h+:ʪǷ_? 5+D+Ѝ;{L -˳/5u5Qujir +A?_O;7ն*dR•_~Ya}Cg 9>#"zjl*)}BL<1w Wi #2%mW.cQb>2~p?`}vG> ";??B=sͭ7!`Tah4 G+>7{cm' YE}=#c']wZe^4Bnۢrr~9ޒ6T{J3(>K|BiT R35o-xPnR{$pgO30!ߣ{n/U6`}̯$n++o1˲np)AӞAkTēܳvFJ6%hni cGUQKPz]]m]^:|pxr&w|IəwIs+abDX4P4 Pomn YԸnK#_ >5"{ek_m70yi~r5_L+گ !&2H)pKNZy,f)b|>,$g儨\Z2rGR:Dg"H{J1pƽ׏~ѡ hVI˪p9{\[ERߧ+\|d#Dޮp+YB] zrωO`֡*A:]EK/a'.2q8aTAjo?w p Td6nXf~SfQ>°L-[lz8bڅzuT=G_xJӋONĤeKv(fT{R~s{Gv?&9Ʒ|p0us2_ǫSM/p|D$IGS{u 4jn72/oh(>gWTLy& (e_6r:YMaqX mY k4"CfR_*ĹG~XU.K`A¡ۗXz ^B\G8}JyISWВ9B6"eZg "b (DۛAQV_Oe9 {ᘾi PNw^ho/?4EELhX3; VY721LJ,(7%Oo;R !YT漅_Q[ =gO]\DVP]Ah}?#?xdX6+d:Q!r4Dl}t/Sx?OCXrUr#C,W=]4V!(ȭ_n!ED?g$I5-$&;*io)@!Fo"tr`3CoM%?#B̂TǍKԑ l(N <̚fo=HK5bFˊZc{41|RC<öqz靃=2-0 n|%(Twғ$y!et |@|d6YNN n9sZW)a5̳K9Y!x7"K+wb.DzȮ+WN.SWǶ Pal9&Ǻ~cq(~| )k6B-O"з-!]»  x [a>/Sx)oGEhHbp`{FAMQ)M\3@U->- *M[ .ytfFҹ"H\|Jw#GѓM>~B 0Q%[FbxܑiØ:|!F'yK2Cw74m_{qT|gXE:폼{}B7EhQb)U@c0RYGUUk]Y1xysS؃MΓ3" g`Lf]6c(e$1{l d~)-?ĩK-.qW\NO w '6I/o+]a=?#Cx: wƶϝi8v%8<$48N NUYGQo +q?tC3z%ۀ `""itF<S-t(tG G%ࣶ"ɯ L!Sw:DՅ_jp"tE bH5;2z3/;9}Q7Q qxlSNekY -ү/\"+qd<}T [֘?{ !_| N4A]tí$3M/mY\ϝS2Ь.&~zW Q0r.F[@YG.&sݜ|*< e?avMW Ykdц͚_ V0Qqz+bZgct!ub| z>4/UNjOV=Uu1ta]AfDhs__ƑO!sT#9ITFؕ@F̊@S79|4r ':fuiDg94BaWƒUk8M:n3}zAyW/EG+d[]3JyL^M:yvX} z2jJ182V[C/n,1Cq'_\x_@3̼,n59F$;~I*&]I= gŤPZ_oHM1lRuz{>꡻ 8#PXOQg}M =%$tj` }N +avuK3[Gjɟ陿yбi ~bD-_)  DDe!Hi_],n; l8VeKO/?-o_-r`FϹfJrL _fdρA9"_,Cp+w#o#[F * >_WYՈ|ٻVïk0P܄ J9o$'L]Wo+HD0d#j1/OAA6hCϯu7dS /,a3[g 9Iqa{ 7 @# 8j %TφGFECf؋R4 ",3Tu0|k[GR54OOٍm^H4H47EWҙtgq=}vKBd>//kRQe?>yQ]gϰ[M~ 21}go [F[=K> `8Ϛͦ0$ MD⢌!MƊ0u%a"Lh݆ QHjP@fIC˾X"RT5mΘ ? +`Sf]`ԟ bh&|\{SnF;W{_lŠǎn淴HRh04 9e+Rzzh~NqjhdIm-636a_n#VųrQiֺä{-^2 7cS"EC$5\%%]OհeHԍ/xuP̠,O*e:B'(l}+&ݼ[KE.xgJ㗢P Q"!]p,/tCaHy 5Ys;\ PiHv*-,MY HxM?aih]VĶ%?kb7lkl#$(")$Hs%r7* bEwQngF7{ʾkQ]/^!' Vsi %Αygo_a:jTLYvZiH٣U>)!Fɇ]1Jd{2iC?5:mt/IN*AUS`jK|gwWRW9.{[EŲ%s΄O;=-D?Kl-]νAN ƫjuy],2з [~ +ikU&zɉVZ ǟDUԛU696˗G؆f'07M&FlTy`67-2ģcMXEv+|euZwQkHmeb\G9]Z`mH -i>WCVHEϝz^#TU4)y8Ճ&߷Eڠg.ihz?y$*ӄG PχtَRom%TD4$0>'h⚾BZp 6DTihBL<wL*;foq@^0OLE&;[ r|i.k87r[M1Ӊ=lq[fzL械԰;@b88EYRlH1K[ вu!C8OnVrnذ0_aO O|"d=鵤4i>K`ӌAU ԇ SmH=3=ZLqNQ"6S\y4DZxRwN="1\:m|B1IܥQCPsn%h;dbA{H#?r:!*h @4۔}Un&MTir^ zkR6)?)AemZL_DWY@'KKp*1M#4e M_l[T/u063q0@㫴T`AEB.>_T) /)KEߕ2{0gKa- Ro1Crzӯތg\T\}͗ tT/|MgF-Tc}_<N LՒyV+*dV*Ђd3m4ݪ. M ҪlѬ3NW+xp^G$RCR>9(ErȓZliȷѭ=1Z0(F|t%S]@J.̜r@xع3a >Jc i{5wxx{<$k{^SS2mqǸ'mM,57{o;O(KG9XOLƫ S q YYt{cpC#†HH]o:q #!\aJӋBqW) Gdb,OR44UƫMқė8i%I v50wZfΧNCi`dv+AޟhNX|Ps<`aaTK3;ɴw ^%1BH4! {۱\_kVa¨I32oB=;oL<һ.n<DlFX}pE#W3]ToPfJH 1W,Q2ZgLK`>;Q:mՇ̇zEktSllG"iJhR @tlN^鎄jzjdWپ4q\moa1Sq1-( G7-|4r}}Ȍǿ=E[9/G+x(=y!o|hC!慍nѠA [xa9庰ۡl{3&*| vc:Sr-aޭ8xl|{QX(0ڍkл4R.sC͞ ohWH.d RIor8Yr8K_3cxw۞ ݓd`'S GgS彛k"&Բpz 7Hxs9)ˋ~#uA@inc +(g_?1,g,7M6Z:v E0;*|"=Zф`KDe^u\}^q^vw'Dh|[fKViebQv^+7Cԧ)tʅӺ̽)JQ$e}2Wpqbvs 7E`o;üx,~;ݍ/7i*k8\z^18PìnZ4[ڎw^k3C8LҿI6XN`kzB, I}5vUc?d|JP&|A_v| /2>f 0K*h )q am2_? K[?hm.^KNrEJW )%eh& \l^rAV|0ϧU4GB+x9-Ȓ$dfVKѫsL~Y;0uWh?!/'j(^Su}_Dԕ7KK)ўY^8Wө ˒W'@A[:A3_'QMz!iiB@RaEc/fQA&$E~Q 641Еc-`$1IG7"98L XG: ԑ"Pf[xVȻ-T>Iϛ;^Edr{Q?1"5$jj Ku8P>/v^s`ue Te4<<*\7-u/y k;x_RiEx\i}*%2v"(\BbX?gݲS,ͬ+ж: \ԏ+Ntڧ&7YUs!E&j(M\hvot R0FP~ߌ%XtJaȡхyD- uDccZ$7ta'I~!e۰ll:(k(Սbc'LN#OgqAɳbz*_@D4{̒-d2 b)HؐTtyɼ [DcBj Vj }^XTUK~Z[2wLRĘb g- a ɎU7#=wj?"00U` -rNF;a#߭ISv>ًF L#lU~6VB .t-Y2_:mm)U7[ûw5)iBمBɣ D8qb+6|#L|.;-C(\yE@&GgIM;n futֶ?"+VY;p$U?H{@=*|({%laɅ<=wtߌФݫ.T:^;{0q @kQav"H<̻h2RK1ZfMF.bP*R[:)=ԂdB[%C 5ӫTlyYcӃa*Θ\؎]4pxEn #]/trϟ п"gL~>5sLuv6~0}4%̣iAhC/*3WwׯݤNsE] hs:DUw`?s5 D">{sM(.TYm^_Ρ%E;ǤZg%cqZy $9+2wWIu^<#%ϟ 1i #?\(#[f&][ܵ/۰م4y6١hg@AS& Xй́7g; @d89G.Q$Dĩ|B>apbxBs{+?=on)A'9Hkf2έZ"42qjBY ER͓w\-Z:7^t+vРVᴳH^ѿ1C1 uyw8PBԼYZ[&Ezo `XiS;"@LǜuzXCϊ+BqT$/hfF3ߤu!މZߋ0ƵXkA^@`!egmUv#O#{d/ᵳn_Ƽ}פ|NQ0 GתL,;Yg+{ J}wR=T9.iJo_*tֳ(V%gOelX|G8!5|T+oOi6̒vKuh]|۴Isз i6a}<"_p= iNA0j#iT8@ b_l;>f$YPztNXL] otAMہW9 j~"4%Ew2.k%>={Zn:g*H@FʿCg3faeW8'.N )ˢd7m^Xaex7U]uOR~:E!ru{ b$hd{Q"e8nqdaR O - =Ȧзkcvƀo|# ?!dry5G ?O 8t7gyg;  Fu4jCԧX/)S28En_*d%mi3[PK5i4\JJqDKdESU&fF\H>fƭ",sanQ8}d7R Sd @ꏋr#Rob7َY[A/ՆmhMoP˛^|c ""]mM5splؖ{/ yLd/pqOxCѲ8-̭e(X&A;|)~urWu\t1h)/r*dwFB;C3L$C@4(Cm =յ,2|#2U0ɛT霒J2[T{N(^ / ge%oș{+, w "&2z?=Jf;݇ތU)_R9:,A.m),Z~}I~`['!km[9@0qQ%(&zCT qu^(FXY |g)@dtSW_)IQSd XydjA)9$˭tIe*Tx(L6#蓳uHA +Da.Q_1ro ,HAyjԡ lkR4M5= g\iPvj~D)K;*玨O\`(rUR8`@=1e&}@CgQ5%_8MӀy+Y?^)dl:($52 ~UĵFn_Pl:B-'=? Kݺo7~\۾>|XhrQ3j(37$fynj473 qH-.)r9>.zV녪s:Tw:(mV·@זN21;vs !2.. ڽ@7-R.!݃!8T kpYDvhlv+  +&W~Q "tIM(o S?G#[_ X2l"7b,E./lEx0'gM pՙt# +>iA9B[LƦ/|hvi>i wG1jfIGGD)ni5'0j9}H6q /ᶵo^ Iܒ:NZj'q48H3)D3lx$Et˛N C_ 9s4Pdz"pgC޽3tZ`o=&$ldop)q:F+$ aGK6,݇[nKxJFBnP?=p{zⱳD`veCSFܥ3m^qp T0PU f!6 Y|L (A ٌi@574rn?-LurmYv_؏Erg}4msBҝSB\%nOe@o ׭¯vX2Stfx^3Q\_q6>NY.sP%oqib/ Bhe<(CaztL{!ƄT`3Dz<o;8ck v! 4Ĭ=H Y$$iʖX#y!$*g9MQB5!:MTܴ"Dt9ddx#N/KHE'=BAbk>ߤ͗١Hbvjb~"b% d$Dڔ3'ITsK\nR?aLLW6<ڳXK+`8SX*zò2\<=;eO@9]RK$ $j^v'Nʎ=~%kR\MdM}$i1bA>C$5$ד!_/Z d8Ic'0_a`l.ᜧ.S  \½v>bczqGWE;81ɛqO^r'+'2>\K@F sZTtO:㳂nb&]$j 2I; 9G!890\'8$U~D'RT5] a`wfAy 4UHHTT\V k<)M7Eq'Am-*S3>yOS:KRDIV!7Rqm) ~nRerNc=U; `ƴ,g糋3}p,HK YMz&Y[ %owFG˞4~JVehmp ?MP{XhڶRvqgXT?}> Aё|:J2:pn8 ZP27y6x dP$7DGgdd.0̻Pc3H7^\U&SZfidy8EOKV ^%#5ϤQV:+o^_"Rռ᫜MIEz*2?nc[VDȰ\,BsC@;"Chb΄ $\Ll:9 T^nƒ(s0u 2ZKL\Dd*l3rTP_=?g(es [YQnRDSQ 5HHW3E3Rh䜂lJ5dF?]K 3s. #2Q9ZUֻlrt蠸aܞNp?0%h(+PDۀ%eBRwga][O~-Q~葟$+}"\;N,$>;\GcuഊnZH|ΡE_²Ɣ -?F .7S'S+HE ah5*i& uPѮ[]J{yae,] mWrLE_-qR( m|k͙? ן%k(@^x)c=X* ,4}-کwholXA.;j4W8˭fMDK)ݶ޳)ǔRNZ VvnE :̽yIFh H hpj}•h\Gz EofnZϸew2kGSR9X6ۥcUD`,*5Y떈&"qלzMRYXC2)9ð:1x0D7&w` +;G- _2nHq W? t mf$0s~ 0{Z./j^7~ |-'=`H#5&B\7L+G*j<ep+jE-'qȄy4_*J ̈́(J+SmX>0y,6Z\gD@FVp Dj0Y#Qe:942f`9ʹìSbv ˪nda@2s 장7pڮ>ydv*@gֻdeb<#&۳q@t^>XĞF@f_$+ ivz63)cjZb_'8p$'NrwLlg_gSI#%L??H<}}'\Ր{SupJ |ۺ ĵ F%Q7uGnGi]_=;dob%Rm8ޞ(Y,ACI3e=aK%%-"; ISpټ4#.3sFis{lK@ގmK,(c+2 G1gbz eϊP륑 廷`@W{{X^],Sg4X\NT yބ?bv7:nR=Bzd4f_?˺n}C6p OU f)f@gv ʷ*فx|sǁ8ZJi6v^d4$`Ab8XV REL@rWAa;YR;;z62/SrIJ6)m7HGy̪':% | \ݮw̯^* 8U6& F(mo ee8f&=G]`dϗ!4i#x[Ϡ Z-VM>sjpɿ2=vR= rR[J20QsSփtтG+qR~.w1yAoӖK:\*3/yg~ m{gl<`!ԋxQ!itlK,^A#m @I9i}#e,6STϧ[哀ΣpP Bmm;߇ 8!Os]ۨBT^y=) Ԋ1ПJi]\A{hl,qU]Ok3W. d6n@V4H(D{]@I{ɴ{{OKҷYl@xbe3(CzK;K Rwf&ڔE~"9dHڔՂ1*|aNӇF:JiJkbo>}ܶٺYZ. AB*jQŀhbIbt\ESS*fn⣮dss,+nif9$;ng%&/Vq:j-7`m1ӡS.ڠ}Hk&i?Iiψ: FL@>G; b'';`n -SAjk;o>Ls.1VTrjT3DR*GAԡFA5[_jҔ߳lǤkԗ< s|ZS9F+= Qg.hE_4lx=u=2: Yb;eXxf9[͹N)T1$w+x|=Z(:)t !l抾,èUu {yd@Yp€椟>p'3!'Rp,kN`+qB jҐ/Nn$y<ݢF;?LBIZ~̒^ZB⒉̡q`7@ Q[hҳ4pQ%eWBxg ~+8bP ՞xWmZQ@bg%/4ܹ(1q*&e_o E,Oޱ~I!.|/B_wt@PLA!nvMX{6E͸U0uD:Ij<A)}? zYFgTKGsJW M™@+4,uB9A1 J0piV$]0bX2IM^dmEjV%ޔtŽ؞i!Uv/|s<[Wv \"gټ7~Y~+,fQǖmׂ/ã󵇮SSC^3Q^0{`'AƫryVnWneQC7ނL~|9a̪gVzxWRΚT[ jFDRyU-I*lRj_uj MT}&'3wR$%A;F/>LBX'+vG)ln{ E ;7"C 6m)6uV] ]c{yfR3-2+RTni߈f0l-^W]<$P2Fszbw:OKk ]Yqz@<Լ2I☼=G, V8كy/(x^hi:l?y<(e 4M1uBD qV\k8W yjspvcCAM6>f7\, TpZˡ}=tR<ͷΠ|bկqe3%%mUC:?-&HE1vG}"{$,M?הLwS}-:C7 㩍0j)b4Ԡ[ M0$*v~91\(^b=|ψZvz˩A:"eMn-qc#/" 3lgUcw%pHsH_h7uL4.ǯ$OrlQ OJrFsezڠ_++ Oo~I"C4SFD!Pj[9|8Z :54,]7A -/Ij4$SF-*f y @/VG!ɡWln2&黇Vv+E5)@pQ`XMAk\ jUWF a_:?[U^&lGԇ,޺d &|mahFU{fJVcf{W0H#b:3F@]4KHeAY #rt th8Y^zd_ܵ ^>Gp鰲st*j1[K Ɲ&WAR >vf&[jjEk+U_-Y] (GIh/ >kMgR7",$CgͲjl4 =ZJI7H%Jp!Mo j1ς0a{ZiL\.uj"1?atK 6T8Q믱2&|Γi՘S3TQWIrwGy(= uGȻ52Qi9zcxm_CtsN(Qv"&4)6R_n S@F£)WHV*Usy"ȫ#pk;ﹷyeNPՅS8B`oiB"`%QA0=xn|fzRt;/%[QpֽC2]i?&}6D=hGsdp6mtA׻A <цk{H2 =i >"' krdyX^`]S9s:K˰2)e #]#b$~UA0<n` cfGJ̆L%nswE8&SO (3Yn{%Τ4|~f&<)y PVkWoh>l02+ qݒJ3&FD_"CL^/_C!冫U^w#4&}u:HQA"o7|+A "%ۆTXa` oӎ Ī3I^LY˸eٰ"+jU A`#/ ZE(omsSjߌ֔cwQ0:eQ-gwE-CW4B;{Ȧ֠]Ψy<}ABO]W Uc VA3dދ( .H̒Ǘ12K GyЉ(ghܧIiU0`-֨"]DmM%;΃la;{f6ЄZX=[%˞`Dq.vNn+{=Qlqrp aQgD3j%2 +߫bT0^Jn ,!Zn()-$8H `ɶӿgQBD4&c{~%se%1Or2%Mnt0NJ?P-*ֆj= G(ϴќHOBcR=+@* k<Heϋi5kR2q%/܅d`f4H#ZGLIW>Ys-ry|8/_qa|b$j(1T، kj홋A֕pWTײm:Wԁҕ0^OR^n؇l)0uT?bpRG95/o|Z`:T8yLo!I9dtƵ])M `Fk64JbTKt9s2G\ R1'oEΉ{MOp;sY.'>$Yxѧ^FHwȗtsgK[ ɍT2362V)=RL*IrPc8L;U[1^1g'JU O]bBS3" ~ +_B7pX[ F-{NUiۅV02>A,717Ż Ɲ7+Y b:e"-T<.<0xnl- @z b6Bpn5Hݖ3!7EY_7#9$. W4DpУHflIj8dvs >mqh*6!sb7bE 6lV Pm",ލx~l؆.^wtUH} mpon Wwkvҍ\Eu"4X#mcDI@9e"ђOi;Uڼcwq =ݺM Mm,0r*g2ڜ[1!p(u/NgU 8/c{4KK5ifc"Zm~iHf6D@Ӫ:A!.UYc3zwc O*9 V߃"gDPq6BPGlKr7c@VY4u/2 #@%쪼ogδw>Do~@LH2ԇ汖DnPV 8zƛCUKR3^qeA+DK&g[qgBx z Hﺂq{ i;s8L`UW|b ^Κ'o80|.&8iL|֟HF=|콳i"-xJ;FvPL=OzƁ/ϩ0WiAӭu dFeod笥~q+/bdvH8ACMCU)/?<*BI 2VX!,w7b$X'Ӱuv?SmN|+Xn?ϟh'~5C̟[g2W8A\R^"N \b~B Gj僑}7X<96WJ?=>󰬭:HC eWp 1zy)|娖`/Тe#Y珛)>C0 rM0 ?`ZN @ց~g`u^;Yb j"3Β䕎Ӛնh(oZEaّz*"Cʉ4hy~Fވ|C7TՒ׋F2QG U; zAE2g#Dʎ~.S"qW;2Lᅑ4LdN2fZ6zSѹZ} \2= m]G'\_݀gG4` kt;\F;^#(}#cw SkE#]x4ͬ@D=D,r.Wo2ٷZS^I%6`!E0|I Jᐄ P{t>%\J]6> h^3xW)D%)9❂(OMc*707Ǣ;tC/'ʾ ÌC C  \4[ \idع"džIK+MnUBEi$sgelm}%'u"HvqfceTڴ5U˾0˙#‹A~"\Mie=|[p@>/&:zp Ym@,2obe񸃄'}=]b)߀ z$jx87Y/ʪ=їPA8cL)@;2Cn[K͟FKR%lׁ#$7??*䍞_V#Q^+复"\o,\C 3ʻUCBJ.;(o? >}%*1a."I'T& 1 D]9Re$ {#m{j\op ;~Gc#ļո*(kЮTҍGmg;Z @qs 8 p8Ogz9_{0R@d_bV1k{A2<Mo!lˋz*blG3Etb.ܠ_zB3Lvtۑ}(X`$%k$;H'明s*r&sl2bVHw8f/y bVE,>ƌխͶ[{žRxmN6kťj* \,*4/$Tߥgco)emмGC랅<+s@mŇ>y/d#I3d=95I ڮbHOrE&(D2hOK+7@B~J|Xqɛ2\^Yρ ؝䠸oBvL4Ǿ=vqa, <_Yb>]IDk-Q{>4ؘH"뛆HA4a?eJ-si[۽z*0;qx,nUDCk)H@$S/O[UNqEq,!!0cg׵_a ݏTyv > X-M#6q蚈꽃yGAmVs!\Wsxh'pni[-x ,x^E3&YSD(L ,FCjg֧TF :ꥍEȠUST#J-V$U"pS'DM?Tm$n;U2&r@B `%¿s2TxjbM1i ;OeBzP^ v,wb"ҳ -2%Sjy(s!+5+ טE{ƞe@)Ӏ$"}#~c4(4uP{2K-%-O+[cfvzăW/(mtdi+ҝnWeа/Lrco{)"˛9׶3 VÌHHV>q+|p%^mv<eJ %wGĂL@ BwP[hj~H\`2+ie9[7??0ʷu B3ZۉCGsgg\ҿXH00c*N 1wgƢvFJ`G*o9C#i]]sf5VX;' p^7XjȬ%~?q6ݡ;ۑ1d(AA>EwlAY rbI*6UnnTEtf-w|d{]"Rb\Hu,ƨ9:Pj; V6R55^GaHxih L AdYΆ //*5KZ8(ea|9([u:5 \ճ+<v'# [F:Ԥ@ӸRѕ ܽRRysinj m ĞɅHuqu{?YYk0. aBȎ$4[]{RFKmyl]LsTmI_P\h"u vIܬrc1dl1e\E"_LdqZ[t G>V~l'v/Wz@QT&ڸedl\=)\NhDpFڹU#W!VBia1Wk*C}O!>t𳣾Era=`1Eڼ%KIdFs^5_ysXmI$0an")idEirġ, !nI4~EPGMXiom4?@͹.\*lz-OLl&H/C-^;M&'5ΌUHmm*H7q*'LYy ٧)f&fd&]\-ef0Ufk}AM2kV7r"qHzmĉ}/d#X [WՃM^Dt} ǰ6h.̭OT 5ʵi@fDniZOdA5Y5Exi`󟺴"-usLn+&P\^Z',qNLt\rw&e=` C_;bK,AG?@HDg^q']a:W=3s 1hSy_0oјXi /q̮P,u&sA,Gb!'rR)ϠԪ+λ`ӥE^8<3I -ygUKe><;Sd$JO! Z͑,x`sPnTf!b Z_ܯ I 5&|ls4mK!J m&hghFYQOA% ɫAP6HJ~mhE5&x`"1nJ  !6uX5-?)SQpSrvv3ə|eaDM?:AEٖD_(Qc|=䉒ם?0]0h܍K#%7xߗ5{Ke{G )5Z*O& {ļh80Za<2˿2 兩UV.,-̆f)%eK婈$ɴj5?I+63Cxv yYZkUfµR^|F_08]0YRAAz;E]p< G am}̤ t;Zq3uO%6nZ mX$]9Zsڒ߾oTh=o XP>tͰFONIa/ZM;&#DqH L6όsb7MRMzP#GƦA4Zu%"'cpZ i`v{rEc mp3" O65Ax1<@\vu]NzCvj V'b)vKkV3'O%93F\\ojxl+E݄pnƻVBrFNvs >^m;wI!7kc`xBf=+. { !p$l4〵% 8Vө?}G 5lFBK 5x1Y_yI_$~vrxιC:g޳=g!nЉ"*lVF1iHjРNID(}^ }=aW"S.H `xs1_O[$є-1lV&OR ʑ_z'tWCc7cڵ}D`@>kQs_FkBF6f:ڊRsH =2`Aび_k=!s7=zxW#ZWNܕiy:}2JCǛ T/jdpˆO3Z5팎 }yDoN--TZ{}B6a︆WX f'W15` Dk :_ D {{bFPWŚ^,Dv1xpf{n(%T&բP0=2wY%)s9Dd ׳Чc6+nXk/>,#dBsf%qOL' p+QGUq♞"~AC`kTfpv _pO1Oh>l/Y~xijTNa(o 1-PNE̷?[+NԤuⵢ-`!!t_7!7n  _L+#(7_ᑟll qy*9EzBL0Cw-M=9W(E@9CwS[S;ƹ*&5y &rnjcմ*"b%a0ڠf*lfEym DD.`TΎň[j4S&,*9lE6)vdMR_&G3RS1# 3 {r#q > @̺zh@ߵyK~V}&=6A`*5pw@LV{ߪc1؝MᡋP\>F*fpR6974VJvrI b^hY@Ы t?J>{dnW7ԫEi3S%Y3 W`Z}@POçĈ2-hwfG>Qb vKߍෝs>פ;c*`ں h% mGOTKW@)2$R<.CiCXx+w^?%{R˚T͚N_}jt? ^>.ESN¸w[q@.%o&Z;b$=A WI<@ 2Ln$URxt~HYsgQ H$տ!xf*-u}B'hCx; Ѐ X܄L}b4OdGk?Xb2KȒ zQڱ1]d/qk Q-ܚo9͝&{N36;q0~.ځi5N\ ZׁN N0kF4w6:dgLa{=&oA<)Py<ʥDYɒ MG% Iz !K+{ʦ^ GA<cyh'6ggӤ߼ c2!n#Ur-0iDsNtZ-n{&j~A'BV^j|o0ͧSl&h4?·>5cL~G$vfzW?~:C^ )@HV]2L/3 IF1҂{4M>av2H;8>95>ٳj`UHg<489cհU5f rޮ c5, /AM`QHXw8]YeAĘ}jOjw8q^pKLIؙnv8]DNBbτHϱ@| 4 q*5#1 , ꧣ\n8X#ՄUӹ8)አ u,i5D$k`YJ08[w9u8Xĩ |П~.5IpU-6=]'cc,p,V:#O"`!N.f8x6 ':o`YR@d MW5nfvWV0 rVɟ!+ `\šy0U&V{hbAs_v\L+@8Ɉl8 xѿ*"ebh*\kQhyijI.*e4k5q9L=Ҩ|ԄJL 7lynp<[oYGX6ה~rSíHى1m Xm-RǠEW߳w!cgTjiG'wu6g]n:D݁)$7&' Z{G0ufm?BKqԋo֣0tݠģc;+HX˚ iEFZ 9CU}`rNSTd0dh<`;1)X(^!0Lk] Sp݃5&`h]Ѳ!!fGz_5O",(݄iRF.zX)׎) ŶX7 Ԋe|jYnY9|t&M7%&,;/$p7g>Q&`xN'V(:Rn(jKv8H_K즀 fÃȀE ?&!7)Nsci|U~,|kxhj8uK%i톳 R̳LS&c z`+ Kko0]+K!.zYG{rfm~r^;L#ikIz,^ RZz== Bc.>f.-{RcypG#Mo寺 }@nS=Vv7pf_ȘIߍ>'N`T]))xzJ=~ui /^<ܖTNV:tդ) B8aAP$s6ˎw<jl }ԳelrDžD*F&>$EE ŢQ!OjI}_N. ,ʂ#Y*SmU @϶=[i٘Tc9tOn@JALN L|> 놛׹u vv6gbb *kS^$Jes暖fYwi|!XY1+6KZé:YžnNTwwsßbǿ^#œSbS(ڐ+&Oڲ$aFMa8kqce"cl(P\Ubƒ)Z㶀3c.\}ԯbyJVcBl\7 >>j7 ĒirƐ[)ۈp M{=kX>➦@XV o%C&Rzĕl!2 R9- zj1څ2{3ߗh{񯶼R9 6hb/4o46C!t~V9w;5л2@cx;:57==?UjT,x^lN'JpK`]\9:MvF81L &y,sT&Н{QM$0li/\'& JR!ygr#%Hf%{ӏH.YG8:;w{\'NxxLrK#Hȅ2:dxw gk~P7Dy6{|:p<޶%q"vǬ[>5dd'Elí;Oyy%}՘W+A$E".ozaoFr}{C-۬oM?meH׎ĆNVV`j?ynhO: ?θM28av'_|8DnbIP:t$@l6}> \#fHZ*ॾAY5ˑW_IGfJ;. Bg񝚼cR 0hO:HyE XiK!.H@f˸cEC UD(53-'x2V_ͯÛ0W#] ;m\1 DYK0ʧ@Jxz@ |a'{ɻ+B r5/`['$ѢSul3&US\kn᪂3QѢm@/a!0)C2W?zhv'rgVXHWk՟Hf`qP@Tt뚼*r1_1$ד&C]e&b3ҩxݐ\w'5e<$䛎VFL*lέE*rrD_h=2:0(ަE\ ]裖"yI5G׿=z u(xڦH Is&b.ġe(B$(ݫ7Xf2D,"VI&eC ATV4PgW [L`bAS0T*\U|.U(Ǫ iK|zSqe;#8_>kf ~>n'0kէ686.dó$E#f|X$c]pSB{G&@\`&Q Ͳԭ;U6LZda҈Wc ENi'(hJ!A"Iwkؙ36mѡ;ӹ\_$ E]۲u3pi CAPiQh8SP U>ݷ1%yȿK& !LTuZBY741h-DZy<-8MT.6ʠ䍼)Z"Zp["9td g7W Y+j\ B)09p7j݅a,ta(CȔwr7ʢ}=ڪEmi'ԥzeP|!p2/BtVVVe% Ym]V\IU;Lc % CST<$):xfؿ5C6?ӽoH-z{ `.ttȈɅkAjbKo}Uf."qyvL,nݡŸtpO=ӈe*HO\U~ۏ9-HԀ P.IUm]ku"[Uq-PX[]o*d9SpUO5=oGm~:Ji+kl`ʅ=1B<4N4rMK8ȣf/_?GS}vmT4T!G㍃2*KFx G;3}QbJ? HP5\G |<c>䈝JUlp`-J Ӯ+.ꤶߢIjҁaL n&0QUKi>*YWK:s{M-Rfg\X tct5'D>AuIb(v4ƿ p.N0#8{ =i-q)qBDE KS<@qzl*!Hݐs-2 (;pr{ yQW< fr3g? Za3s*Igsr۵g[ oF,T8$2̱*\_W˕"^rh(g4c/򼄣dJ0$(l 8ʰrLŽeIiVɞ{L% hĴ %~)ɿpˎ- W*䮜[@$=N DŽ1yIm,N#c֮A^4^-ZO#"ϔkCB`n}ˬeTH p:/89h@R:v?DuWu*o|ʥ0(#Ʒv" :eq^]O#l;N禪B5$Hwځ6{nU"K?QqɨEhM^q6ON~ZgH ^Q8wfx;}$4Ձ6ɻ]֓k2Gǣ% :$agRѕ({NfS@X0PxTo<& )ޑAtÁ Q-THfB|KJMldm""44ٍdՁԲMU:˕,uVD~X2MA. |!)FM׳Uҷ5NʵgSp rbS,[B#B ߶O:vzҹ1׳TƧĞaJ?x8D ~_Mo+d'U'# Dkhk< 61͎KwK1p&86CCbt>BHiNĆ)pRѺwNkkwEc5nз&j׉47gM;{V'<,iC6_YxDLgK!Jzkƙ`翜"$0B[92ŶKIU~QN P1 p@?F@߰&jńoVoY=͓~0Xe T +0) !?n5OL1b"I%nFpN^;?&8! #@qvym0l'$j튋 m9;VC dy4}X\OE5&é&l#e?wf*rc7%PZ`'EXE~Lac'r,&uF?LPES8EpmpD&Vf~h3qVOK]HP.G1 D{9Zcyȓq9[16ym6v4ԿO,  [ ?ש)OG|3Zu )ck9~2;6lpn~8M{?fn|xb8toAɧw"(26fNtI0pذBFʞt.gP|:´! (Lb^nJ\"T%]B8輍01a5qo,8ҋ/T4)F 4K0޼ fk&dp\Pnrp>rNv.M򔏹mdn;1([VBpݶΜVw|J*AjIڒ6o fGWa?PCy"k~/^maz`M\hT%r,{9_ZAwD1Ft6X!L2#] ̿m@6 }PxT/&@Im>cY5fA4a2mLn%ozʩ\;59PĒ㹄2>l)_Bڒ8\t&:7κ@^q஡[m_n4I!~oqOh f;᳗|n-9v6[s%lV6c :-yrx/}pHP qs5Šń̏di_Pw6U]=FvdVy7Yj,˰`Wm#uو{[IK{|lIy@.˞:u9Նvi5vL&; YZsg[I-~ 6PNRV(i ̧b%Xee> O-Ϭ )?(Aec4kÌ=s6ⵂLW5 4N>| ^)Ndie˥!MɻC 7lJc> +,jK)s&YL0lcP~5b,͟8fdK_ݖҘߟuUӼN9eVmb8t˱0߱N`/4 bz7~VFM۲?pAb@iTշzGk|A&^|hs:K/j?U aF)֮w#8W*uT$Ȩ"a&(7@TF0u٧b]N.ʀaN ݽ _H`qK ,^TZ=`i#ߩ"&LKe!ږ8m/;5$N -!wZ'D:9_'Hb!5AIB߾z /C4Ewax/Pd <J%E#K~;i@B&׌K V 2 & `y` < 5 & `x` \%in\% c('A', 'B')")}. } }} \item{repel}{a logical value, whether to use ggrepel to avoid overplotting text labels or not.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link[ggplot2]{geom_violin}}, \code{\link{ggpar}} and \code{\link{facet}}.} } \description{ Create a violin plot with error bars. Violin plots are similar to box plots, except that they also show the kernel probability density of the data at different values. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Load data data("ToothGrowth") df <- ToothGrowth # Basic plot # +++++++++++++++++++++++++++ ggviolin(df, x = "dose", y = "len") # Change the plot orientation: horizontal ggviolin(df, "dose", "len", orientation = "horiz") # Add summary statistics # ++++++++++++++++++++++++++ # Draw quantiles ggviolin(df, "dose", "len", add = "none", draw_quantiles = 0.5) # Add box plot ggviolin(df, x = "dose", y = "len", add = "boxplot") ggviolin(df, x = "dose", y = "len", add = "dotplot") # Add jitter points and # change point shape by groups ("dose") ggviolin(df, x = "dose", y = "len", add = "jitter", shape = "dose") # Add mean_sd + jittered points ggviolin(df, x = "dose", y = "len", add = c("jitter", "mean_sd")) # Change error.plot to "crossbar" ggviolin(df, x = "dose", y = "len", add = "mean_sd", error.plot = "crossbar") # Change colors # +++++++++++++++++++++++++++ # Change outline and fill colors ggviolin(df, "dose", "len", color = "black", fill = "gray") # Change outline colors by groups: dose # Use custom color palette and add boxplot ggviolin(df, "dose", "len", color = "dose", palette = c("#00AFBB", "#E7B800", "#FC4E07"), add = "boxplot") # Change fill color by groups: dose # add boxplot with white fill color ggviolin(df, "dose", "len", fill = "dose", palette = c("#00AFBB", "#E7B800", "#FC4E07"), add = "boxplot", add.params = list(fill = "white")) # Plot with multiple groups # +++++++++++++++++++++ # fill or color box plot by a second group : "supp" ggviolin(df, "dose", "len", color = "supp", palette = c("#00AFBB", "#E7B800"), add = "boxplot") } \seealso{ \code{\link{ggpar}} } ggpubr/man/gene_citation.Rd0000644000176200001440000000253514333713444015425 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/gene_citation.R \docType{data} \name{gene_citation} \alias{gene_citation} \title{Gene Citation Index} \format{ A data frame with 66 rows and 2 columns. \describe{ \item{\code{gene}}{gene names} \item{\code{citation_index}}{mean citation index} } } \usage{ data("gene_citation") } \description{ Contains the mean citation index of 66 genes obtained by assessing PubMed abstracts and annotations using two key words i) Gene name + b cell differentiation and ii) Gene name + plasma cell differentiation. } \examples{ data(gene_citation) # Some key genes of interest to be highlighted key.gns <- c("MYC", "PRDM1", "CD69", "IRF4", "CASP3", "BCL2L1", "MYB", "BACH2", "BIM1", "PTEN", "KRAS", "FOXP1", "IGF1R", "KLF4", "CDK6", "CCND2", "IGF1", "TNFAIP3", "SMAD3", "SMAD7", "BMPR2", "RB1", "IGF2R", "ARNT") # Density distribution ggdensity(gene_citation, x = "citation_index", y = "..count..", xlab = "Number of citation", ylab = "Number of genes", fill = "lightgray", color = "black", label = "gene", label.select = key.gns, repel = TRUE, font.label = list(color= "citation_index"), xticks.by = 20, # Break x ticks by 20 gradient.cols = c("blue", "red"), legend = "bottom", legend.title = "" # Hide legend title ) } ggpubr/man/stat_friedman_test.Rd0000644000176200001440000002061314367517301016472 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_friedman_test.R \name{stat_friedman_test} \alias{stat_friedman_test} \title{Add Friedman Test P-values to a GGPlot} \usage{ stat_friedman_test( mapping = NULL, data = NULL, wid = NULL, group.by = NULL, label = "{method}, p = {p.format}", label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, step.increase = 0.1, p.adjust.method = "holm", significance = list(), geom = "text", position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, parse = FALSE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{wid}{(factor) column name containing individuals/subjects identifier. Should be unique per individual. Required only for repeated measure tests (\code{"one_way_repeated", "two_way_repeated", "friedman_test", etc}).} \item{group.by}{(optional) character vector specifying the grouping variable; it should be used only for grouped plots. Possible values are : \itemize{ \item \code{"x.var"}: Group by the x-axis variable and perform the test between legend groups. In other words, the p-value is compute between legend groups at each x position \item \code{"legend.var"}: Group by the legend variable and perform the test between x-axis groups. In other words, the test is performed between the x-groups for each legend level. }} \item{label}{the column containing the label (e.g.: label = "p" or label = "p.adj"), where \code{p} is the p-value. Can be also an expression that can be formatted by the \code{\link[glue]{glue}()} package. For example, when specifying label = "t-test, p = \{p\}", the expression \{p\} will be replaced by its value.} \item{label.x.npc, label.y.npc}{can be \code{numeric} or \code{character} vector of the same length as the number of groups and/or panels. If too short they will be recycled. \itemize{ \item If \code{numeric}, value should be between 0 and 1. Coordinates to be used for positioning the label, expressed in "normalized parent coordinates". \item If \code{character}, allowed values include: i) one of c('right', 'left', 'center', 'centre', 'middle') for x-axis; ii) and one of c( 'bottom', 'top', 'center', 'centre', 'middle') for y-axis.}} \item{label.x, label.y}{\code{numeric} Coordinates (in data units) to be used for absolute positioning of the label. If too short they will be recycled.} \item{step.increase}{numeric vector with the increase in fraction of total height for every additional comparison to minimize overlap.} \item{p.adjust.method}{method for adjusting p values (see \code{\link[stats]{p.adjust}}). Has impact only in a situation, where multiple pairwise tests are performed; or when there are multiple grouping variables. Allowed values include "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none". If you don't want to adjust the p value (not recommended), use p.adjust.method = "none".} \item{significance}{a list of arguments specifying the signifcance cutpoints and symbols. For example, \code{significance <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, 0.05, Inf), symbols = c("****", "***", "**", "*", "ns"))}. In other words, we use the following convention for symbols indicating statistical significance: \itemize{ \item \code{ns}: p > 0.05 \item \code{*}: p <= 0.05 \item \code{**}: p <= 0.01 \item \code{***}: p <= 0.001 \item \code{****}: p <= 0.0001 }} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If FALSE (the default), removes missing values with a warning. If TRUE silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{parse}{If TRUE, the labels will be parsed into expressions and displayed as described in \code{?plotmath}.} \item{...}{other arguments passed to the function \code{geom_bracket()} or \code{geom_text()}} } \description{ Add automatically Friedman test p-values to a ggplot, such as box blots, dot plots and stripcharts. } \section{Computed variables}{ \itemize{ \item{statistic}: the value of the test statistic (Chi-squared). \item{df}: the degrees of freedom of the approximate chi-squared distribution of the test statistic. \item{p}: p-value. \item{p.adj}: Adjusted p-values. \item{p.signif}: P-value significance. \item{p.adj.signif}: Adjusted p-value significance. \item{p.format}: Formated p-value. \item{p.adj.format}: Formated adjusted p-value. \item{n}: number of samples. } } \examples{ # Data preparation #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Transform `dose` into factor variable df <- ToothGrowth df$dose <- as.factor(df$dose) df$id <- as.factor(c(rep(1:10, 3), rep(11:20, 3))) # Add a random grouping variable set.seed(123) df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) df$len <- ifelse(df$group == "grp2", df$len+2, df$len) df$len <- ifelse(df$group == "grp3", df$len+7, df$len) head(df, 3) # Basic boxplot #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Create a basic boxplot # Add 5\% and 10\% space to the plot bottom and the top, respectively bxp <- ggboxplot(df, x = "dose", y = "len") + scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) # Add the p-value to the boxplot bxp + stat_friedman_test(aes(wid = id)) # Change the label position # Using coordinates in data units bxp + stat_friedman_test(aes(wid = id), label.x = "1", label.y = 10, hjust = 0) # Format the p-value differently custom_p_format <- function(p) { rstatix::p_format(p, accuracy = 0.0001, digits = 3, leading.zero = FALSE) } bxp + stat_friedman_test( aes(wid = id), label = "Friedman test, italic(p) = {custom_p_format(p)}{p.signif}" ) # Show a detailed label in italic bxp + stat_friedman_test(aes(wid = id), label = "as_detailed_italic") # Faceted plots #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Create a ggplot facet df$id <- rep(1:10,6) bxp <- ggboxplot(df, x = "dose", y = "len", facet.by = "supp") + scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) # Add p-values bxp + stat_friedman_test(aes(wid = id)) # Grouped plots #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% df$id <- rep(1:10,6) bxp <- ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") # For each legend group, computes tests within x variable groups bxp + stat_friedman_test(aes(wid = id, group = supp, color = supp), within = "x") # For each x-position, computes tests within legend variable groups bxp + stat_friedman_test( aes(wid = id, group = supp, color = supp), within = "group", label = "p = {p.format}" ) } ggpubr/man/background_image.Rd0000644000176200001440000000160314333713444016071 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/background_image.R \name{background_image} \alias{background_image} \title{Add Background Image to ggplot2} \usage{ background_image(raster.img) } \arguments{ \item{raster.img}{raster object to display, as returned by the function \code{readPNG()}[in \code{png} package] and \code{readJPEG()} [in \code{jpeg} package].} } \description{ Add background image to ggplot2. } \examples{ \dontrun{ install.packages("png") # Import the image img.file <- system.file(file.path("images", "background-image.png"), package = "ggpubr") img <- png::readPNG(img.file) # Plot with background image ggplot(iris, aes(Species, Sepal.Length))+ background_image(img)+ geom_boxplot(aes(fill = Species), color = "white")+ fill_palette("jco") } } \author{ Alboukadel Kassambara } ggpubr/man/annotate_figure.Rd0000644000176200001440000000442714333713444015771 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/annotate_figure.R \name{annotate_figure} \alias{annotate_figure} \title{Annotate Arranged Figure} \usage{ annotate_figure( p, top = NULL, bottom = NULL, left = NULL, right = NULL, fig.lab = NULL, fig.lab.pos = c("top.left", "top", "top.right", "bottom.left", "bottom", "bottom.right"), fig.lab.size, fig.lab.face ) } \arguments{ \item{p}{(arranged) ggplots.} \item{top, bottom, left, right}{optional string, or grob.} \item{fig.lab}{figure label (e.g.: "Figure 1").} \item{fig.lab.pos}{position of the figure label, can be one of "top.left", "top", "top.right", "bottom.left", "bottom", "bottom.right". Default is "top.left".} \item{fig.lab.size}{optional size of the figure label.} \item{fig.lab.face}{optional font face of the figure label. Allowed values include: "plain", "bold", "italic", "bold.italic".} } \description{ Annotate figures including: i) ggplots, ii) arranged ggplots from \code{\link{ggarrange}()}, \code{\link[gridExtra:arrangeGrob]{grid.arrange}()} and \code{\link[cowplot]{plot_grid}()}. } \examples{ data("ToothGrowth") df <- ToothGrowth df$dose <- as.factor(df$dose) # Create some plots # :::::::::::::::::::::::::::::::::::::::::::::::::: # Box plot bxp <- ggboxplot(df, x = "dose", y = "len", color = "dose", palette = "jco") # Dot plot dp <- ggdotplot(df, x = "dose", y = "len", color = "dose", palette = "jco") # Density plot dens <- ggdensity(df, x = "len", fill = "dose", palette = "jco") # Arrange and annotate # :::::::::::::::::::::::::::::::::::::::::::::::::: figure <- ggarrange(bxp, dp, dens, ncol = 2, nrow = 2) annotate_figure(figure, top = text_grob("Visualizing Tooth Growth", color = "red", face = "bold", size = 14), bottom = text_grob("Data source: \n ToothGrowth data set", color = "blue", hjust = 1, x = 1, face = "italic", size = 10), left = text_grob("Figure arranged using ggpubr", color = "green", rot = 90), right = text_grob(bquote("Superscript: ("*kg~NH[3]~ha^-1~yr^-1*")"), rot = 90), fig.lab = "Figure 1", fig.lab.face = "bold" ) } \seealso{ \code{\link{ggarrange}()} } \author{ Alboukadel Kassambara \email{alboukadel.kassambara@gmail.com} } ggpubr/man/desc_statby.Rd0000644000176200001440000000273314337240740015117 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/desc_statby.R \name{desc_statby} \alias{desc_statby} \title{Descriptive statistics by groups} \usage{ desc_statby(data, measure.var, grps, ci = 0.95) } \arguments{ \item{data}{a data frame.} \item{measure.var}{the name of a column containing the variable to be summarized.} \item{grps}{a character vector containing grouping variables; e.g.: grps = c("grp1", "grp2")} \item{ci}{the percent range of the confidence interval (default is 0.95).} } \value{ A data frame containing descriptive statistics, such as: \itemize{ \item \strong{length}: the number of elements in each group \item \strong{min}: minimum \item \strong{max}: maximum \item \strong{median}: median \item \strong{mean}: mean \item \strong{iqr}: interquartile range \item \strong{mad}: median absolute deviation (see ?MAD) \item \strong{sd}: standard deviation of the sample \item \strong{se}: standard error of the mean. It's calculated as the sample standard deviation divided by the root of the sample size. \item \strong{ci}: confidence interval of the mean \item \strong{range}: the range = max - min \item \strong{cv}: coefficient of variation, sd/mean \item \strong{var}: variance, sd^2 } } \description{ Computes descriptive statistics by groups for a measure variable. } \examples{ # Load data data("ToothGrowth") # Descriptive statistics res <- desc_statby(ToothGrowth, measure.var = "len", grps = c("dose", "supp")) head(res[, 1:10]) } ggpubr/man/npc_to_data_coord.Rd0000644000176200001440000000137514333713444016257 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/npc_to_data_coord.R \name{npc_to_data_coord} \alias{npc_to_data_coord} \title{Convert NPC to Data Coordinates} \usage{ npc_to_data_coord(npc, data.ranges) } \arguments{ \item{npc}{a numeric vector. Each value should be in [0-1]} \item{data.ranges}{a numeric vector of length 2 containing the data ranges (minimum and the maximum)} } \value{ a numeric vector representing data coordinates. } \description{ Convert NPC (Normalized Parent Coordinates) into data coordinates. } \examples{ npc_to_data_coord(npc = c(0.2, 0.95), data.ranges = c(1, 20)) as_npc(c("top", "right")) \%>\% npc_to_data_coord(data.ranges = c(1, 20)) } \seealso{ \code{\link{as_npc}}, \code{\link{get_coord}}. } ggpubr/man/axis_scale.Rd0000644000176200001440000000147714332553656014742 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/axis_scale.R \name{axis_scale} \alias{axis_scale} \alias{xscale} \alias{yscale} \title{Change Axis Scale: log2, log10 and more} \usage{ xscale(.scale, .format = FALSE) yscale(.scale, .format = FALSE) } \arguments{ \item{.scale}{axis scale. Allowed values are one of c("none", "log2", "log10", "sqrt", "percent", "dollar", "scientific"); e.g.: .scale="log2".} \item{.format}{ogical value. If TRUE, axis tick mark labels will be formatted when .scale = "log2" or "log10".} } \description{ Change axis scale. \itemize{ \item \code{xscale}: change x axis scale. \item \code{yscale}: change y axis scale. } } \examples{ # Basic scatter plots data(cars) p <- ggscatter(cars, x = "speed", y = "dist") p # Set log scale p + yscale("log2", .format = TRUE) } ggpubr/man/gene_expression.Rd0000644000176200001440000000174114336762430016012 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/gene_expression.R \docType{data} \name{gene_expression} \alias{gene_expression} \title{Gene Expression Data} \format{ A data frame with 1305 rows and 5 columns. \describe{ \item{\code{bcr_patient_barcode}}{sample ID} \item{\code{dataset}}{cance type} \item{\code{GATA3}}{GATA3 gene expression} \item{\code{PTEN}}{PTEN gene expression}\item{\code{XBP1}}{XBP1 gene expression.}} } \usage{ data("gene_expression") } \description{ Gene expression data extracted from TCGA using the `RTCGA` and `RTCGA.mRNA` R packages. It contains the mRNA expression for 3 genes - GATA3, PTEN and XBP1- from 3 different datasets: Breast invasive carcinoma (BRCA), Ovarian serous cystadenocarcinoma (OV) and Lung squamous cell carcinoma (LUSC) } \examples{ data(gene_expression) ggboxplot(gene_expression, x = "dataset", y = c("GATA3", "PTEN", "XBP1"), combine = TRUE, ylab = "Expression", color = "dataset", palette = "jco") } ggpubr/man/ggpubr_args.Rd0000644000176200001440000000641314333713444015116 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggpubr_args.R \name{ggpubr_args} \alias{ggpubr_args} \title{ggpubr General Arguments Description} \arguments{ \item{data}{a data frame} \item{x}{character string containing the name of x variable.} \item{y}{character vector containing one or more variables to plot} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{color}{outline color.} \item{fill}{fill color.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{linetype}{line types.} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{select}{character vector specifying which items to display.} \item{remove}{character vector specifying which items to remove from the plot.} \item{order}{character vector specifying the order of items.} \item{add}{character vector for adding another plot element (e.g.: dot plot or error bars). Allowed values are one or the combination of: "none", "dotplot", "jitter", "boxplot", "point", "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_mad", "median_range"; see ?desc_statby for more details.} \item{add.params}{parameters (color, shape, size, fill, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{error.plot}{plot type used to visualize error. Allowed values are one of c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", "lower_linerange"). Default value is "pointrange" or "errorbar". Used only when add != "none" and add contains one "mean_*" or "med_*" where "*" = sd, se, ....} \item{font.label}{a list which can contain the combination of the following elements: the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of labels. For example font.label = list(size = 14, face = "bold", color ="red"). To specify only the size and the style, use font.label = list(size = 14, face = "plain").} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} } \description{ ggpubr General Arguments Description } ggpubr/man/stat_overlay_normal_density.Rd0000644000176200001440000000641714333713444020443 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_overlay_normal_density.R \name{stat_overlay_normal_density} \alias{stat_overlay_normal_density} \title{Overlay Normal Density Plot} \usage{ stat_overlay_normal_density( mapping = NULL, data = NULL, geom = "line", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If FALSE (the default), removes missing values with a warning. If TRUE silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{...}{other arguments to pass to \code{\link[ggplot2:geom_path]{geom_line}}.} } \description{ Overlay normal density plot (with the same mean and SD) to the density distribution of 'x'. This is useful for visually inspecting the degree of deviance from normality. } \examples{ # Simpledensity plot data("mtcars") ggdensity(mtcars, x = "mpg", fill = "red") + scale_x_continuous(limits = c(-1, 50)) + stat_overlay_normal_density(color = "red", linetype = "dashed") # Color by groups data(iris) ggdensity(iris, "Sepal.Length", color = "Species") + stat_overlay_normal_density(aes(color = Species), linetype = "dashed") # Facet ggdensity(iris, "Sepal.Length", facet.by = "Species") + stat_overlay_normal_density(color = "red", linetype = "dashed") } \seealso{ \code{\link{ggdensity}} } ggpubr/man/text_grob.Rd0000644000176200001440000000417014333713444014607 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/text_grob.R \name{text_grob} \alias{text_grob} \title{Create a Text Graphical object} \usage{ text_grob( label, just = "centre", hjust = NULL, vjust = NULL, rot = 0, color = "black", face = "plain", size = NULL, lineheight = NULL, family = NULL, ... ) } \arguments{ \item{label}{A character or \link{expression} vector. Other objects are coerced by \code{\link{as.graphicsAnnot}}.} \item{just}{The justification of the text relative to its (x, y) location. If there are two values, the first value specifies horizontal justification and the second value specifies vertical justification. Possible string values are: \code{"left"}, \code{"right"}, \code{"centre"}, \code{"center"}, \code{"bottom"}, and \code{"top"}. For numeric values, 0 means left (bottom) alignment and 1 means right (top) alignment. } \item{hjust}{A numeric vector specifying horizontal justification. If specified, overrides the \code{just} setting.} \item{vjust}{A numeric vector specifying vertical justification. If specified, overrides the \code{just} setting.} \item{rot}{The angle to rotate the text.} \item{color}{text font color.} \item{face}{font face. Allowed values include one of \code{"plain", "bold", "italic", "bold.italic"}.} \item{size}{font size (e.g.: size = 12)} \item{lineheight}{line height (e.g.: lineheight = 2).} \item{family}{font family.} \item{...}{other arguments passed to \link[grid:grid.text]{textGrob}.} } \value{ a text grob. } \description{ Create easily a customized text grob (graphical object). Wrapper around \code{\link[grid:grid.text]{textGrob}}. } \examples{ text <- paste("iris data set gives the measurements in cm", "of the variables sepal length and width", "and petal length and width, respectively,", "for 50 flowers from each of 3 species of iris.", "The species are Iris setosa, versicolor, and virginica.", sep = "\n") # Create a text grob tgrob <- text_grob(text, face = "italic", color = "steelblue") # Draw the text as_ggplot(tgrob) } ggpubr/man/stat_mean.Rd0000644000176200001440000000562414333713444014572 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_mean.R \name{stat_mean} \alias{stat_mean} \title{Draw group mean points} \usage{ stat_mean( mapping = NULL, data = NULL, geom = "point", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If FALSE (the default), removes missing values with a warning. If TRUE silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{...}{other arguments to pass to \code{\link[ggplot2]{geom_point}}.} } \description{ Draw the mean point of each group. } \examples{ # Load data data("mtcars") df <- mtcars df$cyl <- as.factor(df$cyl) # Scatter plot with ellipses and group mean points ggscatter(df, x = "wt", y = "mpg", color = "cyl", shape = "cyl", ellipse = TRUE)+ stat_mean(aes(color = cyl, shape = cyl), size = 4) } \seealso{ \code{\link{stat_conf_ellipse}}, \code{\link{stat_chull}} and \code{\link{ggscatter}} } ggpubr/man/create_aes.Rd0000644000176200001440000000144314333664263014711 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/create_aes.R \name{create_aes} \alias{create_aes} \title{Create Aes Mapping from a List} \usage{ create_aes(.list, parse = TRUE) } \arguments{ \item{.list}{a list of aesthetic arguments; for example .list = list(x = "dose", y = "len", color = "dose").} \item{parse}{logical. If TRUE, parse the input as an expression.} } \description{ Create aes mapping to make programming easy with ggplot2. } \examples{ # Simple aes creation create_aes(list(x = "Sepal.Length", y = "Petal.Length" )) # Parse an expression x <- "log2(Sepal.Length)" y <- "log2(Petal.Length)" create_aes(list(x = x, y = y ), parse = TRUE) # Create a ggplot mapping <- create_aes(list(x = x, y = y ), parse = TRUE) ggplot(iris, mapping) + geom_point() } ggpubr/man/stat_chull.Rd0000644000176200001440000000616314332576562014767 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_chull.R \name{stat_chull} \alias{stat_chull} \title{Plot convex hull of a set of points} \usage{ stat_chull( mapping = NULL, data = NULL, geom = "path", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If \code{FALSE}, the default, missing values are removed with a warning. If \code{TRUE}, missing values are silently removed.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{layer()}}. These are often aesthetics, used to set an aesthetic to a fixed value, like \code{colour = "red"} or \code{size = 3}. They may also be parameters to the paired geom/stat.} } \description{ Plot convex hull of a set of points. } \examples{ # Load data data("mtcars") df <- mtcars df$cyl <- as.factor(df$cyl) # scatter plot with convex hull ggscatter(df, x = "wt", y = "mpg", color = "cyl")+ stat_chull(aes(color = cyl)) ggscatter(df, x = "wt", y = "mpg", color = "cyl")+ stat_chull(aes(color = cyl, fill = cyl), alpha = 0.1, geom = "polygon") } \seealso{ \code{\link{ggpar}}, \code{\link{ggscatter}} } ggpubr/man/geom_pwc.Rd0000644000176200001440000003313514343207174014414 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/geom_pwc.R \name{stat_pwc} \alias{stat_pwc} \alias{geom_pwc} \title{Add Pairwise Comparisons P-values to a GGPlot} \usage{ stat_pwc( mapping = NULL, data = NULL, method = "wilcox_test", method.args = list(), ref.group = NULL, label = "p.format", y.position = NULL, group.by = NULL, dodge = 0.8, bracket.nudge.y = 0.05, bracket.shorten = 0, bracket.group.by = c("x.var", "legend.var"), step.increase = 0.12, tip.length = 0.03, size = 0.3, label.size = 3.88, family = "", vjust = 0, hjust = 0.5, p.adjust.method = "holm", p.adjust.by = c("group", "panel"), symnum.args = list(), hide.ns = FALSE, remove.bracket = FALSE, position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, parse = FALSE, ... ) geom_pwc( mapping = NULL, data = NULL, stat = "pwc", method = "wilcox_test", method.args = list(), ref.group = NULL, label = "p.format", y.position = NULL, group.by = NULL, dodge = 0.8, stack = FALSE, step.increase = 0.12, tip.length = 0.03, bracket.nudge.y = 0.05, bracket.shorten = 0, bracket.group.by = c("x.var", "legend.var"), size = 0.3, label.size = 3.88, family = "", vjust = 0, hjust = 0.5, p.adjust.method = "holm", p.adjust.by = c("group", "panel"), symnum.args = list(), hide.ns = FALSE, remove.bracket = FALSE, position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, parse = FALSE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{method}{a character string indicating which method to be used for pairwise comparisons. Default is \code{"wilcox_test"}. Allowed methods include pairwise comparisons methods implemented in the \code{rstatix} R package. These methods are: \code{"wilcox_test", "t_test", "sign_test", "dunn_test", "emmeans_test", "tukey_hsd", "games_howell_test"}.} \item{method.args}{a list of additional arguments used for the test method. For example one might use \code{method.args = list(alternative = "greater")} for wilcoxon test.} \item{ref.group}{a character string or a numeric value specifying the reference group. If specified, for a given grouping variable, each of the group levels will be compared to the reference group (i.e. control group). \code{ref.group} can be also \code{"all"}. In this case, each of the grouping variable levels is compared to all (i.e. basemean). Allowed values can be: \itemize{ \item \strong{numeric value}: specifying the rank of the reference group. For example, use \code{ref.group = 1} when the first group is the reference; use \code{ref.group = 2} when the second group is the reference, and so on. This works for all situations, including i) when comparisons are performed between x-axis groups and ii) when comparisons are performed between legend groups. \item \strong{character value}: For example, you can use \code{ref.group = "ctrl"} instead of using the numeric rank value of the "ctrl" group. \item \strong{"all"}: In this case, each of the grouping variable levels is compared to all (i.e. basemean). }} \item{label}{character string specifying label. Can be: \itemize{ \item the column containing the label (e.g.: \code{label = "p"} or \code{label = "p.adj"}), where \code{p} is the p-value. Other possible values are \code{"p.signif", "p.adj.signif", "p.format", "p.adj.format"}. \item an expression that can be formatted by the \code{\link[glue]{glue}()} package. For example, when specifying \code{label = "Wilcoxon, p = \{p\}"}, the expression \{p\} will be replaced by its value. \item a combination of plotmath expressions and glue expressions. You may want some of the statistical parameter in italic; for example:\code{label = "Wilcoxon, italic(p)= {p}"}}.} \item{y.position}{numeric vector with the y positions of the brackets} \item{group.by}{(optional) character vector specifying the grouping variable; it should be used only for grouped plots. Possible values are : \itemize{ \item \code{"x.var"}: Group by the x-axis variable and perform the test between legend groups. In other words, the p-value is compute between legend groups at each x position \item \code{"legend.var"}: Group by the legend variable and perform the test between x-axis groups. In other words, the test is performed between the x-groups for each legend level. }} \item{dodge}{dodge width for grouped ggplot/test. Default is 0.8. It's used to dodge the brackets position when \code{group.by = "legend.var"}.} \item{bracket.nudge.y}{Vertical adjustment to nudge brackets by (in fraction of the total height). Useful to move up or move down the bracket. If positive value, brackets will be moved up; if negative value, brackets are moved down.} \item{bracket.shorten}{a small numeric value in [0-1] for shortening the width of bracket.} \item{bracket.group.by}{(optional); a variable name for grouping brackets before adding step.increase. Useful for grouped plots. Possible values include \code{"x.var"} and \code{"legend.var"}.} \item{step.increase}{numeric vector with the increase in fraction of total height for every additional comparison to minimize overlap.} \item{tip.length}{numeric vector with the fraction of total height that the bar goes down to indicate the precise column/} \item{size}{change the width of the lines of the bracket} \item{label.size}{change the size of the label text} \item{family}{change the font used for the text} \item{vjust}{move the text up or down relative to the bracket.} \item{hjust}{move the text left or right relative to the bracket.} \item{p.adjust.method}{method for adjusting p values (see \code{\link[stats]{p.adjust}}). Has impact only in a situation, where multiple pairwise tests are performed; or when there are multiple grouping variables. Ignored when the specified method is \code{"tukey_hsd"} or \code{"games_howell_test"} because they come with internal p adjustment method. Allowed values include "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none". If you don't want to adjust the p value (not recommended), use p.adjust.method = "none".} \item{p.adjust.by}{possible value is one of \code{c("group", "panel")}. Default is \code{"group"}: for a grouped data, if pairwise test is performed, then the p-values are adjusted for each group level independently. P-values are adjusted by panel when \code{p.adjust.by = "panel"}.} \item{symnum.args}{a list of arguments to pass to the function \code{\link[stats]{symnum}} for symbolic number coding of p-values. For example, \code{symnum.args <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, 0.05, Inf), symbols = c("****", "***", "**", "*", "ns"))}. In other words, we use the following convention for symbols indicating statistical significance: \itemize{ \item \code{ns}: p > 0.05 \item \code{*}: p <= 0.05 \item \code{**}: p <= 0.01 \item \code{***}: p <= 0.001 \item \code{****}: p <= 0.0001 }} \item{hide.ns}{can be logical value (\code{TRUE} or \code{FALSE}) or a character vector (\code{"p.adj"} or \code{"p"}).} \item{remove.bracket}{logical, if \code{TRUE}, brackets are removed from the plot. \itemize{ \item Case when logical value. If TRUE, hide ns symbol when displaying significance levels. Filter is done by checking the column \code{p.adj.signif}, \code{p.signif}, \code{p.adj} and \code{p}. \item Case when character value. Possible values are "p" or "p.adj", for filtering out non significant. }} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If \code{FALSE} (the default), removes missing values with a warning. If \code{TRUE} silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{parse}{logical for parsing plotmath expression.} \item{...}{other arguments passed on to \code{\link{layer}}. These are often aesthetics, used to set an aesthetic to a fixed value, like \code{color = "red"} or \code{size = 3}. They may also be parameters to the paired geom/stat.} \item{stat}{The statistical transformation to use on the data for this layer, either as a \code{ggproto} \code{Geom} subclass or as a string naming the stat stripped of the \code{stat_} prefix (e.g. \code{"count"} rather than \code{"stat_count"})} \item{stack}{logical value. Default is FALSE; should be set to TRUE for stacked bar plots or line plots. If TRUE, then the brackets are automatically removed and the \code{dodge} value is set to zero.} } \description{ add pairwise comparison p-values to a ggplot such as box plots, dot plots and stripcharts. } \details{ \bold{Notes on adjusted p-values and facet}. When using the ggplot facet functions, the p-values are computed and adjusted by panel, without taking into account the other panels. This is by design in ggplot2. In this case, when there is only one computed p-value by panel, then using `label = "p"` or `label = "p.adj"` will give the same results using `geom_pwc()`. Again, p-value computation and adjustment in a given facet panel is done independently to the other panels. One might want to adjust the p-values of all the facet panels together. There are two solutions for that: \itemize{ \item Using \code{\link{ggadjust_pvalue}(p)} after creating the plot \code{p} \item or adding the adjusted p-value manually using \code{\link{stat_pvalue_manual}()}. Read more at: \itemize{ \item \href{https://www.datanovia.com/en/blog/how-to-add-p-values-to-ggplot-facets/}{How to Add P-values to GGPLOT Facets} \item \href{https://www.datanovia.com/en/blog/add-p-values-to-ggplot-facets-with-different-scales/}{Add P-values to GGPLOT Facets with Different Scales} } } } \examples{ df <- ToothGrowth df$dose <- factor(df$dose) # Data preparation #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Transform `dose` into factor variable df <- ToothGrowth df$dose <- as.factor(df$dose) # Add a random grouping variable df$group <- factor(rep(c("grp1", "grp2"), 30)) head(df, 3) # Two groups by x position #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Create a box plot # Add 10\% spaces between the p-value labels and the plot border bxp <- ggboxplot( df, x = "dose", y = "len", color = "supp", palette = c("#00AFBB", "#E7B800") ) + scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) # Add p-values onto the box plots # label can be "p.format" or "p.adj.format" bxp + geom_pwc( aes(group = supp), tip.length = 0, method = "t_test", label = "p.format" ) # Show adjusted p-values and significance levels # Hide ns (non-significant) bxp + geom_pwc( aes(group = supp), tip.length = 0, method = "t_test", label = "{p.adj.format}{p.adj.signif}", p.adjust.method = "bonferroni", p.adjust.by = "panel", hide.ns = TRUE ) # Complex cases #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # 1. Add p-values of OJ vs VC at each dose group bxp.complex <- bxp + geom_pwc( aes(group = supp), tip.length = 0, method = "t_test", label = "p.adj.format", p.adjust.method = "bonferroni", p.adjust.by = "panel" ) # 2. Add pairwise comparisons between dose levels # Nudge up the brackets by 20\% of the total height bxp.complex <- bxp.complex + geom_pwc( method = "t_test", label = "p.adj.format", p.adjust.method = "bonferroni", bracket.nudge.y = 0.2 ) # 3. Display the plot bxp.complex # Three groups by x position #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Simple plots #_____________________________________ # Box plots with p-values bxp <- ggboxplot( df, x = "supp", y = "len", fill = "dose", palette = "npg" ) bxp + geom_pwc( aes(group = dose), tip.length = 0, method = "t_test", label = "p.adj.format", bracket.nudge.y = -0.08 ) + scale_y_continuous(expand = expansion(mult = c(0, 0.1))) # Bar plots with p-values bp <- ggbarplot( df, x = "supp", y = "len", fill = "dose", palette = "npg", add = "mean_sd", position = position_dodge(0.8) ) bp + geom_pwc( aes(group = dose), tip.length = 0, method = "t_test", label = "p.adj.format", bracket.nudge.y = -0.08 ) + scale_y_continuous(expand = expansion(mult = c(0, 0.1))) } \seealso{ \code{\link{ggadjust_pvalue}} } ggpubr/man/ggdensity.Rd0000644000176200001440000001371514367732422014620 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggdensity.R \name{ggdensity} \alias{ggdensity} \title{Density plot} \usage{ ggdensity( data, x, y = "density", combine = FALSE, merge = FALSE, color = "black", fill = NA, palette = NULL, size = NULL, linetype = "solid", alpha = 0.5, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, add = c("none", "mean", "median"), add.params = list(linetype = "dashed"), rug = FALSE, label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x}{variable to be drawn.} \item{y}{one of "density" or "count".} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{color, fill}{density line color and fill color.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{linetype}{line type. See \code{\link{show_line_types}}.} \item{alpha}{numeric value specifying fill color transparency. Value should be in [0, 1], where 0 is full transparency and 1 is no transparency.} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{add}{allowed values are one of "mean" or "median" (for adding mean or median line, respectively).} \item{add.params}{parameters (color, size, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{rug}{logical value. If TRUE, add marginal rug.} \item{label}{the name of the column containing point labels. Can be also a character vector with length = nrow(data).} \item{font.label}{a list which can contain the combination of the following elements: the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of labels. For example font.label = list(size = 14, face = "bold", color ="red"). To specify only the size and the style, use font.label = list(size = 14, face = "plain").} \item{label.select}{can be of two formats: \itemize{ \item a character vector specifying some labels to show. \item a list containing one or the combination of the following components: \itemize{ \item \code{top.up} and \code{top.down}: to display the labels of the top up/down points. For example, \code{label.select = list(top.up = 10, top.down = 4)}. \item \code{criteria}: to filter, for example, by x and y variabes values, use this: \code{label.select = list(criteria = "`y` > 2 & `y` < 5 & `x` \%in\% c('A', 'B')")}. } }} \item{repel}{a logical value, whether to use ggrepel to avoid overplotting text labels or not.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link[ggplot2]{geom_density}} and \code{\link{ggpar}}.} } \description{ Create a density plot. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Create some data format set.seed(1234) wdata = data.frame( sex = factor(rep(c("F", "M"), each=200)), weight = c(rnorm(200, 55), rnorm(200, 58))) head(wdata, 4) # Basic density plot # Add mean line and marginal rug ggdensity(wdata, x = "weight", fill = "lightgray", add = "mean", rug = TRUE) # Change outline colors by groups ("sex") # Use custom palette ggdensity(wdata, x = "weight", add = "mean", rug = TRUE, color = "sex", palette = c("#00AFBB", "#E7B800")) # Change outline and fill colors by groups ("sex") # Use custom palette ggdensity(wdata, x = "weight", add = "mean", rug = TRUE, color = "sex", fill = "sex", palette = c("#00AFBB", "#E7B800")) } \seealso{ \code{\link{gghistogram}} and \code{\link{ggpar}}. } ggpubr/man/as_ggplot.Rd0000644000176200001440000000170614343207174014572 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/as_ggplot.R \name{as_ggplot} \alias{as_ggplot} \title{Storing grid.arrange() arrangeGrob() and plots} \usage{ as_ggplot(x) } \arguments{ \item{x}{an object of class gtable or grob as returned by the functions \code{\link[gridExtra:arrangeGrob]{arrangeGrob}()} and \code{\link[gridExtra:arrangeGrob]{grid.arrange}()}.} } \value{ an object of class ggplot. } \description{ Transform the output of \code{\link[gridExtra:arrangeGrob]{arrangeGrob}()} and \code{\link[gridExtra:arrangeGrob]{grid.arrange}()} to a an object of class ggplot. } \examples{ # Creat some plots bxp <- ggboxplot(iris, x = "Species", y = "Sepal.Length") vp <- ggviolin(iris, x = "Species", y = "Sepal.Length", add = "mean_sd") # Arrange the plots in one page # Returns a gtable (grob) object library(gridExtra) gt <- arrangeGrob(bxp, vp, ncol = 2) # Transform to a ggplot and print as_ggplot(gt) } ggpubr/man/ggadjust_pvalue.Rd0000644000176200001440000000731614343207174016002 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggadjust_pvalue.R \name{ggadjust_pvalue} \alias{ggadjust_pvalue} \title{Adjust p-values Displayed on a GGPlot} \usage{ ggadjust_pvalue( p, layer = NULL, p.adjust.method = "holm", label = "p.adj", hide.ns = NULL, symnum.args = list(), output = c("plot", "stat_test") ) } \arguments{ \item{p}{a ggplot} \item{layer}{An integer indicating the statistical layer rank in the ggplot (in the order added to the plot).} \item{p.adjust.method}{method for adjusting p values (see \code{\link[stats]{p.adjust}}). Has impact only in a situation, where multiple pairwise tests are performed; or when there are multiple grouping variables. Ignored when the specified method is \code{"tukey_hsd"} or \code{"games_howell_test"} because they come with internal p adjustment method. Allowed values include "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none". If you don't want to adjust the p value (not recommended), use p.adjust.method = "none".} \item{label}{character string specifying label. Can be: \itemize{ \item the column containing the label (e.g.: \code{label = "p"} or \code{label = "p.adj"}), where \code{p} is the p-value. Other possible values are \code{"p.signif", "p.adj.signif", "p.format", "p.adj.format"}. \item an expression that can be formatted by the \code{\link[glue]{glue}()} package. For example, when specifying \code{label = "Wilcoxon, p = \{p\}"}, the expression \{p\} will be replaced by its value. \item a combination of plotmath expressions and glue expressions. You may want some of the statistical parameter in italic; for example:\code{label = "Wilcoxon, italic(p)= {p}"}}.} \item{hide.ns}{can be logical value (\code{TRUE} or \code{FALSE}) or a character vector (\code{"p.adj"} or \code{"p"}).} \item{symnum.args}{a list of arguments to pass to the function \code{\link[stats]{symnum}} for symbolic number coding of p-values. For example, \code{symnum.args <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, 0.05, Inf), symbols = c("****", "***", "**", "*", "ns"))}. In other words, we use the following convention for symbols indicating statistical significance: \itemize{ \item \code{ns}: p > 0.05 \item \code{*}: p <= 0.05 \item \code{**}: p <= 0.01 \item \code{***}: p <= 0.001 \item \code{****}: p <= 0.0001 }} \item{output}{character. Possible values are one of \code{c("plot", "stat_test")}. Default is "plot".} } \description{ Adjust p-values produced by \code{\link{geom_pwc}()} on a ggplot. This is mainly useful when using facet, where p-values are generally computed and adjusted by panel without taking into account the other panels. In this case, one might want to adjust after the p-values of all panels together. } \examples{ # Data preparation #::::::::::::::::::::::::::::::::::::::: df <- ToothGrowth df$dose <- as.factor(df$dose) # Add a random grouping variable df$group <- factor(rep(c("grp1", "grp2"), 30)) head(df, 3) # Boxplot: Two groups by panel #::::::::::::::::::::::::::::::::::::::: # Create a box plot bxp <- ggboxplot( df, x = "supp", y = "len", fill = "#00AFBB", facet.by = "dose" ) # Make facet and add p-values bxp <- bxp + geom_pwc(method = "t_test") bxp # Adjust all p-values together after ggadjust_pvalue( bxp, p.adjust.method = "bonferroni", label = "{p.adj.format}{p.adj.signif}", hide.ns = TRUE ) # Boxplot: Three groups by panel #::::::::::::::::::::::::::::::::::::::: # Create a box plot bxp <- ggboxplot( df, x = "dose", y = "len", fill = "#00AFBB", facet.by = "supp" ) # Make facet and add p-values bxp <- bxp + geom_pwc(method = "t_test") bxp # Adjust all p-values together after ggadjust_pvalue( bxp, p.adjust.method = "bonferroni", label = "{p.adj.format}{p.adj.signif}" ) } ggpubr/man/stat_kruskal_test.Rd0000644000176200001440000001757614367517301016377 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_kruskal_test.R \name{stat_kruskal_test} \alias{stat_kruskal_test} \title{Add Kruskal-Wallis Test P-values to a GGPlot} \usage{ stat_kruskal_test( mapping = NULL, data = NULL, group.by = NULL, label = "{method}, p = {p.format}", label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, step.increase = 0.1, p.adjust.method = "holm", significance = list(), geom = "text", position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, parse = FALSE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{group.by}{(optional) character vector specifying the grouping variable; it should be used only for grouped plots. Possible values are : \itemize{ \item \code{"x.var"}: Group by the x-axis variable and perform the test between legend groups. In other words, the p-value is compute between legend groups at each x position \item \code{"legend.var"}: Group by the legend variable and perform the test between x-axis groups. In other words, the test is performed between the x-groups for each legend level. }} \item{label}{the column containing the label (e.g.: label = "p" or label = "p.adj"), where \code{p} is the p-value. Can be also an expression that can be formatted by the \code{\link[glue]{glue}()} package. For example, when specifying label = "t-test, p = \{p\}", the expression \{p\} will be replaced by its value.} \item{label.x.npc, label.y.npc}{can be \code{numeric} or \code{character} vector of the same length as the number of groups and/or panels. If too short they will be recycled. \itemize{ \item If \code{numeric}, value should be between 0 and 1. Coordinates to be used for positioning the label, expressed in "normalized parent coordinates". \item If \code{character}, allowed values include: i) one of c('right', 'left', 'center', 'centre', 'middle') for x-axis; ii) and one of c( 'bottom', 'top', 'center', 'centre', 'middle') for y-axis.}} \item{label.x, label.y}{\code{numeric} Coordinates (in data units) to be used for absolute positioning of the label. If too short they will be recycled.} \item{step.increase}{numeric vector with the increase in fraction of total height for every additional comparison to minimize overlap.} \item{p.adjust.method}{method for adjusting p values (see \code{\link[stats]{p.adjust}}). Has impact only in a situation, where multiple pairwise tests are performed; or when there are multiple grouping variables. Allowed values include "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none". If you don't want to adjust the p value (not recommended), use p.adjust.method = "none".} \item{significance}{a list of arguments specifying the signifcance cutpoints and symbols. For example, \code{significance <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, 0.05, Inf), symbols = c("****", "***", "**", "*", "ns"))}. In other words, we use the following convention for symbols indicating statistical significance: \itemize{ \item \code{ns}: p > 0.05 \item \code{*}: p <= 0.05 \item \code{**}: p <= 0.01 \item \code{***}: p <= 0.001 \item \code{****}: p <= 0.0001 }} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If FALSE (the default), removes missing values with a warning. If TRUE silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{parse}{If TRUE, the labels will be parsed into expressions and displayed as described in \code{?plotmath}.} \item{...}{other arguments passed to the function \code{geom_bracket()} or \code{geom_text()}} } \description{ Add Kruskal-Wallis test p-values to a ggplot, such as box blots, dot plots and stripcharts. } \section{Computed variables}{ \itemize{ \item{statistic}: the Kruskal-Wallis rank sum chi-squared statistic used to compute the p-value. \item{p}: p-value. \item{p.adj}: Adjusted p-values. \item{p.signif}: P-value significance. \item{p.adj.signif}: Adjusted p-value significance. \item{p.format}: Formated p-value. \item{p.adj.format}: Formated adjusted p-value. \item{n}: number of samples. } } \examples{ # Data preparation #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Transform `dose` into factor variable df <- ToothGrowth df$dose <- as.factor(df$dose) # Add a random grouping variable set.seed(123) df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) df$len <- ifelse(df$group == "grp2", df$len+2, df$len) df$len <- ifelse(df$group == "grp3", df$len+7, df$len) head(df, 3) # Basic boxplot #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Create a basic boxplot # Add 5\% and 10\% space to the plot bottom and the top, respectively bxp <- ggboxplot(df, x = "dose", y = "len") + scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) # Add the p-value to the boxplot bxp + stat_kruskal_test() # Change the label position # Using coordinates in data units bxp + stat_kruskal_test(label.x = "1", label.y = 10, hjust = 0) # Format the p-value differently custom_p_format <- function(p) { rstatix::p_format(p, accuracy = 0.0001, digits = 3, leading.zero = FALSE) } bxp + stat_kruskal_test( label = "Kruskal-Wallis, italic(p) = {custom_p_format(p)}{p.signif}" ) # Show a detailed label in italic bxp + stat_kruskal_test(label = "as_detailed_italic") # Faceted plots #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Create a ggplot facet bxp <- ggboxplot(df, x = "dose", y = "len", facet.by = "supp") + scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) # Add p-values bxp + stat_kruskal_test() # Grouped plots #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% bxp2 <- ggboxplot(df, x = "group", y = "len", color = "dose", palette = "npg") # For each x-position, computes tests between legend groups bxp2 + stat_kruskal_test(aes(group = dose), label = "p = {p.format}{p.signif}") # For each legend group, computes tests between x variable groups bxp2 + stat_kruskal_test(aes(group = dose, color = dose), group.by = "legend.var") } ggpubr/man/stat_conf_ellipse.Rd0000644000176200001440000000706714333713444016317 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_conf_ellipse.R \name{stat_conf_ellipse} \alias{stat_conf_ellipse} \title{Plot confidence ellipses.} \usage{ stat_conf_ellipse( mapping = NULL, data = NULL, geom = "path", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, level = 0.95, npoint = 100, bary = TRUE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If \code{FALSE}, the default, missing values are removed with a warning. If \code{TRUE}, missing values are silently removed.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{level}{confidence level used to construct the ellipses. By default, 0.95.} \item{npoint}{number of points used to draw the ellipses.} \item{bary}{logical value. If TRUE, the coordinates of the ellipse around the barycentre of individuals are calculated.} \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{layer()}}. These are often aesthetics, used to set an aesthetic to a fixed value, like \code{colour = "red"} or \code{size = 3}. They may also be parameters to the paired geom/stat.} } \description{ Plot confidence ellipses around barycenters. The method for computing confidence ellipses has been modified from \code{FactoMineR::coord.ellipse()}. } \examples{ # Load data data("mtcars") df <- mtcars df$cyl <- as.factor(df$cyl) # scatter plot with confidence ellipses ggscatter(df, x = "wt", y = "mpg", color = "cyl")+ stat_conf_ellipse(aes(color = cyl)) ggscatter(df, x = "wt", y = "mpg", color = "cyl")+ stat_conf_ellipse(aes(color = cyl, fill = cyl), alpha = 0.1, geom = "polygon") } \seealso{ \code{\link{stat_conf_ellipse}} } ggpubr/man/facet.Rd0000644000176200001440000000630214333713444013673 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/facet.R \name{facet} \alias{facet} \title{Facet a ggplot into Multiple Panels} \usage{ facet( p, facet.by, nrow = NULL, ncol = NULL, scales = "fixed", short.panel.labs = TRUE, labeller = "label_value", panel.labs = NULL, panel.labs.background = list(color = NULL, fill = NULL), panel.labs.font = list(face = NULL, color = NULL, size = NULL, angle = NULL), panel.labs.font.x = panel.labs.font, panel.labs.font.y = panel.labs.font, strip.position = "top", ... ) } \arguments{ \item{p}{a ggplot} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{nrow, ncol}{Number of rows and columns in the panel. Used only when the data is faceted by one grouping variable.} \item{scales}{should axis scales of panels be fixed ("fixed", the default), free ("free"), or free in one dimension ("free_x", "free_y").} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{labeller}{Character vector. An alternative to the argument \code{short.panel.labs}. Possible values are one of "label_both" (panel labelled by both grouping variable names and levels) and "label_value" (panel labelled with only grouping levels).} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{panel.labs.background}{a list to customize the background of panel labels. Should contain the combination of the following elements: \itemize{ \item \code{color, linetype, size}: background line color, type and size \item \code{fill}: background fill color. } For example, panel.labs.background = list(color = "blue", fill = "pink", linetype = "dashed", size = 0.5).} \item{panel.labs.font}{a list of aestheics indicating the size (e.g.: 14), the face/style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") and the orientation angle (e.g.: 45) of panel labels.} \item{panel.labs.font.x, panel.labs.font.y}{same as panel.labs.font but for only x and y direction, respectively.} \item{strip.position}{(used only in \code{facet_wrap()}). By default, the labels are displayed on the top of the plot. Using \code{strip.position} it is possible to place the labels on either of the four sides by setting \code{strip.position = c("top", "bottom", "left", "right")}} \item{...}{not used} } \description{ Create multi-panel plots of a data set grouped by one or two grouping variables. Wrapper around \code{\link[ggplot2]{facet_wrap}} } \examples{ p <- ggboxplot(ToothGrowth, x = "dose", y = "len", color = "supp") print(p) facet(p, facet.by = "supp") # Customize facet(p + theme_bw(), facet.by = "supp", short.panel.labs = FALSE, # Allow long labels in panels panel.labs.background = list(fill = "steelblue", color = "steelblue") ) } ggpubr/man/ggtexttable.Rd0000644000176200001440000003237314350533257015133 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggtexttable.R \name{ggtexttable} \alias{ggtexttable} \alias{ttheme} \alias{colnames_style} \alias{rownames_style} \alias{tbody_style} \alias{table_cell_font} \alias{table_cell_bg} \alias{tab_cell_crossout} \alias{tab_ncol} \alias{tab_nrow} \alias{tab_add_hline} \alias{tab_add_vline} \alias{tab_add_border} \alias{tbody_add_border} \alias{thead_add_border} \alias{tab_add_title} \alias{tab_add_footnote} \title{Draw a Textual Table} \usage{ ggtexttable( x, rows = rownames(x), cols = colnames(x), vp = NULL, theme = ttheme(), ... ) ttheme( base_style = "default", base_size = 11, base_colour = "black", padding = unit(c(4, 4), "mm"), colnames.style = colnames_style(size = base_size), rownames.style = rownames_style(size = base_size), tbody.style = tbody_style(size = base_size) ) colnames_style( color = "black", face = "bold", size = 12, fill = "grey80", linewidth = 1, linecolor = "white", parse = FALSE, ... ) rownames_style( color = "black", face = "italic", size = 12, fill = NA, linewidth = 1, linecolor = "white", parse = FALSE, ... ) tbody_style( color = "black", face = "plain", size = 12, fill = c("grey95", "grey90"), linewidth = 1, linecolor = "white", parse = FALSE, ... ) table_cell_font(tab, row, column, face = NULL, size = NULL, color = NULL) table_cell_bg( tab, row, column, fill = NULL, color = NULL, linewidth = NULL, alpha = NULL ) tab_cell_crossout( tab, row, column, linetype = 1, linewidth = 1, linecolor = "black", reduce.size.by = 0 ) tab_ncol(tab) tab_nrow(tab) tab_add_hline( tab, at.row = 2:tab_nrow(tab), row.side = c("bottom", "top"), from.column = 1, to.column = tab_ncol(tab), linetype = 1, linewidth = 1, linecolor = "black" ) tab_add_vline( tab, at.column = 2:tab_ncol(tab), column.side = c("left", "right"), from.row = 1, to.row = tab_nrow(tab), linetype = 1, linewidth = 1, linecolor = "black" ) tab_add_border( tab, from.row = 2, to.row = tab_nrow(tab), from.column = 1, to.column = tab_ncol(tab), linetype = 1, linewidth = 1, linecolor = "black" ) tbody_add_border( tab, from.row = 2, to.row = tab_nrow(tab), from.column = 1, to.column = tab_ncol(tab), linetype = 1, linewidth = 1, linecolor = "black" ) thead_add_border( tab, from.row = 1, to.row = 1, from.column = 1, to.column = tab_ncol(tab), linetype = 1, linewidth = 1, linecolor = "black" ) tab_add_title( tab, text, face = NULL, size = NULL, color = NULL, family = NULL, padding = unit(1.5, "line"), just = "left", hjust = NULL, vjust = NULL ) tab_add_footnote( tab, text, face = NULL, size = NULL, color = NULL, family = NULL, padding = unit(1.5, "line"), just = "right", hjust = NULL, vjust = NULL ) } \arguments{ \item{x}{a \code{data.frame} or \code{matrix}.} \item{rows}{optional vector to specify row names} \item{cols}{optional vector to specify column names} \item{vp}{optional viewport} \item{theme}{a list, as returned by the function \code{ttheme()}, defining the parameters of the table theme. Allowed values include one of \code{ttheme()} and \code{ttheme_clean()}.} \item{...}{extra parameters for text justification, e.g.: hjust and x. Default is "centre" for the body and header, and "right" for the row names. Left justification: \code{hjust = 0, x = 0.1}. Right justification: \code{hjust = 1, x = 0.9}.} \item{base_style}{character string the table style/theme. The available themes are illustrated in the \href{https://rpkgs.datanovia.com/ggpubr/files/ggtexttable-theme.pdf}{ggtexttable-theme.pdf} file. Allowed values include one of \code{c("default", "blank", "classic", "minimal", "light", "lBlack", "lBlue", "lRed", "lGreen", "lViolet", "lCyan", "lOrange", "lBlackWhite", "lBlueWhite", "lRedWhite", "lGreenWhite", "lVioletWhite", "lCyanWhite", "lOrangeWhite", "mBlack", "mBlue", "mRed", "mGreen", "mViolet", "mCyan", "mOrange", "mBlackWhite", "mBlueWhite", "mRedWhite", "mGreenWhite", "mVioletWhite", "mCyanWhite", "mOrangeWhite" )}. Note that, l = "light"; m = "medium".} \item{base_size}{default font size} \item{base_colour}{default font colour} \item{padding}{length-2 unit vector specifying the horizontal and vertical padding of text within each cell} \item{colnames.style}{a list, as returned by the function \code{colnames_style()}, defining the style of the table column names. Considered only when \code{base_size = "default"}.} \item{rownames.style}{a list, as returned by the function \code{rownames_style()}, defining the style of the table row names. Considered only when \code{base_size = "default"}.} \item{tbody.style}{a list, as returned by the function \code{tbody_style()}, defining the style of the table body. Considered only when \code{base_size = "default"}.} \item{color, face, size}{text font color, face and size, respectively. Allowed values for face include c("plain", "bold", "italic", "bold.italic").} \item{fill}{background color.} \item{linewidth, linecolor}{line width and color, respectively.} \item{parse}{logical, default behaviour for parsing text as plotmath} \item{tab}{an object from \code{ggtexttable} or from \code{gridExtra::tableGrob()}.} \item{row, column}{an integer specifying the row and the column numbers for the cell of interest.} \item{alpha}{numeric value specifying fill color transparency. Value should be in [0, 1], where 0 is full transparency and 1 is no transparency.} \item{linetype}{line type} \item{reduce.size.by}{Numeric value in [0, 1] to reduce the size by.} \item{at.row}{a numeric vector of row indexes; for example \code{at.row = c(1, 2)}.} \item{row.side}{row side to which the horinzotal line should be added. Can be one of \code{c("bottom", "top")}.} \item{from.column}{integer indicating the column from which to start drawing the horizontal line.} \item{to.column}{integer indicating the column to which the horizontal line should end.} \item{at.column}{a numeric vector of column indexes; for example \code{at.column = c(1, 2)}.} \item{column.side}{column side to which the vertical line should be added. Can be one of \code{c("left", "right")}.} \item{from.row}{integer indicating the row from which to start drawing the horizontal line.} \item{to.row}{integer indicating the row to which the vertical line should end.} \item{text}{text to be added as title or footnote.} \item{family}{font family} \item{just}{The justification of the text relative to its (x, y) location. If there are two values, the first value specifies horizontal justification and the second value specifies vertical justification. Possible string values are: "left", "right", "centre", "center", "bottom", and "top". For numeric values, 0 means left (bottom) alignment and 1 means right (top) alignment.} \item{hjust}{A numeric vector specifying horizontal justification. If specified, overrides the just setting.} \item{vjust}{A numeric vector specifying vertical justification. If specified, overrides the just setting.} } \value{ an object of class ggplot. } \description{ Draw a textual table. \itemize{ \item \code{ggtexttable()}: draw a textual table. \item \code{ttheme()}: customize table theme. \item \code{rownames_style(), colnames_style(), tbody_style()}: helper functions to customize the table row names, column names and body. \item \code{table_cell_font()}: access to a table cell for changing the text font (size and face). \item \code{table_cell_bg()}: access to a table cell for changing the background (fill, color, linewidth). \item \code{tab_cell_crossout()}: cross out a table cell. \item \code{tab_ncol(), tab_nrow()}: returns, respectively, the number of columns and rows in a ggtexttable. \item \code{tab_add_hline()}: Creates horizontal lines or separators at the top or the bottom side of a given specified row. \item \code{tab_add_vline()}: Creates vertical lines or separators at the right or the left side of a given specified column. \item \code{tab_add_border(), tbody_add_border(), thead_add_border()}: Add borders to table; tbody is for table body and thead is for table head. \item \code{tab_add_title(),tab_add_footnote()}: Add title, subtitle and footnote to a table. } } \examples{ # data df <- head(iris) # Default table # Remove row names using rows = NULL ggtexttable(df, rows = NULL) # Text justification for individual cells/rows/columns (#335) # First column is left justified i.e., hjust = 0 , x = 0.1 # Remaining columns are right justified i.e., hjust = 1 , x = 0.9 table_theme <- ttheme( tbody.style = tbody_style( hjust = as.vector(matrix(c(0, 1, 1, 1, 1), ncol = 5, nrow = nrow(df), byrow = TRUE)), x = as.vector(matrix(c(.1, .9, .9,.9, .9), ncol = 5, nrow = nrow(df), byrow = TRUE)) ) ) ggtexttable(df, rows = NULL, theme = table_theme) # Blank theme ggtexttable(df, rows = NULL, theme = ttheme("blank")) # light theme ggtexttable(df, rows = NULL, theme = ttheme("light")) # Column names border only ggtexttable(df, rows = NULL, theme = ttheme("blank")) \%>\% tab_add_hline(at.row = 1:2, row.side = "top", linewidth = 2) # classic theme ggtexttable(df, rows = NULL, theme = ttheme("classic")) # minimal theme ggtexttable(df, rows = NULL, theme = ttheme("minimal")) # Medium blue (mBlue) theme ggtexttable(df, rows = NULL, theme = ttheme("mBlue")) # Customize the table as you want ggtexttable(df, rows = NULL, theme = ttheme( colnames.style = colnames_style(color = "white", fill = "#8cc257"), tbody.style = tbody_style(color = "black", fill = c("#e8f3de", "#d3e8bb")) ) ) # Use RColorBrewer palette # Provide as many fill color as there are rows in the table body, here nrow = 6 ggtexttable(df, theme = ttheme( colnames.style = colnames_style(fill = "white"), tbody.style = tbody_style(fill = get_palette("RdBu", 6)) ) ) # Text justification #:::::::::::::::::::::::::::::::::::::::::::::: # Default is "centre" for the body and header, and "right" for the row names. # Left justification: hjust=0, x=0.1 # Right justification: hjust=1, x=0.9 tbody.style = tbody_style(color = "black", fill = c("#e8f3de", "#d3e8bb"), hjust=1, x=0.9) ggtexttable(head(iris), rows = NULL, theme = ttheme( colnames.style = colnames_style(color = "white", fill = "#8cc257"), tbody.style = tbody.style ) ) # Access and modify the font and # the background of table cells # ::::::::::::::::::::::::::::::::::::::::::::: tab <- ggtexttable(head(iris), rows = NULL, theme = ttheme("classic")) tab <- table_cell_font(tab, row = 3, column = 2, face = "bold") tab <- table_cell_bg(tab, row = 4, column = 3, linewidth = 5, fill="darkolivegreen1", color = "darkolivegreen4") tab # Change table cells background and font for column 3, # Spaning from row 2 to the last row in the data tab <- ggtexttable(df, rows = NULL, theme = ttheme("classic")) tab \%>\% table_cell_bg(row = 2:tab_nrow(tab), column = 3, fill = "darkblue") \%>\% table_cell_font(row = 2:tab_nrow(tab), column = 3, face = "italic", color = "white") # Add separators and borders # ::::::::::::::::::::::::::::::::::::::::::::::::::: # Table with blank theme tab <- ggtexttable(df, theme = ttheme("blank"), rows = NULL) # Add horizontal and vertical lines tab \%>\% tab_add_hline(at.row = c(1, 2), row.side = "top", linewidth = 3, linetype = 1) \%>\% tab_add_hline(at.row = c(7), row.side = "bottom", linewidth = 3, linetype = 1) \%>\% tab_add_vline(at.column = 2:tab_ncol(tab), column.side = "left", from.row = 2, linetype = 2) # Add borders to table body and header # Cross out some cells tab \%>\% tbody_add_border() \%>\% thead_add_border() \%>\% tab_cell_crossout( row = c(2, 4), column = 3, linecolor = "red", reduce.size.by = 0.6 ) # Add titles andd footnote # ::::::::::::::::::::::::::::::::::::::::::::::::::: # Add titles and footnote # Wrap subtitle into multiple lines using strwrap() main.title <- "Edgar Anderson's Iris Data" subtitle <- paste0( "This famous (Fisher's or Anderson's) iris data set gives the measurements", " in centimeters of the variables sepal length and width and petal length and width,", " respectively, for 50 flowers from each of 3 species of iris.", " The species are Iris setosa, versicolor, and virginica." ) \%>\% strwrap(width = 80) \%>\% paste(collapse = "\n") tab <- ggtexttable(head(iris), theme = ttheme("light")) tab \%>\% tab_add_title(text = subtitle, face = "plain", size = 10) \%>\% tab_add_title(text = main.title, face = "bold", padding = unit(0.1, "line")) \%>\% tab_add_footnote(text = "*Table created using ggpubr", size = 10, face = "italic") # Combine density plot and summary table #::::::::::::::::::::::::::::::::::::: # Density plot of "Sepal.Length" density.p <- ggdensity(iris, x = "Sepal.Length", fill = "Species", palette = "jco") # Draw the summary table of Sepal.Length # Descriptive statistics by groups stable <- desc_statby(iris, measure.var = "Sepal.Length", grps = "Species") stable <- stable[, c("Species", "length", "mean", "sd")] stable.p <- ggtexttable(stable, rows = NULL, theme = ttheme("mOrange")) # Arrange the plots on the same page ggarrange(density.p, stable.p, ncol = 1, nrow = 2, heights = c(1, 0.5)) } ggpubr/man/geom_bracket.Rd0000644000176200001440000001525214333713444015237 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/geom_bracket.R \name{stat_bracket} \alias{stat_bracket} \alias{geom_bracket} \title{Add Brackets with Labels to a GGPlot} \usage{ stat_bracket( mapping = NULL, data = NULL, position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, label = NULL, type = c("text", "expression"), y.position = NULL, xmin = NULL, xmax = NULL, step.increase = 0, step.group.by = NULL, tip.length = 0.03, bracket.nudge.y = 0, bracket.shorten = 0, size = 0.3, label.size = 3.88, family = "", vjust = 0, ... ) geom_bracket( mapping = NULL, data = NULL, stat = "bracket", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, label = NULL, type = c("text", "expression"), y.position = NULL, xmin = NULL, xmax = NULL, step.increase = 0, step.group.by = NULL, tip.length = 0.03, bracket.nudge.y = 0, bracket.shorten = 0, size = 0.3, label.size = 3.88, family = "", vjust = 0, coord.flip = FALSE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If \code{FALSE} (the default), removes missing values with a warning. If \code{TRUE} silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{label}{character vector with alternative label, if not null test is ignored} \item{type}{the label type. Can be one of "text" and "expression" (for parsing plotmath expression).} \item{y.position}{numeric vector with the y positions of the brackets} \item{xmin}{numeric vector with the positions of the left sides of the brackets} \item{xmax}{numeric vector with the positions of the right sides of the brackets} \item{step.increase}{numeric vector with the increase in fraction of total height for every additional comparison to minimize overlap.} \item{step.group.by}{a variable name for grouping brackets before adding step.increase. Useful to group bracket by facet panel.} \item{tip.length}{numeric vector with the fraction of total height that the bar goes down to indicate the precise column} \item{bracket.nudge.y}{Vertical adjustment to nudge brackets by. Useful to move up or move down the bracket. If positive value, brackets will be moved up; if negative value, brackets are moved down.} \item{bracket.shorten}{a small numeric value in [0-1] for shortening the with of bracket.} \item{size}{change the width of the lines of the bracket} \item{label.size}{change the size of the label text} \item{family}{change the font used for the text} \item{vjust}{move the text up or down relative to the bracket} \item{...}{other arguments passed on to \code{\link{layer}}. These are often aesthetics, used to set an aesthetic to a fixed value, like \code{color = "red"} or \code{size = 3}. They may also be parameters to the paired geom/stat.} \item{stat}{The statistical transformation to use on the data for this layer, either as a \code{ggproto} \code{Geom} subclass or as a string naming the stat stripped of the \code{stat_} prefix (e.g. \code{"count"} rather than \code{"stat_count"})} \item{coord.flip}{logical. If \code{TRUE}, flip x and y coordinates so that horizontal becomes vertical, and vertical, horizontal. When adding the p-values to a horizontal ggplot (generated using \code{\link[ggplot2]{coord_flip}()}), you need to specify the option \code{coord.flip = TRUE}.} } \description{ add brackets with label annotation to a ggplot. Helpers for adding p-value or significance levels to a plot. } \examples{ df <- ToothGrowth df$dose <- factor(df$dose) # Add bracket with labels ggboxplot(df, x = "dose", y = "len") + geom_bracket( xmin = "0.5", xmax = "1", y.position = 30, label = "t-test, p < 0.05" ) # Customize bracket tip.length tip.length ggboxplot(df, x = "dose", y = "len") + geom_bracket( xmin = "0.5", xmax = "1", y.position = 30, label = "t-test, p < 0.05", tip.length = c(0.2, 0.02) ) #Using plotmath expression ggboxplot(df, x = "dose", y = "len") + geom_bracket( xmin = "0.5", xmax = "1", y.position = 30, label = "list(~italic(p)<=0.001)", type = "expression", tip.length = c(0.2, 0.02) ) # Specify multiple brackets manually ggboxplot(df, x = "dose", y = "len") + geom_bracket( xmin = c("0.5", "1"), xmax = c("1", "2"), y.position = c(30, 35), label = c("***", "**"), tip.length = 0.01 ) # Compute statistical tests and add p-values stat.test <- compare_means(len ~ dose, ToothGrowth, method = "t.test") ggboxplot(df, x = "dose", y = "len") + geom_bracket( aes(xmin = group1, xmax = group2, label = signif(p, 2)), data = stat.test, y.position = 35 ) # Increase step length between brackets ggboxplot(df, x = "dose", y = "len") + geom_bracket( aes(xmin = group1, xmax = group2, label = signif(p, 2)), data = stat.test, y.position = 35, step.increase = 0.1 ) # Or specify the positions of each comparison ggboxplot(df, x = "dose", y = "len") + geom_bracket( aes(xmin = group1, xmax = group2, label = signif(p, 2)), data = stat.test, y.position = c(32, 35, 38) ) } ggpubr/man/stat_stars.Rd0000644000176200001440000000561114332576562015011 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_stars.R \name{stat_stars} \alias{stat_stars} \title{Add Stars to a Scatter Plot} \usage{ stat_stars( mapping = NULL, data = NULL, geom = "segment", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If FALSE (the default), removes missing values with a warning. If TRUE silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{...}{other arguments to pass to \code{\link[ggplot2]{geom_segment}}.} } \description{ Create a star plot by drawing segments from group centroid to each points. } \examples{ # Load data data("mtcars") df <- mtcars df$cyl <- as.factor(df$cyl) # Scatter plot with ellipses and group mean points ggscatter(df, x = "wt", y = "mpg", color = "cyl", shape = "cyl", mean.point = TRUE, ellipse = TRUE)+ stat_stars(aes(color = cyl)) } \seealso{ \code{\link{ggscatter}} } ggpubr/man/stat_compare_means.Rd0000644000176200001440000001760614334200505016454 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_compare_means.R \name{stat_compare_means} \alias{stat_compare_means} \title{Add Mean Comparison P-values to a ggplot} \usage{ stat_compare_means( mapping = NULL, data = NULL, method = NULL, paired = FALSE, method.args = list(), ref.group = NULL, comparisons = NULL, hide.ns = FALSE, label.sep = ", ", label = NULL, label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, vjust = 0, tip.length = 0.03, bracket.size = 0.3, step.increase = 0, symnum.args = list(), geom = "text", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{method}{a character string indicating which method to be used for comparing means.} \item{paired}{a logical indicating whether you want a paired test. Used only in \code{\link[stats]{t.test}} and in \link[stats]{wilcox.test}.} \item{method.args}{a list of additional arguments used for the test method. For example one might use \code{method.args = list(alternative = "greater")} for wilcoxon test.} \item{ref.group}{a character string specifying the reference group. If specified, for a given grouping variable, each of the group levels will be compared to the reference group (i.e. control group). \code{ref.group} can be also \code{".all."}. In this case, each of the grouping variable levels is compared to all (i.e. basemean).} \item{comparisons}{A list of length-2 vectors. The entries in the vector are either the names of 2 values on the x-axis or the 2 integers that correspond to the index of the groups of interest, to be compared.} \item{hide.ns}{logical value. If TRUE, hide ns symbol when displaying significance levels.} \item{label.sep}{a character string to separate the terms. Default is ", ", to separate the correlation coefficient and the p.value.} \item{label}{character string specifying label type. Allowed values include "p.signif" (shows the significance levels), "p.format" (shows the formatted p value).} \item{label.x.npc, label.y.npc}{can be \code{numeric} or \code{character} vector of the same length as the number of groups and/or panels. If too short they will be recycled. \itemize{ \item If \code{numeric}, value should be between 0 and 1. Coordinates to be used for positioning the label, expressed in "normalized parent coordinates". \item If \code{character}, allowed values include: i) one of c('right', 'left', 'center', 'centre', 'middle') for x-axis; ii) and one of c( 'bottom', 'top', 'center', 'centre', 'middle') for y-axis.}} \item{label.x, label.y}{\code{numeric} Coordinates (in data units) to be used for absolute positioning of the label. If too short they will be recycled.} \item{vjust}{move the text up or down relative to the bracket.} \item{tip.length}{numeric vector with the fraction of total height that the bar goes down to indicate the precise column. Default is 0.03. Can be of same length as the number of comparisons to adjust specifically the tip lenth of each comparison. For example tip.length = c(0.01, 0.03). If too short they will be recycled.} \item{bracket.size}{Width of the lines of the bracket.} \item{step.increase}{numeric vector with the increase in fraction of total height for every additional comparison to minimize overlap.} \item{symnum.args}{a list of arguments to pass to the function \code{\link[stats]{symnum}} for symbolic number coding of p-values. For example, \code{symnum.args <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, 0.05, Inf), symbols = c("****", "***", "**", "*", "ns"))}. In other words, we use the following convention for symbols indicating statistical significance: \itemize{ \item \code{ns}: p > 0.05 \item \code{*}: p <= 0.05 \item \code{**}: p <= 0.01 \item \code{***}: p <= 0.001 \item \code{****}: p <= 0.0001 }} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If FALSE (the default), removes missing values with a warning. If TRUE silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{...}{other arguments to pass to \code{\link[ggplot2]{geom_text}} or \code{\link[ggplot2:geom_text]{geom_label}}.} } \description{ Add mean comparison p-values to a ggplot, such as box blots, dot plots and stripcharts. } \examples{ # Load data data("ToothGrowth") head(ToothGrowth) # Two independent groups #::::::::::::::::::::::::::::::::::::::::::::::::: p <- ggboxplot(ToothGrowth, x = "supp", y = "len", color = "supp", palette = "npg", add = "jitter") # Add p-value p + stat_compare_means() # Change method p + stat_compare_means(method = "t.test") # Paired samples #::::::::::::::::::::::::::::::::::::::::::::::::: ggpaired(ToothGrowth, x = "supp", y = "len", color = "supp", line.color = "gray", line.size = 0.4, palette = "npg")+ stat_compare_means(paired = TRUE) # More than two groups #::::::::::::::::::::::::::::::::::::::::::::::::: # Pairwise comparisons: Specify the comparisons you want my_comparisons <- list( c("0.5", "1"), c("1", "2"), c("0.5", "2") ) ggboxplot(ToothGrowth, x = "dose", y = "len", color = "dose", palette = "npg")+ # Add pairwise comparisons p-value stat_compare_means(comparisons = my_comparisons, label.y = c(29, 35, 40))+ stat_compare_means(label.y = 45) # Add global Anova p-value # Multiple pairwise test against a reference group ggboxplot(ToothGrowth, x = "dose", y = "len", color = "dose", palette = "npg")+ stat_compare_means(method = "anova", label.y = 40)+ # Add global p-value stat_compare_means(aes(label = after_stat(p.signif)), method = "t.test", ref.group = "0.5") # Multiple grouping variables #::::::::::::::::::::::::::::::::::::::::::::::::: # Box plot facetted by "dose" p <- ggboxplot(ToothGrowth, x = "supp", y = "len", color = "supp", palette = "npg", add = "jitter", facet.by = "dose", short.panel.labs = FALSE) # Use only p.format as label. Remove method name. p + stat_compare_means( aes(label = paste0("p = ", after_stat(p.format))) ) } \seealso{ \code{\link{compare_means}} } ggpubr/man/ggbarplot.Rd0000644000176200001440000002161314367732422014600 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggbarplot.R \name{ggbarplot} \alias{ggbarplot} \title{Bar plot} \usage{ ggbarplot( data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "white", palette = NULL, size = NULL, width = NULL, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, select = NULL, remove = NULL, order = NULL, add = "none", add.params = list(), error.plot = "errorbar", label = FALSE, lab.col = "black", lab.size = 4, lab.pos = c("out", "in"), lab.vjust = NULL, lab.hjust = NULL, lab.nb.digits = NULL, sort.val = c("none", "desc", "asc"), sort.by.groups = TRUE, top = Inf, position = position_stack(), ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x, y}{x and y variables for drawing.} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{color, fill}{outline and fill colors.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{width}{numeric value between 0 and 1 specifying box width.} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{select}{character vector specifying which items to display.} \item{remove}{character vector specifying which items to remove from the plot.} \item{order}{character vector specifying the order of items.} \item{add}{character vector for adding another plot element (e.g.: dot plot or error bars). Allowed values are one or the combination of: "none", "dotplot", "jitter", "boxplot", "point", "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", "median_range"; see ?desc_statby for more details.} \item{add.params}{parameters (color, shape, size, fill, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{error.plot}{plot type used to visualize error. Allowed values are one of c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", "lower_linerange"). Default value is "pointrange" or "errorbar". Used only when add != "none" and add contains one "mean_*" or "med_*" where "*" = sd, se, ....} \item{label}{specify whether to add labels on the bar plot. Allowed values are: \itemize{ \item \strong{logical value}: If TRUE, y values is added as labels on the bar plot \item \strong{character vector}: Used as text labels; must be the same length as y. }} \item{lab.col, lab.size}{text color and size for labels.} \item{lab.pos}{character specifying the position for labels. Allowed values are "out" (for outside) or "in" (for inside). Ignored when lab.vjust != NULL.} \item{lab.vjust}{numeric, vertical justification of labels. Provide negative value (e.g.: -0.4) to put labels outside the bars or positive value to put labels inside (e.g.: 2).} \item{lab.hjust}{numeric, horizontal justification of labels.} \item{lab.nb.digits}{integer indicating the number of decimal places (round) to be used.} \item{sort.val}{a string specifying whether the value should be sorted. Allowed values are "none" (no sorting), "asc" (for ascending) or "desc" (for descending).} \item{sort.by.groups}{logical value. If TRUE the data are sorted by groups. Used only when sort.val != "none".} \item{top}{a numeric value specifying the number of top elements to be shown.} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to be passed to ggpar().} } \description{ Create a bar plot. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Data df <- data.frame(dose=c("D0.5", "D1", "D2"), len=c(4.2, 10, 29.5)) print(df) # Basic plot with label outsite # +++++++++++++++++++++++++++ ggbarplot(df, x = "dose", y = "len", label = TRUE, label.pos = "out") # Change width ggbarplot(df, x = "dose", y = "len", width = 0.5) # Change the plot orientation: horizontal ggbarplot(df, "dose", "len", orientation = "horiz") # Change the default order of items ggbarplot(df, "dose", "len", order = c("D2", "D1", "D0.5")) # Change colors # +++++++++++++++++++++++++++ # Change fill and outline color # add labels inside bars ggbarplot(df, "dose", "len", fill = "steelblue", color = "steelblue", label = TRUE, lab.pos = "in", lab.col = "white") # Change colors by groups: dose # Use custom color palette ggbarplot(df, "dose", "len", color = "dose", palette = c("#00AFBB", "#E7B800", "#FC4E07")) # Change fill and outline colors by groups ggbarplot(df, "dose", "len", fill = "dose", color = "dose", palette = c("#00AFBB", "#E7B800", "#FC4E07")) # Plot with multiple groups # +++++++++++++++++++++ # Create some data df2 <- data.frame(supp=rep(c("VC", "OJ"), each=3), dose=rep(c("D0.5", "D1", "D2"),2), len=c(6.8, 15, 33, 4.2, 10, 29.5)) print(df2) # Plot "len" by "dose" and change color by a second group: "supp" # Add labels inside bars ggbarplot(df2, "dose", "len", fill = "supp", color = "supp", palette = "Paired", label = TRUE, lab.col = "white", lab.pos = "in") # Change position: Interleaved (dodged) bar plot ggbarplot(df2, "dose", "len", fill = "supp", color = "supp", palette = "Paired", label = TRUE, position = position_dodge(0.9)) # Add points and errors # ++++++++++++++++++++++++++ # Data: ToothGrowth data set we'll be used. df3 <- ToothGrowth head(df3, 10) # It can be seen that for each group we have # different values ggbarplot(df3, x = "dose", y = "len") # Visualize the mean of each group ggbarplot(df3, x = "dose", y = "len", add = "mean") # Add error bars: mean_se # (other values include: mean_sd, mean_ci, median_iqr, ....) # Add labels ggbarplot(df3, x = "dose", y = "len", add = "mean_se", label = TRUE, lab.vjust = -1.6) # Use only "upper_errorbar" ggbarplot(df3, x = "dose", y = "len", add = "mean_se", error.plot = "upper_errorbar") # Change error.plot to "pointrange" ggbarplot(df3, x = "dose", y = "len", add = "mean_se", error.plot = "pointrange") # Add jitter points and errors (mean_se) ggbarplot(df3, x = "dose", y = "len", add = c("mean_se", "jitter")) # Add dot and errors (mean_se) ggbarplot(df3, x = "dose", y = "len", add = c("mean_se", "dotplot")) # Multiple groups with error bars and jitter point ggbarplot(df3, x = "dose", y = "len", color = "supp", add = "mean_se", palette = c("#00AFBB", "#E7B800"), position = position_dodge()) } \seealso{ \code{\link{ggpar}}, \code{\link{ggline}} } ggpubr/man/ggpubr-package.Rd0000644000176200001440000000434414343207174015473 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggpubr-package.R \docType{package} \name{ggpubr-package} \alias{ggpubr} \alias{ggpubr-package} \title{ggpubr: 'ggplot2' Based Publication Ready Plots} \description{ The 'ggplot2' package is excellent and flexible for elegant data visualization in R. However the default generated plots requires some formatting before we can send them for publication. Furthermore, to customize a 'ggplot', the syntax is opaque and this raises the level of difficulty for researchers with no advanced R programming skills. 'ggpubr' provides some easy-to-use functions for creating and customizing 'ggplot2'- based publication ready plots. } \details{ General resources: \itemize{ \item \href{https://rpkgs.datanovia.com/ggpubr/}{ggpubr documentation} \item \href{https://www.datanovia.com/en/blog/tag/ggpubr/}{ggpubr tutorials} } } \section{Package options}{ \describe{ \item{ggpubr.parse_aes}{logical indicating whether to parse or not aesthetics variables names. Default is \code{TRUE}. For example, if you want \code{ggpubr} to handle non-standard column names, like \code{A-A}, without parsing, then set this option to \code{FALSE} using \code{options(ggpubr.parse_aes = FALSE)}.} \item{ggpubr.null_device}{A function that creates an appropriate null device. These include: \code{\link[cowplot:pdf_null_device]{cowplot::pdf_null_device}}, \code{\link[cowplot:png_null_device]{cowplot::png_null_device}}, \code{\link[cowplot:cairo_null_device]{cowplot::cairo_null_device}} and \code{\link[cowplot:agg_null_device]{cowplot::agg_null_device}}. Default is \code{\link[cowplot:pdf_null_device]{cowplot::pdf_null_device}}. This is used in function like \code{\link{as_ggplot}()}, which needs to open a graphics device to render ggplot objects into grid graphics objects. This function is used to open null device for avoiding the display of unnecessary blank page when calling \code{\link{ggarrange}()} or \code{\link{as_ggplot}()}} } } \seealso{ Useful links: \itemize{ \item \url{https://rpkgs.datanovia.com/ggpubr/} \item Report bugs at \url{https://github.com/kassambara/ggpubr/issues} } } \author{ \strong{Maintainer}: Alboukadel Kassambara \email{alboukadel.kassambara@gmail.com} } \keyword{internal} ggpubr/man/stat_welch_anova_test.Rd0000644000176200001440000002002214367517301017165 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_welch_anova_test.R \name{stat_welch_anova_test} \alias{stat_welch_anova_test} \title{Add Welch One-Way ANOVA Test P-values to a GGPlot} \usage{ stat_welch_anova_test( mapping = NULL, data = NULL, group.by = NULL, label = "{method}, p = {p.format}", label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, step.increase = 0.1, p.adjust.method = "holm", significance = list(), geom = "text", position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, parse = FALSE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{group.by}{(optional) character vector specifying the grouping variable; it should be used only for grouped plots. Possible values are : \itemize{ \item \code{"x.var"}: Group by the x-axis variable and perform the test between legend groups. In other words, the p-value is compute between legend groups at each x position \item \code{"legend.var"}: Group by the legend variable and perform the test between x-axis groups. In other words, the test is performed between the x-groups for each legend level. }} \item{label}{the column containing the label (e.g.: label = "p" or label = "p.adj"), where \code{p} is the p-value. Can be also an expression that can be formatted by the \code{\link[glue]{glue}()} package. For example, when specifying label = "t-test, p = \{p\}", the expression \{p\} will be replaced by its value.} \item{label.x.npc, label.y.npc}{can be \code{numeric} or \code{character} vector of the same length as the number of groups and/or panels. If too short they will be recycled. \itemize{ \item If \code{numeric}, value should be between 0 and 1. Coordinates to be used for positioning the label, expressed in "normalized parent coordinates". \item If \code{character}, allowed values include: i) one of c('right', 'left', 'center', 'centre', 'middle') for x-axis; ii) and one of c( 'bottom', 'top', 'center', 'centre', 'middle') for y-axis.}} \item{label.x, label.y}{\code{numeric} Coordinates (in data units) to be used for absolute positioning of the label. If too short they will be recycled.} \item{step.increase}{numeric vector with the increase in fraction of total height for every additional comparison to minimize overlap.} \item{p.adjust.method}{method for adjusting p values (see \code{\link[stats]{p.adjust}}). Has impact only in a situation, where multiple pairwise tests are performed; or when there are multiple grouping variables. Allowed values include "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none". If you don't want to adjust the p value (not recommended), use p.adjust.method = "none".} \item{significance}{a list of arguments specifying the signifcance cutpoints and symbols. For example, \code{significance <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, 0.05, Inf), symbols = c("****", "***", "**", "*", "ns"))}. In other words, we use the following convention for symbols indicating statistical significance: \itemize{ \item \code{ns}: p > 0.05 \item \code{*}: p <= 0.05 \item \code{**}: p <= 0.01 \item \code{***}: p <= 0.001 \item \code{****}: p <= 0.0001 }} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If FALSE (the default), removes missing values with a warning. If TRUE silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{parse}{If TRUE, the labels will be parsed into expressions and displayed as described in \code{?plotmath}.} \item{...}{other arguments passed to the function \code{geom_bracket()} or \code{geom_text()}} } \description{ Add Welch one-way ANOVA test p-values to a ggplot, such as box blots, dot plots and stripcharts. } \section{Computed variables}{ \itemize{ \item{statistic}: the value of the test statistic (F-value) \item{DFn}: Degrees of Freedom in the numerator (i.e. DF effect) \item{DFd}: Degrees of Freedom in the denominator (i.e., DF error) \item{p}: p-value. \item{p.adj}: Adjusted p-values. \item{p.signif}: P-value significance. \item{p.adj.signif}: Adjusted p-value significance. \item{p.format}: Formated p-value. \item{p.adj.format}: Formated adjusted p-value. \item{n}: number of samples. } } \examples{ # Data preparation #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Transform `dose` into factor variable df <- ToothGrowth df$dose <- as.factor(df$dose) # Add a random grouping variable set.seed(123) df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) df$len <- ifelse(df$group == "grp2", df$len+2, df$len) df$len <- ifelse(df$group == "grp3", df$len+7, df$len) head(df, 3) # Basic boxplot #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Create a basic boxplot # Add 5\% and 10\% space to the plot bottom and the top, respectively bxp <- ggboxplot(df, x = "dose", y = "len") + scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) # Add the p-value to the boxplot bxp + stat_welch_anova_test() # Change the label position # Using coordinates in data units bxp + stat_welch_anova_test(label.x = "1", label.y = 10, hjust = 0) # Format the p-value differently custom_p_format <- function(p) { rstatix::p_format(p, accuracy = 0.0001, digits = 3, leading.zero = FALSE) } bxp + stat_welch_anova_test( label = "Welch Anova, italic(p) = {custom_p_format(p)}{p.signif}" ) # Show a detailed label in italic bxp + stat_welch_anova_test(label = "as_detailed_italic") # Faceted plots #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Create a ggplot facet bxp <- ggboxplot(df, x = "dose", y = "len", facet.by = "supp") + scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) # Add p-values bxp + stat_welch_anova_test() # Grouped plots #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% bxp2 <- ggboxplot(df, x = "group", y = "len", color = "dose", palette = "npg") # For each x-position, computes tests between legend groups bxp2 + stat_welch_anova_test(aes(group = dose), label = "p = {p.format}{p.signif}") # For each legend group, computes tests between x variable groups bxp2 + stat_welch_anova_test(aes(group = dose, color = dose), group.by = "legend.var") } ggpubr/man/show_line_types.Rd0000644000176200001440000000057414332553656016037 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/show_line_types.R \name{show_line_types} \alias{show_line_types} \title{Line types available in R} \usage{ show_line_types() } \value{ a ggplot. } \description{ Show line types available in R. } \examples{ show_line_types()+ theme_minimal() } \seealso{ \code{\link{ggpar}} and \code{\link{ggline}}. } ggpubr/man/bgcolor.Rd0000644000176200001440000000100614332553656014242 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/bgcolor.R \name{bgcolor} \alias{bgcolor} \title{Change ggplot Panel Background Color} \usage{ bgcolor(color) } \arguments{ \item{color}{background color.} } \description{ Change ggplot panel background color. } \examples{ # Load data data("ToothGrowth") df <- ToothGrowth # Basic plot p <- ggboxplot(df, x = "dose", y = "len") p # Change panel background color p + bgcolor("#BFD5E3")+ border("#BFD5E3") } \seealso{ \link{border}(). } ggpubr/man/ggline.Rd0000644000176200001440000002173514367732422014071 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggline.R \name{ggline} \alias{ggline} \title{Line plot} \usage{ ggline( data, x, y, group = 1, numeric.x.axis = FALSE, combine = FALSE, merge = FALSE, color = "black", palette = NULL, linetype = "solid", plot_type = c("b", "l", "p"), size = 0.5, shape = 19, stroke = NULL, point.size = size, point.color = color, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, select = NULL, remove = NULL, order = NULL, add = "none", add.params = list(), error.plot = "errorbar", label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, show.line.label = FALSE, position = "identity", ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x, y}{x and y variables for drawing.} \item{group}{grouping variable to connect points by line. Allowed values are 1 (for one line, one group) or a character vector specifying the name of the grouping variable (case of multiple lines).} \item{numeric.x.axis}{logical. If TRUE, x axis will be treated as numeric. Default is FALSE.} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{color}{line colors.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{linetype}{line type.} \item{plot_type}{plot type. Allowed values are one of "b" for both line and point; "l" for line only; and "p" for point only. Default is "b".} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{shape}{point shapes.} \item{stroke}{point stroke. Used only for shapes 21-24 to control the thickness of points border.} \item{point.size}{point size.} \item{point.color}{point color.} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{select}{character vector specifying which items to display.} \item{remove}{character vector specifying which items to remove from the plot.} \item{order}{character vector specifying the order of items.} \item{add}{character vector for adding another plot element (e.g.: dot plot or error bars). Allowed values are one or the combination of: "none", "dotplot", "jitter", "boxplot", "point", "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", "median_range"; see ?desc_statby for more details.} \item{add.params}{parameters (color, shape, size, fill, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{error.plot}{plot type used to visualize error. Allowed values are one of c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", "lower_linerange"). Default value is "pointrange" or "errorbar". Used only when add != "none" and add contains one "mean_*" or "med_*" where "*" = sd, se, ....} \item{label}{the name of the column containing point labels. Can be also a character vector with length = nrow(data).} \item{font.label}{a list which can contain the combination of the following elements: the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of labels. For example font.label = list(size = 14, face = "bold", color ="red"). To specify only the size and the style, use font.label = list(size = 14, face = "plain").} \item{label.select}{can be of two formats: \itemize{ \item a character vector specifying some labels to show. \item a list containing one or the combination of the following components: \itemize{ \item \code{top.up} and \code{top.down}: to display the labels of the top up/down points. For example, \code{label.select = list(top.up = 10, top.down = 4)}. \item \code{criteria}: to filter, for example, by x and y variabes values, use this: \code{label.select = list(criteria = "`y` > 2 & `y` < 5 & `x` \%in\% c('A', 'B')")}. } }} \item{repel}{a logical value, whether to use ggrepel to avoid overplotting text labels or not.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{show.line.label}{logical value. If TRUE, shows line labels.} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to geom_dotplot.} } \description{ Create a line plot. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Data df <- data.frame(dose=c("D0.5", "D1", "D2"), len=c(4.2, 10, 29.5)) print(df) # Basic plot # +++++++++++++++++++++++++++ ggline(df, x = "dose", y = "len") # Plot with multiple groups # +++++++++++++++++++++ # Create some data df2 <- data.frame(supp=rep(c("VC", "OJ"), each=3), dose=rep(c("D0.5", "D1", "D2"),2), len=c(6.8, 15, 33, 4.2, 10, 29.5)) print(df2) # Plot "len" by "dose" and # Change line types and point shapes by a second groups: "supp" ggline(df2, "dose", "len", linetype = "supp", shape = "supp") # Change colors # +++++++++++++++++++++ # Change color by group: "supp" # Use custom color palette ggline(df2, "dose", "len", linetype = "supp", shape = "supp", color = "supp", palette = c("#00AFBB", "#E7B800")) # Add points and errors # ++++++++++++++++++++++++++ # Data: ToothGrowth data set we'll be used. df3 <- ToothGrowth head(df3, 10) # It can be seen that for each group we have # different values ggline(df3, x = "dose", y = "len") # Visualize the mean of each group ggline(df3, x = "dose", y = "len", add = "mean") # Add error bars: mean_se # (other values include: mean_sd, mean_ci, median_iqr, ....) # Add labels ggline(df3, x = "dose", y = "len", add = "mean_se") # Change error.plot to "pointrange" ggline(df3, x = "dose", y = "len", add = "mean_se", error.plot = "pointrange") # Add jitter points and errors (mean_se) ggline(df3, x = "dose", y = "len", add = c("mean_se", "jitter")) # Add dot and errors (mean_se) ggline(df3, x = "dose", y = "len", add = c("mean_se", "dotplot"), color = "steelblue") # Add violin and errors (mean_se) ggline(df3, x = "dose", y = "len", add = c("mean_se", "violin"), color = "steelblue") # Multiple groups with error bars # ++++++++++++++++++++++ ggline(df3, x = "dose", y = "len", color = "supp", add = "mean_se", palette = c("#00AFBB", "#E7B800")) # Add jitter ggline(df3, x = "dose", y = "len", color = "supp", add = c("mean_se", "jitter"), palette = c("#00AFBB", "#E7B800")) # Add dot plot ggline(df3, x = "dose", y = "len", color = "supp", add = c("mean_se", "dotplot"), palette = c("#00AFBB", "#E7B800")) } \seealso{ \code{\link{ggpar}}, \code{\link{ggbarplot}} } ggpubr/man/gghistogram.Rd0000644000176200001440000001554414367732422015140 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/gghistogram.R \name{gghistogram} \alias{gghistogram} \title{Histogram plot} \usage{ gghistogram( data, x, y = "count", combine = FALSE, merge = FALSE, weight = NULL, color = "black", fill = NA, palette = NULL, size = NULL, linetype = "solid", alpha = 0.5, bins = NULL, binwidth = NULL, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, add = c("none", "mean", "median"), add.params = list(linetype = "dashed"), rug = FALSE, add_density = FALSE, label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, position = position_identity(), ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x}{variable to be drawn.} \item{y}{one of "density" or "count".} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{weight}{a variable name available in the input data for creating a weighted histogram.} \item{color, fill}{histogram line color and fill color.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{linetype}{line type. See \code{\link{show_line_types}}.} \item{alpha}{numeric value specifying fill color transparency. Value should be in [0, 1], where 0 is full transparency and 1 is no transparency.} \item{bins}{Number of bins. Defaults to 30.} \item{binwidth}{numeric value specifying bin width. use value between 0 and 1 when you have a strong dense dotplot. For example binwidth = 0.2.} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{add}{allowed values are one of "mean" or "median" (for adding mean or median line, respectively).} \item{add.params}{parameters (color, size, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{rug}{logical value. If TRUE, add marginal rug.} \item{add_density}{logical value. If TRUE, add density curves.} \item{label}{the name of the column containing point labels. Can be also a character vector with length = nrow(data).} \item{font.label}{a list which can contain the combination of the following elements: the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of labels. For example font.label = list(size = 14, face = "bold", color ="red"). To specify only the size and the style, use font.label = list(size = 14, face = "plain").} \item{label.select}{can be of two formats: \itemize{ \item a character vector specifying some labels to show. \item a list containing one or the combination of the following components: \itemize{ \item \code{top.up} and \code{top.down}: to display the labels of the top up/down points. For example, \code{label.select = list(top.up = 10, top.down = 4)}. \item \code{criteria}: to filter, for example, by x and y variabes values, use this: \code{label.select = list(criteria = "`y` > 2 & `y` < 5 & `x` \%in\% c('A', 'B')")}. } }} \item{repel}{a logical value, whether to use ggrepel to avoid overplotting text labels or not.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{position}{Position adjustment, either as a string, or the result of a call to a position adjustment function. Allowed values include "identity", "stack", "dodge".} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link[ggplot2]{geom_histogram}} and \code{\link{ggpar}}.} } \description{ Create a histogram plot. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Create some data format set.seed(1234) wdata = data.frame( sex = factor(rep(c("F", "M"), each=200)), weight = c(rnorm(200, 55), rnorm(200, 58))) head(wdata, 4) # Basic density plot # Add mean line and marginal rug gghistogram(wdata, x = "weight", fill = "lightgray", add = "mean", rug = TRUE) # Change outline colors by groups ("sex") # Use custom color palette gghistogram(wdata, x = "weight", add = "mean", rug = TRUE, color = "sex", palette = c("#00AFBB", "#E7B800")) # Change outline and fill colors by groups ("sex") # Use custom color palette gghistogram(wdata, x = "weight", add = "mean", rug = TRUE, color = "sex", fill = "sex", palette = c("#00AFBB", "#E7B800")) # Combine histogram and density plots gghistogram(wdata, x = "weight", add = "mean", rug = TRUE, fill = "sex", palette = c("#00AFBB", "#E7B800"), add_density = TRUE) # Weighted histogram gghistogram(iris, x = "Sepal.Length", weight = "Petal.Length") } \seealso{ \code{\link{ggdensity}} and \code{\link{ggpar}} } ggpubr/man/ggqqplot.Rd0000644000176200001440000000775014367732422014463 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggqqplot.R \name{ggqqplot} \alias{ggqqplot} \title{QQ Plots} \usage{ ggqqplot( data, x, combine = FALSE, merge = FALSE, color = "black", palette = NULL, size = NULL, shape = NULL, add = c("qqline", "none"), add.params = list(linetype = "solid"), conf.int = TRUE, conf.int.level = 0.95, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x}{variable to be drawn.} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{color}{point color.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{size}{point size.} \item{shape}{point shape.} \item{add}{character vector. Allowed values are one of "none" and "qqline" (for adding qqline).} \item{add.params}{parameters (color, size, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{conf.int}{logical value. If TRUE, confidence interval is added.} \item{conf.int.level}{the confidence level. Default value is 0.95.} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link{ggpar}}.} } \description{ Quantile-Quantile plot. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Create some data format set.seed(1234) wdata = data.frame( sex = factor(rep(c("F", "M"), each=200)), weight = c(rnorm(200, 55), rnorm(200, 58))) head(wdata, 4) # Basic QQ plot ggqqplot(wdata, x = "weight") # Change colors and shape by groups ("sex") # Use custom palette ggqqplot(wdata, x = "weight", color = "sex", palette = c("#00AFBB", "#E7B800")) } \seealso{ \code{\link{ggpar}} } ggpubr/man/show_point_shapes.Rd0000644000176200001440000000061214332553656016351 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/show_point_shapes.R \name{show_point_shapes} \alias{show_point_shapes} \title{Point shapes available in R} \usage{ show_point_shapes() } \value{ a ggplot. } \description{ Show point shapes available in R. } \examples{ show_point_shapes()+ theme_minimal() } \seealso{ \code{\link{ggpar}} and \code{\link{ggline}}. } ggpubr/man/ggsummarystats.Rd0000644000176200001440000001240414367517301015704 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggsummarystats.R \name{ggsummarytable} \alias{ggsummarytable} \alias{ggsummarystats} \alias{print.ggsummarystats} \alias{print.ggsummarystats_list} \title{GGPLOT with Summary Stats Table Under the Plot} \usage{ ggsummarytable( data, x, y, digits = 0, size = 3, color = "black", palette = NULL, facet.by = NULL, labeller = "label_value", position = "identity", ggtheme = theme_pubr(), ... ) ggsummarystats( data, x, y, summaries = c("n", "median", "iqr"), ggfunc = ggboxplot, color = "black", fill = "white", palette = NULL, facet.by = NULL, free.panels = FALSE, labeller = "label_value", heights = c(0.8, 0.2), digits = 0, table.font.size = 3, ggtheme = theme_pubr(), ... ) \method{print}{ggsummarystats}(x, heights = c(0.8, 0.2), ...) \method{print}{ggsummarystats_list}(x, heights = c(0.8, 0.2), legend = NULL, ...) } \arguments{ \item{data}{a data frame} \item{x}{a list of \code{ggsummarystats}.} \item{y}{character vector containing one or more variables to plot} \item{digits}{integer indicating the number of decimal places (round) to be used.} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{color}{outline color.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{labeller}{Character vector. An alternative to the argument \code{short.panel.labs}. Possible values are one of "label_both" (panel labelled by both grouping variable names and levels) and "label_value" (panel labelled with only grouping levels).} \item{position}{Position adjustment, either as a string, or the result of a call to a position adjustment function.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments passed to the function \code{\link{ggpar}()}, \code{\link{facet}()} or \code{\link{ggarrange}()} when printing the plot.} \item{summaries}{summary stats to display in the table. Possible values are those returned by the function \code{\link[rstatix]{get_summary_stats}()}, including: \code{"n", "min", "max", "median", "q1", "q2", "q3", "mad", "mean", "sd", "se", "ci"}.} \item{ggfunc}{a ggpubr function, including: ggboxplot, ggviolin, ggdotplot, ggbarplot, ggline, etc. Can be any other ggplot function that accepts the following arguments \code{data, x, color, fill, palette, ggtheme, facet.by}.} \item{fill}{fill color.} \item{free.panels}{logical. If TRUE, create free plot panels when the argument \code{facet.by} is specified.} \item{heights}{a numeric vector of length 2, specifying the heights of the main and the summary table, respectively.} \item{table.font.size}{the summary table font size.} \item{legend}{character specifying legend position. Allowed values are one of c("top", "bottom", "left", "right", "none"). To remove the legend use legend = "none".} } \description{ Create a ggplot with summary stats (n, median, mean, iqr) table under the plot. Read more: \href{https://www.datanovia.com/en/blog/how-to-create-a-beautiful-plots-in-r-with-summary-statistics-labels/}{How to Create a Beautiful Plots in R with Summary Statistics Labels}. } \section{Functions}{ \itemize{ \item \code{ggsummarytable()}: Create a table of summary stats \item \code{ggsummarystats()}: Create a ggplot with a summary stat table under the plot. }} \examples{ # Data preparation #:::::::::::::::::::::::::::::::::::::::::::::::: data("ToothGrowth") df <- ToothGrowth df$dose <- as.factor(df$dose) # Add random QC column set.seed(123) qc <- rep(c("pass", "fail"), 30) df$qc <- as.factor(sample(qc, 60)) # Inspect the data head(df) # Basic summary stats #:::::::::::::::::::::::::::::::::::::::::::::::: # Compute summary statistics summary.stats <- df \%>\% group_by(dose) \%>\% get_summary_stats(type = "common") summary.stats # Visualize summary table ggsummarytable( summary.stats, x = "dose", y = c("n", "median", "iqr"), ggtheme = theme_bw() ) # Create plots with summary table under the plot #:::::::::::::::::::::::::::::::::::::::::::::::: # Basic plot ggsummarystats( df, x = "dose", y = "len", ggfunc = ggboxplot, add = "jitter" ) # Color by groups ggsummarystats( df, x = "dose", y = "len", ggfunc = ggboxplot, add = "jitter", color = "dose", palette = "npg" ) # Create a barplot ggsummarystats( df, x = "dose", y = "len", ggfunc = ggbarplot, add = c("jitter", "median_iqr"), color = "dose", palette = "npg" ) # Facet #:::::::::::::::::::::::::::::::::::::::::::::::: # Specify free.panels = TRUE for free panels ggsummarystats( df, x = "dose", y = "len", ggfunc = ggboxplot, add = "jitter", color = "dose", palette = "npg", facet.by = c("supp", "qc"), labeller = "label_both" ) } ggpubr/man/as_npc.Rd0000644000176200001440000000444714367517301014065 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/as_npc.R \name{as_npc} \alias{as_npc} \alias{as_npcx} \alias{as_npcy} \title{Convert Character Coordinates into Normalized Parent Coordinates (NPC)} \usage{ as_npc( value, group = 1L, step = 0.1, margin.npc = 0.05, axis = c("xy", "x", "y") ) as_npcx(value, group = 1L, step = 0.1, margin.npc = 0.05) as_npcy(value, group = 1L, step = 0.1, margin.npc = 0.05) } \arguments{ \item{value}{numeric (in [0-1]) or character vector of coordinates. If character, should be one of \code{c('right', 'left', 'bottom', 'top', 'center', 'centre', 'middle')}.} \item{group}{integer ggplot's group id. Used to shift coordinates to avoid overlaps.} \item{step}{numeric value in [0-1]. The step size for shifting coordinates in npc units. Considered as horizontal step for x-axis and vertical step for y-axis. For y-axis, the step value can be negative to reverse the order of groups.} \item{margin.npc}{numeric [0-1] The margin added towards the nearest plotting area edge when converting character coordinates into npc.} \item{axis}{the concerned axis . Should be one of \code{c("xy", "x", "y")}.} } \value{ A numeric vector with values in the range [0-1] representing npc coordinates. } \description{ Convert character coordinates to npc units and shift postions to avoid overlaps when grouping is active. If numeric validate npc values. } \details{ the \code{as_npc()} function is an adaptation from \code{ggpmisc::compute_npc()}. } \section{Functions}{ \itemize{ \item \code{as_npc()}: converts x or y coordinate values into npc. Input values should be numeric or one of the following values \code{c('right', 'left', 'bottom', 'top', 'center', 'centre', 'middle')}. \item \code{as_npcx()}: converts x coordinate values into npc. Input values should be numeric or one of the following values \code{c('right', 'left', 'center', 'centre', 'middle')}. Wrapper around \code{as_npc(axis = "x")}. \item \code{as_npcy()}: converts y coordinate values into npc. Input values should be numeric or one of the following values \code{c( 'bottom', 'top', 'center', 'centre', 'middle')}. Wrapper around \code{as_npc(axis = "y")}. }} \examples{ as_npc(c("left", "right")) as_npc(c("top", "right")) } \seealso{ \code{\link{npc_to_data_coord}}, \code{\link{get_coord}}. } ggpubr/man/rremove.Rd0000644000176200001440000000257114333713444014274 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rremove.R \name{rremove} \alias{rremove} \title{Remove a ggplot Component} \usage{ rremove(object) } \arguments{ \item{object}{character string specifying the plot components. Allowed values include: \itemize{ \item \code{"grid"} for both x and y grids \item \code{"x.grid"} for x axis grids \item \code{"y.grid"} for y axis grids \item \code{"axis"} for both x and y axes \item \code{"x.axis"} for x axis \item \code{"y.axis"} for y axis \item \code{"xlab", or "x.title"} for x axis label \item \code{"ylab", or "y.title"} for y axis label \item \code{"xylab", "xy.title" or "axis.title"} for both x and y axis labels \item \code{"x.text"} for x axis texts (x axis tick labels) \item \code{"y.text"} for y axis texts (y axis tick labels) \item \code{"xy.text"} or \code{"axis.text"} for both x and y axis texts \item \code{"ticks"} for both x and y ticks \item \code{"x.ticks"} for x ticks \item \code{"y.ticks"} for y ticks \item \code{"legend.title"} for the legend title \item \code{"legend"} for the legend }} } \description{ Remove a specific component from a ggplot. } \examples{ # Load data data("ToothGrowth") # Basic plot p <- ggboxplot(ToothGrowth, x = "dose", y = "len", ggtheme = theme_gray()) p # Remove all grids p + rremove("grid") # Remove only x grids p + rremove("x.grid") } ggpubr/man/compare_means.Rd0000644000176200001440000001132714333713444015425 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/compare_means.R \name{compare_means} \alias{compare_means} \title{Comparison of Means} \usage{ compare_means( formula, data, method = "wilcox.test", paired = FALSE, group.by = NULL, ref.group = NULL, symnum.args = list(), p.adjust.method = "holm", ... ) } \arguments{ \item{formula}{a formula of the form \code{x ~ group} where \code{x} is a numeric variable giving the data values and \code{group} is a factor with one or multiple levels giving the corresponding groups. For example, \code{formula = TP53 ~ cancer_group}. It's also possible to perform the test for multiple response variables at the same time. For example, \code{formula = c(TP53, PTEN) ~ cancer_group}.} \item{data}{a data.frame containing the variables in the formula.} \item{method}{the type of test. Default is \link[stats]{wilcox.test}. Allowed values include: \itemize{ \item \code{\link[stats]{t.test}} (parametric) and \code{\link[stats]{wilcox.test}} (non-parametric). Perform comparison between two groups of samples. If the grouping variable contains more than two levels, then a pairwise comparison is performed. \item \code{\link[stats]{anova}} (parametric) and \code{\link[stats]{kruskal.test}} (non-parametric). Perform one-way ANOVA test comparing multiple groups. }} \item{paired}{a logical indicating whether you want a paired test. Used only in \code{\link[stats]{t.test}} and in \link[stats]{wilcox.test}.} \item{group.by}{a character vector containing the name of grouping variables.} \item{ref.group}{a character string specifying the reference group. If specified, for a given grouping variable, each of the group levels will be compared to the reference group (i.e. control group). \code{ref.group} can be also \code{".all."}. In this case, each of the grouping variable levels is compared to all (i.e. basemean).} \item{symnum.args}{a list of arguments to pass to the function \code{\link[stats]{symnum}} for symbolic number coding of p-values. For example, \code{symnum.args <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, 0.05, Inf), symbols = c("****", "***", "**", "*", "ns"))}. In other words, we use the following convention for symbols indicating statistical significance: \itemize{ \item \code{ns}: p > 0.05 \item \code{*}: p <= 0.05 \item \code{**}: p <= 0.01 \item \code{***}: p <= 0.001 \item \code{****}: p <= 0.0001 }} \item{p.adjust.method}{method for adjusting p values (see \code{\link[stats]{p.adjust}}). Has impact only in a situation, where multiple pairwise tests are performed; or when there are multiple grouping variables. Allowed values include "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none". If you don't want to adjust the p value (not recommended), use p.adjust.method = "none". Note that, when the \code{formula} contains multiple variables, the p-value adjustment is done independently for each variable.} \item{...}{Other arguments to be passed to the test function.} } \value{ return a data frame with the following columns: \itemize{ \item \code{.y.}: the y variable used in the test. \item \code{group1,group2}: the compared groups in the pairwise tests. Available only when \code{method = "t.test"} or \code{method = "wilcox.test"}. \item \code{p}: the p-value. \item \code{p.adj}: the adjusted p-value. Default for \code{p.adjust.method = "holm"}. \item \code{p.format}: the formatted p-value. \item \code{p.signif}: the significance level. \item \code{method}: the statistical test used to compare groups. } } \description{ Performs one or multiple mean comparisons. } \examples{ # Load data #::::::::::::::::::::::::::::::::::::::: data("ToothGrowth") df <- ToothGrowth # One-sample test #::::::::::::::::::::::::::::::::::::::::: compare_means(len ~ 1, df, mu = 0) # Two-samples unpaired test #::::::::::::::::::::::::::::::::::::::::: compare_means(len ~ supp, df) # Two-samples paired test #::::::::::::::::::::::::::::::::::::::::: compare_means(len ~ supp, df, paired = TRUE) # Compare supp levels after grouping the data by "dose" #:::::::::::::::::::::::::::::::::::::::: compare_means(len ~ supp, df, group.by = "dose") # pairwise comparisons #:::::::::::::::::::::::::::::::::::::::: # As dose contains more thant two levels ==> # pairwise test is automatically performed. compare_means(len ~ dose, df) # Comparison against reference group #:::::::::::::::::::::::::::::::::::::::: compare_means(len ~ dose, df, ref.group = "0.5") # Comparison against all #:::::::::::::::::::::::::::::::::::::::: compare_means(len ~ dose, df, ref.group = ".all.") # Anova and kruskal.test #:::::::::::::::::::::::::::::::::::::::: compare_means(len ~ dose, df, method = "anova") compare_means(len ~ dose, df, method = "kruskal.test") } ggpubr/man/ggscatter.Rd0000644000176200001440000002305414367733325014606 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggscatter.R \name{ggscatter} \alias{ggscatter} \title{Scatter plot} \usage{ ggscatter( data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "lightgray", palette = NULL, shape = 19, size = 2, point = TRUE, rug = FALSE, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, add = c("none", "reg.line", "loess"), add.params = list(), conf.int = FALSE, conf.int.level = 0.95, fullrange = FALSE, ellipse = FALSE, ellipse.level = 0.95, ellipse.type = "norm", ellipse.alpha = 0.1, ellipse.border.remove = FALSE, mean.point = FALSE, mean.point.size = ifelse(is.numeric(size), 2 * size, size), star.plot = FALSE, star.plot.lty = 1, star.plot.lwd = NULL, label = NULL, font.label = c(12, "plain"), font.family = "", label.select = NULL, repel = FALSE, label.rectangle = FALSE, parse = FALSE, cor.coef = FALSE, cor.coeff.args = list(), cor.method = "pearson", cor.coef.coord = c(NULL, NULL), cor.coef.size = 4, ggp = NULL, show.legend.text = NA, ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x}{x variables for drawing.} \item{y}{y variables for drawing.} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{color, fill}{point colors.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{shape}{point shape. See \code{\link{show_point_shapes}}.} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{point}{logical value. If TRUE, show points.} \item{rug}{logical value. If TRUE, add marginal rug.} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{add}{allowed values are one of "none", "reg.line" (for adding linear regression line) or "loess" (for adding local regression fitting).} \item{add.params}{parameters (color, size, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{conf.int}{logical value. If TRUE, adds confidence interval.} \item{conf.int.level}{Level controlling confidence region. Default is 95\%. Used only when add != "none" and conf.int = TRUE.} \item{fullrange}{should the fit span the full range of the plot, or just the data. Used only when add != "none".} \item{ellipse}{logical value. If TRUE, draws ellipses around points.} \item{ellipse.level}{the size of the concentration ellipse in normal probability.} \item{ellipse.type}{Character specifying frame type. Possible values are \code{"convex"}, \code{"confidence"} or types supported by \code{\link[ggplot2]{stat_ellipse}()} including one of \code{c("t", "norm", "euclid")} for plotting concentration ellipses. \itemize{ \item \code{"convex"}: plot convex hull of a set o points. \item \code{"confidence"}: plot confidence ellipses arround group mean points as \code{FactoMineR::coord.ellipse()}. \item \code{"t"}: assumes a multivariate t-distribution. \item \code{"norm"}: assumes a multivariate normal distribution. \item \code{"euclid"}: draws a circle with the radius equal to level, representing the euclidean distance from the center. This ellipse probably won't appear circular unless \code{\link[ggplot2]{coord_fixed}()} is applied.}} \item{ellipse.alpha}{Alpha for ellipse specifying the transparency level of fill color. Use alpha = 0 for no fill color.} \item{ellipse.border.remove}{logical value. If TRUE, remove ellipse border lines.} \item{mean.point}{logical value. If TRUE, group mean points are added to the plot.} \item{mean.point.size}{numeric value specifying the size of mean points.} \item{star.plot}{logical value. If TRUE, a star plot is generated.} \item{star.plot.lty, star.plot.lwd}{line type and line width (size) for star plot, respectively.} \item{label}{the name of the column containing point labels. Can be also a character vector with length = nrow(data).} \item{font.label}{a vector of length 3 indicating respectively the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of point labels. For example \emph{font.label = c(14, "bold", "red")}. To specify only the size and the style, use font.label = c(14, "plain").} \item{font.family}{character vector specifying font family.} \item{label.select}{character vector specifying some labels to show.} \item{repel}{a logical value, whether to use ggrepel to avoid overplotting text labels or not.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{parse}{If \code{TRUE}, the labels will be parsed into expressions and displayed as described in \code{?plotmath}.} \item{cor.coef}{logical value. If TRUE, correlation coefficient with the p-value will be added to the plot.} \item{cor.coeff.args}{a list of arguments to pass to the function \code{\link{stat_cor}} for customizing the displayed correlation coefficients. For example: \code{cor.coeff.args = list(method = "pearson", label.x.npc = "right", label.y.npc = "top")}.} \item{cor.method}{method for computing correlation coefficient. Allowed values are one of "pearson", "kendall", or "spearman".} \item{cor.coef.coord}{numeric vector, of length 2, specifying the x and y coordinates of the correlation coefficient. Default values are NULL.} \item{cor.coef.size}{correlation coefficient text font size.} \item{ggp}{a ggplot. If not NULL, points are added to an existing plot.} \item{show.legend.text}{logical. Should text be included in the legends? NA, the default, includes if any aesthetics are mapped. FALSE never includes, and TRUE always includes.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link[ggplot2]{geom_point}} and \code{\link{ggpar}}.} } \description{ Create a scatter plot. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Load data data("mtcars") df <- mtcars df$cyl <- as.factor(df$cyl) head(df[, c("wt", "mpg", "cyl")], 3) # Basic plot # +++++++++++++++++++++++++++ ggscatter(df, x = "wt", y = "mpg", color = "black", shape = 21, size = 3, # Points color, shape and size add = "reg.line", # Add regressin line add.params = list(color = "blue", fill = "lightgray"), # Customize reg. line conf.int = TRUE, # Add confidence interval cor.coef = TRUE, # Add correlation coefficient. see ?stat_cor cor.coeff.args = list(method = "pearson", label.x = 3, label.sep = "\n") ) # loess method: local regression fitting ggscatter(df, x = "wt", y = "mpg", add = "loess", conf.int = TRUE) # Control point size by continuous variable values ("qsec") ggscatter(df, x = "wt", y = "mpg", color = "#00AFBB", size = "qsec") # Change colors # +++++++++++++++++++++++++++ # Use custom color palette # Add marginal rug ggscatter(df, x = "wt", y = "mpg", color = "cyl", palette = c("#00AFBB", "#E7B800", "#FC4E07") ) # Add group ellipses and mean points # Add stars # +++++++++++++++++++ ggscatter(df, x = "wt", y = "mpg", color = "cyl", shape = "cyl", palette = c("#00AFBB", "#E7B800", "#FC4E07"), ellipse = TRUE, mean.point = TRUE, star.plot = TRUE) # Textual annotation # +++++++++++++++++ df$name <- rownames(df) ggscatter(df, x = "wt", y = "mpg", color = "cyl", palette = c("#00AFBB", "#E7B800", "#FC4E07"), label = "name", repel = TRUE) } \seealso{ \code{\link{stat_cor}}, \code{\link{stat_stars}}, \code{\link{stat_conf_ellipse}} and \code{\link{ggpar}}. } ggpubr/man/stat_pvalue_manual.Rd0000644000176200001440000001522014333713444016474 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_pvalue_manual.R \name{stat_pvalue_manual} \alias{stat_pvalue_manual} \title{Add Manually P-values to a ggplot} \usage{ stat_pvalue_manual( data, label = NULL, y.position = "y.position", xmin = "group1", xmax = "group2", x = NULL, size = 3.88, label.size = size, bracket.size = 0.3, bracket.nudge.y = 0, bracket.shorten = 0, color = "black", linetype = 1, tip.length = 0.03, remove.bracket = FALSE, step.increase = 0, step.group.by = NULL, hide.ns = FALSE, vjust = 0, coord.flip = FALSE, position = "identity", ... ) } \arguments{ \item{data}{a data frame containing statitistical test results. The expected default format should contain the following columns: \code{group1 | group2 | p | y.position | etc}. \code{group1} and \code{group2} are the groups that have been compared. \code{p} is the resulting p-value. \code{y.position} is the y coordinates of the p-values in the plot.} \item{label}{the column containing the label (e.g.: label = "p" or label = "p.adj"), where \code{p} is the p-value. Can be also an expression that can be formatted by the \code{\link[glue]{glue}()} package. For example, when specifying label = "t-test, p = \{p\}", the expression \{p\} will be replaced by its value.} \item{y.position}{column containing the coordinates (in data units) to be used for absolute positioning of the label. Default value is "y.position". Can be also a numeric vector.} \item{xmin}{column containing the position of the left sides of the brackets. Default value is "group1".} \item{xmax}{(optional) column containing the position of the right sides of the brackets. Default value is "group2". If NULL, the p-values are plotted as a simple text.} \item{x}{x position of the p-value. Should be used only when you want plot the p-value as text (without brackets).} \item{size, label.size}{size of label text.} \item{bracket.size}{Width of the lines of the bracket.} \item{bracket.nudge.y}{Vertical adjustment to nudge brackets by. Useful to move up or move down the bracket. If positive value, brackets will be moved up; if negative value, brackets are moved down.} \item{bracket.shorten}{a small numeric value in [0-1] for shortening the with of bracket.} \item{color}{text and line color. Can be variable name in the data for coloring by groups.} \item{linetype}{linetype. Can be variable name in the data for changing linetype by groups.} \item{tip.length}{numeric vector with the fraction of total height that the bar goes down to indicate the precise column. Default is 0.03.} \item{remove.bracket}{logical, if \code{TRUE}, brackets are removed from the plot. Considered only in the situation, where comparisons are performed against reference group or against "all".} \item{step.increase}{numeric vector with the increase in fraction of total height for every additional comparison to minimize overlap.} \item{step.group.by}{a variable name for grouping brackets before adding step.increase. Useful to group bracket by facet panel.} \item{hide.ns}{can be logical value or a character vector. \itemize{ \item Case when logical value. If TRUE, hide ns symbol when displaying significance levels. Filter is done by checking the column \code{p.adj.signif}, \code{p.signif}, \code{p.adj} and \code{p}. \item Case when character value. Possible values are "p" or "p.adj", for filtering out non significant. }} \item{vjust}{move the text up or down relative to the bracket. Can be also a column name available in the data.} \item{coord.flip}{logical. If \code{TRUE}, flip x and y coordinates so that horizontal becomes vertical, and vertical, horizontal. When adding the p-values to a horizontal ggplot (generated using \code{\link[ggplot2]{coord_flip}()}), you need to specify the option \code{coord.flip = TRUE}.} \item{position}{position adjustment, either as a string, or the result of a call to a position adjustment function.} \item{...}{other arguments passed to the function \code{geom_bracket()} or \code{geom_text()}} } \description{ Add manually p-values to a ggplot, such as box blots, dot plots and stripcharts. Frequently asked questions are available on \href{https://www.datanovia.com/en/blog/tag/ggpubr/}{Datanovia ggpubr FAQ page}, for example: \itemize{ \item \href{https://www.datanovia.com/en/blog/how-to-add-p-values-onto-basic-ggplots/}{How to Add P-Values onto Basic GGPLOTS} \item \href{https://www.datanovia.com/en/blog/ggpubr-how-to-add-adjusted-p-values-to-a-multi-panel-ggplot/}{How to Add Adjusted P-values to a Multi-Panel GGPlot} \item \href{https://www.datanovia.com/en/blog/how-to-add-p-values-to-ggplot-facets/}{How to Add P-values to GGPLOT Facets} \item \href{https://www.datanovia.com/en/blog/ggpubr-how-to-add-p-values-generated-elsewhere-to-a-ggplot/}{How to Add P-Values Generated Elsewhere to a GGPLOT} \item \href{https://www.datanovia.com/en/blog/how-to-add-p-values-onto-a-grouped-ggplot-using-the-ggpubr-r-package/}{How to Add P-Values onto a Grouped GGPLOT using the GGPUBR R Package} \item \href{https://www.datanovia.com/en/blog/how-to-create-stacked-bar-plots-with-error-bars-and-p-values/}{How to Create Stacked Bar Plots with Error Bars and P-values} \item \href{https://www.datanovia.com/en/blog/how-to-add-p-values-onto-horizontal-ggplots/}{How to Add P-Values onto Horizontal GGPLOTS} } } \examples{ # T-test stat.test <- compare_means( len ~ dose, data = ToothGrowth, method = "t.test" ) stat.test # Create a simple box plot p <- ggboxplot(ToothGrowth, x = "dose", y = "len") p # Perform a t-test between groups stat.test <- compare_means( len ~ dose, data = ToothGrowth, method = "t.test" ) stat.test # Add manually p-values from stat.test data # First specify the y.position of each comparison stat.test <- stat.test \%>\% mutate(y.position = c(29, 35, 39)) p + stat_pvalue_manual(stat.test, label = "p.adj") # Customize the label with glue expression # (https://github.com/tidyverse/glue) p + stat_pvalue_manual(stat.test, label = "p = {p.adj}") # Grouped bar plots #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% ToothGrowth$dose <- as.factor(ToothGrowth$dose) # Comparisons against reference stat.test <- compare_means( len ~ dose, data = ToothGrowth, group.by = "supp", method = "t.test", ref.group = "0.5" ) stat.test # Plot bp <- ggbarplot(ToothGrowth, x = "supp", y = "len", fill = "dose", palette = "jco", add = "mean_sd", add.params = list(group = "dose"), position = position_dodge(0.8)) bp + stat_pvalue_manual( stat.test, x = "supp", y.position = 33, label = "p.signif", position = position_dodge(0.8) ) } \seealso{ \code{\link{stat_compare_means}} } ggpubr/man/gradient_color.Rd0000644000176200001440000000247014332553656015614 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/gradient_color.R \name{gradient_color} \alias{gradient_color} \alias{gradient_fill} \title{Set Gradient Color} \usage{ gradient_color(palette) gradient_fill(palette) } \arguments{ \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty". Can be also a numeric vector; in this case a basic color palette is created using the function \link[grDevices]{palette}.} } \description{ Change gradient color. \itemize{ \item \code{gradient_color()}: Change gradient color. \item \code{gradient_fill()}: Change gradient fill. } } \examples{ df <- mtcars p <- ggscatter(df, x = "wt", y = "mpg", color = "mpg") # Change gradient color # Use one custom color p + gradient_color("red") # Two colors p + gradient_color(c("blue", "red")) # Three colors p + gradient_color(c("blue", "white", "red")) # Use RColorBrewer palette p + gradient_color("RdYlBu") # Use ggsci color palette p + gradient_color("npg") } \seealso{ \link{set_palette}. } ggpubr/man/ggstripchart.Rd0000644000176200001440000002012314367732422015313 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggstripchart.R \name{ggstripchart} \alias{ggstripchart} \title{Stripcharts} \usage{ ggstripchart( data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "white", palette = NULL, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, shape = 19, size = NULL, select = NULL, remove = NULL, order = NULL, add = "mean_se", add.params = list(), error.plot = "pointrange", label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, jitter = 0.2, position = position_jitter(jitter, seed = 123), ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x}{character string containing the name of x variable.} \item{y}{character vector containing one or more variables to plot} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{color}{outline color.} \item{fill}{fill color.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{shape}{point shape} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{select}{character vector specifying which items to display.} \item{remove}{character vector specifying which items to remove from the plot.} \item{order}{character vector specifying the order of items.} \item{add}{character vector for adding another plot element (e.g.: dot plot or error bars). Allowed values are one or the combination of: "none", "dotplot", "jitter", "boxplot", "point", "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", "median_range"; see ?desc_statby for more details.} \item{add.params}{parameters (color, shape, size, fill, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{error.plot}{plot type used to visualize error. Allowed values are one of c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", "lower_linerange"). Default value is "pointrange" or "errorbar". Used only when add != "none" and add contains one "mean_*" or "med_*" where "*" = sd, se, ....} \item{label}{the name of the column containing point labels. Can be also a character vector with length = nrow(data).} \item{font.label}{a list which can contain the combination of the following elements: the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of labels. For example font.label = list(size = 14, face = "bold", color ="red"). To specify only the size and the style, use font.label = list(size = 14, face = "plain").} \item{label.select}{can be of two formats: \itemize{ \item a character vector specifying some labels to show. \item a list containing one or the combination of the following components: \itemize{ \item \code{top.up} and \code{top.down}: to display the labels of the top up/down points. For example, \code{label.select = list(top.up = 10, top.down = 4)}. \item \code{criteria}: to filter, for example, by x and y variabes values, use this: \code{label.select = list(criteria = "`y` > 2 & `y` < 5 & `x` \%in\% c('A', 'B')")}. } }} \item{repel}{a logical value, whether to use ggrepel to avoid overplotting text labels or not.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{jitter}{the amount of jitter.} \item{position}{position adjustment, either as a string, or the result of a call to a position adjustment function. Used to adjust position for multiple groups.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link[ggplot2]{geom_jitter}}, \code{\link{ggpar}} and \code{\link{facet}}.} } \description{ Create a stripchart, also known as one dimensional scatter plots. These plots are suitable compared to box plots when sample sizes are small. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Load data data("ToothGrowth") df <- ToothGrowth # Basic plot with summary statistics: mean_se # +++++++++++++++++++++++++++ # Change point shapes by groups: "dose" ggstripchart(df, x = "dose", y = "len", shape = "dose", size = 3, add = "mean_se") # Use mean_sd # Change error.plot to "crossbar" ggstripchart(df, x = "dose", y = "len", shape = "dose", size = 3, add = "mean_sd", add.params = list(width = 0.5), error.plot = "crossbar") # Add summary statistics # ++++++++++++++++++++++++++ # Add box plot ggstripchart(df, x = "dose", y = "len", shape = "dose", add = "boxplot") # Add violin + mean_sd ggstripchart(df, x = "dose", y = "len", shape = "dose", add = c("violin", "mean_sd")) # Change colors # +++++++++++++++++++++++++++ # Change colors by groups: dose # Use custom color palette ggstripchart(df, "dose", "len", shape = "dose", color = "dose", palette = c("#00AFBB", "#E7B800", "#FC4E07"), add = "mean_sd") # Plot with multiple groups # +++++++++++++++++++++ # Change shape and color by a second group : "supp" ggstripchart(df, "dose", "len", shape = "supp", color = "supp", palette = c("#00AFBB", "#E7B800")) # Adjust point position ggstripchart(df, "dose", "len", shape = "supp", color = "supp", palette = c("#00AFBB", "#E7B800"), position = position_dodge(0.8) ) # You can also use position_jitterdodge() # but fill aesthetic is required ggstripchart(df, "dose", "len", shape = "supp", color = "supp", palette = c("#00AFBB", "#E7B800"), position = position_jitterdodge() ) # Add boxplot ggstripchart(df, "dose", "len", shape = "supp", color = "supp", palette = c("#00AFBB", "#E7B800"), add = "boxplot", add.params = list(color = "black") ) } \seealso{ \code{\link{ggpar}}, \code{\link{ggviolin}}, \code{\link{ggdotplot}} and \code{\link{ggboxplot}}. } ggpubr/man/geom_signif.Rd0000644000176200001440000000045214332553656015105 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils-geom-signif.R \name{geom_signif} \alias{geom_signif} \title{geom_signif exported from ggsignif package} \description{ See \code{ggsignif::\link[ggsignif:stat_signif]{geom_signif}} for details. } \keyword{internal} ggpubr/man/ggdotplot.Rd0000644000176200001440000001611514367732422014623 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggdotplot.R \name{ggdotplot} \alias{ggdotplot} \title{Dot plot} \usage{ ggdotplot( data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "lightgray", palette = NULL, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, size = NULL, binwidth = NULL, select = NULL, remove = NULL, order = NULL, add = "mean_se", add.params = list(), error.plot = "pointrange", label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x}{character string containing the name of x variable.} \item{y}{character vector containing one or more variables to plot} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{color}{outline color.} \item{fill}{fill color.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{binwidth}{numeric value specifying bin width. use value between 0 and 1 when you have a strong dense dotplot. For example binwidth = 0.2.} \item{select}{character vector specifying which items to display.} \item{remove}{character vector specifying which items to remove from the plot.} \item{order}{character vector specifying the order of items.} \item{add}{character vector for adding another plot element (e.g.: dot plot or error bars). Allowed values are one or the combination of: "none", "dotplot", "jitter", "boxplot", "point", "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", "median_range"; see ?desc_statby for more details.} \item{add.params}{parameters (color, shape, size, fill, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{error.plot}{plot type used to visualize error. Allowed values are one of c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", "lower_linerange"). Default value is "pointrange" or "errorbar". Used only when add != "none" and add contains one "mean_*" or "med_*" where "*" = sd, se, ....} \item{label}{the name of the column containing point labels. Can be also a character vector with length = nrow(data).} \item{font.label}{a list which can contain the combination of the following elements: the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of labels. For example font.label = list(size = 14, face = "bold", color ="red"). To specify only the size and the style, use font.label = list(size = 14, face = "plain").} \item{label.select}{can be of two formats: \itemize{ \item a character vector specifying some labels to show. \item a list containing one or the combination of the following components: \itemize{ \item \code{top.up} and \code{top.down}: to display the labels of the top up/down points. For example, \code{label.select = list(top.up = 10, top.down = 4)}. \item \code{criteria}: to filter, for example, by x and y variabes values, use this: \code{label.select = list(criteria = "`y` > 2 & `y` < 5 & `x` \%in\% c('A', 'B')")}. } }} \item{repel}{a logical value, whether to use ggrepel to avoid overplotting text labels or not.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link[ggplot2]{geom_dotplot}}, \code{\link{ggpar}} and \code{\link{facet}}.} } \description{ Create a dot plot. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Load data data("ToothGrowth") df <- ToothGrowth # Basic plot with summary statistics : mean_sd # +++++++++++++++++++++++++++ ggdotplot(df, x = "dose", y = "len", add = "mean_sd") # Change error.plot to "crossbar" ggdotplot(df, x = "dose", y = "len", add = "mean_sd", add.params = list(width = 0.5), error.plot = "crossbar") # Add box plot ggdotplot(df, x = "dose", y = "len", add = "boxplot") # Add violin + mean_sd ggdotplot(df, x = "dose", y = "len", add = c("violin", "mean_sd")) # Change colors # +++++++++++++++++++++++++++ # Change fill and outline colors by groups: dose # Use custom color palette ggdotplot(df, "dose", "len", add = "boxplot", color = "dose", fill = "dose", palette = c("#00AFBB", "#E7B800", "#FC4E07")) # Plot with multiple groups # +++++++++++++++++++++ # Change color by a second group : "supp" ggdotplot(df, "dose", "len", fill = "supp", color = "supp", palette = c("#00AFBB", "#E7B800")) } \seealso{ \code{\link{ggpar}}, \code{\link{ggviolin}}, \code{\link{ggboxplot}} and \code{\link{ggstripchart}}. } ggpubr/man/ggmaplot.Rd0000644000176200001440000001265514367732422014437 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggmaplot.R \name{ggmaplot} \alias{ggmaplot} \title{MA-plot from means and log fold changes} \usage{ ggmaplot( data, fdr = 0.05, fc = 1.5, genenames = NULL, detection_call = NULL, size = NULL, alpha = 1, seed = 42, font.label = c(12, "plain", "black"), label.rectangle = FALSE, palette = c("#B31B21", "#1465AC", "darkgray"), top = 15, select.top.method = c("padj", "fc"), label.select = NULL, main = NULL, xlab = "Log2 mean expression", ylab = "Log2 fold change", ggtheme = theme_classic(), ... ) } \arguments{ \item{data}{an object of class DESeqResults, get_diff, DE_Results, matrix or data frame containing the columns baseMean (or baseMeanLog2), log2FoldChange, and padj. Rows are genes. Two possible formats are accepted for the input data: \itemize{ \item 1/ \code{baseMean | log2FoldChange | padj}. This is a typical output from DESeq2 pipeline. Here, we'll use log2(baseMean) as the x-axis variable. \item 2/ \code{baseMeanLog2 | log2FoldChange | padj}. Here, baseMeanLog2 is assumed to be the mean of logged values; so we'll use it as the x-axis variable without any transformation. This is the real A in MA plot. In other words, it is the average of two log-scales values: \code{A = (log2(x) + log2(y))/2 = log2(xy)*1/2} } Terminology: \itemize{ \item baseMean: the mean expression of genes in the two groups. \item log2FoldChange: the log2 fold changes of group 2 compared to group 1 \item padj: the adjusted p-value of the used statiscal test. }} \item{fdr}{Accepted false discovery rate for considering genes as differentially expressed.} \item{fc}{the fold change threshold. Only genes with a fold change >= fc and padj <= fdr are considered as significantly differentially expressed.} \item{genenames}{a character vector of length nrow(data) specifying gene names corresponding to each row. Used for point labels.} \item{detection_call}{a numeric vector with length = nrow(data), specifying if the genes is expressed (value = 1) or not (value = 0). For example detection_call = c(1, 1, 0, 1, 0, 1). Default is NULL. If detection_call column is available in data, it will be used.} \item{size}{points size.} \item{alpha}{numeric value betwenn 0 an 1 specifying point alpha for controlling transparency. For example, use alpha = 0.5.} \item{seed}{Random seed passed to \code{set.seed}. if \code{NA}, set.seed will not be called. Default is 42 for reproducibility.} \item{font.label}{a vector of length 3 indicating respectively the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of point labels. For example \emph{font.label = c(14, "bold", "red")}.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{top}{the number of top genes to be shown on the plot. Use top = 0 to hide to gene labels.} \item{select.top.method}{methods to be used for selecting top genes. Allowed values include "padj" and "fc" for selecting by adjusted p values or fold changes, respectively.} \item{label.select}{character vector specifying some labels to show.} \item{main}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link{ggpar}}.} } \value{ returns a ggplot. } \description{ Make MA-plot which is a scatter plot of log2 fold changes (M, on the y-axis) versus the average expression signal (A, on the x-axis). \code{M = log2(x/y)} and \code{A = (log2(x) + log2(y))/2 = log2(xy)*1/2}, where x and y are respectively the mean of the two groups being compared. } \examples{ data(diff_express) # Default plot ggmaplot(diff_express, main = expression("Group 1" \%->\% "Group 2"), fdr = 0.05, fc = 2, size = 0.4, palette = c("#B31B21", "#1465AC", "darkgray"), genenames = as.vector(diff_express$name), legend = "top", top = 20, font.label = c("bold", 11), font.legend = "bold", font.main = "bold", ggtheme = ggplot2::theme_minimal()) # Add rectangle around labels ggmaplot(diff_express, main = expression("Group 1" \%->\% "Group 2"), fdr = 0.05, fc = 2, size = 0.4, palette = c("#B31B21", "#1465AC", "darkgray"), genenames = as.vector(diff_express$name), legend = "top", top = 20, font.label = c("bold", 11), label.rectangle = TRUE, font.legend = "bold", font.main = "bold", ggtheme = ggplot2::theme_minimal()) # Select specific genes to show # set top = 0, then specify genes using label.select argument ggmaplot(diff_express, main = expression("Group 1" \%->\% "Group 2"), fdr = 0.05, fc = 2, size = 0.4, genenames = as.vector(diff_express$name), ggtheme = ggplot2::theme_minimal(), top = 0, label.select = c("BUB1", "CD83") ) } ggpubr/man/ggparagraph.Rd0000644000176200001440000000326114333713444015075 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggparagraph.R \name{ggparagraph} \alias{ggparagraph} \alias{drawDetails.splitText} \title{Draw a Paragraph of Text} \usage{ ggparagraph( text, color = NULL, size = NULL, face = NULL, family = NULL, lineheight = NULL ) \method{drawDetails}{splitText}(x, recording) } \arguments{ \item{text}{the text to plot.} \item{color}{font color, example: color = "black"} \item{size}{font size, example: size = 12} \item{face}{font face. Allowed values are one of "plain", "italic", "bold", "bold.italic".} \item{family}{font family} \item{lineheight}{Line height, example: lineheight = 2.} \item{x}{a grid grob} \item{recording}{a logical value indicating whether a grob is being added to the display list or redrawn from the display list.} } \description{ Draw a paragraph o text. Splits a long text into multiple lines (by inserting line breaks) so that the output will fit within the current viewport. } \examples{ # Density plot density.p <- ggdensity(iris, x = "Sepal.Length", fill = "Species", palette = "jco") # Text plot text <- paste("iris data set gives the measurements in cm", "of the variables sepal length and width", "and petal length and width, respectively,", "for 50 flowers from each of 3 species of iris.", "The species are Iris setosa, versicolor, and virginica.", sep = " ") text.p <- ggparagraph(text, face = "italic", size = 12) # Arrange the plots on the same page ggarrange(density.p, text.p, ncol = 1, nrow = 2, heights = c(1, 0.3)) } \author{ Alboukadel Kassambara } ggpubr/man/reexports.Rd0000644000176200001440000000102014332553656014642 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/reexports.R \docType{import} \name{reexports} \alias{reexports} \alias{mutate} \alias{group_by} \alias{get_summary_stats} \title{Objects exported from other packages} \keyword{internal} \description{ These objects are imported from other packages. Follow the links below to see their documentation. \describe{ \item{dplyr}{\code{\link[dplyr]{group_by}}, \code{\link[dplyr]{mutate}}} \item{rstatix}{\code{\link[rstatix]{get_summary_stats}}} }} ggpubr/man/ggboxplot.Rd0000644000176200001440000002073714367732422014632 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggboxplot.R \name{ggboxplot} \alias{ggboxplot} \title{Box plot} \usage{ ggboxplot( data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "white", palette = NULL, title = NULL, xlab = NULL, ylab = NULL, bxp.errorbar = FALSE, bxp.errorbar.width = 0.4, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, linetype = "solid", size = NULL, width = 0.7, notch = FALSE, outlier.shape = 19, select = NULL, remove = NULL, order = NULL, add = "none", add.params = list(), error.plot = "pointrange", label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x}{character string containing the name of x variable.} \item{y}{character vector containing one or more variables to plot} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{color}{outline color.} \item{fill}{fill color.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{bxp.errorbar}{logical value. If TRUE, shows error bars of box plots.} \item{bxp.errorbar.width}{numeric value specifying the width of box plot error bars. Default is 0.4.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{linetype}{line types.} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{width}{numeric value between 0 and 1 specifying box width.} \item{notch}{If \code{FALSE} (default) make a standard box plot. If \code{TRUE}, make a notched box plot. Notches are used to compare groups; if the notches of two boxes do not overlap, this suggests that the medians are significantly different.} \item{outlier.shape}{point shape of outlier. Default is 19. To hide outlier, specify \code{outlier.shape = NA}. When jitter is added, then outliers will be automatically hidden.} \item{select}{character vector specifying which items to display.} \item{remove}{character vector specifying which items to remove from the plot.} \item{order}{character vector specifying the order of items.} \item{add}{character vector for adding another plot element (e.g.: dot plot or error bars). Allowed values are one or the combination of: "none", "dotplot", "jitter", "boxplot", "point", "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", "median_range"; see ?desc_statby for more details.} \item{add.params}{parameters (color, shape, size, fill, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{error.plot}{plot type used to visualize error. Allowed values are one of c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", "lower_linerange"). Default value is "pointrange" or "errorbar". Used only when add != "none" and add contains one "mean_*" or "med_*" where "*" = sd, se, ....} \item{label}{the name of the column containing point labels. Can be also a character vector with length = nrow(data).} \item{font.label}{a list which can contain the combination of the following elements: the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of labels. For example font.label = list(size = 14, face = "bold", color ="red"). To specify only the size and the style, use font.label = list(size = 14, face = "plain").} \item{label.select}{can be of two formats: \itemize{ \item a character vector specifying some labels to show. \item a list containing one or the combination of the following components: \itemize{ \item \code{top.up} and \code{top.down}: to display the labels of the top up/down points. For example, \code{label.select = list(top.up = 10, top.down = 4)}. \item \code{criteria}: to filter, for example, by x and y variabes values, use this: \code{label.select = list(criteria = "`y` > 2 & `y` < 5 & `x` \%in\% c('A', 'B')")}. } }} \item{repel}{a logical value, whether to use ggrepel to avoid overplotting text labels or not.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link[ggplot2]{geom_boxplot}}, \code{\link{ggpar}} and \code{\link{facet}}.} } \description{ Create a box plot with points. Box plots display a group of numerical data through their quartiles. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \section{Suggestions for the argument "add"}{ Suggested values are one of c("dotplot", "jitter"). } \examples{ # Load data data("ToothGrowth") df <- ToothGrowth # Basic plot # +++++++++++++++++++++++++++ # width: change box plots width ggboxplot(df, x = "dose", y = "len", width = 0.8) # Change orientation: horizontal ggboxplot(df, "dose", "len", orientation = "horizontal") # Notched box plot ggboxplot(df, x = "dose", y = "len", notch = TRUE) # Add dots # ++++++++++++++++++++++++++ ggboxplot(df, x = "dose", y = "len", add = "dotplot") # Add jitter points and change the shape by groups ggboxplot(df, x = "dose", y = "len", add = "jitter", shape = "dose") # Select and order items # ++++++++++++++++++++++++++++++ # Select which items to display: "0.5" and "2" ggboxplot(df, "dose", "len", select = c("0.5", "2")) # Change the default order of items ggboxplot(df, "dose", "len", order = c("2", "1", "0.5")) # Change colors # +++++++++++++++++++++++++++ # Change outline and fill colors ggboxplot(df, "dose", "len", color = "black", fill = "gray") # Change outline colors by groups: dose # Use custom color palette # Add jitter points and change the shape by groups ggboxplot(df, "dose", "len", color = "dose", palette =c("#00AFBB", "#E7B800", "#FC4E07"), add = "jitter", shape = "dose") # Change fill color by groups: dose ggboxplot(df, "dose", "len", fill = "dose", palette = c("#00AFBB", "#E7B800", "#FC4E07")) # Box plot with multiple groups # +++++++++++++++++++++ # fill or color box plot by a second group : "supp" ggboxplot(df, "dose", "len", color = "supp", palette = c("#00AFBB", "#E7B800")) } \seealso{ \code{\link{ggpar}}, \code{\link{ggviolin}}, \code{\link{ggdotplot}} and \code{\link{ggstripchart}}. } ggpubr/man/ggerrorplot.Rd0000644000176200001440000001474114367732422015171 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggerrorplot.R \name{ggerrorplot} \alias{ggerrorplot} \title{Visualizing Error} \usage{ ggerrorplot( data, x, y, desc_stat = "mean_se", numeric.x.axis = FALSE, combine = FALSE, merge = FALSE, color = "black", fill = "white", palette = NULL, size = NULL, width = NULL, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, select = NULL, remove = NULL, order = NULL, add = "none", add.params = list(), error.plot = "pointrange", ci = 0.95, position = position_dodge(), ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x, y}{x and y variables for drawing.} \item{desc_stat}{descriptive statistics to be used for visualizing errors. Default value is "mean_se". Allowed values are one of , "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", "median_range"; see \code{\link{desc_statby}} for more details.} \item{numeric.x.axis}{logical. If TRUE, x axis will be treated as numeric. Default is FALSE.} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{color, fill}{outline and fill colors.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{width}{numeric value between 0 and 1 specifying box width.} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{select}{character vector specifying which items to display.} \item{remove}{character vector specifying which items to remove from the plot.} \item{order}{character vector specifying the order of items. Considered only when x axis is a factor variable.} \item{add}{character vector for adding another plot element (e.g.: dot plot or error bars). Allowed values are one or the combination of: "none", "dotplot", "jitter", "boxplot", "point", "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", "median_range"; see ?desc_statby for more details.} \item{add.params}{parameters (color, shape, size, fill, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{error.plot}{plot type used to visualize error. Allowed values are one of c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", "lower_linerange"). Default value is "pointrange" or "errorbar". Used only when add != "none" and add contains one "mean_*" or "med_*" where "*" = sd, se, ....} \item{ci}{the percent range of the confidence interval (default is 0.95).} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to be passed to ggpar().} } \description{ Visualizing error. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Data: ToothGrowth data set we'll be used. df<- ToothGrowth head(df, 10) # Plot mean_se ggerrorplot(df, x = "dose", y = "len") # Change desc_stat to mean_sd # (other values include: mean_sd, mean_ci, median_iqr, ....) # Add labels ggerrorplot(df, x = "dose", y = "len", desc_stat = "mean_sd") # Change error.plot to "errorbar" and add mean point # Visualize the mean of each group ggerrorplot(df, x = "dose", y = "len", add = "mean", error.plot = "errorbar") # Horizontal plot ggerrorplot(df, x = "dose", y = "len", add = "mean", error.plot = "errorbar", orientation = "horizontal") # Change error.plot to "crossbar" ggerrorplot(df, x = "dose", y = "len", error.plot = "crossbar", width = 0.5) # Add jitter points and errors (mean_se) ggerrorplot(df, x = "dose", y = "len", add = "jitter") # Add dot and errors (mean_se) ggerrorplot(df, x = "dose", y = "len", add = "dotplot") # Multiple groups with error bars and jitter point ggerrorplot(df, x = "dose", y = "len", color = "supp", palette = "Paired", error.plot = "pointrange", position = position_dodge(0.5)) } \seealso{ \code{\link{ggpar}}, \code{\link{ggline}} } ggpubr/man/stat_regline_equation.Rd0000644000176200001440000001331614333713444017201 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_regline_equation.R \name{stat_regline_equation} \alias{stat_regline_equation} \title{Add Regression Line Equation and R-Square to a GGPLOT.} \usage{ stat_regline_equation( mapping = NULL, data = NULL, formula = y ~ x, label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, output.type = "expression", geom = "text", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{formula}{a formula object} \item{label.x.npc, label.y.npc}{can be \code{numeric} or \code{character} vector of the same length as the number of groups and/or panels. If too short they will be recycled. \itemize{ \item If \code{numeric}, value should be between 0 and 1. Coordinates to be used for positioning the label, expressed in "normalized parent coordinates". \item If \code{character}, allowed values include: i) one of c('right', 'left', 'center', 'centre', 'middle') for x-axis; ii) and one of c( 'bottom', 'top', 'center', 'centre', 'middle') for y-axis.} If too short they will be recycled.} \item{label.x, label.y}{\code{numeric} Coordinates (in data units) to be used for absolute positioning of the label. If too short they will be recycled.} \item{output.type}{character One of "expression", "latex" or "text".} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If FALSE (the default), removes missing values with a warning. If TRUE silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{...}{other arguments to pass to \code{\link[ggplot2]{geom_text}} or \code{\link[ggplot2:geom_text]{geom_label}}.} } \description{ Add regression line equation and R^2 to a ggplot. Regression model is fitted using the function \code{\link[stats]{lm}}. } \section{Computed variables}{ \describe{ \item{x}{x position for left edge} \item{y}{y position near upper edge} \item{eq.label}{equation for the fitted polynomial as a character string to be parsed} \item{rr.label}{\eqn{R^2} of the fitted model as a character string to be parsed} \item{adj.rr.label}{Adjusted \eqn{R^2} of the fitted model as a character string to be parsed} \item{AIC.label}{AIC for the fitted model.} \item{BIC.label}{BIC for the fitted model.} \item{hjust}{Set to zero to override the default of the "text" geom.}} } \examples{ # Simple scatter plot with correlation coefficient and # regression line #:::::::::::::::::::::::::::::::::::::::::::::::::::: ggscatter(mtcars, x = "wt", y = "mpg", add = "reg.line") + stat_cor(label.x = 3, label.y = 34) + stat_regline_equation(label.x = 3, label.y = 32) # Groupped scatter plot #:::::::::::::::::::::::::::::::::::::::::::::::::::: ggscatter( iris, x = "Sepal.Length", y = "Sepal.Width", color = "Species", palette = "jco", add = "reg.line" ) + facet_wrap(~Species) + stat_cor(label.y = 4.4) + stat_regline_equation(label.y = 4.2) # Polynomial equation #:::::::::::::::::::::::::::::::::::::::::::::::::::: # Demo data set.seed(4321) x <- 1:100 y <- (x + x^2 + x^3) + rnorm(length(x), mean = 0, sd = mean(x^3) / 4) my.data <- data.frame(x, y, group = c("A", "B"), y2 = y * c(0.5,2), block = c("a", "a", "b", "b")) # Fit polynomial regression line and add labels formula <- y ~ poly(x, 3, raw = TRUE) p <- ggplot(my.data, aes(x, y2, color = group)) + geom_point() + stat_smooth(aes(fill = group, color = group), method = "lm", formula = formula) + stat_regline_equation( aes(label = paste(..eq.label.., ..adj.rr.label.., sep = "~~~~")), formula = formula ) + theme_bw() ggpar(p, palette = "jco") } \references{ the source code of the function \code{stat_regline_equation()} is inspired from the code of the function \code{stat_poly_eq()} (in ggpmisc package). } \seealso{ \code{\link{ggscatter}} } ggpubr/man/ggecdf.Rd0000644000176200001440000000726114367732422014041 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggecdf.R \name{ggecdf} \alias{ggecdf} \title{Empirical cumulative density function} \usage{ ggecdf( data, x, combine = FALSE, merge = FALSE, color = "black", palette = NULL, size = NULL, linetype = "solid", title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x}{variable to be drawn.} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{merge}{logical or character value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, merge multiple y variables in the same plotting area. Allowed values include also "asis" (TRUE) and "flip". If merge = "flip", then y variables are used as x tick labels and the x variable is used as grouping variable.} \item{color}{line and point color.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{size}{line and point size.} \item{linetype}{line type. See \code{\link{show_line_types}}.} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link[ggplot2]{stat_ecdf}} and \code{\link{ggpar}}.} } \description{ Empirical Cumulative Density Function (ECDF). } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Create some data format set.seed(1234) wdata = data.frame( sex = factor(rep(c("F", "M"), each=200)), weight = c(rnorm(200, 55), rnorm(200, 58))) head(wdata, 4) # Basic ECDF plot ggecdf(wdata, x = "weight") # Change colors and linetype by groups ("sex") # Use custom palette ggecdf(wdata, x = "weight", color = "sex", linetype = "sex", palette = c("#00AFBB", "#E7B800")) } \seealso{ \code{\link{ggpar}} } ggpubr/man/ggarrange.Rd0000644000176200001440000001014414333713444014545 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggarrange.R \name{ggarrange} \alias{ggarrange} \title{Arrange Multiple ggplots} \usage{ ggarrange( ..., plotlist = NULL, ncol = NULL, nrow = NULL, labels = NULL, label.x = 0, label.y = 1, hjust = -0.5, vjust = 1.5, font.label = list(size = 14, color = "black", face = "bold", family = NULL), align = c("none", "h", "v", "hv"), widths = 1, heights = 1, legend = NULL, common.legend = FALSE, legend.grob = NULL ) } \arguments{ \item{...}{list of plots to be arranged into the grid. The plots can be either ggplot2 plot objects or arbitrary gtables.} \item{plotlist}{(optional) list of plots to display.} \item{ncol}{(optional) number of columns in the plot grid.} \item{nrow}{(optional) number of rows in the plot grid.} \item{labels}{(optional) list of labels to be added to the plots. You can also set labels="AUTO" to auto-generate upper-case labels or labels="auto" to auto-generate lower-case labels.} \item{label.x}{(optional) Single value or vector of x positions for plot labels, relative to each subplot. Defaults to 0 for all labels. (Each label is placed all the way to the left of each plot.)} \item{label.y}{(optional) Single value or vector of y positions for plot labels, relative to each subplot. Defaults to 1 for all labels. (Each label is placed all the way to the top of each plot.)} \item{hjust}{Adjusts the horizontal position of each label. More negative values move the label further to the right on the plot canvas. Can be a single value (applied to all labels) or a vector of values (one for each label). Default is -0.5.} \item{vjust}{Adjusts the vertical position of each label. More positive values move the label further down on the plot canvas. Can be a single value (applied to all labels) or a vector of values (one for each label). Default is 1.5.} \item{font.label}{a list of arguments for customizing labels. Allowed values are the combination of the following elements: size (e.g.: 14), face (e.g.: "plain", "bold", "italic", "bold.italic"), color (e.g.: "red") and family. For example font.label = list(size = 14, face = "bold", color ="red").} \item{align}{(optional) Specifies whether graphs in the grid should be horizontally ("h") or vertically ("v") aligned. Options are "none" (default), "hv" (align in both directions), "h", and "v".} \item{widths}{(optional) numerical vector of relative columns widths. For example, in a two-column grid, widths = c(2, 1) would make the first column twice as wide as the second column.} \item{heights}{same as \code{widths} but for column heights.} \item{legend}{character specifying legend position. Allowed values are one of c("top", "bottom", "left", "right", "none"). To remove the legend use legend = "none".} \item{common.legend}{logical value. Default is FALSE. If TRUE, a common unique legend will be created for arranged plots.} \item{legend.grob}{a legend grob as returned by the function \code{\link{get_legend}()}. If provided, it will be used as the common legend.} } \value{ return an object of class \code{ggarrange}, which is a ggplot or a list of ggplot. } \description{ Arrange multiple ggplots on the same page. Wrapper around \code{\link[cowplot]{plot_grid}()}. Can arrange multiple ggplots over multiple pages, compared to the standard \code{\link[cowplot]{plot_grid}()}. Can also create a common unique legend for multiple plots. } \examples{ data("ToothGrowth") df <- ToothGrowth df$dose <- as.factor(df$dose) # Create some plots # :::::::::::::::::::::::::::::::::::::::::::::::::: # Box plot bxp <- ggboxplot(df, x = "dose", y = "len", color = "dose", palette = "jco") # Dot plot dp <- ggdotplot(df, x = "dose", y = "len", color = "dose", palette = "jco") # Density plot dens <- ggdensity(df, x = "len", fill = "dose", palette = "jco") # Arrange # :::::::::::::::::::::::::::::::::::::::::::::::::: ggarrange(bxp, dp, dens, ncol = 2, nrow = 2) # Use a common legend for multiple plots ggarrange(bxp, dp, common.legend = TRUE) } \seealso{ \code{\link{annotate_figure}()} } \author{ Alboukadel Kassambara \email{alboukadel.kassambara@gmail.com} } ggpubr/man/ggadd.Rd0000644000176200001440000000757714340445172013674 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggadd.R \name{ggadd} \alias{ggadd} \title{Add Summary Statistics or a Geom onto a ggplot} \usage{ ggadd( p, add = NULL, color = "black", fill = "white", group = 1, width = 1, shape = 19, size = NULL, alpha = 1, jitter = 0.2, seed = 123, binwidth = NULL, dotsize = size, linetype = 1, show.legend = NA, error.plot = "pointrange", ci = 0.95, data = NULL, position = position_dodge(0.8), p_geom = "" ) } \arguments{ \item{p}{a ggplot} \item{add}{character vector specifying other plot elements to be added. Allowed values are one or the combination of: "none", "dotplot", "jitter", "boxplot", "point", "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", "median_range".} \item{color}{point or outline color.} \item{fill}{fill color. Used only when \code{error.plot = "crossbar"}.} \item{group}{grouping variable. Allowed values are 1 (for one group) or a character vector specifying the name of the grouping variable. Used only for adding statistical summary per group.} \item{width}{numeric value between 0 and 1 specifying bar or box width. Example width = 0.8. Used only when \code{error.plot} is one of c("crossbar", "errorbar").} \item{shape}{point shape. Allowed values can be displayed using the function \code{\link{show_point_shapes}()}.} \item{size}{numeric value in [0-1] specifying point and line size.} \item{alpha}{numeric value specifying fill color transparency. Value should be in [0, 1], where 0 is full transparency and 1 is no transparency.} \item{jitter}{a numeric value specifying the amount of jittering. Used only when \code{add} contains "jitter".} \item{seed}{A random seed to make the jitter reproducible. Default is `123`. Useful if you need to apply the same jitter twice, e.g., for a point and a corresponding label. The random seed is reset after jittering. If `NA`, the seed is initialized with a random value; this makes sure that two subsequent calls start with a different seed. Use NULL to use the current random seed and also avoid resetting (the behaviour of ggplot 2.2.1 and earlier).} \item{binwidth}{numeric value specifying bin width. use value between 0 and 1 when you have a strong dense dotplot. For example binwidth = 0.2. Used only when \code{add} contains "dotplot".} \item{dotsize}{as \code{size} but applied only to dotplot.} \item{linetype}{line type.} \item{show.legend}{logical. Should this layer be included in the legends? NA, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and TRUE always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{error.plot}{plot type used to visualize error. Allowed values are one of \code{c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", "lower_linerange")}. Default value is "pointrange".} \item{ci}{the percent range of the confidence interval (default is 0.95).} \item{data}{a \code{data.frame} to be displayed. If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \link[ggplot2]{ggplot}.} \item{position}{position adjustment, either as a string, or the result of a call to a position adjustment function. Used to adjust position for multiple groups.} \item{p_geom}{the geometry of the main plot. Ex: p_geom = "geom_line". If NULL, the geometry is extracted from p. Used only by \link{ggline}().} } \description{ Add summary statistics or a geometry onto a ggplot. } \examples{ # Basic violin plot data("ToothGrowth") p <- ggviolin(ToothGrowth, x = "dose", y = "len", add = "none") # Add mean +/- SD and jitter points p \%>\% ggadd(c("mean_sd", "jitter"), color = "dose") # Add box plot p \%>\% ggadd(c("boxplot", "jitter"), color = "dose") } ggpubr/man/grids.Rd0000644000176200001440000000141114332553656013723 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/grids.R \name{grids} \alias{grids} \title{Add Grids to a ggplot} \usage{ grids(axis = c("xy", "x", "y"), color = "grey92", size = NULL, linetype = NULL) } \arguments{ \item{axis}{axis for which grid should be added. Allowed values include \code{c("xy", "x", "y")}.} \item{color}{grid line color.} \item{size}{numeric value specifying grid line size.} \item{linetype}{line type. An integer (0:8), a name (blank, solid, dashed, dotted, dotdash, longdash, twodash). Sess \code{\link{show_line_types}}.} } \description{ Add grids to ggplot. } \examples{ # Load data data("ToothGrowth") # Basic plot p <- ggboxplot(ToothGrowth, x = "dose", y = "len") p # Add border p + grids(linetype = "dashed") } ggpubr/man/rotate.Rd0000644000176200001440000000107214333713444014106 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rotate.R \name{rotate} \alias{rotate} \title{Rotate a ggplot Horizontally} \usage{ rotate(...) } \arguments{ \item{...}{other arguments to pass to \code{\link[ggplot2]{coord_flip}}.} } \description{ Rotate a ggplot to create horizontal plots. Wrapper around \code{\link[ggplot2]{coord_flip}}. } \examples{ # Load data data("ToothGrowth") df <- ToothGrowth # Basic plot p <- ggboxplot(df, x = "dose", y = "len", color = "dose", palette = "jco") p # Create horizontal plots p + rotate() } ggpubr/man/pipe.Rd0000644000176200001440000000040514332553656013552 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils-pipe.R \name{\%>\%} \alias{\%>\%} \title{Pipe operator} \usage{ lhs \%>\% rhs } \description{ See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. } \keyword{internal} ggpubr/man/get_legend.Rd0000644000176200001440000000157714332553656014725 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/get_legend.R \name{get_legend} \alias{get_legend} \title{Extract Legends from a ggplot object} \usage{ get_legend(p, position = NULL) } \arguments{ \item{p}{an object of class ggplot or a list of ggplots. If p is a list, only the first legend is returned.} \item{position}{character specifying legend position. Allowed values are one of c("top", "bottom", "left", "right", "none"). To remove the legend use legend = "none".} } \value{ an object of class gtable. } \description{ Extract the legend labels from a ggplot object. } \examples{ # Create a scatter plot p <- ggscatter(iris, x = "Sepal.Length", y = "Sepal.Width", color = "Species", palette = "jco", ggtheme = theme_minimal()) p # Extract the legend. Returns a gtable leg <- get_legend(p) # Convert to a ggplot and print as_ggplot(leg) } ggpubr/man/ggpaired.Rd0000644000176200001440000001126614367732422014404 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggpaired.R \name{ggpaired} \alias{ggpaired} \title{Plot Paired Data} \usage{ ggpaired( data, cond1, cond2, x = NULL, y = NULL, id = NULL, color = "black", fill = "white", palette = NULL, width = 0.5, point.size = 1.2, line.size = 0.5, line.color = "black", linetype = "solid", title = NULL, xlab = "Condition", ylab = "Value", facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{cond1}{variable name corresponding to the first condition.} \item{cond2}{variable name corresponding to the second condition.} \item{x, y}{x and y variables, where x is a grouping variable and y contains values for each group. Considered only when \code{cond1} and \code{cond2} are missing.} \item{id}{variable name corresponding to paired samples' id. Used to connect paired points with lines.} \item{color}{points and box plot colors. To color by conditions, use color = "condition".} \item{fill}{box plot fill color. To change fill color by conditions, use fill = "condition".} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{width}{box plot width.} \item{point.size, line.size}{point and line size, respectively.} \item{line.color}{line color.} \item{linetype}{line type.} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{label}{the name of the column containing point labels. Can be also a character vector with length = nrow(data).} \item{font.label}{a list which can contain the combination of the following elements: the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of labels. For example font.label = list(size = 14, face = "bold", color ="red"). To specify only the size and the style, use font.label = list(size = 14, face = "plain").} \item{label.select}{can be of two formats: \itemize{ \item a character vector specifying some labels to show. \item a list containing one or the combination of the following components: \itemize{ \item \code{top.up} and \code{top.down}: to display the labels of the top up/down points. For example, \code{label.select = list(top.up = 10, top.down = 4)}. \item \code{criteria}: to filter, for example, by x and y variabes values, use this: \code{label.select = list(criteria = "`y` > 2 & `y` < 5 & `x` \%in\% c('A', 'B')")}. } }} \item{repel}{a logical value, whether to use ggrepel to avoid overplotting text labels or not.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to be passed to \link{ggpar}().} } \description{ Plot paired data. } \examples{ # Example 1 #:::::::::::::::::::::::::::::::::::::::::: before <-c(200.1, 190.9, 192.7, 213, 241.4, 196.9, 172.2, 185.5, 205.2, 193.7) after <-c(392.9, 393.2, 345.1, 393, 434, 427.9, 422, 383.9, 392.3, 352.2) d <- data.frame(before = before, after = after) ggpaired(d, cond1 = "before", cond2 = "after", fill = "condition", palette = "jco") # Example 2 #:::::::::::::::::::::::::::::::::::::::::: ggpaired(ToothGrowth, x = "supp", y = "len", color = "supp", line.color = "gray", line.size = 0.4, palette = "npg") } ggpubr/man/get_breaks.Rd0000644000176200001440000000315114333713444014716 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/get_breaks.R \name{get_breaks} \alias{get_breaks} \title{Easy Break Creation for Numeric Axes} \usage{ get_breaks(n = NULL, by = NULL, from = NULL, to = NULL) } \arguments{ \item{n}{number of breaks.} \item{by}{number: the step between breaks.} \item{from}{the starting value of breaks. By default, 0 is used for positive variables} \item{to}{the end values of breaks. This corresponds generally to the maximum limit of the axis.} } \value{ a break function } \description{ Creates breaks for numeric axes to be used in the functions \code{\link[ggplot2:scale_continuous]{scale_x_continuous}()} and \code{\link[ggplot2:scale_continuous]{scale_y_continuous}()}. Can be used to increase the number of x and y ticks by specifying the option \code{n}. It's also possible to control axis breaks by specifying a step between ticks. For example, if \code{by = 5}, a tick mark is shown on every 5. } \examples{ # Generate 5 breaks for a variable x get_breaks(n = 5)(x = 1:100) # Generate breaks using an increasing step get_breaks(by = 10)(x = 1:100) # Combine with ggplot scale_xx functions library(ggplot2) # Create a basic plot p <- ggscatter(mtcars, x = "wt", y = "mpg") p # Increase the number of ticks p + scale_x_continuous(breaks = get_breaks(n = 10)) + scale_y_continuous(breaks = get_breaks(n = 10)) # Set ticks according to a specific step, starting from 0 p + scale_x_continuous( breaks = get_breaks(by = 1.5, from = 0), limits = c(0, 6) ) + scale_y_continuous( breaks = get_breaks(by = 10, from = 0), limits = c(0, 40) ) } ggpubr/man/add_summary.Rd0000644000176200001440000001203114367517301015113 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/add_summary.R \name{add_summary} \alias{add_summary} \alias{mean_se_} \alias{mean_sd} \alias{mean_ci} \alias{mean_range} \alias{median_iqr} \alias{median_hilow_} \alias{median_q1q3} \alias{median_mad} \alias{median_range} \title{Add Summary Statistics onto a ggplot.} \usage{ add_summary( p, fun = "mean_se", error.plot = "pointrange", color = "black", fill = "white", group = 1, width = NULL, shape = 19, size = 1, linetype = 1, show.legend = NA, ci = 0.95, data = NULL, position = position_dodge(0.8) ) mean_se_(x, error.limit = "both") mean_sd(x, error.limit = "both") mean_ci(x, ci = 0.95, error.limit = "both") mean_range(x, error.limit = "both") median_iqr(x, error.limit = "both") median_hilow_(x, ci = 0.95, error.limit = "both") median_q1q3(x, error.limit = "both") median_mad(x, error.limit = "both") median_range(x, error.limit = "both") } \arguments{ \item{p}{a ggplot on which you want to add summary statistics.} \item{fun}{a function that is given the complete data and should return a data frame with variables ymin, y, and ymax. Allowed values are one of: "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", "median_range".} \item{error.plot}{plot type used to visualize error. Allowed values are one of \code{c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", "lower_linerange")}. Default value is "pointrange".} \item{color}{point or outline color.} \item{fill}{fill color. Used only whne \code{error.plot = "crossbar"}.} \item{group}{grouping variable. Allowed values are 1 (for one group) or a character vector specifying the name of the grouping variable. Used only for adding statistical summary per group.} \item{width}{numeric value between 0 and 1 specifying bar or box width. Example width = 0.8. Used only when \code{error.plot} is one of c("crossbar", "errorbar").} \item{shape}{point shape. Allowed values can be displayed using the function \code{\link{show_point_shapes}()}.} \item{size}{numeric value in [0-1] specifying point and line size.} \item{linetype}{line type.} \item{show.legend}{logical. Should this layer be included in the legends? NA, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and TRUE always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{ci}{the percent range of the confidence interval (default is 0.95).} \item{data}{a \code{data.frame} to be displayed. If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \link[ggplot2]{ggplot}.} \item{position}{position adjustment, either as a string, or the result of a call to a position adjustment function. Used to adjust position for multiple groups.} \item{x}{a numeric vector.} \item{error.limit}{allowed values are one of ("both", "lower", "upper", "none") specifying whether to plot the lower and/or the upper limits of error interval.} } \description{ add summary statistics onto a ggplot. } \section{Functions}{ \itemize{ \item \code{add_summary()}: add summary statistics onto a ggplot. \item \code{mean_se_()}: returns the \code{mean} and the error limits defined by the \code{standard error}. We used the name \code{mean_se_}() to avoid masking \code{\link[ggplot2]{mean_se}}(). \item \code{mean_sd()}: returns the \code{mean} and the error limits defined by the \code{standard deviation}. \item \code{mean_ci()}: returns the \code{mean} and the error limits defined by the \code{confidence interval}. \item \code{mean_range()}: returns the \code{mean} and the error limits defined by the \code{range = max - min}. \item \code{median_iqr()}: returns the \code{median} and the error limits defined by the \code{interquartile range}. \item \code{median_hilow_()}: computes the sample median and a selected pair of outer quantiles having equal tail areas. This function is a reformatted version of \code{Hmisc::smedian.hilow()}. The confidence limits are computed as follow: \code{lower.limits = (1-ci)/2} percentiles; \code{upper.limits = (1+ci)/2} percentiles. By default (\code{ci = 0.95}), the 2.5th and the 97.5th percentiles are used as the lower and the upper confidence limits, respectively. If you want to use the 25th and the 75th percentiles as the confidence limits, then specify \code{ci = 0.5} or use the function \code{median_q1q3()}. \item \code{median_q1q3()}: computes the sample median and, the 25th and 75th percentiles. Wrapper around the function \code{median_hilow_()} using \code{ci = 0.5}. \item \code{median_mad()}: returns the \code{median} and the error limits defined by the \code{median absolute deviation}. \item \code{median_range()}: returns the \code{median} and the error limits defined by the \code{range = max - min}. }} \examples{ # Basic violin plot p <- ggviolin(ToothGrowth, x = "dose", y = "len", add = "none") p # Add mean_sd add_summary(p, "mean_sd") } ggpubr/man/font.Rd0000644000176200001440000000463314333713444013564 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/font.R \name{font} \alias{font} \title{Change the Appearance of Titles and Axis Labels} \usage{ font(object, size = NULL, color = NULL, face = NULL, family = NULL, ...) } \arguments{ \item{object}{character string specifying the plot components. Allowed values include: \itemize{ \item \code{"title"} for the main title \item \code{"subtitle"} for the plot subtitle \item \code{"caption"} for the plot caption \item \code{"legend.title"} for the legend title \item \code{"legend.text"} for the legend text \item \code{"x", "xlab", or "x.title"} for x axis label \item \code{"y", "ylab", or "y.title"} for y axis label \item \code{"xy", "xylab", "xy.title" or "axis.title"} for both x and y axis labels \item \code{"x.text"} for x axis texts (x axis tick labels) \item \code{"y.text"} for y axis texts (y axis tick labels) \item \code{"xy.text"} or \code{"axis.text"} for both x and y axis texts }} \item{size}{numeric value specifying the font size, (e.g.: \code{size = 12}).} \item{color}{character string specifying the font color, (e.g.: \code{color = "red"}).} \item{face}{the font face or style. Allowed values include one of \code{"plain", "bold", "italic", "bold.italic"}, (e.g.: \code{face = "bold.italic"}).} \item{family}{the font family.} \item{...}{other arguments to pass to the function \code{\link[ggplot2:element]{element_text}()}.} } \description{ Change the appearance of the main title, subtitle, caption, axis labels and text, as well as the legend title and texts. Wrapper around \code{\link[ggplot2:element]{element_text}()}. } \examples{ # Load data data("ToothGrowth") # Basic plot p <- ggboxplot(ToothGrowth, x = "dose", y = "len", color = "dose", title = "Box Plot created with ggpubr", subtitle = "Length by dose", caption = "Source: ggpubr", xlab ="Dose (mg)", ylab = "Teeth length") p # Change the appearance of titles and labels p + font("title", size = 14, color = "red", face = "bold.italic")+ font("subtitle", size = 10, color = "orange")+ font("caption", size = 10, color = "orange")+ font("xlab", size = 12, color = "blue")+ font("ylab", size = 12, color = "#993333")+ font("xy.text", size = 12, color = "gray", face = "bold") # Change the appearance of legend title and texts p + font("legend.title", color = "blue", face = "bold")+ font("legend.text", color = "red") } ggpubr/man/theme_pubr.Rd0000644000176200001440000000447314333713444014752 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/theme_pubr.R \name{theme_pubr} \alias{theme_pubr} \alias{theme_pubclean} \alias{labs_pubr} \alias{theme_classic2} \alias{clean_theme} \alias{clean_table_theme} \title{Publication ready theme} \usage{ theme_pubr( base_size = 12, base_family = "", border = FALSE, margin = TRUE, legend = c("top", "bottom", "left", "right", "none"), x.text.angle = 0 ) theme_pubclean(base_size = 12, base_family = "", flip = FALSE) labs_pubr(base_size = 14, base_family = "") theme_classic2(base_size = 12, base_family = "") clean_theme() clean_table_theme() } \arguments{ \item{base_size}{base font size} \item{base_family}{base font family} \item{border}{logical value. Default is FALSE. If TRUE, add panel border.} \item{margin}{logical value. Default is TRUE. If FALSE, reduce plot margin.} \item{legend}{character specifying legend position. Allowed values are one of c("top", "bottom", "left", "right", "none"). Default is "top" side position. to remove the legend use legend = "none". Legend position can be also specified using a numeric vector c(x, y). In this case it is possible to position the legend inside the plotting area. x and y are the coordinates of the legend box. Their values should be between 0 and 1. c(0,0) corresponds to the "bottom left" and c(1,1) corresponds to the "top right" position. For instance use legend = c(0.8, 0.2).} \item{x.text.angle}{Rotation angle of x axis tick labels. Default value is 0. Use 90 for vertical text.} \item{flip}{logical. If TRUE, grid lines are added to y axis instead of x axis.} } \description{ \itemize{ \item \strong{theme_pubr()}: Create a publication ready theme \item \strong{theme_pubclean()}: a clean theme without axis lines, to direct more attention to the data. \item \strong{labs_pubr()}: Format only plot labels to a publication ready style \item \strong{theme_classic2()}: Create a classic theme with axis lines. \item \strong{clean_theme()}: Remove axis lines, ticks, texts and titles. \item \strong{clean_table_theme()}: Clean the the theme of a table, such as those created by \code{\link{ggsummarytable}()}}. } \examples{ p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point(aes(color = gear)) # Default plot p # Use theme_pubr() p + theme_pubr() # Format labels p + labs_pubr() } ggpubr/man/ggpar.Rd0000644000176200001440000001465414367732422013726 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggpar.R \name{ggpar} \alias{ggpar} \title{Graphical parameters} \usage{ ggpar( p, palette = NULL, gradient.cols = NULL, main = NULL, submain = NULL, caption = NULL, xlab = NULL, ylab = NULL, title = NULL, subtitle = NULL, font.main = NULL, font.submain = NULL, font.x = NULL, font.y = NULL, font.caption = NULL, font.title = NULL, font.subtitle = NULL, font.family = "", xlim = NULL, ylim = NULL, xscale = c("none", "log2", "log10", "sqrt"), yscale = c("none", "log2", "log10", "sqrt"), format.scale = FALSE, legend = NULL, legend.title = NULL, font.legend = NULL, ticks = TRUE, tickslab = TRUE, font.tickslab = NULL, font.xtickslab = font.tickslab, font.ytickslab = font.tickslab, x.text.angle = NULL, y.text.angle = NULL, xtickslab.rt = x.text.angle, ytickslab.rt = y.text.angle, xticks.by = NULL, yticks.by = NULL, rotate = FALSE, orientation = c("vertical", "horizontal", "reverse"), ggtheme = NULL, ... ) } \arguments{ \item{p}{an object of class ggplot or a list of ggplots} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty". Can be also a numeric vector of length(groups); in this case a basic color palette is created using the function \link[grDevices]{palette}.} \item{gradient.cols}{vector of colors to use for n-colour gradient. Allowed values include brewer and ggsci color palettes.} \item{main}{plot main title.} \item{submain, subtitle}{plot subtitle.} \item{caption}{plot caption.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{title}{plot main title.} \item{font.main, font.submain, font.caption, font.x, font.y}{a vector of length 3 indicating respectively the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of main title, subtitle, caption, xlab and ylab, respectively. For example \emph{font.x = c(14, "bold", "red")}. Use font.x = 14, to change only font size; or use font.x = "bold", to change only font face.} \item{font.title, font.subtitle}{alias of font.submain and font.submain, respectively.} \item{font.family}{character vector specifying font family.} \item{xlim, ylim}{a numeric vector of length 2, specifying x and y axis limits (minimum and maximum), respectively. e.g.: ylim = c(0, 50).} \item{xscale, yscale}{x and y axis scale, respectively. Allowed values are one of c("none", "log2", "log10", "sqrt"); e.g.: yscale="log2".} \item{format.scale}{logical value. If TRUE, axis tick mark labels will be formatted when xscale or yscale = "log2" or "log10".} \item{legend}{character specifying legend position. Allowed values are one of c("top", "bottom", "left", "right", "none"). To remove the legend use legend = "none". Legend position can be also specified using a numeric vector c(x, y); see details section.} \item{legend.title}{legend title, e.g.: \code{legend.title = "Species"}. Can be also a list, \code{legend.title = list(color = "Species", linetype = "Species", shape = "Species")}.} \item{font.legend}{legend text font style; e.g.: font.legend = c(10, "plain", "black").} \item{ticks}{logical value. Default is TRUE. If FALSE, hide axis tick marks.} \item{tickslab}{logical value. Default is TRUE. If FALSE, hide axis tick labels.} \item{font.tickslab, font.xtickslab, font.ytickslab}{Font style (size, face, color) for tick labels, e.g.: c(14, "bold", "red").} \item{x.text.angle, y.text.angle}{Numeric value specifying the rotation angle of x and y axis tick labels, respectively. Default value is NULL. For vertical x axis texts use x.text.angle = 90.} \item{xtickslab.rt, ytickslab.rt}{Same as x.text.angle and y.text.angle, respectively. Will be deprecated in the near future.} \item{xticks.by, yticks.by}{numeric value controlling x and y axis breaks, respectively. For example, if yticks.by = 5, a tick mark is shown on every 5. Default value is NULL.} \item{rotate}{logical value. If TRUE, rotate the graph by setting the plot orientation to horizontal.} \item{orientation}{change the orientation of the plot. Allowed values are one of c( "vertical", "horizontal", "reverse"). Partial match is allowed.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{not used} } \description{ Graphical parameters } \examples{ # Load data data("ToothGrowth") df <- ToothGrowth # Basic box plot # +++++++++++++++++++++++++++ p <- ggboxplot(df, x = "dose", y = "len") # Change the plot orientation: horizontal ggpar(p, orientation = "horiz") # Change main title and axis labels # ++++++++++++++++++++++++++++ ggpar(p, main = "Plot of length \n by dose", xlab = "Dose (mg)", ylab = "Length") # Title font styles: 'plain', 'italic', 'bold', 'bold.italic' ggpar(p, main = "Length by dose", font.main = c(14,"bold.italic", "red"), font.x = c(14, "bold", "#2E9FDF"), font.y = c(14, "bold", "#E7B800")) # Hide axis labels ggpar(p, xlab = FALSE, ylab = FALSE) # Change colors # ++++++++++++++++++++++ # Change outline colors by groups: dose p2 <- ggboxplot(df, "dose", "len", color = "dose") p2 # Use custom color palette ggpar(p2, palette = c("#00AFBB", "#E7B800", "#FC4E07")) # Use brewer palette ggpar(p2, palette = "Dark2" ) # Use grey palette ggpar(p2, palette = "grey") # Use scientific journal palette from ggsci package ggpar(p2, palette = "npg") # nature # Axis ticks, limits, scales # +++++++++++++++++++++++++ # Axis ticks labels and rotation ggpar(p, font.tickslab = c(14,"bold", "#993333"), xtickslab.rt = 45, ytickslab.rt = 45) # Hide axis ticks and tick labels ggpar(p, ticks = FALSE, tickslab = FALSE) # Axis limits ggpar(p, ylim = c(0, 50)) # Axis scale ggpar(p, yscale = "log2") # Format axis scale ggpar(p, yscale = "log2", format.scale = TRUE) # Legends # ++++++++++++++++++ # Change legend position and title ggpar(p2, legend = "right", legend.title = "Dose (mg)", font.legend = c(10, "bold", "red")) } ggpubr/man/ggdotchart.Rd0000644000176200001440000001541114367732422014744 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggdotchart.R \name{ggdotchart} \alias{ggdotchart} \alias{theme_cleveland} \title{Cleveland's Dot Plots} \usage{ ggdotchart( data, x, y, group = NULL, combine = FALSE, color = "black", palette = NULL, shape = 19, size = NULL, dot.size = size, sorting = c("ascending", "descending", "none"), add = c("none", "segment"), add.params = list(), x.text.col = TRUE, rotate = FALSE, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, select = NULL, remove = NULL, order = NULL, label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, position = "identity", ggtheme = theme_pubr(), ... ) theme_cleveland(rotate = TRUE) } \arguments{ \item{data}{a data frame} \item{x, y}{x and y variables for drawing.} \item{group}{an optional column name indicating how the elements of x are grouped.} \item{combine}{logical value. Default is FALSE. Used only when y is a vector containing multiple variables to plot. If TRUE, create a multi-panel plot by combining the plot of y variables.} \item{color, size}{points color and size.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{shape}{point shape. See \code{\link{show_point_shapes}}.} \item{dot.size}{numeric value specifying the dot size.} \item{sorting}{a character vector for sorting into ascending or descending order. Allowed values are one of "descending", "ascending" and "none". Partial match are allowed (e.g. sorting = "desc" or "asc"). Default is "descending".} \item{add}{character vector for adding another plot element (e.g.: dot plot or error bars). Allowed values are one or the combination of: "none", "dotplot", "jitter", "boxplot", "point", "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", "median_range"; see ?desc_statby for more details.} \item{add.params}{parameters (color, shape, size, fill, linetype) for the argument 'add'; e.g.: add.params = list(color = "red").} \item{x.text.col}{logical. If TRUE (default), x axis texts are colored by groups.} \item{rotate}{logical value. If TRUE, rotate the graph by setting the plot orientation to horizontal.} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{panel.labs}{a list of one or two character vectors to modify facet panel labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies the labels for the "sex" variable. For two grouping variables, you can use for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", "Lev", "Lev2") ).} \item{short.panel.labs}{logical value. Default is TRUE. If TRUE, create short labels for panels by omitting variable names; in other words panels will be labelled only by variable grouping levels.} \item{select}{character vector specifying which items to display.} \item{remove}{character vector specifying which items to remove from the plot.} \item{order}{character vector specifying the order of items.} \item{label}{the name of the column containing point labels.} \item{font.label}{a list which can contain the combination of the following elements: the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of labels. For example font.label = list(size = 14, face = "bold", color ="red"). To specify only the size and the style, use font.label = list(size = 14, face = "plain").} \item{label.select}{can be of two formats: \itemize{ \item a character vector specifying some labels to show. \item a list containing one or the combination of the following components: \itemize{ \item \code{top.up} and \code{top.down}: to display the labels of the top up/down points. For example, \code{label.select = list(top.up = 10, top.down = 4)}. \item \code{criteria}: to filter, for example, by x and y variabes values, use this: \code{label.select = list(criteria = "`y` > 2 & `y` < 5 & `x` \%in\% c('A', 'B')")}. } }} \item{repel}{a logical value, whether to use ggrepel to avoid overplotting text labels or not.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{position}{Position adjustment, either as a string, or the result of a call to a position adjustment function.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link[ggplot2]{geom_point}} and \code{\link{ggpar}}.} } \description{ Draw a Cleveland dot plot. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Load data data("mtcars") df <- mtcars df$cyl <- as.factor(df$cyl) df$name <- rownames(df) head(df[, c("wt", "mpg", "cyl")], 3) # Basic plot ggdotchart(df, x = "name", y ="mpg", ggtheme = theme_bw()) # Change colors by group cyl ggdotchart(df, x = "name", y = "mpg", group = "cyl", color = "cyl", palette = c('#999999','#E69F00','#56B4E9'), rotate = TRUE, sorting = "descending", ggtheme = theme_bw(), y.text.col = TRUE ) # Plot with multiple groups # +++++++++++++++++++++ # Create some data df2 <- data.frame(supp=rep(c("VC", "OJ"), each=3), dose=rep(c("D0.5", "D1", "D2"),2), len=c(6.8, 15, 33, 4.2, 10, 29.5)) print(df2) ggdotchart(df2, x = "dose", y = "len", color = "supp", size = 3, add = "segment", add.params = list(color = "lightgray", size = 1.5), position = position_dodge(0.3), palette = "jco", ggtheme = theme_pubclean() ) } \seealso{ \code{\link{ggpar}} } ggpubr/man/stat_cor.Rd0000644000176200001440000001521014333713444014425 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_cor.R \name{stat_cor} \alias{stat_cor} \title{Add Correlation Coefficients with P-values to a Scatter Plot} \usage{ stat_cor( mapping = NULL, data = NULL, method = "pearson", alternative = "two.sided", cor.coef.name = c("R", "rho", "tau"), label.sep = ", ", label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, output.type = "expression", digits = 2, r.digits = digits, p.digits = digits, r.accuracy = NULL, p.accuracy = NULL, geom = "text", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{method}{a character string indicating which correlation coefficient (or covariance) is to be computed. One of "pearson" (default), "kendall", or "spearman".} \item{alternative}{a character string specifying the alternative hypothesis, must be one of "two.sided" (default), "greater" or "less". You can specify just the initial letter.} \item{cor.coef.name}{character. Can be one of \code{"R"} (pearson coef), \code{"rho"} (spearman coef) and \code{"tau"} (kendall coef). Uppercase and lowercase are allowed.} \item{label.sep}{a character string to separate the terms. Default is ", ", to separate the correlation coefficient and the p.value.} \item{label.x.npc, label.y.npc}{can be \code{numeric} or \code{character} vector of the same length as the number of groups and/or panels. If too short they will be recycled. \itemize{ \item If \code{numeric}, value should be between 0 and 1. Coordinates to be used for positioning the label, expressed in "normalized parent coordinates". \item If \code{character}, allowed values include: i) one of c('right', 'left', 'center', 'centre', 'middle') for x-axis; ii) and one of c( 'bottom', 'top', 'center', 'centre', 'middle') for y-axis.} If too short they will be recycled.} \item{label.x, label.y}{\code{numeric} Coordinates (in data units) to be used for absolute positioning of the label. If too short they will be recycled.} \item{output.type}{character One of "expression", "latex", "tex" or "text".} \item{digits, r.digits, p.digits}{integer indicating the number of decimal places (round) or significant digits (signif) to be used for the correlation coefficient and the p-value, respectively..} \item{r.accuracy}{a real value specifying the number of decimal places of precision for the correlation coefficient. Default is NULL. Use (e.g.) 0.01 to show 2 decimal places of precision. If specified, then \code{r.digits} is ignored.} \item{p.accuracy}{a real value specifying the number of decimal places of precision for the p-value. Default is NULL. Use (e.g.) 0.0001 to show 4 decimal places of precision. If specified, then \code{p.digits} is ignored.} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If FALSE (the default), removes missing values with a warning. If TRUE silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{...}{other arguments to pass to \code{\link[ggplot2]{geom_text}} or \code{\link[ggplot2:geom_text]{geom_label}}.} } \description{ Add correlation coefficients with p-values to a scatter plot. Can be also used to add `R2`. } \section{Computed variables}{ \describe{ \item{r}{correlation coefficient} \item{rr}{correlation coefficient squared} \item{r.label}{formatted label for the correlation coefficient} \item{rr.label}{formatted label for the squared correlation coefficient} \item{p.label}{label for the p-value} \item{label}{default labeldisplayed by \code{stat_cor()}} } } \examples{ # Load data data("mtcars") df <- mtcars df$cyl <- as.factor(df$cyl) # Scatter plot with correlation coefficient #::::::::::::::::::::::::::::::::::::::::::::::::: sp <- ggscatter(df, x = "wt", y = "mpg", add = "reg.line", # Add regressin line add.params = list(color = "blue", fill = "lightgray"), # Customize reg. line conf.int = TRUE # Add confidence interval ) # Add correlation coefficient sp + stat_cor(method = "pearson", label.x = 3, label.y = 30) # Specify the number of decimal places of precision for p and r # Using 3 decimal places for the p-value and # 2 decimal places for the correlation coefficient (r) sp + stat_cor(p.accuracy = 0.001, r.accuracy = 0.01) # Show only the r.label but not the p.label sp + stat_cor(aes(label = ..r.label..), label.x = 3) # Use R2 instead of R ggscatter(df, x = "wt", y = "mpg", add = "reg.line") + stat_cor( aes(label = paste(..rr.label.., ..p.label.., sep = "~`,`~")), label.x = 3 ) # Color by groups and facet #:::::::::::::::::::::::::::::::::::::::::::::::::::: sp <- ggscatter(df, x = "wt", y = "mpg", color = "cyl", palette = "jco", add = "reg.line", conf.int = TRUE) sp + stat_cor(aes(color = cyl), label.x = 3) } \seealso{ \code{\link{ggscatter}} } ggpubr/man/rotate_axis_text.Rd0000644000176200001440000000205414333713444016177 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rotate_axis_text.R \name{rotate_axis_text} \alias{rotate_axis_text} \alias{rotate_x_text} \alias{rotate_y_text} \title{Rotate Axes Text} \usage{ rotate_x_text(angle = 90, hjust = NULL, vjust = NULL, ...) rotate_y_text(angle = 90, hjust = NULL, vjust = NULL, ...) } \arguments{ \item{angle}{numeric value specifying the rotation angle. Default is 90 for vertical x-axis text.} \item{hjust}{horizontal justification (in [0, 1]).} \item{vjust}{vertical justification (in [0, 1]).} \item{...}{other arguments to pass to the function \code{\link[ggplot2:element]{element_text}()}.} } \description{ Rotate the x-axis text (tick mark labels). \itemize{ \item \code{rotate_x_text}(): Rotate x axis text. \item \code{rotate_y_text}(): Rotate y axis text. } } \examples{ # Load data data("ToothGrowth") df <- ToothGrowth # Basic plot p <- ggboxplot(df, x = "dose", y = "len") p # Vertical x axis text p + rotate_x_text() # Set rotation angle to 45 p + rotate_x_text(45) p + rotate_y_text(45) } ggpubr/man/set_palette.Rd0000644000176200001440000000271014332553656015127 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/set_palette.R \name{set_palette} \alias{set_palette} \alias{change_palette} \alias{color_palette} \alias{fill_palette} \title{Set Color Palette} \usage{ set_palette(p, palette) change_palette(p, palette) color_palette(palette = NULL, ...) fill_palette(palette = NULL, ...) } \arguments{ \item{p}{a ggplot} \item{palette}{Color palette. Allowed values include: \itemize{ \item \strong{Grey color palettes}: "grey" or "gray"; \item \strong{RColorBrewer palettes}, see \code{\link[RColorBrewer:ColorBrewer]{brewer.pal}} and details section. Examples of palette names include: "RdBu", "Blues", "Dark2", "Set2", ...; \item \strong{Custom color palettes}. For example, palette = c("#00AFBB", "#E7B800", "#FC4E07"); \item \strong{ggsci scientific journal palettes}, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty". }} \item{...}{other arguments passed to ggplot2 scale_color_xxx() and scale_fill_xxx() functions.} } \description{ \itemize{ \item \code{change_palette(), set_palette()}: Change both color and fill palettes. \item \code{color_palette()}: change color palette only. \item \code{fill_palette()}: change fill palette only. } } \examples{ # Load data data("ToothGrowth") df <- ToothGrowth # Basic plot p <- ggboxplot(df, x = "dose", y = "len", color = "dose") p # Change the color palette set_palette(p, "jco") } \seealso{ \link{get_palette}. } ggpubr/man/geom_exec.Rd0000644000176200001440000000174514333713444014552 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/geom_exec.R \name{geom_exec} \alias{geom_exec} \title{Execute ggplot2 functions} \usage{ geom_exec(geomfunc = NULL, data = NULL, position = NULL, ...) } \arguments{ \item{geomfunc}{a ggplot2 function (e.g.: geom_point)} \item{data}{a data frame to be used for mapping} \item{position}{Position adjustment, either as a string, or the result of a call to a position adjustment function.} \item{...}{arguments accepted by the function} } \value{ return a plot if geomfunc!=Null or a list(option, mapping) if geomfunc = NULL. } \description{ A helper function used by ggpubr functions to execute any geom_* functions in ggplot2. Useful only when you want to call a geom_* function without carrying about the arguments to put in aes(). Basic users of ggpubr don't need this function. } \examples{ \dontrun{ ggplot() + geom_exec(geom_point, data = mtcars, x = "mpg", y = "wt", size = "cyl", color = "cyl") } } ggpubr/man/stat_anova_test.Rd0000644000176200001440000003050714333713444016013 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_anova_test.R \name{stat_anova_test} \alias{stat_anova_test} \title{Add Anova Test P-values to a GGPlot} \usage{ stat_anova_test( mapping = NULL, data = NULL, method = c("one_way", "one_way_repeated", "two_way", "two_way_repeated", "two_way_mixed"), wid = NULL, group.by = NULL, type = NULL, effect.size = "ges", error = NULL, correction = c("auto", "GG", "HF", "none"), label = "{method}, p = {p.format}", label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, step.increase = 0.1, p.adjust.method = "holm", significance = list(), geom = "text", position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, parse = FALSE, ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{method}{ANOVA test methods. Possible values are one of \code{c("one_way", "one_way_repeated", "two_way", "two_way_repeated", "two_way_mixed")}.} \item{wid}{(factor) column name containing individuals/subjects identifier. Should be unique per individual. Required only for repeated measure tests (\code{"one_way_repeated", "two_way_repeated", "friedman_test", etc}).} \item{group.by}{(optional) character vector specifying the grouping variable; it should be used only for grouped plots. Possible values are : \itemize{ \item \code{"x.var"}: Group by the x-axis variable and perform the test between legend groups. In other words, the p-value is compute between legend groups at each x position \item \code{"legend.var"}: Group by the legend variable and perform the test between x-axis groups. In other words, the test is performed between the x-groups for each legend level. }} \item{type}{the type of sums of squares for ANOVA. Allowed values are either 1, 2 or 3. \code{type = 2} is the default because this will yield identical ANOVA results as type = 1 when data are balanced but type = 2 will additionally yield various assumption tests where appropriate. When the data are unbalanced the \code{type = 3} is used by popular commercial softwares including SPSS.} \item{effect.size}{the effect size to compute and to show in the ANOVA results. Allowed values can be either "ges" (generalized eta squared) or "pes" (partial eta squared) or both. Default is "ges".} \item{error}{(optional) for a linear model, an lm model object from which the overall error sum of squares and degrees of freedom are to be calculated. Read more in \code{\link[car]{Anova}()} documentation.} \item{correction}{character. Used only in repeated measures ANOVA test to specify which correction of the degrees of freedom should be reported for the within-subject factors. Possible values are: \itemize{ \item{"GG"}: applies Greenhouse-Geisser correction to all within-subjects factors even if the assumption of sphericity is met (i.e., Mauchly's test is not significant, p > 0.05). \item{"HF"}: applies Hyunh-Feldt correction to all within-subjects factors even if the assumption of sphericity is met, \item{"none"}: returns the ANOVA table without any correction and \item{"auto"}: apply automatically GG correction to only within-subjects factors violating the sphericity assumption (i.e., Mauchly's test p-value is significant, p <= 0.05). }} \item{label}{character string specifying label. Can be: \itemize{ \item the column containing the label (e.g.: \code{label = "p"} or \code{label = "p.adj"}), where \code{p} is the p-value. Other possible values are \code{"p.signif", "p.adj.signif", "p.format", "p.adj.format"}. \item an expression that can be formatted by the \code{\link[glue]{glue}()} package. For example, when specifying \code{label = "Anova, p = \{p\}"}, the expression \{p\} will be replaced by its value. \item a combination of plotmath expressions and glue expressions. You may want some of the statistical parameter in italic; for example:\code{label = "Anova, italic(p) = {p}"}. \item a constant: \code{label = "as_italic"}: display statistical parameters in italic; \code{label = "as_detailed"}: detailed plain text; \code{label = "as_detailed_expression"} or \code{label = "as_detailed_italic"}: detailed plotmath expression. Statistical parameters will be displayed in italic.}.} \item{label.x.npc, label.y.npc}{can be \code{numeric} or \code{character} vector of the same length as the number of groups and/or panels. If too short they will be recycled. \itemize{ \item If \code{numeric}, value should be between 0 and 1. Coordinates to be used for positioning the label, expressed in "normalized parent coordinates". \item If \code{character}, allowed values include: i) one of c('right', 'left', 'center', 'centre', 'middle') for x-axis; ii) and one of c( 'bottom', 'top', 'center', 'centre', 'middle') for y-axis.}} \item{label.x, label.y}{\code{numeric} Coordinates (in data units) to be used for absolute positioning of the label. If too short they will be recycled.} \item{step.increase}{numeric value in with the increase in fraction of total height for every additional comparison to minimize overlap. The step value can be negative to reverse the order of groups.} \item{p.adjust.method}{method for adjusting p values (see \code{\link[stats]{p.adjust}}). Has impact only in a situation, where multiple pairwise tests are performed; or when there are multiple grouping variables. Allowed values include "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none". If you don't want to adjust the p value (not recommended), use p.adjust.method = "none".} \item{significance}{a list of arguments specifying the signifcance cutpoints and symbols. For example, \code{significance <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, 0.05, Inf), symbols = c("****", "***", "**", "*", "ns"))}. In other words, we use the following convention for symbols indicating statistical significance: \itemize{ \item \code{ns}: p > 0.05 \item \code{*}: p <= 0.05 \item \code{**}: p <= 0.01 \item \code{***}: p <= 0.001 \item \code{****}: p <= 0.0001 }} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If FALSE (the default), removes missing values with a warning. If TRUE silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{parse}{If TRUE, the labels will be parsed into expressions and displayed as described in \code{?plotmath}.} \item{...}{other arguments to pass to \code{\link[ggplot2:geom_text]{geom_text}}, such as:\itemize{ \item \code{hjust}: horizontal justification of the text. Move the text left or right and \item \code{vjust}: vertical justification of the text. Move the text up or down. }} } \description{ Adds automatically one-way and two-way ANOVA test p-values to a ggplot, such as box blots, dot plots and stripcharts. } \section{Computed variables}{ \itemize{ \item{DFn}: Degrees of Freedom in the numerator (i.e. DF effect). \item{DFd}: Degrees of Freedom in the denominator (i.e., DF error). \item{ges}: Generalized Eta-Squared measure of effect size. Computed only when the option \code{effect.size = "ges"}. \item{pes}: Partial Eta-Squared measure of effect size. Computed only when the option \code{effect.size = "pes"}. \item{F}: F-value. \item{p}: p-value. \item{p.adj}: Adjusted p-values. \item{p.signif}: P-value significance. \item{p.adj.signif}: Adjusted p-value significance. \item{p.format}: Formated p-value. \item{p.adj.format}: Formated adjusted p-value. \item{n}: number of samples. } } \examples{ # Data preparation #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Transform `dose` into factor variable df <- ToothGrowth df$dose <- as.factor(df$dose) # Add individuals id df$id <- rep(1:10, 6) # Add a random grouping variable set.seed(123) df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) df$len <- ifelse(df$group == "grp2", df$len+2, df$len) df$len <- ifelse(df$group == "grp3", df$len+7, df$len) head(df, 3) # Basic boxplot #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Create a basic boxplot # Add 5\% and 10\% space to the plot bottom and the top, respectively bxp <- ggboxplot(df, x = "dose", y = "len") + scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) # Add the p-value to the boxplot bxp + stat_anova_test() \dontrun{ # Change the label position # Using coordinates in data units bxp + stat_anova_test(label.x = "1", label.y = 10, hjust = 0) } # Format the p-value differently custom_p_format <- function(p) { rstatix::p_format(p, accuracy = 0.0001, digits = 3, leading.zero = FALSE) } bxp + stat_anova_test( label = "Anova, italic(p) = {custom_p_format(p)}{p.signif}" ) # Show a detailed label in italic bxp + stat_anova_test(label = "as_detailed_italic") # Faceted plots #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Create a ggplot facet bxp <- ggboxplot(df, x = "dose", y = "len", facet.by = "supp") + scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) # Add p-values bxp + stat_anova_test() # Grouped plots #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% bxp2 <- ggboxplot(df, x = "group", y = "len", color = "dose", palette = "npg") # For each x-position, computes tests between legend groups bxp2 + stat_anova_test(aes(group = dose), label = "p = {p.format}{p.signif}") # For each legend group, computes tests between x variable groups bxp2 + stat_anova_test(aes(group = dose, color = dose), group.by = "legend.var") \dontrun{ # Two-way ANOVA: Independent measures #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% # Visualization: box plots with p-values # Two-way interaction p-values between x and legend (group) variables bxp3 <- ggboxplot( df, x = "supp", y = "len", color = "dose", palette = "jco" ) bxp3 + stat_anova_test(aes(group = dose), method = "two_way") # One-way repeatead measures ANOVA #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% df$id <- as.factor(c(rep(1:10, 3), rep(11:20, 3))) ggboxplot(df, x = "dose", y = "len") + stat_anova_test(method = "one_way_repeated", wid = "id") # Two-way repeatead measures ANOVA #\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\%\% df$id <- as.factor(rep(1:10, 6)) ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") + stat_anova_test(aes(group = supp), method = "two_way_repeated", wid = "id") # Grouped one-way repeated measures ANOVA ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") + stat_anova_test(aes(group = supp, color = supp), method = "one_way_repeated", wid = "id", group.by = "legend.var") } } ggpubr/man/ggexport.Rd0000644000176200001440000000341714333713444014454 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggexport.R \name{ggexport} \alias{ggexport} \title{Export ggplots} \usage{ ggexport( ..., plotlist = NULL, filename = NULL, ncol = NULL, nrow = NULL, width = 480, height = 480, pointsize = 12, res = NA, verbose = TRUE ) } \arguments{ \item{...}{list of plots to be arranged into the grid. The plots can be either ggplot2 plot objects, arbitrary gtables or an object of class \code{\link{ggarrange}}.} \item{plotlist}{(optional) list of plots to display.} \item{filename}{File name to create on disk.} \item{ncol}{(optional) number of columns in the plot grid.} \item{nrow}{(optional) number of rows in the plot grid.} \item{width, height}{plot width and height, respectively (example, width = 800, height = 800). Applied only to raster plots: "png", "jpeg", "jpg", "bmp" and "tiff".} \item{pointsize}{the default pointsize of plotted text (example, pointsize = 8). Used only for raster plots.} \item{res}{the resolution in ppi (example, res = 250). Used only for raster plots.} \item{verbose}{logical. If TRUE, show message.} } \description{ Export ggplots } \examples{ \dontrun{ require("magrittr") # Load data data("ToothGrowth") df <- ToothGrowth df$dose <- as.factor(df$dose) # Box plot bxp <- ggboxplot(df, x = "dose", y = "len", color = "dose", palette = "jco") # Dot plot dp <- ggdotplot(df, x = "dose", y = "len", color = "dose", palette = "jco") # Density plot dens <- ggdensity(df, x = "len", fill = "dose", palette = "jco") # Export to pdf ggarrange(bxp, dp, dens, ncol = 2) \%>\% ggexport(filename = "test.pdf") # Export to png ggarrange(bxp, dp, dens, ncol = 2) \%>\% ggexport(filename = "test.png") } } \author{ Alboukadel Kassambara } ggpubr/man/ggdonutchart.Rd0000644000176200001440000000665414337251252015312 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggdonutchart.R \name{ggdonutchart} \alias{ggdonutchart} \title{Donut chart} \usage{ ggdonutchart( data, x, label = x, lab.pos = c("out", "in"), lab.adjust = 0, lab.font = c(4, "plain", "black"), font.family = "", color = "black", fill = "white", palette = NULL, size = NULL, ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x}{variable containing values for drawing.} \item{label}{variable specifying the label of each slice.} \item{lab.pos}{character specifying the position for labels. Allowed values are "out" (for outside) or "in" (for inside).} \item{lab.adjust}{numeric value, used to adjust label position when lab.pos = "in". Increase or decrease this value to see the effect.} \item{lab.font}{a vector of length 3 indicating respectively the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of label font. For example \emph{lab.font= c(4, "bold", "red")}.} \item{font.family}{character vector specifying font family.} \item{color, fill}{outline and fill colors.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to be passed to ggpar().} } \description{ Create a donut chart. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Data: Create some data # +++++++++++++++++++++++++++++++ df <- data.frame( group = c("Male", "Female", "Child"), value = c(25, 25, 50)) head(df) # Basic pie charts # ++++++++++++++++++++++++++++++++ ggdonutchart(df, "value", label = "group") # Change color # ++++++++++++++++++++++++++++++++ # Change fill color by group # set line color to white # Use custom color palette ggdonutchart(df, "value", label = "group", fill = "group", color = "white", palette = c("#00AFBB", "#E7B800", "#FC4E07") ) # Change label # ++++++++++++++++++++++++++++++++ # Show group names and value as labels labs <- paste0(df$group, " (", df$value, "\%)") ggdonutchart(df, "value", label = labs, fill = "group", color = "white", palette = c("#00AFBB", "#E7B800", "#FC4E07")) # Change the position and font color of labels ggdonutchart(df, "value", label = labs, lab.pos = "in", lab.font = "white", fill = "group", color = "white", palette = c("#00AFBB", "#E7B800", "#FC4E07")) } \seealso{ \code{\link{ggpar}}, \code{\link{ggpie}} } ggpubr/man/ggpie.Rd0000644000176200001440000000677114341741173013715 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggpie.R \name{ggpie} \alias{ggpie} \title{Pie chart} \usage{ ggpie( data, x, label = x, lab.pos = c("out", "in"), lab.adjust = 0, lab.font = c(4, "plain", "black"), font.family = "", color = "black", fill = "white", palette = NULL, size = NULL, ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x}{variable containing values for drawing.} \item{label}{variable specifying the label of each slice.} \item{lab.pos}{character specifying the position for labels. Allowed values are "out" (for outside) or "in" (for inside).} \item{lab.adjust}{numeric value, used to adjust label position when lab.pos = "in". Increase or decrease this value to see the effect.} \item{lab.font}{a vector of length 3 indicating respectively the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of label font. For example \emph{lab.font= c(4, "bold", "red")}.} \item{font.family}{character vector specifying font family.} \item{color, fill}{outline and fill colors.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to be passed to ggpar().} } \description{ Create a pie chart. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" \item plot orientation : orientation = c("vertical", "horizontal", "reverse") } } \examples{ # Data: Create some data # +++++++++++++++++++++++++++++++ df <- data.frame( group = c("Male", "Female", "Child"), value = c(25, 25, 50)) head(df) # Basic pie charts # ++++++++++++++++++++++++++++++++ ggpie(df, "value", label = "group") # Reducing margins around the pie chart ggpie(df, "value", label = "group") + theme( plot.margin = unit(c(-.75,-.75,-.75,-.75),"cm")) # Change color # ++++++++++++++++++++++++++++++++ # Change fill color by group # set line color to white # Use custom color palette ggpie(df, "value", label = "group", fill = "group", color = "white", palette = c("#00AFBB", "#E7B800", "#FC4E07") ) # Change label # ++++++++++++++++++++++++++++++++ # Show group names and value as labels labs <- paste0(df$group, " (", df$value, "\%)") ggpie(df, "value", label = labs, fill = "group", color = "white", palette = c("#00AFBB", "#E7B800", "#FC4E07")) # Change the position and font color of labels ggpie(df, "value", label = labs, lab.pos = "in", lab.font = "white", fill = "group", color = "white", palette = c("#00AFBB", "#E7B800", "#FC4E07")) } \seealso{ \code{\link{ggpar}}, \code{\link{ggline}} } ggpubr/man/get_coord.Rd0000644000176200001440000000521214333713444014555 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/get_coord.R \name{get_coord} \alias{get_coord} \title{Checks and Returns Data Coordinates from Multiple Input Options} \usage{ get_coord( group = 1L, data.ranges = NULL, coord = NULL, npc = "left", step = 0.1, margin.npc = 0.05 ) } \arguments{ \item{group}{integer ggplot's group id. Used to shift coordinates to avoid overlaps.} \item{data.ranges}{a numeric vector of length 2 containing the data ranges (minimum and the maximum). Should be specified only when \code{coord = NULL} and \code{npc} is specified. Used to convert \code{npc} to data coordinates. Considered only when the argument \code{npc} is specified.} \item{coord}{data coordinates (i.e., either x or y coordinates).} \item{npc}{numeric (in [0-1]) or character vector of coordinates. If character, should be one of c('right', 'left', 'bottom', 'top', 'center', 'centre', 'middle'). Note that, the \code{data.ranges}, \code{step} and \code{margin.npc}, arguments are considered only when \code{npc} is specified. The option \code{npc} is ignored when the argument \code{coord} is specified.} \item{step}{numeric value in [0-1]. The step size for shifting coordinates in npc units. Considered as horizontal step for x-axis and vertical step for y-axis. For y-axis, the step value can be negative to reverse the order of groups.} \item{margin.npc}{numeric [0-1] The margin added towards the nearest plotting area edge when converting character coordinates into npc.} } \value{ a numeric vector representing data coordinates. } \description{ Checks and returns selected coordinates from multiple input options, which can be either data (x-y) coordinates or npc (normalized parent coordinates). Helper function internally used in \code{ggpubr} function to guess the type of coordinates specified by the user. For example, in the function \code{stat_cor()}, users can specify either the option \code{label.x} (data coordinates) or \code{label.x.npc} (npc coordinates); those coordinates are passed to \code{get_coord()}, which will make some checking and then return a unique coordinates for the label position. } \examples{ # If npc is specified, it is converted into data coordinates get_coord(data.ranges = c(2, 20), npc = "left") get_coord(data.ranges = c(2, 20), npc = 0.1) # When coord is specified, no transformation is performed # because this is assumed to be a data coordinate get_coord(coord = 5) # For grouped plots res_top <- get_coord( data.ranges = c(4.2, 36.4), group = c(1, 2, 3), npc = "top", step = -0.1, margin.npc = 0 ) res_top } \seealso{ \code{\link{as_npc}}, \code{\link{npc_to_data_coord}}. } ggpubr/man/ggscatterhist.Rd0000644000176200001440000001026714367733325015500 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggscatterhist.R \name{ggscatterhist} \alias{ggscatterhist} \alias{print.ggscatterhist} \title{Scatter Plot with Marginal Histograms} \usage{ ggscatterhist( data, x, y, group = NULL, color = "black", fill = NA, palette = NULL, shape = 19, size = 2, linetype = "solid", bins = 30, margin.plot = c("density", "histogram", "boxplot"), margin.params = list(), margin.ggtheme = theme_void(), margin.space = FALSE, main.plot.size = 2, margin.plot.size = 1, title = NULL, xlab = NULL, ylab = NULL, legend = "top", ggtheme = theme_pubr(), print = TRUE, ... ) \method{print}{ggscatterhist}( x, margin.space = FALSE, main.plot.size = 2, margin.plot.size = 1, title = NULL, legend = "top", ... ) } \arguments{ \item{data}{a data frame} \item{x}{an object of class \code{ggscatterhist}.} \item{y}{y variables for drawing.} \item{group}{a grouping variable. Change points color and shape by groups if the options \code{color} and \code{shape} are missing. Should be also specified when you want to create a marginal box plot that is grouped.} \item{color, fill}{point colors.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{shape}{point shape. See \code{\link{show_point_shapes}}.} \item{size}{Numeric value (e.g.: size = 1). change the size of points and outlines.} \item{linetype}{line type ("solid", "dashed", ...)} \item{bins}{Number of histogram bins. Defaults to 30. Pick a better value that fit to your data.} \item{margin.plot}{the type of the marginal plot. Default is "hist".} \item{margin.params}{parameters to be applied to the marginal plots.} \item{margin.ggtheme}{the theme of the marginal plot. Default is \code{\link[ggplot2:ggtheme]{theme_void}()}.} \item{margin.space}{logical value. If TRUE, adds space between the main plot and the marginal plot.} \item{main.plot.size}{the width of the main plot. Default is 2.} \item{margin.plot.size}{the width of the marginal plot. Default is 1.} \item{title}{plot main title.} \item{xlab}{character vector specifying x axis labels. Use xlab = FALSE to hide xlab.} \item{ylab}{character vector specifying y axis labels. Use ylab = FALSE to hide ylab.} \item{legend}{specify the legend position. Allowed values include: "top", "bottom", "left", "right".} \item{ggtheme}{the theme to be used for the scatter plot. Default is \code{\link{theme_pubr}()}.} \item{print}{logical value. If \code{TRUE} (default), print the plot.} \item{...}{other arguments passed to the function \code{\link{ggscatter}()}.} } \value{ an object of class \code{ggscatterhist}, which is list of ggplots, including the following elements: \itemize{\item sp: main scatter plot; \item xplot: marginal x-axis plot; \item yplot: marginal y-axis plot. }. User can modify each of plot before printing. } \description{ Create a scatter plot with marginal histograms, density plots or box plots. } \examples{ # Basic scatter plot with marginal density plot ggscatterhist(iris, x = "Sepal.Length", y = "Sepal.Width", color = "#00AFBB", margin.params = list(fill = "lightgray")) # Grouped data ggscatterhist( iris, x = "Sepal.Length", y = "Sepal.Width", color = "Species", size = 3, alpha = 0.6, palette = c("#00AFBB", "#E7B800", "#FC4E07"), margin.params = list(fill = "Species", color = "black", size = 0.2) ) # Use boxplot as marginal ggscatterhist( iris, x = "Sepal.Length", y = "Sepal.Width", color = "Species", size = 3, alpha = 0.6, palette = c("#00AFBB", "#E7B800", "#FC4E07"), margin.plot = "boxplot", ggtheme = theme_bw() ) # Add vertical and horizontal line to a ggscatterhist plots <- ggscatterhist(iris, x = "Sepal.Length", y = "Sepal.Width", print = FALSE) plots$sp <- plots$sp + geom_hline(yintercept = 3, linetype = "dashed", color = "blue") + geom_vline(xintercept = 6, linetype = "dashed", color = "red") plots } ggpubr/man/theme_transparent.Rd0000644000176200001440000000125314332553656016342 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/theme_transparent.R \name{theme_transparent} \alias{theme_transparent} \title{Create a ggplot with Transparent Background} \usage{ theme_transparent(base_size = 12, base_family = "") } \arguments{ \item{base_size}{base font size} \item{base_family}{base font family} } \description{ Create a ggplot with transparent background. } \examples{ # Create a scatter plot sp <- ggscatter(iris, x = "Sepal.Length", y = "Sepal.Width", color = "Species", palette = "jco", size = 3, alpha = 0.6) sp # Transparent theme sp + theme_transparent() } \seealso{ \code{\link{theme_pubr}} } ggpubr/man/ggpubr_options.Rd0000644000176200001440000000044414333716602015652 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggpubr_options.R \name{ggpubr_options} \alias{ggpubr_options} \title{Global Options for GGPubr} \usage{ ggpubr_options() } \description{ Displays allowed global options in ggpubr. } \examples{ ggpubr_options() } ggpubr/man/diff_express.Rd0000644000176200001440000000302714333713444015273 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/diff_express.R \docType{data} \name{diff_express} \alias{diff_express} \title{Differential gene expression analysis results} \format{ A data frame with 36028 rows and 5 columns. \describe{ \item{\code{name}}{gene names} \item{\code{baseMean}}{mean expression signal across all samples} \item{\code{log2FoldChange}}{log2 fold change} \item{\code{padj}}{Adjusted p-value}\item{\code{detection_call}}{a numeric vector specifying whether the genes is expressed (value = 1) or not (value = 0).}} } \usage{ data("diff_express") } \description{ Differential gene expression analysis results obtained from comparing the RNAseq data of two different cell populations using DESeq2 } \examples{ data(diff_express) # Default plot ggmaplot(diff_express, main = expression("Group 1" \%->\% "Group 2"), fdr = 0.05, fc = 2, size = 0.4, palette = c("#B31B21", "#1465AC", "darkgray"), genenames = as.vector(diff_express$name), legend = "top", top = 20, font.label = c("bold", 11), font.legend = "bold", font.main = "bold", ggtheme = ggplot2::theme_minimal()) # Add rectangle around labesl ggmaplot(diff_express, main = expression("Group 1" \%->\% "Group 2"), fdr = 0.05, fc = 2, size = 0.4, palette = c("#B31B21", "#1465AC", "darkgray"), genenames = as.vector(diff_express$name), legend = "top", top = 20, font.label = c("bold", 11), label.rectangle = TRUE, font.legend = "bold", font.main = "bold", ggtheme = ggplot2::theme_minimal()) } ggpubr/man/ggballoonplot.Rd0000644000176200001440000001200214333713444015446 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggballoonplot.R \name{ggballoonplot} \alias{ggballoonplot} \title{Ballon plot} \usage{ ggballoonplot( data, x = NULL, y = NULL, size = "value", facet.by = NULL, size.range = c(1, 10), shape = 21, color = "black", fill = "gray", show.label = FALSE, font.label = list(size = 12, color = "black"), rotate.x.text = TRUE, ggtheme = theme_minimal(), ... ) } \arguments{ \item{data}{a data frame. Can be: \itemize{ \item \bold{a standard contingency table} formed by two categorical variables: a data frame with row names and column names. The categories of the first variable are columns and the categories of the second variable are rows. \item \bold{a streched contingency table}: a data frame containing at least three columns corresponding, respectively, to (1) the categories of the first variable, (2) the categories of the second varible, (3) the frequency value. In this case, you should specify the argument x and y in the function \code{ggballoonplot()}}.} \item{x, y}{the column names specifying, respectively, the first and the second variable forming the contingency table. Required only when the data is a stretched contingency table.} \item{size}{point size. By default, the points size reflects the relative magnitude of the value of the corresponding cell (\code{size = "value"}). Can be also numeric (\code{size = 4}).} \item{facet.by}{character vector, of length 1 or 2, specifying grouping variables for faceting the plot into multiple panels. Should be in the data.} \item{size.range}{a numeric vector of length 2 that specifies the minimum and maximum size of the plotting symbol. Default values are \code{size.range = c(1, 10)}.} \item{shape}{points shape. The default value is 21. Alternaive values include 22, 23, 24, 25.} \item{color}{point border line color.} \item{fill}{point fill color. Default is "lightgray". Considered only for points 21 to 25.} \item{show.label}{logical. If TRUE, show the data cell values as point labels.} \item{font.label}{a vector of length 3 indicating respectively the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the color (e.g.: "red") of point labels. For example font.label = c(14, "bold", "red"). To specify only the size and the style, use font.label = c(14, "plain").} \item{rotate.x.text}{logica. If TRUE (default), rotate the x axis text.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments passed to the function \code{\link{ggpar}}} } \description{ Plot a graphical matrix where each cell contains a dot whose size reflects the relative magnitude of the corresponding component. Useful to visualize contingency table formed by two categorical variables. } \examples{ # Define color palette my_cols <- c("#0D0887FF", "#6A00A8FF", "#B12A90FF", "#E16462FF", "#FCA636FF", "#F0F921FF") # Standard contingency table #::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Read a contingency table: housetasks # Repartition of 13 housetasks in the couple data <- read.delim( system.file("demo-data/housetasks.txt", package = "ggpubr"), row.names = 1 ) data # Basic ballon plot ggballoonplot(data) # Change color and fill ggballoonplot(data, color = "#0073C2FF", fill = "#0073C2FF") # Change color according to the value of table cells ggballoonplot(data, fill = "value")+ scale_fill_gradientn(colors = my_cols) # Change the plotting symbol shape ggballoonplot(data, fill = "value", shape = 23)+ gradient_fill(c("blue", "white", "red")) # Set points size to 8, but change fill color by values # Sow labels ggballoonplot(data, fill = "value", color = "lightgray", size = 10, show.label = TRUE)+ gradient_fill(c("blue", "white", "red")) # Streched contingency table #::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Create an Example Data Frame Containing Car x Color data carnames <- c("bmw","renault","mercedes","seat") carcolors <- c("red","white","silver","green") datavals <- round(rnorm(16, mean=100, sd=60),1) car_data <- data.frame(Car = rep(carnames,4), Color = rep(carcolors, c(4,4,4,4) ), Value=datavals ) car_data ggballoonplot(car_data, x = "Car", y = "Color", size = "Value", fill = "Value") + scale_fill_gradientn(colors = my_cols) + guides(size = FALSE) # Grouped frequency table #::::::::::::::::::::::::::::::::::::::::::::::::::::::::: data("Titanic") dframe <- as.data.frame(Titanic) head(dframe) ggballoonplot( dframe, x = "Class", y = "Sex", size = "Freq", fill = "Freq", facet.by = c("Survived", "Age"), ggtheme = theme_bw() )+ scale_fill_gradientn(colors = my_cols) # Hair and Eye Color of Statistics Students data(HairEyeColor) ggballoonplot( as.data.frame(HairEyeColor), x = "Hair", y = "Eye", size = "Freq", ggtheme = theme_gray()) \%>\% facet("Sex") } ggpubr/man/stat_central_tendency.Rd0000644000176200001440000000777214333713444017201 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stat_central_tendency.R \name{stat_central_tendency} \alias{stat_central_tendency} \title{Add Central Tendency Measures to a GGPLot} \usage{ stat_central_tendency( mapping = NULL, data = NULL, geom = c("line", "point"), position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, type = c("mean", "median", "mode"), ... ) } \arguments{ \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and \code{inherit.aes = TRUE} (the default), it is combined with the default mapping at the top level of the plot. You must supply \code{mapping} if there is no plot mapping.} \item{data}{The data to be displayed in this layer. There are three options: If \code{NULL}, the default, the data is inherited from the plot data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. A \code{data.frame}, or other object, will override the plot data. All objects will be fortified to produce a data frame. See \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. A \code{function} will be called with a single argument, the plot data. The return value must be a \code{data.frame}, and will be used as the layer data. A \code{function} can be created from a \code{formula} (e.g. \code{~ head(.x, 10)}).} \item{geom}{The geometric object to use to display the data, either as a \code{ggproto} \code{Geom} subclass or as a string naming the geom stripped of the \code{geom_} prefix (e.g. \code{"point"} rather than \code{"geom_point"})} \item{position}{Position adjustment, either as a string naming the adjustment (e.g. \code{"jitter"} to use \code{position_jitter}), or the result of a call to a position adjustment function. Use the latter if you need to change the settings of the adjustment.} \item{na.rm}{If FALSE (the default), removes missing values with a warning. If TRUE silently removes missing values.} \item{show.legend}{logical. Should this layer be included in the legends? \code{NA}, the default, includes if any aesthetics are mapped. \code{FALSE} never includes, and \code{TRUE} always includes. It can also be a named logical vector to finely select the aesthetics to display.} \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, rather than combining with them. This is most useful for helper functions that define both data and aesthetics and shouldn't inherit behaviour from the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} \item{type}{the type of central tendency measure to be used. Possible values include: \code{"mean", "median", "mode"}.} \item{...}{other arguments to pass to \code{\link[ggplot2:geom_path]{geom_line}}.} } \description{ Add central tendency measures (mean, median, mode) to density and histogram plots created using ggplots. Note that, normally, the mode is used for categorical data where we wish to know which is the most common category. Therefore, we can have have two or more values that share the highest frequency. This might be problematic for continuous variable. For continuous variable, we can consider using mean or median as the measures of the central tendency. } \examples{ # Simple density plot data("mtcars") ggdensity(mtcars, x = "mpg", fill = "red") + scale_x_continuous(limits = c(-1, 50)) + stat_central_tendency(type = "mean", linetype = "dashed") # Color by groups data(iris) ggdensity(iris, "Sepal.Length", color = "Species") + stat_central_tendency(aes(color = Species), type = "median", linetype = 2) # Use geom = "point" for central tendency data(iris) ggdensity(iris, "Sepal.Length", color = "Species") + stat_central_tendency( aes(color = Species), type = "median", geom = "point", size = 4 ) # Facet ggdensity(iris, "Sepal.Length", facet.by = "Species") + stat_central_tendency(type = "mean", color = "red", linetype = 2) + stat_central_tendency(type = "median", color = "blue", linetype = 2) } \seealso{ \code{\link{ggdensity}} } ggpubr/man/get_palette.Rd0000644000176200001440000000517514333713444015115 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/get_palette.R \name{get_palette} \alias{get_palette} \title{Generate Color Palettes} \usage{ get_palette(palette = "default", k) } \arguments{ \item{palette}{Color palette. Allowed values include: \itemize{ \item \strong{Grey color palettes}: "grey" or "gray"; \item \strong{RColorBrewer palettes}, see \code{\link[RColorBrewer:ColorBrewer]{brewer.pal}} and details section. Examples of palette names include: "RdBu", "Blues", "Dark2", "Set2", ...; \item \strong{Custom color palettes}. For example, palette = c("#00AFBB", "#E7B800", "#FC4E07"); \item \strong{ggsci scientific journal palettes}, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty". }} \item{k}{the number of colors to generate.} } \value{ Returns a vector of color palettes. } \description{ Generate a palette of k colors from ggsci palettes, RColorbrewer palettes and custom color palettes. Useful to extend RColorBrewer and ggsci to support more colors. } \details{ \strong{RColorBrewer palettes}: To display all available color palettes, type this in R:RColorBrewer::display.brewer.all(). Color palette names include: \itemize{ \item \strong{Sequential palettes}, suited to ordered data that progress from low to high. Palette names include: Blues BuGn BuPu GnBu Greens Greys Oranges OrRd PuBu PuBuGn PuRd Purples RdPu Reds YlGn YlGnBu YlOrBr YlOrRd. \item \strong{Diverging palettes}:Gradient colors. Names include: BrBG PiYG PRGn PuOr RdBu RdGy RdYlBu RdYlGn Spectral. \item \strong{Qualitative palettes}: Best suited to representing nominal or categorical data. Names include: Accent, Dark2, Paired, Pastel1, Pastel2, Set1, Set2, Set3. } } \examples{ data("iris") iris$Species2 <- factor(rep(c(1:10), each = 15)) # Generate a gradient of 10 colors ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", color = "Species2", palette = get_palette(c("#00AFBB", "#E7B800", "#FC4E07"), 10)) # Scatter plot with default color palette ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", color = "Species") # RColorBrewer color palettes ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", color = "Species", palette = get_palette("Dark2", 3)) # ggsci color palettes ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", color = "Species", palette = get_palette("npg", 3)) # Custom color palette ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", color = "Species", palette = c("#00AFBB", "#E7B800", "#FC4E07")) # Or use this ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", color = "Species", palette = get_palette(c("#00AFBB", "#FC4E07"), 3)) } ggpubr/man/border.Rd0000644000176200001440000000123514332553656014074 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/border.R \name{border} \alias{border} \title{Set ggplot Panel Border Line} \usage{ border(color = "black", size = 0.8, linetype = NULL) } \arguments{ \item{color}{border line color.} \item{size}{numeric value specifying border line size.} \item{linetype}{line type. An integer (0:8), a name (blank, solid, dashed, dotted, dotdash, longdash, twodash). Sess \code{\link{show_line_types}}.} } \description{ Change or set ggplot panel border. } \examples{ # Load data data("ToothGrowth") df <- ToothGrowth # Basic plot p <- ggboxplot(df, x = "dose", y = "len") p # Add border p + border() } ggpubr/man/ggtext.Rd0000644000176200001440000000745214333713444014122 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ggtext.R \name{ggtext} \alias{ggtext} \title{Text} \usage{ ggtext( data, x = NULL, y = NULL, label = NULL, color = "black", palette = NULL, size = 11, face = "plain", family = "", show.legend = NA, label.select = NULL, repel = FALSE, label.rectangle = FALSE, parse = FALSE, grouping.vars = NULL, position = "identity", ggp = NULL, ggtheme = theme_pubr(), ... ) } \arguments{ \item{data}{a data frame} \item{x, y}{x and y variables for drawing.} \item{label}{the name of the column containing point labels. Can be also a character vector with length = nrow(data).} \item{color}{text font color.} \item{palette}{the color palette to be used for coloring or filling by groups. Allowed values include "grey" for grey color palettes; brewer palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty".} \item{size}{text font size.} \item{face}{text font style. Allowed values are one of c("plain", "bold", "italic", "bold.italic").} \item{family}{character vector specifying font family.} \item{show.legend}{logical. Should text be included in the legends? NA, the default, includes if any aesthetics are mapped. FALSE never includes, and TRUE always includes.} \item{label.select}{can be of two formats: \itemize{ \item a character vector specifying some labels to show. \item a list containing one or the combination of the following components: \itemize{ \item \code{top.up} and \code{top.down}: to display the labels of the top up/down points. For example, \code{label.select = list(top.up = 10, top.down = 4)}. \item \code{criteria}: to filter, for example, by x and y variabes values, use this: \code{label.select = list(criteria = "`y` > 2 & `y` < 5 & `x` \%in\% c('A', 'B')")}. } }} \item{repel}{a logical value, whether to use ggrepel to avoid overplotting text labels or not.} \item{label.rectangle}{logical value. If TRUE, add rectangle underneath the text, making it easier to read.} \item{parse}{If \code{TRUE}, the labels will be parsed into expressions and displayed as described in \code{?plotmath}.} \item{grouping.vars}{grouping variables to sort the data by, when the user wants to display the top n up/down labels.} \item{position}{Position adjustment, either as a string, or the result of a call to a position adjustment function.} \item{ggp}{a ggplot. If not NULL, points are added to an existing plot.} \item{ggtheme}{function, ggplot2 theme name. Default value is theme_pubr(). Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), theme_minimal(), theme_classic(), theme_void(), ....} \item{...}{other arguments to be passed to \code{\link{ggpar}}.} } \description{ Add text to a plot. } \details{ The plot can be easily customized using the function ggpar(). Read ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels and position: legend = "right" } } \examples{ # Load data data("mtcars") df <- mtcars df$cyl <- as.factor(df$cyl) df$name <- rownames(df) head(df[, c("wt", "mpg", "cyl")], 3) # Textual annotation # +++++++++++++++++ ggtext(df, x = "wt", y = "mpg", color = "cyl", palette = c("#00AFBB", "#E7B800", "#FC4E07"), label = "name", repel = TRUE) # Add rectangle around label ggtext(df, x = "wt", y = "mpg", color = "cyl", palette = c("#00AFBB", "#E7B800", "#FC4E07"), label = "name", repel = TRUE, label.rectangle = TRUE) } \seealso{ \code{\link{ggpar}} } ggpubr/DESCRIPTION0000644000176200001440000000613714371467262013271 0ustar liggesusersPackage: ggpubr Type: Package Title: 'ggplot2' Based Publication Ready Plots Version: 0.6.0 Date: 2023-02-05 Authors@R: c( person("Alboukadel", "Kassambara", role = c("aut", "cre"), email = "alboukadel.kassambara@gmail.com")) Description: The 'ggplot2' package is excellent and flexible for elegant data visualization in R. However the default generated plots requires some formatting before we can send them for publication. Furthermore, to customize a 'ggplot', the syntax is opaque and this raises the level of difficulty for researchers with no advanced R programming skills. 'ggpubr' provides some easy-to-use functions for creating and customizing 'ggplot2'- based publication ready plots. License: GPL (>= 2) LazyData: TRUE Encoding: UTF-8 Depends: R (>= 3.1.0), ggplot2 (>= 3.4.0) Imports: ggrepel (>= 0.9.2), grid, ggsci, stats, utils, tidyr (>= 1.3.0), purrr, dplyr (>= 0.7.1), cowplot (>= 1.1.1), ggsignif, scales, gridExtra, glue, polynom, rlang (>= 0.4.6), rstatix (>= 0.7.2), tibble, magrittr Suggests: grDevices, knitr, RColorBrewer, gtable, testthat URL: https://rpkgs.datanovia.com/ggpubr/ BugReports: https://github.com/kassambara/ggpubr/issues RoxygenNote: 7.2.3 Collate: 'utilities_color.R' 'utilities_base.R' 'desc_statby.R' 'utilities.R' 'add_summary.R' 'annotate_figure.R' 'as_ggplot.R' 'as_npc.R' 'axis_scale.R' 'background_image.R' 'bgcolor.R' 'border.R' 'compare_means.R' 'create_aes.R' 'diff_express.R' 'facet.R' 'font.R' 'gene_citation.R' 'gene_expression.R' 'geom_bracket.R' 'geom_exec.R' 'utils-aes.R' 'utils_stat_test_label.R' 'geom_pwc.R' 'get_breaks.R' 'get_coord.R' 'get_legend.R' 'get_palette.R' 'ggadd.R' 'ggadjust_pvalue.R' 'ggarrange.R' 'ggballoonplot.R' 'ggpar.R' 'ggbarplot.R' 'ggboxplot.R' 'ggdensity.R' 'ggpie.R' 'ggdonutchart.R' 'stat_conf_ellipse.R' 'stat_chull.R' 'ggdotchart.R' 'ggdotplot.R' 'ggecdf.R' 'ggerrorplot.R' 'ggexport.R' 'gghistogram.R' 'ggline.R' 'ggmaplot.R' 'ggpaired.R' 'ggparagraph.R' 'ggpubr-package.R' 'ggpubr_args.R' 'ggpubr_options.R' 'ggqqplot.R' 'utilities_label.R' 'stat_cor.R' 'stat_stars.R' 'ggscatter.R' 'ggscatterhist.R' 'ggstripchart.R' 'ggsummarystats.R' 'ggtext.R' 'ggtexttable.R' 'ggviolin.R' 'gradient_color.R' 'grids.R' 'npc_to_data_coord.R' 'reexports.R' 'rotate.R' 'rotate_axis_text.R' 'rremove.R' 'set_palette.R' 'show_line_types.R' 'show_point_shapes.R' 'stat_anova_test.R' 'stat_central_tendency.R' 'stat_compare_means.R' 'stat_friedman_test.R' 'stat_kruskal_test.R' 'stat_mean.R' 'stat_overlay_normal_density.R' 'stat_pvalue_manual.R' 'stat_regline_equation.R' 'stat_welch_anova_test.R' 'text_grob.R' 'theme_pubr.R' 'theme_transparent.R' 'utils-geom-signif.R' 'utils-pipe.R' 'utils-tidyr.R' NeedsCompilation: no Packaged: 2023-02-06 02:39:47 UTC; kassambara Author: Alboukadel Kassambara [aut, cre] Maintainer: Alboukadel Kassambara Repository: CRAN Date/Publication: 2023-02-10 16:20:02 UTC ggpubr/tests/0000755000176200001440000000000014344455133012710 5ustar liggesusersggpubr/tests/testthat/0000755000176200001440000000000014371467262014556 5ustar liggesusersggpubr/tests/testthat/test-check_data.R0000644000176200001440000000610414336762430017721 0ustar liggesusers # Gene expression data df_expr <- tibble::tribble( ~sample, ~dataset, ~GATA3, ~PTEN, ~XBP1, "ID.1", "BRCA.mRNA", 2.23, 0.77, 2.91, "ID.2", "BRCA.mRNA", 1.24, 1.32, 1.68, "ID.3", "OV.mRNA", -3.44, 1.65, -1.29, "ID.4", "OV.mRNA", -5.21, 1.11, -0.62, "ID.5", "LUSC.mRNA", -4.01, -0.05, -0.57, "ID.6", "LUSC.mRNA", -3.29, 0.3, -0.02 ) test_that("check_data works when combine=TRUE and length(y) > 1", { observed <- .check_data(df_expr, x = "dataset", y = c("GATA3", "PTEN", "XBP1"), combine = TRUE) expected_y <- c(".value." = ".value.") expected_x <- c("dataset" = "dataset") expected_data <- tibble::tribble( ~sample, ~dataset, ~.y., ~.value., "ID.1", "BRCA.mRNA", "GATA3", 2.23, "ID.2", "BRCA.mRNA", "GATA3", 1.24, "ID.3", "OV.mRNA", "GATA3", -3.44, "ID.4", "OV.mRNA", "GATA3", -5.21, "ID.5", "LUSC.mRNA", "GATA3", -4.01, "ID.6", "LUSC.mRNA", "GATA3", -3.29, "ID.1", "BRCA.mRNA", "PTEN", 0.77, "ID.2", "BRCA.mRNA", "PTEN", 1.32, "ID.3", "OV.mRNA", "PTEN", 1.65, "ID.4", "OV.mRNA", "PTEN", 1.11, "ID.5", "LUSC.mRNA", "PTEN", -0.05, "ID.6", "LUSC.mRNA", "PTEN", 0.3, "ID.1", "BRCA.mRNA", "XBP1", 2.91, "ID.2", "BRCA.mRNA", "XBP1", 1.68, "ID.3", "OV.mRNA", "XBP1", -1.29, "ID.4", "OV.mRNA", "XBP1", -0.62, "ID.5", "LUSC.mRNA", "XBP1", -0.57, "ID.6", "LUSC.mRNA", "XBP1", -0.02 ) %>% dplyr::mutate( .y. = factor(.y., levels = c("GATA3", "PTEN", "XBP1")), dataset = factor(dataset, levels = c("BRCA.mRNA", "OV.mRNA", "LUSC.mRNA")) ) expect_equal(observed$y, expected_y) expect_equal(observed$x, expected_x) expect_equal(observed$data, expected_data) }) test_that("check_data works when combine=TRUE and length(x) > 1", { observed <- .check_data(df_expr, x = c("GATA3", "PTEN", "XBP1"), y = "..density..", combine = TRUE) expected_y <- c("..density.." = "..density..") expected_x <- c(".value." = ".value.") expected_data <- tibble::tribble( ~sample, ~dataset, ~.y., ~.value., "ID.1", "BRCA.mRNA", "GATA3", 2.23, "ID.2", "BRCA.mRNA", "GATA3", 1.24, "ID.3", "OV.mRNA", "GATA3", -3.44, "ID.4", "OV.mRNA", "GATA3", -5.21, "ID.5", "LUSC.mRNA", "GATA3", -4.01, "ID.6", "LUSC.mRNA", "GATA3", -3.29, "ID.1", "BRCA.mRNA", "PTEN", 0.77, "ID.2", "BRCA.mRNA", "PTEN", 1.32, "ID.3", "OV.mRNA", "PTEN", 1.65, "ID.4", "OV.mRNA", "PTEN", 1.11, "ID.5", "LUSC.mRNA", "PTEN", -0.05, "ID.6", "LUSC.mRNA", "PTEN", 0.3, "ID.1", "BRCA.mRNA", "XBP1", 2.91, "ID.2", "BRCA.mRNA", "XBP1", 1.68, "ID.3", "OV.mRNA", "XBP1", -1.29, "ID.4", "OV.mRNA", "XBP1", -0.62, "ID.5", "LUSC.mRNA", "XBP1", -0.57, "ID.6", "LUSC.mRNA", "XBP1", -0.02 ) %>% dplyr::mutate(.y. = factor(.y., levels = c("GATA3", "PTEN", "XBP1"))) expect_equal(observed$y, expected_y) expect_equal(observed$x, expected_x) expect_equal(observed$data, expected_data) }) ggpubr/tests/testthat/test-stat_kruskal_test.R0000644000176200001440000000342014332576562021424 0ustar liggesuserscontext("test-stat_kruskal_test") # Data preparation df <- ToothGrowth df$dose <- as.factor(df$dose) df$id <- rep(1:10, 6) # Add individuals id # Add a random grouping variable set.seed(123) df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) df <- df %>% mutate( len = ifelse(group == "grp2", len+2, len), len = ifelse(group == "grp3", len+7, len) ) # Basic plots ----------------------------------- test_that("stat_kruskal_test works for basic ggplots", { bxp <- ggboxplot(df, x = "dose", y = "len") + stat_kruskal_test() bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), 1) expect_equal(as.numeric(stat.test$y), 36.4) expect_equal(stat.test$label, "Kruskal-Wallis, p < 0.0001") }) # Grouped plots----------------------------------- test_that("stat_kruskal_test works for grouped plots: grouped by x position", { bxp <- ggboxplot(df, x = "group", y = "len", color = "dose") + stat_kruskal_test(aes(group = dose), label = "{p.adj.format}") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), c(1, 2, 3)) expect_equal(as.numeric(stat.test$y), c(36.4, 36.4, 36.4)) expect_equal(stat.test$label, c("0.0028", "0.0056", "0.0056")) }) test_that("stat_kruskal_test works for grouped plots: grouped by legend variable", { bxp <- ggboxplot(df, x = "group", y = "len", color = "dose") + stat_kruskal_test(aes(group = dose), label = "{p.format}", group.by = "legend.var") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), c(0.73, 0.73, 0.73)) expect_equal(as.numeric(stat.test$y), c(36.4, 39.62, 42.84)) expect_equal(stat.test$label, c("0.012", "0.018", "0.038")) }) ggpubr/tests/testthat/test-ggadjust_pvalue.R0000644000176200001440000000274314343207174021041 0ustar liggesusers# Data preparation #::::::::::::::::::::::::::::::::::::::: df <- ToothGrowth df$dose <- as.factor(df$dose) # Add a random grouping variable df$group <- factor(rep(c("grp1", "grp2"), 30)) test_that("ggadjust_pvalue works for geom_pwc() pairwise comparison using facet", { p <- ggboxplot(df, x = "supp", y = "len", facet.by = "dose") + geom_pwc(method = "t_test") # Adjust all p-values together after stat_test <- ggadjust_pvalue( p, p.adjust.method = "bonferroni", label = "{p.adj.format}{p.adj.signif}", output = "stat_test" ) stat_test <- stat_test %>% dplyr::select(PANEL, x, y, group, group1, group2, label) %>% mutate(x = as.numeric(x), label = as.character(label)) expected <- tibble::tribble( ~PANEL, ~x, ~y, ~group, ~group1, ~group2, ~label, "1", 1, 34.494, 1, "1", "2", "0.0191*", "1", 1, 35.385, 1, "1", "2", "0.0191*", "1", 2, 35.385, 1, "1", "2", "0.0191*", "2", 1, 34.494, 1, "1", "2", "0.0031**", "2", 1, 35.385, 1, "1", "2", "0.0031**", "2", 2, 35.385, 1, "1", "2", "0.0031**", "3", 1, 34.494, 1, "1", "2", "1ns", "3", 1, 35.385, 1, "1", "2", "1ns", "3", 2, 35.385, 1, "1", "2", "1ns" ) %>% dplyr::mutate(PANEL = as.factor(PANEL)) %>% as.data.frame(stringAsFactor = FALSE) expect_equal(stat_test, expected) }) ggpubr/tests/testthat/test-stat_welch_anova_test.R0000644000176200001440000000344714332576562022247 0ustar liggesuserscontext("test-stat_welch_anova_test") # Data preparation df <- ToothGrowth df$dose <- as.factor(df$dose) df$id <- rep(1:10, 6) # Add individuals id # Add a random grouping variable set.seed(123) df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) df <- df %>% mutate( len = ifelse(group == "grp2", len+2, len), len = ifelse(group == "grp3", len+7, len) ) # Basic plots ----------------------------------- test_that("stat_welch_anova_test works for basic ggplots", { bxp <- ggboxplot(df, x = "dose", y = "len") + stat_welch_anova_test() bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), 1) expect_equal(as.numeric(stat.test$y), 36.4) expect_equal(stat.test$label, "Welch Anova, p < 0.0001") }) # Grouped plots----------------------------------- test_that("stat_welch_anova_test works for grouped plots: grouped by x position", { bxp <- ggboxplot(df, x = "group", y = "len", color = "dose") + stat_welch_anova_test(aes(group = dose), label = "{p.adj.format}") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), c(1, 2, 3)) expect_equal(as.numeric(stat.test$y), c(36.4, 36.4, 36.4)) expect_equal(stat.test$label, c("0.004", "0.004", "0.0024")) }) test_that("stat_welch_anova_test works for grouped plots: grouped by legend variable", { bxp <- ggboxplot(df, x = "group", y = "len", color = "dose") + stat_welch_anova_test(aes(group = dose), label = "{p.format}", group.by = "legend.var") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), c(0.73, 0.73, 0.73)) expect_equal(as.numeric(stat.test$y), c(36.4, 39.62, 42.84)) expect_equal(stat.test$label, c("0.039", "0.023", "0.045")) }) ggpubr/tests/testthat/test-create_aes.R0000644000176200001440000000111414333662066017743 0ustar liggesuserscontext("test-create_aes") test_that("parse_expression works for a valid variable name", { observed <- parse_expression("a") expected <- parse(text = "a")[[1]] expect_equal(observed, expected) }) test_that("parse_expression works for a variable name containing space", { observed <- parse_expression("a b") expected <- as.name("a b") expect_equal(observed, expected) }) test_that("parse_expression works for a mathetical expression", { observed <- parse_expression("log2( a + b )") expected <- parse(text = "log2( a + b )")[[1]] expect_equal(observed, expected) }) ggpubr/tests/testthat/test-stat_compare_means.R0000644000176200001440000001326714335521212021515 0ustar liggesusers# Data preparation df <- ToothGrowth df$dose <- as.factor(df$dose) df$group <- factor(rep(c("grp1", "grp2"), 30)) # Comparing two groups .get_stat_test <- function(df, ...){ bxp <- ggboxplot(df, x = "supp", y = "len") + stat_compare_means(...) bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] stat.test } # Pairwise comparison test .get_pwc_test <- function(df, ...){ my_comparisons <- list( c("0.5", "1"), c("1", "2"), c("0.5", "2") ) bxp <- ggboxplot(df, x = "dose", y = "len")+ stat_compare_means(comparisons = my_comparisons, method = "t.test", ...) bxp_build <- ggplot2::ggplot_build(bxp) pwc_test <- bxp_build$data[[2]] pwc_test <- pwc_test %>% dplyr::mutate( x = as.numeric(x), xend = as.numeric(xend), annotation = as.character(annotation) ) pwc_test } # two independent tests ----------------------------------- test_that("stat_compare_means works for two independent tests: Wilcoxon test", { stat.test <- .get_stat_test(df) label_coords_expected <- data.frame( stringsAsFactors = FALSE, x = 1, y = c(33.9), label = c("Wilcoxon, p = 0.064") ) label_coords_observed <- stat.test[, c("x", "y", "label")] label_coords_observed$x <- as.numeric(label_coords_observed$x) expect_equal(label_coords_expected, label_coords_observed) }) test_that("stat_compare_means works for two independent tests when method changed to t.test", { stat.test <- .get_stat_test(df, method = "t.test") label_coords_expected <- data.frame( stringsAsFactors = FALSE, x = 1, y = c(33.9), label = c("T-test, p = 0.061") ) label_coords_observed <- stat.test[, c("x", "y", "label")] label_coords_observed$x <- as.numeric(label_coords_observed$x) expect_equal(label_coords_expected, label_coords_observed) }) test_that("stat_compare_means works when label specified as label='p.signif'", { stat.test <- .get_stat_test(df, label = "p.signif") label_coords_expected <- data.frame( stringsAsFactors = FALSE, x = 1, y = c(33.9), label = c("ns") ) label_coords_observed <- stat.test[, c("x", "y", "label")] label_coords_observed$x <- as.numeric(label_coords_observed$x) expect_equal(label_coords_expected, label_coords_observed) }) test_that("stat_compare_means works when label specified as aes(label=..p.signif..)", { stat.test <- .get_stat_test(df, aes(label = ..p.signif..)) label_coords_expected <- data.frame( stringsAsFactors = FALSE, x = 1, y = c(33.9), label = c("ns") ) label_coords_observed <- stat.test[, c("x", "y", "label")] label_coords_observed$x <- as.numeric(label_coords_observed$x) expect_equal(label_coords_expected, label_coords_observed) }) # Paired samples----------------------------------- test_that("stat_compare_means works for paired samples comparison", { stat.test <- .get_stat_test(df, paired = TRUE) label_coords_expected <- data.frame( stringsAsFactors = FALSE, x = 1, y = c(33.9), label = c("Wilcoxon, p = 0.0043") ) label_coords_observed <- stat.test[, c("x", "y", "label")] label_coords_observed$x <- as.numeric(label_coords_observed$x) expect_equal(label_coords_expected, label_coords_observed) }) # More than two groups------------------------------- test_that("stat_compare_means works for pairwise comparisons with multiple groups", { pwc_test <- .get_pwc_test(df) pwc_observed <- pwc_test[, c("x", "xend", "y", "yend", "annotation")] pwc_observed$annotation <- as.character(pwc_observed$annotation) pwc_expected <- data.frame( x = c(1, 1, 2, 1, 1, 3, 2, 2, 3), xend = c(1, 2, 2, 1, 3, 3, 2, 3, 3), y = c(34.494,35.385,35.385,41.622, 42.513,42.513,38.058,38.949,38.949), yend = c(35.385,35.385,34.494,42.513, 42.513,41.622,38.949,38.949,38.058), annotation = c("1.3e-07", "1.3e-07","1.3e-07","4.4e-14","4.4e-14","4.4e-14", "1.9e-05","1.9e-05","1.9e-05"), stringsAsFactors = FALSE ) expect_equal(pwc_expected, pwc_observed) }) # More than two groups------------------------------- test_that("stat_compare_means works for pairwise comparisons with multiple groups when specifying label as label='p.signif'", { pwc_test <- .get_pwc_test(df, label = "p.signif") pwc_observed <- pwc_test[, c("x", "xend", "y", "yend", "annotation")] pwc_observed$annotation <- as.character(pwc_observed$annotation) pwc_expected <- data.frame( x = c(1, 1, 2, 1, 1, 3, 2, 2, 3), xend = c(1, 2, 2, 1, 3, 3, 2, 3, 3), y = c(34.494,35.385,35.385,41.622, 42.513,42.513,38.058,38.949,38.949), yend = c(35.385,35.385,34.494,42.513, 42.513,41.622,38.949,38.949,38.058), annotation = c("****", "****","****","****","****","****", "****","****","****"), stringsAsFactors = FALSE ) expect_equal(pwc_expected, pwc_observed) }) test_that("stat_compare_means works for pairwise comparisons with multiple groups when specifying label as aes(label=after_stat(p.signif))", { pwc_test <- .get_pwc_test(df, aes(label = after_stat(p.signif))) pwc_observed <- pwc_test[, c("x", "xend", "y", "yend", "annotation")] pwc_observed$annotation <- as.character(pwc_observed$annotation) pwc_expected <- data.frame( x = c(1, 1, 2, 1, 1, 3, 2, 2, 3), xend = c(1, 2, 2, 1, 3, 3, 2, 3, 3), y = c(34.494,35.385,35.385,41.622, 42.513,42.513,38.058,38.949,38.949), yend = c(35.385,35.385,34.494,42.513, 42.513,41.622,38.949,38.949,38.058), annotation = c("****", "****","****","****","****","****", "****","****","****"), stringsAsFactors = FALSE ) expect_equal(pwc_expected, pwc_observed) }) ggpubr/tests/testthat/test-stat_anova_test.R0000644000176200001440000002531214332576562021060 0ustar liggesuserscontext("test-stat_anova_test") # Data preparation df <- ToothGrowth df$dose <- as.factor(df$dose) df$id <- rep(1:10, 6) # Add individuals id # Add a random grouping variable set.seed(123) df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) df <- df %>% mutate( len = ifelse(group == "grp2", len+2, len), len = ifelse(group == "grp3", len+7, len) ) # Basic plots ----------------------------------- test_that("stat_anova_test works for basic ggplots", { bxp <- ggboxplot(df, x = "dose", y = "len") + stat_anova_test() bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), 1) expect_equal(as.numeric(stat.test$y), 36.4) expect_equal(stat.test$label, "Anova, p < 0.0001") }) # Grouped plots----------------------------------- test_that("stat_anova_test works for grouped plots: grouped by x position", { bxp <- ggboxplot(df, x = "group", y = "len", color = "dose") + stat_anova_test(aes(group = dose), label = "{p.adj.format}") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), c(1, 2, 3)) expect_equal(as.numeric(stat.test$y), c(36.4, 36.4, 36.4)) expect_equal(stat.test$label, c("<0.0001", "0.00014", "0.00014")) }) test_that("stat_anova_test works for grouped plots: grouped by legend variable", { bxp <- ggboxplot(df, x = "group", y = "len", color = "dose") + stat_anova_test(aes(group = dose), label = "{p.format}", group.by = "legend.var") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), c(0.73, 0.73, 0.73)) expect_equal(as.numeric(stat.test$y), c(36.4, 39.62, 42.84)) expect_equal(stat.test$label, c("0.009", "0.012", "0.019")) }) # One-way repeated measure ANOVA ---------------------- test_that("stat_anova_test works for one-way repeated measure anova", { df$id <- as.factor(c(rep(1:10, 3), rep(11:20, 3))) bxp <- ggboxplot(df, x = "dose", y = "len") + stat_anova_test(wid = "id", method = "one_way_repeated") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), 1) expect_equal(as.numeric(stat.test$y), 36.4) expect_equal(stat.test$label, "Anova, p < 0.0001") }) test_that("stat_anova_test works for grouped one-way repeated measure anova: group by x var", { df$id <- as.factor(rep(1:10, 6)) bxp <- ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") + stat_anova_test(aes(group = supp, color = supp), label = "p", method = "one_way_repeated", wid = "id", group.by = "x.var") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), c(1, 2, 3)) expect_equal(as.numeric(stat.test$y), c(36.4, 36.4, 36.4)) expect_equal(stat.test$label, c("0.016", "0.05", "0.848")) }) test_that("stat_anova_test works for grouped one-way repeated measure anova: group by legend var", { df$id <- as.factor(rep(1:10, 6)) bxp <- ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") + stat_anova_test(aes(group = supp, color = supp), method = "one_way_repeated", wid = "id", group.by = "legend.var") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), c(0.8, 0.8)) expect_equal(as.numeric(stat.test$y), c(36.40, 39.62)) expect_equal(stat.test$label, c("Anova, p = 0.004", "Anova, p < 0.0001")) }) test_that("stat_anova_test works for two-way repeated measure anova", { df$id <- as.factor(rep(1:10, 6)) bxp <- ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") + stat_anova_test(aes(group = supp), method = "two_way_repeated", wid = "id") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), 0.8) expect_equal(as.numeric(stat.test$y), 36.4) expect_equal(stat.test$label, "Anova, p = 0.12") }) # Two-way mixed anova ----------------------------- test_that("stat_anova_test works for two-way mixed anova", { anxiety <- data.frame( score = c(14.1,14.5,15.7,16,16.5,16.9,17,17, 17.3,17.3,17.8,17.9,19.1,19.4,19.8,13.7,14.7,14.9,15.1, 15.8,16.4,16.6,16.9,16.9,17.2,17.8,17.8,18.2,18.4, 19.3,14.6,15,15.5,15.7,16.4,16.9,17.1,17.3,17.5,17.6, 17.8,17.9,18.4,18.5,19,14.4,14.6,15.2,15.5,15.8,16.5, 16.8,17.1,16.9,17.1,17.7,17.7,19.4,19.2,20,13.4,14.8, 14.4,14.8,14.8,15.7,16.9,16.9,16.9,17.3,18.2,17.7, 17.8,18.5,18.9,13,13,12.7,14.1,14.4,14.5,15.6,15.4, 15.6,14.8,16.1,15.7,16.7,16.4,17.2,14.1,14.3,14.9,15.3, 15.7,16.2,16.5,16.6,16.5,16.7,17.3,17.5,19.3,17.3, 19.4,12.7,13.1,13.6,13.6,14.2,14.9,16.1,16.1,16.3,15.9, 17.4,16.9,17.1,17.3,17.7,11.7,11.9,11,12.1,12.3,13.6, 14.3,14.2,14.4,13.8,14.3,13.8,15.4,15.1,15.5), id = as.factor(c("1","2","3","4","5", "6","7","8","9","10","11","12","13","14", "15","16","17","18","19","20","21","22","23", "24","25","26","27","28","29","30","31","32", "33","34","35","36","37","38","39","40","41", "42","43","44","45","1","2","3","4","5", "6","7","8","9","10","11","12","13","14","15", "16","17","18","19","20","21","22","23","24", "25","26","27","28","29","30","31","32", "33","34","35","36","37","38","39","40","41", "42","43","44","45","1","2","3","4","5","6", "7","8","9","10","11","12","13","14","15", "16","17","18","19","20","21","22","23","24", "25","26","27","28","29","30","31","32","33", "34","35","36","37","38","39","40","41","42", "43","44","45")), group = as.factor(c("grp1","grp1","grp1", "grp1","grp1","grp1","grp1","grp1","grp1", "grp1","grp1","grp1","grp1","grp1","grp1","grp2", "grp2","grp2","grp2","grp2","grp2","grp2","grp2", "grp2","grp2","grp2","grp2","grp2","grp2", "grp2","grp3","grp3","grp3","grp3","grp3","grp3", "grp3","grp3","grp3","grp3","grp3","grp3", "grp3","grp3","grp3","grp1","grp1","grp1","grp1", "grp1","grp1","grp1","grp1","grp1","grp1","grp1", "grp1","grp1","grp1","grp1","grp2","grp2", "grp2","grp2","grp2","grp2","grp2","grp2","grp2", "grp2","grp2","grp2","grp2","grp2","grp2","grp3", "grp3","grp3","grp3","grp3","grp3","grp3", "grp3","grp3","grp3","grp3","grp3","grp3","grp3", "grp3","grp1","grp1","grp1","grp1","grp1", "grp1","grp1","grp1","grp1","grp1","grp1","grp1", "grp1","grp1","grp1","grp2","grp2","grp2","grp2", "grp2","grp2","grp2","grp2","grp2","grp2", "grp2","grp2","grp2","grp2","grp2","grp3","grp3", "grp3","grp3","grp3","grp3","grp3","grp3","grp3", "grp3","grp3","grp3","grp3","grp3","grp3")), time = as.factor(c("t1","t1","t1","t1", "t1","t1","t1","t1","t1","t1","t1","t1","t1", "t1","t1","t1","t1","t1","t1","t1","t1", "t1","t1","t1","t1","t1","t1","t1","t1","t1", "t1","t1","t1","t1","t1","t1","t1","t1","t1", "t1","t1","t1","t1","t1","t1","t2","t2","t2", "t2","t2","t2","t2","t2","t2","t2","t2","t2", "t2","t2","t2","t2","t2","t2","t2","t2","t2", "t2","t2","t2","t2","t2","t2","t2","t2", "t2","t2","t2","t2","t2","t2","t2","t2","t2", "t2","t2","t2","t2","t2","t2","t2","t3","t3", "t3","t3","t3","t3","t3","t3","t3","t3","t3", "t3","t3","t3","t3","t3","t3","t3","t3","t3", "t3","t3","t3","t3","t3","t3","t3","t3","t3", "t3","t3","t3","t3","t3","t3","t3","t3", "t3","t3","t3","t3","t3","t3","t3","t3")) ) # two way bxp <- ggboxplot(anxiety, x = "group", y = "score", color = "time") + stat_anova_test(aes(group = time), method = "two_way_mixed", wid = "id") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] res_mixed_anova <- data.frame( x = as.numeric(stat.test$x), y = as.numeric(stat.test$y), label = as.character(stat.test$label), stringsAsFactors = FALSE ) res_mixed_anova_expected <- data.frame(x = 0.73, y = 20, label = "Anova, p < 0.0001", stringsAsFactors = FALSE) # Effect of group: Group by time and compute anova between x groups bxp <- ggboxplot(anxiety, x = "group", y = "score", color = "time") + stat_anova_test(aes(group = time, color = time), method = "one_way", group.by = "legend.var") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] res_group_effect <- data.frame( x = as.numeric(stat.test$x), y = as.numeric(stat.test$y), label = as.character(stat.test$label), stringsAsFactors = FALSE ) res_group_effect_expected <- data.frame(x = c(0.73, 0.73, 0.73), y = c(20.0, 20.9, 21.8), label = c("Anova, p = 0.696", "Anova, p = 0.006", "Anova, p < 0.0001"), stringsAsFactors = FALSE) # Effect of time: group by x groups and perform the test within group (here time) bxp <- ggboxplot(anxiety, x = "group", y = "score", color = "time") + stat_anova_test(aes(group = time), method = "one_way_repeated", wid = "id", group.by = "x.var") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] res_time_effect <- data.frame( x = as.numeric(stat.test$x), y = as.numeric(stat.test$y), label = as.character(stat.test$label), stringsAsFactors = FALSE ) res_time_effect_expected <- data.frame(x = 1:3, y = c(20, 20, 20), label = c("Anova, p < 0.0001", "Anova, p < 0.0001", "Anova, p < 0.0001"), stringsAsFactors = FALSE) expect_equal(res_mixed_anova, res_mixed_anova_expected ) expect_equal(res_group_effect, res_group_effect_expected ) expect_equal(res_time_effect, res_time_effect_expected ) }) ggpubr/tests/testthat/test-add_stat_label.R0000644000176200001440000001562414332576562020611 0ustar liggesuserscontext("test-add_stat_label") stat.test <- data.frame( stringsAsFactors = FALSE, .y. = c("y", "y", "y"), group1 = c("1", "1", "2"), group2 = c("2", "3", "3"), n1 = c(20L, 20L, 20L), n2 = c(20L, 20L, 20L), statistic = c(33.5, 1.5, 61), p = c(7.02e-06, 8.41e-08, 0.000177), p.adj = c(1.4e-05, 2.52e-07, 0.000177), p.adj.signif = c("****", "****", "***"), method = c("Wilcoxon test", "Wilcoxon test", "Wilcoxon test"), xmin = c(1, 1, 2), xmax = c(2, 3, 3), p.signif = c("****", "****", "***"), p.format = c("<0.0001", "<0.0001", "0.00018"), p.adj.format = c("<0.0001", "<0.0001", "0.00018"), n = c(40L, 40L, 40L) ) test_that("add_stat_label works with basic label", { formatted_p <- add_stat_label(stat.test, label = "p.format") adjusted_p <- add_stat_label(stat.test, label = "p.adj") expect_equal(formatted_p$label, c("<0.0001", "<0.0001", "0.00018")) expect_equal(adjusted_p$label, c("1.4e-05", "2.52e-07","0.000177")) }) test_that("add_stat_label works with glue expression", { glueed <- add_stat_label(stat.test, label = "p = {p.format} {p.signif}") expect_equal(glueed$label, c("p < 0.0001 ****", "p < 0.0001 ****", "p = 0.00018 ***")) }) test_that("add_stat_label works with plotmath: Usage of simple equal '='", { simple_equals <- add_stat_label(stat.test, label = "italic(p)={p.format}{p.signif}") simple_equals_space <- add_stat_label(stat.test, label = "italic(p) = {p.format}{p.signif}") simple_equals_tilde <- add_stat_label(stat.test, label = "italic(p)~=~{p.format}{p.signif}") expect_equal( simple_equals$label, c("list(italic(p)<'0.0001'*`****`)", "list(italic(p)<'0.0001'*`****`)", "list(italic(p)=='0.00018'*`***`)") ) expect_equal( simple_equals_space$label, c("list(italic(p)~`<`~'0.0001'*`****`)", "list(italic(p)~`<`~'0.0001'*`****`)", "list(italic(p)~`=`~'0.00018'*`***`)") ) expect_equal( simple_equals_tilde$label, c("list(italic(p)~`<`~'0.0001'*`****`)", "list(italic(p)~`<`~'0.0001'*`****`)", "list(italic(p)~`=`~'0.00018'*`***`)") ) }) test_that("add_stat_label works with plotmath: Escaping stars in p.signif/p.adj.signif", { # datapasta::dpasta(as.character(res$label)) stars <- add_stat_label(stat.test, label = "italic(p)={p.format}{p.signif}") stars_space <- add_stat_label(stat.test, label = "italic(p)={p.format} {p.signif}") stars_tilde <- add_stat_label(stat.test, label = "italic(p)={p.format}~{p.signif}") stars_equals <- add_stat_label(stat.test, label = "italic(p)={p.signif}") stars_equals_space <- add_stat_label(stat.test, label = "italic(p) = {p.signif}") expect_equal( stars$label, c("list(italic(p)<'0.0001'*`****`)", "list(italic(p)<'0.0001'*`****`)", "list(italic(p)=='0.00018'*`***`)") ) expect_equal( stars_space$label, c("list(italic(p)<'0.0001'~`****`)", "list(italic(p)<'0.0001'~`****`)", "list(italic(p)=='0.00018'~`***`)") ) expect_equal( stars_tilde$label, c("list(italic(p)<'0.0001'~`****`)", "list(italic(p)<'0.0001'~`****`)", "list(italic(p)=='0.00018'~`***`)") ) expect_equal( stars_equals$label, c("list(italic(p)==`****`)", "list(italic(p)==`****`)", "list(italic(p)==`***`)") ) expect_equal( stars_equals_space$label, c("list(italic(p)~`=`~`****`)", "list(italic(p)~`=`~`****`)", "list(italic(p)~`=`~`***`)") ) }) test_that("add_stat_label works with ANOVA stats label formats", { res.aov <- data.frame( stringsAsFactors = FALSE, check.names = FALSE, Effect = c("x"), DFn = c(2), DFd = c(57), F = c(29.543), p = c(1.57e-09), `p<.05` = c("*"), ges = c(0.509), p.adj = c(1.57e-09), p.signif = c("****"), p.adj.signif = c("****"), p.format = c("<0.0001"), p.adj.format = c("<0.0001"), n = c(60L), method = c("Anova") ) res.italic <- add_stat_label(res.aov, label = get_anova_test_label_template("as_italic")) res.detailed <- add_stat_label(res.aov, label = get_anova_test_label_template("as_detailed")) res.detailed.italic <- add_stat_label(res.aov, label = get_anova_test_label_template("as_detailed_italic")) res.detailed.expression <- add_stat_label(res.aov, label = get_anova_test_label_template("as_detailed_expression")) res.plotmath <- add_stat_label(res.aov, label = "bold(Anova), italic(F)({DFn}, {DFd}) = {F}, eta2[g] = {ges}, italic(p) = {p.format}{p.signif}, italic(n) = {n}") res.rounding <- add_stat_label(res.aov, label = "Anova, italic(F)({DFn}, {DFd}) = {round(F, 1)}, eta2[g] = {round(ges, 1)}, italic(p) = {p.format}{p.signif}, italic(n) = {n}") # Custom p format res.customp <- add_stat_label(res.aov, label = "Anova, italic(p) = {rstatix::p_format(p, accuracy = 0.0001, digits = 3, leading.zero = FALSE)}{p.signif}") expect_equal(res.italic$label, "list(Anova,~italic(p)~`<`~'0.0001')") expect_equal(res.detailed$label, "Anova, F(2, 57) = 29.543, eta2[g] = 0.509, p < 0.0001, n = 60") expect_equal(res.detailed.italic$label, "list(Anova,~italic(F)('2',~'57')~`=`~'29.543',~eta[g]^'2'~`=`~'0.509',~italic(p)~`<`~'0.0001',~italic(n)~`=`~'60')") expect_equal(res.detailed.expression$label,"list(Anova,~italic(F)('2',~'57')~`=`~'29.543',~eta[g]^'2'~`=`~'0.509',~italic(p)~`<`~'0.0001',~italic(n)~`=`~'60')") expect_equal(res.plotmath$label, "list(bold(Anova),~italic(F)('2',~'57')~`=`~'29.543',~eta[g]^'2'~`=`~'0.509',~italic(p)~`<`~'0.0001'*`****`,~italic(n)~`=`~'60')") expect_equal(res.rounding$label, "list(Anova,~italic(F)('2',~'57')~`=`~'29.5',~eta[g]^'2'~`=`~'0.5',~italic(p)~`<`~'0.0001'*`****`,~italic(n)~`=`~'60')") expect_equal(res.customp$label, "list(Anova,~italic(p)~`<`~'.0001'*`****`)") }) test_that("add_stat_label works with Kruskal-Wallis stats label formats", { res <- data.frame( stringsAsFactors = FALSE, x = c("1"), y = c(36.4), n = c(60L), statistic = c(31.21), df = c(2L), p = c(1.67e-07), method = c("Kruskal-Wallis"), p.adj = c(1.67e-07), p.signif = c("****"), p.adj.signif = c("****"), p.format = c("<0.0001"), p.adj.format = c("<0.0001") ) res.italic <- add_stat_label(res, label = get_kruskal_test_label_template("as_italic")) res.detailed <- add_stat_label(res, label = get_kruskal_test_label_template("as_detailed")) res.detailed.italic <- add_stat_label(res, label = get_kruskal_test_label_template("as_detailed_italic")) res.detailed.expression <- add_stat_label(res, label = get_kruskal_test_label_template("as_detailed_expression")) expect_equal(res.italic$label, "list('Kruskal-Wallis',~italic(p)~`<`~'0.0001')") expect_equal(res.detailed$label, "Kruskal-Wallis, X2(2) = 31.21, p < 0.0001, n = 60") expect_equal(res.detailed.italic$label, "list('Kruskal-Wallis',~italic(chi)^'2'~('2')~`=`~'31.21',~italic(p)~`<`~'0.0001',~italic(n)~`=`~'60')") expect_equal(res.detailed.expression$label,"list('Kruskal-Wallis',~italic(chi)^'2'('2')~`=`~'31.21',~italic(p)~`<`~'0.0001',~italic(n)~`=`~'60')") }) ggpubr/tests/testthat/test-stat_friedman_test.R0000644000176200001440000000422314333051470021522 0ustar liggesuserscontext("test-stat_friedman_test") # Data preparation df <- ToothGrowth df$dose <- as.factor(df$dose) df$id <- rep(1:10, 6) # Add individuals id # Add a random grouping variable set.seed(123) df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) df <- df %>% mutate( len = ifelse(group == "grp2", len+2, len), len = ifelse(group == "grp3", len+7, len) ) # Basic plots---------------------- test_that("stat_friedman_test works for basic plots", { df$id <- as.factor(c(rep(1:10, 3), rep(11:20, 3))) bxp <- ggboxplot(df, x = "dose", y = "len") + stat_friedman_test(wid = "id") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), 1) expect_equal(as.numeric(stat.test$y), 36.4) expect_equal(stat.test$label, "Friedman test, p < 0.0001") }) test_that("stat_friedman_test works for grouped plot: group by x var", { df$id <- as.factor(rep(1:10, 6)) bxp <- ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") + stat_friedman_test(aes(group = supp, color = supp), label = "p.format", wid = "id", group.by = "x.var") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] # Replace possible "1." (with trailing dot) by "1" # this trailing dot appear only on linux stat.test$label <- gsub(pattern = "^1\\.$", replacement = "1", stat.test$label) expect_equal(as.numeric(stat.test$x), c(1, 2, 3)) expect_equal(as.numeric(stat.test$y), c(36.4, 36.4, 36.4)) expect_equal(stat.test$label, c("0.011", "0.058", "1")) }) test_that("stat_friedman_test works for grouped one-way repeated measure anova: group by legend var", { df$id <- as.factor(rep(1:10, 6)) bxp <- ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") + stat_friedman_test(aes(group = supp, color = supp), wid = "id", group.by = "legend.var") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] expect_equal(as.numeric(stat.test$x), c(0.8, 0.8)) expect_equal(as.numeric(stat.test$y), c(36.40, 39.62)) expect_equal(stat.test$label, c("Friedman test, p = 0.02472", "Friedman test, p = 0.00012")) }) ggpubr/tests/testthat/test-compare_means.R0000644000176200001440000001313514337521425020464 0ustar liggesusers data("gene_expression", package = "ggpubr") data("ToothGrowth") test_that("compare_means works for One-sample test", { results <- compare_means(len ~ 1, ToothGrowth, mu = 0) results <- results %>% dplyr::select(.y., group1, group2, p.format, p.signif, method) expected <- tibble::tribble( ~.y., ~group1, ~group2, ~p.format, ~p.signif, ~method, "len", 1, "null model", "1.7e-11", "****", "Wilcoxon" ) expect_equal(results, expected) }) test_that("compare_means works for Two-samples unpaired test", { results <- compare_means(len ~ supp, ToothGrowth) results <- results %>% dplyr::select(.y., group1, group2, p.format, p.signif, method) expected <- tibble::tribble( ~.y., ~group1, ~group2, ~p.format, ~p.signif, ~method, "len", "OJ", "VC", "0.064", "ns", "Wilcoxon" ) expect_equal(results, expected) }) test_that("compare_means works for Two-samples paired test", { results <- compare_means(len ~ supp, ToothGrowth, paired = TRUE) results <- results %>% dplyr::select(.y., group1, group2, p.format, p.signif, method) expected <- tibble::tribble( ~.y., ~group1, ~group2, ~p.format, ~p.signif, ~method, "len", "OJ", "VC", "0.0043", "**", "Wilcoxon" ) expect_equal(results, expected) }) test_that("compare_means works for pairwise comparisons", { results <- compare_means(len ~ dose, ToothGrowth) results <- results %>% dplyr::select(.y., group1, group2, p.format, p.signif, method) expected <- tibble::tribble( ~.y., ~group1, ~group2, ~p.format, ~p.signif, ~method, "len", "0.5", "1", "7.0e-06", "****", "Wilcoxon", "len", "0.5", "2", "8.4e-08", "****", "Wilcoxon", "len", "1", "2", "0.00018", "***", "Wilcoxon" ) expect_equal(results, expected) }) test_that("compare_means works for comparison against reference groups", { results <- compare_means(len ~ dose, ToothGrowth, ref.group = "0.5") results <- results %>% dplyr::select(.y., group1, group2, p.format, p.signif, method) expected <- tibble::tribble( ~.y., ~group1, ~group2, ~p.format, ~p.signif, ~method, "len", "0.5", "1", "7.0e-06", "****", "Wilcoxon", "len", "0.5", "2", "8.4e-08", "****", "Wilcoxon" ) expect_equal(results, expected) }) test_that("compare_means works when using formula with multiple variables", { results <- compare_means(c(GATA3, XBP1, PTEN) ~ dataset, data = gene_expression) results <- results %>% dplyr::select(.y., group1, group2, p.format, p.signif, method) expected <- tibble::tribble( ~.y., ~group1, ~group2, ~p.format, ~p.signif, ~method, "GATA3", "BRCA", "OV", "< 2e-16", "****", "Wilcoxon", "GATA3", "BRCA", "LUSC", "< 2e-16", "****", "Wilcoxon", "GATA3", "OV", "LUSC", "3.0e-08", "****", "Wilcoxon", "XBP1", "BRCA", "OV", "< 2e-16", "****", "Wilcoxon", "XBP1", "BRCA", "LUSC", "< 2e-16", "****", "Wilcoxon", "XBP1", "OV", "LUSC", "4.2e-11", "****", "Wilcoxon", "PTEN", "BRCA", "OV", "6.8e-05", "****", "Wilcoxon", "PTEN", "BRCA", "LUSC", "< 2e-16", "****", "Wilcoxon", "PTEN", "OV", "LUSC", "1.3e-07", "****", "Wilcoxon" ) %>% dplyr::mutate(.y. = factor(.y., levels = c("GATA3", "XBP1", "PTEN"))) expect_equal(results, expected) }) test_that("compare_means works when using ref.group = '.all.'", { results <- compare_means(len ~ dose, ToothGrowth, ref.group = ".all.") results <- results %>% dplyr::select(.y., group1, group2, p.format, p.signif, method) expected <- tibble::tribble( ~.y., ~group1, ~group2, ~p.format, ~p.signif, ~method, "len", ".all.", "0.5", "5.1e-05", "****", "Wilcoxon", "len", ".all.", "1", "0.76404", "ns", "Wilcoxon", "len", ".all.", "2", "0.00018", "***", "Wilcoxon" ) expect_equal(results, expected) }) test_that("compare_means works for Anova", { results <- compare_means(len ~ dose, ToothGrowth, method = "anova") results <- results %>% dplyr::select(.y., p.format, p.signif, method) expected <- tibble::tribble( ~.y., ~p.format, ~p.signif, ~method, "len", "9.5e-16", "****", "Anova" ) expect_equal(results, expected) }) test_that("compare_means works for kruskal.test", { results <- compare_means(len ~ dose, ToothGrowth, method = "kruskal.test") results <- results %>% dplyr::select(.y., p.format, p.signif, method) expected <- tibble::tribble( ~.y., ~p.format, ~p.signif, ~method, "len", "1.5e-09", "****", "Kruskal-Wallis" ) expect_equal(results, expected) }) test_that("compare_means works when grouping variable levels contain group2", { tibble::tribble( ~val, ~gp, ~by, 923 , 'group4','V1', 1252, 'group4','V1', 1442, 'group4','V1', 1398, 'group2','V1', 1858, 'group2','V1', 1330, 'group2','V1', 2593, 'group2','V1', 23 , 'group4','V2', 252, 'group4','V2', 442, 'group4','V2', 398, 'group2','V2', 858, 'group2','V2', 330, 'group2','V2', 593, 'group2','V2' ) %>% dplyr::mutate(gp=factor(gp, levels = c('group2','group4'))) -> dat results <- compare_means(val ~ gp, data = dat, group.by = 'by', paired = F) results <- results %>% dplyr::select(.y., group1, group2, p.format, p.signif, method) expected <- tibble::tribble( ~.y., ~group1, ~group2, ~p.format, ~p.signif, ~method, "val", "group2", "group4", "0.23", "ns", "Wilcoxon", "val", "group2", "group4", "0.23", "ns", "Wilcoxon" ) expect_equal(results, expected) }) ggpubr/tests/testthat/test-get_coord.R0000644000176200001440000000235514332576562017631 0ustar liggesuserscontext("test-get_coord") # Basic plots: one group ----------------------------------- test_that("No transformation is performed when coord specified", { res_10 <- get_coord(coord = 10) res_text <- get_coord(coord = "text") expect_equal(res_10, 10) expect_equal(res_text, "text") }) test_that("get_coord works for one group", { # x- axis res_left <- get_coord( data.ranges = c(1, 3), group = 1, npc = "left", step = 0.1, margin.npc = 0 ) # Y -axis res_top<- get_coord( data.ranges = c(4.2, 36.4), group = 1, npc = "top", step = -0.1, margin.npc = 0 ) expect_equal(res_top, 36.4) }) # Grouped plots -------------------------- test_that("get_coord works for grouped plots", { # x- axis res_left <- get_coord( data.ranges = c(1, 3), group = 1:3, npc = "left", step = 0.1, margin.npc = 0 ) # no transformation when coord specified res_coord <- get_coord( data.ranges = c(1, 3), group = 1:3, coord = 1:3, step = 0.1, margin.npc = 0 ) # Y-axis res_top <- get_coord( data.ranges = c(4.2, 36.4), group = c(1, 2, 3), npc = "top", step = -0.1, margin.npc = 0 ) expect_equal(res_left, c(1.0, 1.2, 1.4)) expect_equal(res_coord, 1:3) expect_equal(res_top, c(36.40, 39.62, 42.84)) }) ggpubr/tests/testthat/test-utils-tidyr.R0000644000176200001440000000114114336762430020140 0ustar liggesusers # Wide data get_wide_data <- function(){ tibble::tibble( before = c(200.1, 190.9, 192.7), after = c(392.9, 393.2, 345.1) ) } test_that("df_gather is sorting rows as done by gather_()", { df <- get_wide_data() expected_output <- tibble::tribble( ~condition, ~val, "before", 200.1, "before", 190.9, "before", 192.7, "after", 392.9, "after", 393.2, "after", 345.1 ) observed_output <- df_gather( df, cols = c("before", "after"), names_to = "condition", values_to = "val" ) expect_equal(observed_output, expected_output) }) ggpubr/tests/testthat/test-as_npc.R0000644000176200001440000000054614332576562017127 0ustar liggesuserscontext("test-as_npc") test_that("as_npc returns the same value as the input when the input is.numeric", { expect_equal(as_npc(0.5), 0.5) }) test_that("as_npc works correctly for character coordinates", { res <- as_npc(c('right', 'left', 'bottom', 'top', 'center', 'centre', 'middle')) expect_equal(res, c(0.95, 0.05, 0.05, 0.95, 0.5, 0.5, 0.5)) }) ggpubr/tests/testthat/test-ggstripchart.R0000644000176200001440000000223614340445172020352 0ustar liggesusers test_that("ggstripchart is reproducible", { p <- ggstripchart(PlantGrowth, x = "group", y = "weight") jitter_data <- layer_data(p, 1) %>% dplyr::select(x, y) %>% dplyr::mutate(x = as.numeric(round(x, 7)), y = as.numeric(round(y, 7))) expected_data <- data.frame( x = c(0.915031,1.1153221,0.9635908, 1.153207,1.1761869,0.8182226,1.0112422,1.1569676,1.020574, 0.9826459,2.1827333,1.9813337,2.0710283,2.0290534, 1.8411699,2.15993,1.8984351,1.8168238,1.9311683,2.1818015, 3.1558157,3.0771214,3.0562027,3.1977079,3.0622823, 3.0834122,3.0176264,3.0376568,2.9156639,2.8588455), y = c(4.1737042,5.5832184,5.1815256, 6.1123637,4.4961969,4.6098224,5.1720677,4.5277313,5.3285454, 5.137853,4.8071424,4.1693164,4.4093098,3.5889508, 5.8672196,3.8271104,6.0278643,4.8897277,4.3181278,4.6928626, 6.3063666,5.1195376,5.5423914,5.4969752,5.3704876, 5.2876523,4.9170203,6.1520265,5.8031604,5.2589957) ) expect_equal(jitter_data, expected_data) }) ggpubr/tests/testthat/test-ggscatter.R0000644000176200001440000000144614334115242017631 0ustar liggesuserscontext("ggscatter") test_that("ggscatter works when there is spaces in variable names", { data("mtcars") df <- mtcars[, c("wt", "mpg")] colnames(df) <- c("Dimension 1", "Dimension 2") p <- ggscatter(df, x = "Dimension 1", y = "Dimension 2" ) p_build <- ggplot2::ggplot_build(p) df_build <- p_build$data[[1]] expect_equal(df$`Dimension 1`, df_build$x) }) test_that("ggscatter can handle non-standard column names when ggpubr.parse_aes global option is set to FALSE (#229)", { data("mtcars") df <- mtcars[, c("wt", "mpg")] colnames(df) <- c("A-A", "B-B") old_options <- options(ggpubr.parse_aes = FALSE) p <- ggscatter(df, x = "A-A", y = "B-B" ) options(old_options) p_build <- ggplot2::ggplot_build(p) df_build <- p_build$data[[1]] expect_equal(df$`A-A`, df_build$x) }) ggpubr/tests/testthat/test-ggboxplot.R0000644000176200001440000000233614340445172017657 0ustar liggesusers test_that("The position of jittered points is reproducible in ggboxplot", { p <- ggboxplot(PlantGrowth, x = "group", y = "weight", add = "jitter") jitter_data <- layer_data(p, 2) %>% dplyr::select(x, y) %>% dplyr::mutate(x = as.numeric(round(x, 7)), y = as.numeric(round(y, 7))) expected_data <-tibble::tribble( ~x, ~y, 0.915031, 4.1737042, 1.1153221, 5.5832184, 0.9635908, 5.1815256, 1.153207, 6.1123637, 1.1761869, 4.4961969, 0.8182226, 4.6098224, 1.0112422, 5.1720677, 1.1569676, 4.5277313, 1.020574, 5.3285454, 0.9826459, 5.137853, 2.1827333, 4.8071424, 1.9813337, 4.1693164, 2.0710283, 4.4093098, 2.0290534, 3.5889508, 1.8411699, 5.8672196, 2.15993, 3.8271104, 1.8984351, 6.0278643, 1.8168238, 4.8897277, 1.9311683, 4.3181278, 2.1818015, 4.6928626, 3.1558157, 6.3063666, 3.0771214, 5.1195376, 3.0562027, 5.5423914, 3.1977079, 5.4969752, 3.0622823, 5.3704876, 3.0834122, 5.2876523, 3.0176264, 4.9170203, 3.0376568, 6.1520265, 2.9156639, 5.8031604, 2.8588455, 5.2589957 ) %>% as.data.frame() expect_equal(jitter_data, expected_data) }) ggpubr/tests/testthat/test-facet.R0000644000176200001440000000110614335517603016731 0ustar liggesusers # Data preparation data("ToothGrowth") df <- ToothGrowth # Adding column name with space df[['spa ced']] <- df[['supp']] test_that("facet works", { p <- ggpubr::ggboxplot(df, "dose", "len", facet.by = "supp") panels <- ggplot2::layer_data(p)[["PANEL"]] %>% unique() %>% as.numeric() expect_equal(panels, c(1, 2)) }) test_that("facet works when column names contain space", { p <- ggpubr::ggboxplot(df, "dose", "len", facet.by = "spa ced") panels <- ggplot2::layer_data(p)[["PANEL"]] %>% unique() %>% as.numeric() expect_equal(panels, c(1, 2)) }) ggpubr/tests/testthat/test-ggtext.R0000644000176200001440000000142414342646623017157 0ustar liggesusersdata("gene_expression", package = "ggpubr") test_that(".get_label_data works when label.select specified as a list", { results <- .get_label_data( data = gene_expression, x = "dataset", y = "XBP1", label ="bcr_patient_barcode", label.select = list(criteria = "`y` > 4.4 & `x` %in% c('BRCA', 'OV')"), ) expected <- tibble::tribble( ~bcr_patient_barcode, ~dataset, ~GATA3, ~PTEN, ~XBP1, "BRCA149", "BRCA", 2.345125, 1.13357142857143, 4.48758333333333, "BRCA536", "BRCA", 3.1135, 0.846142857142857, 4.73675, "BRCA581", "BRCA", 3.38675, 0.152928571428571, 4.5725 ) %>% data.frame(stringsAsFactors = FALSE) expect_equal(results, expected, tolerance = 1e-4) }) ggpubr/tests/testthat/test-gghistogram.R0000644000176200001440000000154714334106676020176 0ustar liggesuserscontext("gghistogram") test_that("gghistogram works when using after_stat()", { p <- gghistogram(iris, x = "Sepal.Length", y = "after_stat(density * width)", bins = 30) p_build <- ggplot2::ggplot_build(p) df <- p_build$data[[1]] observed_count <- df$count expected_count <- c(4, 1, 4, 2, 11, 10, 9, 4, 7, 7, 6, 8, 7, 9, 6, 4, 9, 12, 2, 8, 3, 5, 1, 3, 1, 1, 1, 4, 0, 1) expect_equal(observed_count, expected_count) }) test_that("gghistogram works when using after_stat() with trailing space inside parentheses", { p <- gghistogram(iris, x = "Sepal.Length", y = "after_stat(density )", bins = 30) p_build <- ggplot2::ggplot_build(p) df <- p_build$data[[1]] observed_count <- df$count expected_count <- c(4, 1, 4, 2, 11, 10, 9, 4, 7, 7, 6, 8, 7, 9, 6, 4, 9, 12, 2, 8, 3, 5, 1, 3, 1, 1, 1, 4, 0, 1) expect_equal(observed_count, expected_count) }) ggpubr/tests/testthat/test-geom_pwc.R0000644000176200001440000003531414332576562017465 0ustar liggesuserscontext("test-geom_pwc") # Data preparation df <- ToothGrowth df$dose <- as.factor(df$dose) df$group <- factor(rep(c("grp1", "grp2"), 30)) # Basic plots ----------------------------------- test_that("geom_pwc works for two independent tests", { bxp <- ggboxplot(df, x = "supp", y = "len") + geom_pwc(method = "wilcox_test") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords_expected <- data.frame( x = 1.5, y = 35.395, angle = 0 ) expect_equal(stat.test$group, c(1, 1, 1)) expect_equal(stat.test$bracket.group, c(1, 1, 1)) expect_equal(as.numeric(stat.test$x), c(1, 1, 2)) expect_equal(as.numeric(stat.test$xend), c(1, 2, 2)) expect_equal(stat.test$y, c(34.494, 35.385, 35.385)) expect_equal(stat.test$yend, c(35.385, 35.385, 34.494)) expect_equal(label_coords, label_coords_expected) }) test_that("geom_pwc works for pairwise comparisons", { bxp <- ggboxplot(df, x = "dose", y = "len") + geom_pwc(method = "wilcox_test") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords_expected <- data.frame( x = c(1.5, 2.0, 2.5), y = c(35.395, 38.959, 42.523), angle = c(0, 0, 0) ) expect_equal(stat.test$group, c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L)) expect_equal(stat.test$bracket.group, c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L)) expect_equal(as.numeric(stat.test$x), c(1, 1, 2, 1, 1, 2, 2, 3, 3)) expect_equal(as.numeric(stat.test$xend), c(1, 1, 2, 2, 3, 3, 2, 3, 3)) expect_equal(stat.test$y, c(34.494, 38.058, 41.622, 35.385, 38.949, 42.513, 35.385, 38.949, 42.513)) expect_equal(stat.test$yend, c(35.385, 38.949, 42.513, 35.385, 38.949, 42.513, 34.494, 38.058, 41.622)) expect_equal(label_coords, label_coords_expected) }) test_that("geom_pwc works for pairwise comparisons against a reference group", { bxp <- ggboxplot(df, x = "dose", y = "len") + geom_pwc(method = "wilcox_test", ref.group = "0.5") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords_expected <- data.frame( x = c(1.5, 2.0), y = c(35.395, 38.959), angle = c(0, 0) ) expect_equal(stat.test$group, c(1L, 2L, 1L, 2L, 1L, 2L)) expect_equal(stat.test$bracket.group, c(1L, 2L, 1L, 2L, 1L, 2L)) expect_equal(as.numeric(stat.test$x), c(1, 1, 1, 1, 2, 3)) expect_equal(as.numeric(stat.test$xend), c(1, 1, 2, 3, 2, 3)) expect_equal(stat.test$y, c(34.494, 38.058, 35.385, 38.949, 35.385, 38.949)) expect_equal(stat.test$yend, c(35.385, 38.949, 35.385, 38.949, 34.494, 38.058)) expect_equal(label_coords, label_coords_expected) }) test_that("geom_pwc works for pairwise comparisons against a reference group when remove.bracket=TRUE", { bxp <- ggboxplot(df, x = "dose", y = "len") + geom_pwc(method = "wilcox_test", ref.group = "0.5", remove.bracket = TRUE) bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords_expected <- data.frame( x = c(2, 3), y = c(35.395, 38.959), angle = c(0, 0) ) expect_equal(label_coords, label_coords_expected) }) test_that("geom_pwc works for pairwise comparisons against all. Same y.position for all labels", { bxp <- ggboxplot(df, x = "dose", y = "len") + geom_pwc(method = "wilcox_test", ref.group = "all") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords_expected <- data.frame( x = c(1, 2, 3), y = c(35.395, 35.395, 35.395), angle = c(0, 0, 0) ) expect_equal(label_coords, label_coords_expected) }) # Grouped plots ----------------------------------- test_that("Grouped plots: Two groups by x position", { bxp <- ggboxplot(df, x = "dose", y = "len", color = "supp") + geom_pwc(aes(group = supp), method = "wilcox_test") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords_expected <- data.frame( x = c(1, 2, 3), y = c(35.395, 35.395, 35.395), angle = c(0, 0, 0) ) expect_equal(stat.test$group, c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L)) expect_equal(stat.test$bracket.group, c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L)) expect_equal(as.numeric(stat.test$x), c(0.8, 1.8, 2.8, 0.8, 1.8, 2.8, 1.2, 2.2, 3.2)) expect_equal(as.numeric(stat.test$xend), c(0.8, 1.8, 2.8, 1.2, 2.2, 3.2, 1.2, 2.2, 3.2)) expect_equal(stat.test$y, c(34.494, 34.494, 34.494, 35.385, 35.385, 35.385, 35.385, 35.385, 35.385)) expect_equal(stat.test$yend, c(35.385, 35.385, 35.385, 35.385, 35.385, 35.385, 34.494, 34.494, 34.494)) expect_equal(label_coords, label_coords_expected) }) test_that("Grouped plots: grouping by legend var and comparing x-axis groups", { bxp <- ggboxplot(df, x = "dose", y = "len", color = "supp") + geom_pwc(aes(group = supp, color = supp), group.by = "legend.var") bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords_expected <- data.frame( x = c(1.3, 1.8, 2.3, 1.7, 2.2, 2.7), y = c(35.395, 38.959, 42.523, 46.087, 49.651, 53.215), angle = c(0, 0, 0, 0, 0, 0) ) expect_equal(stat.test$group, c(1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 2L, 2L)) expect_equal(stat.test$bracket.group, c(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L)) expect_equal(as.numeric(stat.test$x), c(0.8, 0.8, 1.8, 1.2, 1.2, 2.2, 0.8, 0.8, 1.8, 1.2, 1.2, 2.2, 1.8, 2.8, 2.8, 2.2, 3.2, 3.2)) expect_equal(as.numeric(stat.test$xend), c(0.8, 0.8, 1.8, 1.2, 1.2, 2.2, 1.8, 2.8, 2.8, 2.2, 3.2, 3.2, 1.8, 2.8, 2.8, 2.2, 3.2, 3.2)) expect_equal(stat.test$y, c(34.494, 38.058, 41.622, 45.186, 48.75, 52.314, 35.385, 38.949, 42.513, 46.077, 49.641, 53.205, 35.385, 38.949, 42.513, 46.077, 49.641, 53.205)) expect_equal(stat.test$yend, c(35.385, 38.949, 42.513, 46.077, 49.641, 53.205, 35.385, 38.949, 42.513, 46.077, 49.641, 53.205, 34.494, 38.058, 41.622, 45.186, 48.75, 52.314)) expect_equal(label_coords, label_coords_expected) }) test_that("Grouped plots: grouping by legend var and comparing x-axis groups, using dodge=0 and bracket.group.by = 'legend.var'", { bxp <- ggboxplot(df, x = "dose", y = "len", color = "supp") + geom_pwc( aes(group = supp, color = supp), group.by = "legend.var", dodge = 0, bracket.group.by = "legend.var" ) bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords_expected <- data.frame( x = c(1.5, 1.5, 2, 2, 2.5, 2.5), y = c(35.395, 38.959, 42.523, 46.087, 49.651, 53.215), angle = c(0, 0, 0, 0, 0, 0) ) expect_equal(stat.test$group, c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L)) expect_equal(stat.test$bracket.group, c(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L)) expect_equal(as.numeric(stat.test$x), c(1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3)) expect_equal(as.numeric(stat.test$xend), c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 3, 3, 3, 3)) expect_equal(stat.test$y, c(34.494, 38.058, 41.622, 45.186, 48.75, 52.314, 35.385, 38.949, 42.513, 46.077, 49.641, 53.205, 35.385, 38.949, 42.513, 46.077, 49.641, 53.205)) expect_equal(stat.test$yend, c(35.385, 38.949, 42.513, 46.077, 49.641, 53.205, 35.385, 38.949, 42.513, 46.077, 49.641, 53.205, 34.494, 38.058, 41.622, 45.186, 48.75, 52.314)) expect_equal(label_coords, label_coords_expected) }) test_that("Grouped plots: 3 groups at x position. All Pairwise comparisons.", { bxp <- ggboxplot(df, x = "supp", y = "len", color = "dose") + geom_pwc(aes(group = dose)) bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords$x <- round(label_coords$x, 2) label_coords$y <- round(label_coords$y, 2) label_coords_expected <- data.frame( x = c(0.87, 1, 1.13, 1.87, 2, 2.13), y = c(35.39, 38.96, 42.52, 35.39, 38.96, 42.52), angle = c(0, 0, 0, 0, 0, 0) ) stat.test$x <- round(stat.test$x, 2) stat.test$xend <- round(stat.test$xend, 2) stat.test$y <- round(stat.test$y, 2) stat.test$yend <- round(stat.test$yend, 2) expect_equal(stat.test$group, c(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L)) expect_equal(stat.test$bracket.group, c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L)) expect_equal(as.numeric(stat.test$x), c(0.73, 0.73, 1, 1.73, 1.73, 2, 0.73, 0.73, 1, 1.73, 1.73, 2, 1, 1.27, 1.27, 2, 2.27, 2.27)) expect_equal(as.numeric(stat.test$xend), c(0.73, 0.73, 1, 1.73, 1.73, 2, 1, 1.27, 1.27, 2, 2.27, 2.27, 1, 1.27, 1.27, 2, 2.27, 2.27)) expect_equal(stat.test$y, c(34.49, 38.06, 41.62, 34.49, 38.06, 41.62, 35.38, 38.95, 42.51, 35.38, 38.95, 42.51, 35.38, 38.95, 42.51, 35.38, 38.95, 42.51)) expect_equal(stat.test$yend, c(35.38, 38.95, 42.51, 35.38, 38.95, 42.51, 35.38, 38.95, 42.51, 35.38, 38.95, 42.51, 34.49, 38.06, 41.62, 34.49, 38.06, 41.62)) expect_equal(label_coords, label_coords_expected) }) test_that("Grouped plots: 3 groups at x position. Pairwise comparisons against a ref group.", { bxp <- ggboxplot(df, x = "supp", y = "len", color = "dose") + geom_pwc(aes(group = dose), ref.group = 1) bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords$x <- round(label_coords$x, 2) label_coords$y <- round(label_coords$y, 2) label_coords_expected <- data.frame( x = c(0.87, 1, 1.87, 2), y = c(35.39, 38.96, 35.39, 38.96), angle = c(0, 0, 0, 0) ) stat.test$x <- round(stat.test$x, 2) stat.test$xend <- round(stat.test$xend, 2) stat.test$y <- round(stat.test$y, 2) stat.test$yend <- round(stat.test$yend, 2) expect_equal(stat.test$group, c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L)) expect_equal(stat.test$bracket.group, c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L)) expect_equal(as.numeric(stat.test$x), c(0.73, 0.73, 1.73, 1.73, 0.73, 0.73, 1.73, 1.73, 1, 1.27, 2, 2.27)) expect_equal(as.numeric(stat.test$xend), c(0.73, 0.73, 1.73, 1.73, 1, 1.27, 2, 2.27, 1, 1.27, 2, 2.27)) expect_equal(stat.test$y, c(34.49, 38.06, 34.49, 38.06, 35.38, 38.95, 35.38, 38.95, 35.38, 38.95, 35.38, 38.95)) expect_equal(stat.test$yend, c(35.38, 38.95, 35.38, 38.95, 35.38, 38.95, 35.38, 38.95, 34.49, 38.06, 34.49, 38.06)) expect_equal(label_coords, label_coords_expected) }) test_that("Grouped plots: 3 groups at x position. Pairwise comparisons against a ref group. Check label coords when remove.bracket=TRUE.", { bxp <- ggboxplot(df, x = "supp", y = "len", color = "dose") + geom_pwc(aes(group = dose), ref.group = 1, remove.bracket = TRUE) bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords$x <- round(label_coords$x, 2) label_coords$y <- round(label_coords$y, 2) label_coords_expected <- data.frame( x = c(1, 1.27, 2, 2.27), y = c(35.39, 38.96, 35.39, 38.96), angle = c(0, 0, 0, 0) ) expect_equal(label_coords, label_coords_expected) }) test_that("Grouped plots: test that geom_pwc() works with different number of groups at each x pos.", { # https://github.com/kassambara/ggpubr/issues/326 demo_data <- data.frame( stringsAsFactors = FALSE, Study = c("A","A","A","A","A","A", "A","A","A","A","B","B","B","B","B","B","B","B", "B","B","C","C","C","C","C","C","C","C","C", "C","C","C","C","C","C","D","D","D","D","D", "D","D","D","D","D","D","D","D","D","D"), Studytype = c("X","X","X","X","X","X", "X","X","X","X","X","X","X","X","X","X","X","X", "X","X","Y","Y","Y","Y","Y","Y","Y","Y","Y", "Y","Y","Y","Y","Y","Y","Y","Y","Y","Y","Y", "Y","Y","Y","Y","Y","Y","Y","Y","Y","Y"), Values = c(4469L,4797L,5101L,5397L, 4542L,2780L,4326L,3396L,3657L,3199L,9221L,10176L, 9277L,10500L,9707L,7406L,7756L,7601L,7586L,7353L, 1811L,1485L,3003L,1629L,2495L,4207L,4265L,3629L, 4157L,3495L,2075L,2112L,2973L,3086L,2943L,5664L,6690L, 3538L,5741L,7880L,5848L,6390L,6569L,6114L,6520L, 7389L,6843L,7611L,6621L,7340L), Group = as.factor(c("CTR", "CTR","CTR","CTR","CTR","Dis1","Dis1","Dis1", "Dis1","Dis1","CTR","CTR","CTR","CTR", "CTR","Dis1","Dis1","Dis1","Dis1","Dis1", "CTR","CTR","CTR","CTR","CTR","Dis2","Dis2", "Dis2","Dis2","Dis2","Dis3","Dis3", "Dis3","Dis3","Dis3","CTR","CTR","CTR","CTR", "CTR","Dis2","Dis2","Dis2","Dis2","Dis2", "Dis3","Dis3","Dis3","Dis3","Dis3")) ) bxp <- ggboxplot(demo_data, x = "Study", y = "Values", fill = "Group") + geom_pwc(aes(group = Group), dodge = 0.8, label = "p", ref.group = 1) bxp_build <- ggplot2::ggplot_build(bxp) stat.test <- bxp_build$data[[2]] label_coords <- as.data.frame(get_pwc_label_coords(stat.test)) label_coords$x <- round(label_coords$x, 2) label_coords$y <- round(label_coords$y, 2) label_coords_expected <- data.frame( x = c(1, 2, 2.87, 3, 3.87, 4), y = c(10950.76, 10950.76, 10950.76, 12032.56, 10950.76, 12032.56), angle = c(0, 0, 0, 0, 0, 0) ) stat.test$x <- round(stat.test$x, 2) stat.test$xend <- round(stat.test$xend, 2) stat.test$y <- round(stat.test$y, 2) stat.test$yend <- round(stat.test$yend, 2) expect_equal(stat.test$group, c(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L)) expect_equal(stat.test$bracket.group, c(1L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 2L, 1L, 2L)) expect_equal(as.numeric(stat.test$x), c(0.8, 1.8, 2.73, 2.73, 3.73, 3.73, 0.8, 1.8, 2.73, 2.73, 3.73, 3.73, 1.2, 2.2, 3, 3.27, 4, 4.27)) expect_equal(as.numeric(stat.test$xend), c(0.8, 1.8, 2.73, 2.73, 3.73, 3.73, 1.2, 2.2, 3, 3.27, 4, 4.27, 1.2, 2.2, 3, 3.27, 4, 4.27)) expect_equal(stat.test$y, c(10680.3, 10680.3, 10680.3, 11762.1, 10680.3, 11762.1, 10950.75, 10950.75, 10950.75, 12032.55, 10950.75, 12032.55, 10950.75, 10950.75, 10950.75, 12032.55, 10950.75, 12032.55)) expect_equal(stat.test$yend, c(10950.75, 10950.75, 10950.75, 12032.55, 10950.75, 12032.55, 10950.75, 10950.75, 10950.75, 12032.55, 10950.75, 12032.55, 10680.3, 10680.3, 10680.3, 11762.1, 10680.3, 11762.1)) expect_equal(label_coords, label_coords_expected) }) ggpubr/tests/testthat.R0000644000176200001440000000007014332576562014677 0ustar liggesuserslibrary(testthat) library(ggpubr) test_check("ggpubr") ggpubr/R/0000755000176200001440000000000014370060431011737 5ustar liggesusersggpubr/R/ggexport.R0000644000176200001440000000620014337540323013725 0ustar liggesusers#' @include utilities.R NULL #'Export ggplots #'@description Export ggplots #'@inheritParams ggarrange #'@param ... list of plots to be arranged into the grid. The plots can be either #' ggplot2 plot objects, arbitrary gtables or an object of class #' \code{\link{ggarrange}}. #' @param filename File name to create on disk. #'@param width,height plot width and height, respectively (example, width = 800, #' height = 800). Applied only to raster plots: "png", "jpeg", "jpg", "bmp" and #' "tiff". #'@param pointsize the default pointsize of plotted text (example, pointsize = #' 8). Used only for raster plots. #'@param res the resolution in ppi (example, res = 250). Used only for raster #' plots. #'@param verbose logical. If TRUE, show message. #'@author Alboukadel Kassambara #' @examples #' \dontrun{ #' require("magrittr") #' # Load data #' data("ToothGrowth") #' df <- ToothGrowth #' df$dose <- as.factor(df$dose) #' #' # Box plot #' bxp <- ggboxplot(df, x = "dose", y = "len", #' color = "dose", palette = "jco") #' # Dot plot #' dp <- ggdotplot(df, x = "dose", y = "len", #' color = "dose", palette = "jco") #' # Density plot #' dens <- ggdensity(df, x = "len", fill = "dose", palette = "jco") #' #'# Export to pdf #' ggarrange(bxp, dp, dens, ncol = 2) %>% #' ggexport(filename = "test.pdf") #' #' # Export to png #' ggarrange(bxp, dp, dens, ncol = 2) %>% #' ggexport(filename = "test.png") #' } #' #'@export ggexport <- function(..., plotlist = NULL, filename = NULL, ncol = NULL, nrow = NULL, width = 480, height = 480, pointsize = 12, res = NA, verbose = TRUE) { # File name and extension if(is.null(filename)) filename <- .collapse(.random_string(), ".pdf", sep = "") file.ext <- .file_ext(filename) # Device dev <- .device(filename) dev.opts <- list(file = filename) if(file.ext %in% c("ps", "eps")) dev.opts <- dev.opts %>% .add_item(onefile = FALSE, horizontal = FALSE) else if(file.ext %in% c("png", "jpeg", "jpg", "bmp", "tiff")) dev.opts <- dev.opts %>% .add_item(width = width, height = height, pointsize = pointsize, res = res) if(file.ext %in% c("pdf", "svg")){ if(!missing(width)) dev.opts <- dev.opts %>% .add_item(width = width) if(!missing(height)) dev.opts <- dev.opts %>% .add_item(height = height) if(!missing(pointsize)) dev.opts <- dev.opts %>% .add_item(pointsize = pointsize) } #width=800, height=800, pointsize=8, res=250 # Plots plots <- c(list(...), plotlist) nb.plots <- length(plots) if(nb.plots == 1) plots <- plots[[1]] else if(!is.null(ncol) | !is.null(nrow)){ plots <- ggarrange(plotlist = plots, ncol = ncol, nrow = nrow) } if(inherits(plots, "ggarrange") & .is_list(plots)) nb.plots <- length(plots) if(nb.plots > 1 & file.ext %in% c("eps", "ps", "png", "jpeg", "jpg", "tiff", "bmp", "svg")){ filename <- gsub(paste0(".", file.ext), paste0("%03d.",file.ext), filename) dev.opts$file <- filename print(filename) } do.call(dev, dev.opts) utils::capture.output(print(plots)) utils::capture.output(grDevices::dev.off()) if(verbose) message("file saved to ", filename) } ggpubr/R/ggerrorplot.R0000644000176200001440000001453514342705120014440 0ustar liggesusers#'@include utilities.R ggpar.R NULL #'Visualizing Error #'@description Visualizing error. #'@inheritParams ggboxplot #'@inheritParams ggplot2::geom_errorbar #'@param ci the percent range of the confidence interval (default is 0.95). #'@param x,y x and y variables for drawing. #'@param numeric.x.axis logical. If TRUE, x axis will be treated as numeric. Default is FALSE. #'@param order character vector specifying the order of items. Considered only when x axis is a factor variable. #'@param color,fill outline and fill colors. #'@param desc_stat descriptive statistics to be used for visualizing errors. Default value is "mean_se". #'Allowed values are one of , "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", #'"median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", "median_range"; see \code{\link{desc_statby}} for more details. #'@param ... other arguments to be passed to be passed to ggpar(). #'@details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" \item plot orientation : orientation #' = c("vertical", "horizontal", "reverse") } #' @seealso \code{\link{ggpar}}, \code{\link{ggline}} #' @examples #' #' # Data: ToothGrowth data set we'll be used. #' df<- ToothGrowth #' head(df, 10) #' #' # Plot mean_se #' ggerrorplot(df, x = "dose", y = "len") #' #' #' # Change desc_stat to mean_sd #' # (other values include: mean_sd, mean_ci, median_iqr, ....) #' # Add labels #' ggerrorplot(df, x = "dose", y = "len", #' desc_stat = "mean_sd") #' #' # Change error.plot to "errorbar" and add mean point #' # Visualize the mean of each group #' ggerrorplot(df, x = "dose", y = "len", #' add = "mean", error.plot = "errorbar") #' #' # Horizontal plot #' ggerrorplot(df, x = "dose", y = "len", #' add = "mean", error.plot = "errorbar", #' orientation = "horizontal") #' #' #' # Change error.plot to "crossbar" #' ggerrorplot(df, x = "dose", y = "len", #' error.plot = "crossbar", width = 0.5) #' #' #' # Add jitter points and errors (mean_se) #' ggerrorplot(df, x = "dose", y = "len", #' add = "jitter") #' #' # Add dot and errors (mean_se) #' ggerrorplot(df, x = "dose", y = "len", #' add = "dotplot") #' #' # Multiple groups with error bars and jitter point #' ggerrorplot(df, x = "dose", y = "len", #' color = "supp", palette = "Paired", #' error.plot = "pointrange", #' position = position_dodge(0.5)) # #' #' #' @export ggerrorplot <- function(data, x, y, desc_stat = "mean_se", numeric.x.axis = FALSE, combine = FALSE, merge = FALSE, color = "black", fill = "white", palette = NULL, size = NULL, width = NULL, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, select = NULL, remove = NULL, order = NULL, add = "none", add.params = list(), error.plot = "pointrange", ci = 0.95, position = position_dodge(), ggtheme = theme_pubr(), ...) { # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( desc_stat = desc_stat, numeric.x.axis = numeric.x.axis, combine = combine, merge = merge, color = color, fill = fill, palette = palette, size = size, width = width, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, select = select , remove = remove, order = order, add = add, add.params = add.params, error.plot = error.plot, ci = ci, position = position, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x if(!missing(y)) .opts$y <- y # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$fun <- ggerrorplot_core if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggerrorplot_core <- function(data, x, y, desc_stat = "mean_se", numeric.x.axis = FALSE, color = "black", fill = "white", palette = NULL, title = NULL, xlab = NULL, ylab = NULL, size = NULL, width = NULL, select = NULL, order = NULL, add = "none", add.params = list(), error.plot = "pointrange", ci = 0.95, position = position_dodge(0.8), ggtheme = theme_pubr(), ...) { if(numeric.x.axis){} else{ if(!is.null(order)) data[[x]] <- factor(data[[x]], levels = order) else if(!is.factor(data[[x]])) data[[x]] <- as.factor(data[[x]]) } error.plot = error.plot[1] if("none" %in% add) add <- "none" # static summaries for computing mean/median and adding errors if(is.null(add.params$fill)) add.params$fill <- "white" add.params <- .check_add.params(add, add.params, error.plot, data, color, fill, ...) add <- setdiff(add, desc_stat) if(inherits(position, "PositionDodge") & is.null(position$width)) position$width = 0.8 p <- ggplot(data, create_aes(list(x = x, y = y))) add.params <- add.params %>% .add_item(add = add, data = data, error.plot = error.plot, ci = ci, position = position, p = p) p <- do.call(ggadd, add.params) # Main plot add.params <- add.params %>% .add_item(color = color, fill = fill, size = size, width = width, add = desc_stat, p = p) p <- do.call(ggadd, add.params) p <- ggpar(p, palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab,...) p } ggpubr/R/ggsummarystats.R0000644000176200001440000002133014336762430015165 0ustar liggesusers#' @include utilities.R ggpar.R #' @importFrom rstatix df_split_by get_summary_stats NULL #' GGPLOT with Summary Stats Table Under the Plot #' #' @description Create a ggplot with summary stats (n, median, mean, iqr) table #' under the plot. Read more: \href{https://www.datanovia.com/en/blog/how-to-create-a-beautiful-plots-in-r-with-summary-statistics-labels/}{How to Create a Beautiful Plots in R with Summary Statistics Labels}. #' @inheritParams ggboxplot #' @param digits integer indicating the number of decimal places (round) to be #' used. #' @param table.font.size the summary table font size. #' @param position Position adjustment, either as a string, or the result of a #' call to a position adjustment function. #' @param summaries summary stats to display in the table. Possible values are #' those returned by the function \code{\link[rstatix]{get_summary_stats}()}, #' including: \code{"n", "min", "max", "median", "q1", "q2", "q3", "mad", #' "mean", "sd", "se", "ci"}. #' @param ggfunc a ggpubr function, including: ggboxplot, ggviolin, ggdotplot, #' ggbarplot, ggline, etc. Can be any other ggplot function that accepts the #' following arguments \code{data, x, color, fill, palette, ggtheme, #' facet.by}. #' @param free.panels logical. If TRUE, create free plot panels when the #' argument \code{facet.by} is specified. #'@param labeller Character vector. An alternative to the argument #' \code{short.panel.labs}. Possible values are one of "label_both" (panel #' labelled by both grouping variable names and levels) and "label_value" #' (panel labelled with only grouping levels). #' @param ... other arguments passed to the function \code{\link{ggpar}()}, #' \code{\link{facet}()} or \code{\link{ggarrange}()} when printing the plot. #' @examples #' # Data preparation #' #:::::::::::::::::::::::::::::::::::::::::::::::: #' data("ToothGrowth") #' df <- ToothGrowth #' df$dose <- as.factor(df$dose) #' # Add random QC column #' set.seed(123) #' qc <- rep(c("pass", "fail"), 30) #' df$qc <- as.factor(sample(qc, 60)) #' # Inspect the data #' head(df) #' #' #' # Basic summary stats #' #:::::::::::::::::::::::::::::::::::::::::::::::: #' # Compute summary statistics #' summary.stats <- df %>% #' group_by(dose) %>% #' get_summary_stats(type = "common") #' summary.stats #' #' # Visualize summary table #' ggsummarytable( #' summary.stats, x = "dose", y = c("n", "median", "iqr"), #' ggtheme = theme_bw() #' ) #' #' #' # Create plots with summary table under the plot #' #:::::::::::::::::::::::::::::::::::::::::::::::: #' # Basic plot #' ggsummarystats( #' df, x = "dose", y = "len", #' ggfunc = ggboxplot, add = "jitter" #' ) #' #' # Color by groups #' ggsummarystats( #' df, x = "dose", y = "len", #' ggfunc = ggboxplot, add = "jitter", #' color = "dose", palette = "npg" #' ) #' #' # Create a barplot #' ggsummarystats( #' df, x = "dose", y = "len", #' ggfunc = ggbarplot, add = c("jitter", "median_iqr"), #' color = "dose", palette = "npg" #' ) #' #' # Facet #' #:::::::::::::::::::::::::::::::::::::::::::::::: #' # Specify free.panels = TRUE for free panels #' ggsummarystats( #' df, x = "dose", y = "len", #' ggfunc = ggboxplot, add = "jitter", #' color = "dose", palette = "npg", #' facet.by = c("supp", "qc"), #' labeller = "label_both" #' ) #' #' @describeIn ggsummarystats Create a table of summary stats #' @export ggsummarytable <- function(data, x, y, digits = 0, size = 3, color = "black", palette = NULL, facet.by = NULL, labeller = "label_value", position = "identity", ggtheme = theme_pubr(), ...) { if (missing(ggtheme) & !is.null(facet.by)) { ggtheme <- theme_pubr(border = TRUE) } if (is.null(names(y))) names(y) <- y y_values <- as.vector(y) df <- as.data.frame(data) df$x <- df[[x]] if (color %in% colnames(df)) { if (missing(position)) position <- position_dodge(0.8) group <- color } else { group <- 1 } df <- df %>% mutate_if(is.double, round, digits) %>% unite(col = "label", !!!syms(y_values), sep = "\n") %>% mutate(y = paste(names(y), collapse = "\n")) p <- ggplot(data, aes(x, y)) + geom_exec( geom_text, data = df, label = "label", size = size, color = color, group = group, position = position ) p <- ggpar(p, ggtheme = ggtheme, palette = palette, xlab = x, ...) if (!is.null(facet.by)) p <- facet(p, facet.by = facet.by, labeller = labeller, ...) p + rremove("ylab") } #' @describeIn ggsummarystats Create a ggplot with a summary stat table under the plot. #' @export ggsummarystats <- function(data, x, y, summaries = c("n", "median", "iqr"), ggfunc = ggboxplot, color = "black", fill = "white", palette = NULL, facet.by = NULL, free.panels = FALSE, labeller = "label_value", heights = c(0.80, 0.20), digits = 0, table.font.size = 3, ggtheme = theme_pubr(), ...) { if (missing(ggtheme) & !is.null(facet.by)) { ggtheme <- theme_pubr(border = TRUE) } env <- c(as.list(environment()), list(...)) if (is.null(facet.by)) { results <- do.call(ggsummarystats_core, env) } else { if (free.panels) { results <- do.call(ggsummarystats_free_facet, env) } else { results <- do.call(ggsummarystats_core, env) } } results } #' @method print ggsummarystats #' @param x an object of class \code{ggsummarystats}. #' @param heights a numeric vector of length 2, specifying the heights of the #' main and the summary table, respectively. #' @rdname ggsummarystats #' @export print.ggsummarystats <- function(x, heights = c(0.80, 0.20), ...){ res <- ggarrange(plotlist = x, heights = heights, align = "v", ncol = 1) print(res) invisible(res) } #' @method print ggsummarystats_list #' @param legend character specifying legend position. Allowed values are one of #' c("top", "bottom", "left", "right", "none"). To remove the legend use #' legend = "none". #' @param x a list of \code{ggsummarystats}. #' @rdname ggsummarystats #' @export print.ggsummarystats_list <- function(x, heights = c(0.80, 0.20), legend = NULL, ...){ # Create a common legend, if legend exists legend.grob <- get_legend(x[[1]]$main.plot, position = legend) has.legend <- !is.null(legend.grob) remove_legend <- function(ggsummarystats){ ggsummarystats[[1]] <- ggsummarystats[[1]] + theme(legend.position = "none") ggsummarystats } if(has.legend){ x <- map(x, remove_legend) } # Combining each ggsummarystats x <- x %>% map( function(x, ...) {ggarrange(plotlist = x, ...)}, heights = heights, align = "v", ncol = 1 ) # Combine the list of ggsumarystats res <- ggarrange(plotlist = x, legend = legend, legend.grob = legend.grob) # Add legend if exist print(res) invisible(res) } ggsummarystats_core <- function(data, x, y, summaries = c("n", "median", "iqr"), ggfunc = ggboxplot, color = "black", fill = "white", palette = NULL, ggtheme = theme_pubr(), heights = c(0.80, 0.20), facet.by = NULL, free.panels = FALSE, labeller = "label_value", digits = 0, table.font.size = 3,...) { groups <- c(x, color, fill, facet.by) %>% unique() %>% intersect(colnames(data)) summary.stats <- data %>% group_by(!!!syms(groups)) %>% get_summary_stats(!!y) # No need to repeat the panel label on the table table.facet.by <- facet.by if(free.panels) table.facet.by <- NULL main.plot <- ggfunc( data, x = x, y = y, color = color, fill = fill, palette = palette, ggtheme = ggtheme, facet.by = facet.by, labeller = labeller, ... ) summary.plot <- ggsummarytable( summary.stats, x = x, y = summaries, color = color, palette = palette, legend = "none", ggtheme = ggtheme, facet.by = table.facet.by, labeller = labeller, digits = digits, size = table.font.size ) + clean_table_theme() plots <- list( main.plot = main.plot, summary.plot = summary.plot ) class(plots) <- c("ggsummarystats", "list") plots } ggsummarystats_free_facet <- function(data, x, y, facet.by, labeller = "label_value", ...) { labeller_func <- switch (labeller, label_both = rstatix::df_label_both, label_value = rstatix::df_label_value ) groups <- facet.by data.grouped <- data %>% df_split_by(vars = groups, label_col = "panel", labeller = labeller_func) %>% mutate( plots = map(data, ggsummarystats_core, x = x, y = y, facet.by = "panel", ...) ) plots <- data.grouped$plots names(plots) <- data.grouped$panel class(plots) <- c("ggsummarystats_list", "list") plots } ggpubr/R/ggpie.R0000644000176200001440000001730114345714213013165 0ustar liggesusers#'@include utilities.R ggpar.R NULL #'Pie chart #'@description Create a pie chart. #'@inheritParams ggboxplot #'@inheritParams ggplot2::geom_errorbar #'@param x variable containing values for drawing. #'@param label variable specifying the label of each slice. #'@param lab.pos character specifying the position for labels. Allowed values #' are "out" (for outside) or "in" (for inside). #'@param lab.adjust numeric value, used to adjust label position when lab.pos = #' "in". Increase or decrease this value to see the effect. #'@param lab.font a vector of length 3 indicating respectively the size (e.g.: #' 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the #' color (e.g.: "red") of label font. For example \emph{lab.font= c(4, "bold", #' "red")}. #'@param font.family character vector specifying font family. #'@param color,fill outline and fill colors. #'@param ... other arguments to be passed to be passed to ggpar(). #'@details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, #' ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette #' = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels #' and position: legend = "right" \item plot orientation : orientation = #' c("vertical", "horizontal", "reverse") } #'@seealso \code{\link{ggpar}}, \code{\link{ggline}} #' @examples #' #' # Data: Create some data #' # +++++++++++++++++++++++++++++++ #' #' df <- data.frame( #' group = c("Male", "Female", "Child"), #' value = c(25, 25, 50)) #' #' head(df) #' #' #' # Basic pie charts #' # ++++++++++++++++++++++++++++++++ #' #' ggpie(df, "value", label = "group") #' #' # Reducing margins around the pie chart #' ggpie(df, "value", label = "group") + #' theme( plot.margin = unit(c(-.75,-.75,-.75,-.75),"cm")) #' #' #' # Change color #' # ++++++++++++++++++++++++++++++++ #' #' # Change fill color by group #' # set line color to white #' # Use custom color palette #' ggpie(df, "value", label = "group", #' fill = "group", color = "white", #' palette = c("#00AFBB", "#E7B800", "#FC4E07") ) #' #' #' # Change label #' # ++++++++++++++++++++++++++++++++ #' #' # Show group names and value as labels #' labs <- paste0(df$group, " (", df$value, "%)") #' ggpie(df, "value", label = labs, #' fill = "group", color = "white", #' palette = c("#00AFBB", "#E7B800", "#FC4E07")) #' #' # Change the position and font color of labels #' ggpie(df, "value", label = labs, #' lab.pos = "in", lab.font = "white", #' fill = "group", color = "white", #' palette = c("#00AFBB", "#E7B800", "#FC4E07")) #' #' #' #'@export ggpie <- function( data, x, label = x, lab.pos = c("out", "in"), lab.adjust = 0, lab.font = c(4, "plain", "black"), font.family = "", color = "black", fill = "white", palette = NULL, size = NULL, ggtheme = theme_pubr(), ... ) { lab.pos <- match.arg(lab.pos) lab.font <- .parse_font(lab.font) %>% .check_pie_labfont() if(length(label) > 1 & length(label) != nrow(data)) stop("label should be of the same length as data") else if(length(label) > 1){ # 1. Add label column data <- data %>% dplyr::mutate(.label. = label) label <- ".label." } # We should order the data in desc order. Because, # in stacked bar plot the order of factor levels are reversed # Very important to have the label in the right place group.vars <- intersect(c(fill, color), names(data)) if(length(group.vars) != 0){ group.val <- dplyr::pull(data, group.vars[1]) data <- data %>% dplyr::arrange(dplyr::desc(group.val)) } # Label y coordinates when placed inside slices .x <- dplyr::pull(data, x) data <- data %>% dplyr::mutate( .lab.ypos. = cumsum(.x) -0.5*.x -lab.adjust ) p <- ggplot(data, create_aes(list(x = "1", y = x))) + geom_exec( geom_bar, data, stat = "identity", fill = fill, color = color, size = size ) p <- ggpar( p, palette = palette, ggtheme = ggtheme, font.family = font.family, ... ) + coord_polar( theta = "y", start = 0, clip = "off" ) + .remove_axis() # Annotate pie slice #::::::::::::::::::::::::::::::::::: if(!is.null(label)){ # Label each slice at the middle of the slice if(lab.pos == "out"){ p <- p + scale_y_continuous( breaks = cumsum(.x) - .x/2, labels = dplyr::pull(data, label) ) + ggplot2::theme(axis.text.x = element_text( face = lab.font$face, color = lab.font$color, size = 2.5*lab.font$size, family = font.family )) } # Compute the cumulative sum as label ypos if(lab.pos == "in"){ p <- p + geom_text( create_aes(list(y = ".lab.ypos.", label = label)), size = lab.font$size, fontface = lab.font$face, colour = lab.font$color, family = font.family )+ clean_theme() } } p } # Old version ggpie_1 <- function(data, x, label = NULL, lab.pos = c("out", "in"), lab.adjust = 0, lab.font = c(4, "bold", "black"), font.family = "", color = "black", fill = "white", palette = NULL, size = NULL, ggtheme = theme_classic(), ...) { lab.pos <- match.arg(lab.pos) lab.font <- .parse_font(lab.font) # data <- data[order(data[, x]), , drop = FALSE] if(fill %in% colnames(data)) { fill_d <- dplyr::pull(data, fill) data[[fill]] <- factor(fill_d, levels = rev(fill_d)) } if(is.null(lab.font)) lab.font <- list(size = 5, face = "bold", color = "black") p <- ggplot(data, create_aes(list(x = 1, y = x)))+ .geom_exec(geom_bar, data, stat = "identity", fill = fill, color = color, size = size) p <- ggpar(p, palette = palette, ggtheme = ggtheme, font.family = font.family, ...) p <- p + coord_polar(theta = "y", start = 0) + theme( axis.title = element_blank(), axis.text.y = element_blank(), axis.line = element_blank(), # panel.border = element_blank(), # panel.grid=element_blank(), axis.ticks = element_blank() ) # label each slice at the midle of the slice if(!is.null(label)){ if(label[1] %in% names(data)) label <- data[[label]] if(lab.pos == "out"){ p <- p + scale_y_continuous( breaks = cumsum(data[[x]]) - data[[x]]/2, labels = label ) } if(lab.pos == "in"){ df <- data y <- df[, x] df[, x] <- (y/(length(y)-lab.adjust)) + c(0, cumsum(y)[-length(y)]) lab.font$size <- ifelse(is.null(lab.font$size), 5, lab.font$size) lab.font$color <- ifelse(is.null(lab.font$color), "black", lab.font$color) lab.font$face <- ifelse(is.null(lab.font$ace), "bold", lab.font$face) p <- p + .geom_exec(geom_text, data = df, x = 1, y = x, label = label, size = lab.font$size, fontface = lab.font$face, colour = lab.font$color, family = font.family )+ theme( axis.text.x = element_blank(), axis.text.y = element_blank(), axis.ticks = element_blank()) } } p } # Remove axis elements .remove_axis <- function(){ theme( axis.title = element_blank(), axis.text.y = element_blank(), axis.line = element_blank(), # panel.border = element_blank(), # panel.grid=element_blank(), axis.ticks = element_blank() ) } # Check labels font .check_pie_labfont <- function(lab.font){ lab.font$size <- ifelse(is.null(lab.font$size), 3.9, lab.font$size) lab.font$color <- ifelse(is.null(lab.font$color), "black", lab.font$color) lab.font$face <- ifelse(is.null(lab.font$face), "plain", lab.font$face) lab.font } ggpubr/R/gradient_color.R0000644000176200001440000000371014332553655015073 0ustar liggesusers#' @include utilities_color.R NULL #'Set Gradient Color #' #' @description Change gradient color. #' \itemize{ #' \item \code{gradient_color()}: Change gradient color. #' \item \code{gradient_fill()}: Change gradient fill. #' } #' @param palette the color palette to be used for coloring or filling by #' groups. Allowed values include "grey" for grey color palettes; brewer #' palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", #' "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", #' "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and #' "rickandmorty". Can be also a numeric vector; in this #' case a basic color palette is created using the function #' \link[grDevices]{palette}. #' #' @seealso \link{set_palette}. #' #' #'@examples #' df <- mtcars #' p <- ggscatter(df, x = "wt", y = "mpg", #' color = "mpg") #' #' # Change gradient color #' # Use one custom color #' p + gradient_color("red") #' #' # Two colors #' p + gradient_color(c("blue", "red")) #' #' # Three colors #' p + gradient_color(c("blue", "white", "red")) #' #' # Use RColorBrewer palette #' p + gradient_color("RdYlBu") #' #' # Use ggsci color palette #' p + gradient_color("npg") #' @rdname gradient_color #' @export gradient_color <- function(palette){ if(.is_col_palette(palette)) palette <- .get_pal(palette, k = 3) n_palette <- length(palette) if(n_palette == 1) { palette <- grDevices::colorRampPalette(c("white", palette))(10) palette <- palette[c(1, 10)] n_palette <- 2 } ggplot2::scale_color_gradientn(colours = palette) } #' @rdname gradient_color #' @export gradient_fill <- function(palette){ if(.is_col_palette(palette)) palette <- .get_pal(palette, k = 3) n_palette <- length(palette) if(n_palette == 1) { palette <- grDevices::colorRampPalette(c("white", palette))(10) palette <- palette[c(1, 10)] n_palette <- 2 } ggplot2::scale_fill_gradientn(colours = palette) } ggpubr/R/stat_conf_ellipse.R0000644000176200001440000000675714332576562015615 0ustar liggesusers#' @include utilities.R NULL #' Plot confidence ellipses. #' @description Plot confidence ellipses around barycenters. The method for #' computing confidence ellipses has been modified from \code{FactoMineR::coord.ellipse()}. #' @inheritParams ggplot2::layer #' @inheritParams ggplot2::stat_ellipse #' @param level confidence level used to construct the ellipses. By #' default, 0.95. #' @param npoint number of points used to draw the ellipses. #' @param bary logical value. If TRUE, the coordinates of the ellipse around the #' barycentre of individuals are calculated. #' @seealso \code{\link{stat_conf_ellipse}} #' @examples #' # Load data #' data("mtcars") #' df <- mtcars #' df$cyl <- as.factor(df$cyl) #' #' # scatter plot with confidence ellipses #' ggscatter(df, x = "wt", y = "mpg", color = "cyl")+ #' stat_conf_ellipse(aes(color = cyl)) #' #' ggscatter(df, x = "wt", y = "mpg", color = "cyl")+ #' stat_conf_ellipse(aes(color = cyl, fill = cyl), alpha = 0.1, geom = "polygon") #' #' @export stat_conf_ellipse <- function(mapping = NULL, data = NULL, geom = "path", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, level = 0.95, npoint = 100, bary = TRUE, ...) { layer( stat = StatConfEllipse, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(na.rm = na.rm, level = level, npoint = npoint, bary = bary, ...) ) } StatConfEllipse <- ggproto("StatConfEllipse", Stat, required_aes = c("x", "y"), compute_group = function(data, scales, params, level = 0.95, npoint = 100, bary = TRUE) { .coord_ellipse (data$x, data$y, level = level, npoint = npoint, bary = bary) } ) # Compute confidence ellipses. # x,y x and y variables for drawing. # level confidence level used to construct the ellipses. By # default, 0.95. # npoint number of points used to draw the ellipses. # bary logical value. If TRUE, the coordinates of the ellipse around the # barycentre of individuals are calculated. .coord_ellipse <- function ( x, y, level = 0.95, npoint = 100, bary = FALSE) { .ellipse <- function(x, scale = c(1, 1), centre = c(0, 0), level = 0.95, t = sqrt(stats::qchisq(level, 2)), which = c(1, 2), npoints = 100) { names <- c("x", "y") if (is.matrix(x)) { xind <- which[1] yind <- which[2] r <- x[xind, yind] if (missing(scale)) { scale <- sqrt(c(x[xind, xind], x[yind, yind])) if (scale[1] > 0) r <- r/scale[1] if (scale[2] > 0) r <- r/scale[2] } if (!is.null(dimnames(x)[[1]])) names <- dimnames(x)[[1]][c(xind, yind)] } else r <- x r <- min(max(r, -1), 1) d <- acos(r) a <- seq(0, 2 * pi, len = npoints) matrix(c(t * scale[1] * cos(a + d/2) + centre[1], t * scale[2] * cos(a - d/2) + centre[2]), npoints, 2, dimnames = list(NULL, names)) } center <- c(mean(x, na.rm = TRUE), mean(y, na.rm = TRUE)) tab <- data.frame(x = x, y = y) mat.cov <- stats::cov(tab) if (bary) mat.cov = mat.cov/nrow(tab) res <- .ellipse(mat.cov, centre = center, level = level, npoints = npoint) return(data.frame(res, stringsAsFactors = FALSE)) } ggpubr/R/stat_chull.R0000644000176200001440000000240014332553655014235 0ustar liggesusers#' @include utilities.R ggpar.R NULL #' Plot convex hull of a set of points #' @description Plot convex hull of a set of points. #' @inheritParams ggplot2::layer #' @inheritParams ggplot2::stat_ellipse #' @seealso \code{\link{ggpar}}, \code{\link{ggscatter}} #' @examples #' # Load data #' data("mtcars") #' df <- mtcars #' df$cyl <- as.factor(df$cyl) #' #' # scatter plot with convex hull #' ggscatter(df, x = "wt", y = "mpg", color = "cyl")+ #' stat_chull(aes(color = cyl)) #' #' ggscatter(df, x = "wt", y = "mpg", color = "cyl")+ #' stat_chull(aes(color = cyl, fill = cyl), alpha = 0.1, geom = "polygon") #' #' @export stat_chull <- function(mapping = NULL, data = NULL, geom = "path", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ...) { layer( stat = StatChull, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(na.rm = na.rm, ...) ) } # Convex ellipse StatChull <- ggproto("StatChull", Stat, compute_group = function(data, scales) { data[chull(data$x, data$y), , drop = FALSE] }, required_aes = c("x", "y") ) ggpubr/R/ggscatter.R0000644000176200001440000004734014367733317014075 0ustar liggesusers#' @include utilities.R ggpar.R stat_chull.R stat_conf_ellipse.R stat_stars.R stat_cor.R NULL #' Scatter plot #' @description Create a scatter plot. #' @inheritParams ggboxplot #' @inheritParams facet #' @inheritParams ggpar #' @param x x variables for drawing. #' @param y y variables for drawing. #' @param color,fill point colors. #' @param shape point shape. See \code{\link{show_point_shapes}}. #' @param point logical value. If TRUE, show points. #' @param rug logical value. If TRUE, add marginal rug. #' @param add allowed values are one of "none", "reg.line" (for adding linear #' regression line) or "loess" (for adding local regression fitting). #' @param add.params parameters (color, size, linetype) for the argument 'add'; #' e.g.: add.params = list(color = "red"). #' @param conf.int logical value. If TRUE, adds confidence interval. #' @param conf.int.level Level controlling confidence region. Default is 95\%. #' Used only when add != "none" and conf.int = TRUE. #' @param fullrange should the fit span the full range of the plot, or just the #' data. Used only when add != "none". #' @param ellipse logical value. If TRUE, draws ellipses around points. #' @param ellipse.level the size of the concentration ellipse in normal #' probability. #' @param ellipse.type Character specifying frame type. Possible values are #' \code{"convex"}, \code{"confidence"} or types supported by #' \code{\link[ggplot2]{stat_ellipse}()} including one of \code{c("t", "norm", #' "euclid")} for plotting concentration ellipses. #' #' \itemize{ \item \code{"convex"}: plot convex hull of a set o points. \item #' \code{"confidence"}: plot confidence ellipses arround group mean points as #' \code{FactoMineR::coord.ellipse()}. \item \code{"t"}: #' assumes a multivariate t-distribution. \item \code{"norm"}: assumes a #' multivariate normal distribution. \item \code{"euclid"}: draws a circle with #' the radius equal to level, representing the euclidean distance from the #' center. This ellipse probably won't appear circular unless #' \code{\link[ggplot2]{coord_fixed}()} is applied.} #' @param ellipse.alpha Alpha for ellipse specifying the transparency level of #' fill color. Use alpha = 0 for no fill color. #' @param ellipse.border.remove logical value. If TRUE, remove ellipse border lines. #' @param mean.point logical value. If TRUE, group mean points are added to the #' plot. #' @param mean.point.size numeric value specifying the size of mean points. #' @param star.plot logical value. If TRUE, a star plot is generated. #' @param star.plot.lty,star.plot.lwd line type and line width (size) for star #' plot, respectively. #' @param label the name of the column containing point labels. Can be also a #' character vector with length = nrow(data). #' @param font.label a vector of length 3 indicating respectively the size #' (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and #' the color (e.g.: "red") of point labels. For example \emph{font.label = #' c(14, "bold", "red")}. To specify only the size and the style, use #' font.label = c(14, "plain"). #' @param font.family character vector specifying font family. #' @param label.select character vector specifying some labels to show. #' @param repel a logical value, whether to use ggrepel to avoid overplotting #' text labels or not. #' @param label.rectangle logical value. If TRUE, add rectangle underneath the #' text, making it easier to read. #' @param parse If \code{TRUE}, the labels will be parsed into expressions and #' displayed as described in \code{?plotmath}. #' @param cor.coef logical value. If TRUE, correlation coefficient with the #' p-value will be added to the plot. #' @param cor.coeff.args a list of arguments to pass to the function #' \code{\link{stat_cor}} for customizing the displayed correlation #' coefficients. For example: \code{cor.coeff.args = list(method = "pearson", #' label.x.npc = "right", label.y.npc = "top")}. #' @param cor.method method for computing correlation coefficient. Allowed #' values are one of "pearson", "kendall", or "spearman". #' @param cor.coef.coord numeric vector, of length 2, specifying the x and y #' coordinates of the correlation coefficient. Default values are NULL. #' @param cor.coef.size correlation coefficient text font size. #' @param ggp a ggplot. If not NULL, points are added to an existing plot. #' @param show.legend.text logical. Should text be included in the legends? NA, #' the default, includes if any aesthetics are mapped. FALSE never includes, #' and TRUE always includes. #' @param ... other arguments to be passed to \code{\link[ggplot2]{geom_point}} #' and \code{\link{ggpar}}. #' @details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" \item plot orientation : orientation #' = c("vertical", "horizontal", "reverse") } #' @seealso \code{\link{stat_cor}}, \code{\link{stat_stars}}, \code{\link{stat_conf_ellipse}} and \code{\link{ggpar}}. #' @examples #' # Load data #' data("mtcars") #' df <- mtcars #' df$cyl <- as.factor(df$cyl) #' head(df[, c("wt", "mpg", "cyl")], 3) #' #' # Basic plot #' # +++++++++++++++++++++++++++ #' ggscatter(df, x = "wt", y = "mpg", #' color = "black", shape = 21, size = 3, # Points color, shape and size #' add = "reg.line", # Add regressin line #' add.params = list(color = "blue", fill = "lightgray"), # Customize reg. line #' conf.int = TRUE, # Add confidence interval #' cor.coef = TRUE, # Add correlation coefficient. see ?stat_cor #' cor.coeff.args = list(method = "pearson", label.x = 3, label.sep = "\n") #' ) #' #' # loess method: local regression fitting #' ggscatter(df, x = "wt", y = "mpg", #' add = "loess", conf.int = TRUE) #' #' #' # Control point size by continuous variable values ("qsec") #' ggscatter(df, x = "wt", y = "mpg", #' color = "#00AFBB", size = "qsec") #' #' #' # Change colors #' # +++++++++++++++++++++++++++ #' # Use custom color palette #' # Add marginal rug #' ggscatter(df, x = "wt", y = "mpg", color = "cyl", #' palette = c("#00AFBB", "#E7B800", "#FC4E07") ) #' #' #' #' #' # Add group ellipses and mean points #' # Add stars #' # +++++++++++++++++++ #' ggscatter(df, x = "wt", y = "mpg", #' color = "cyl", shape = "cyl", #' palette = c("#00AFBB", "#E7B800", "#FC4E07"), #' ellipse = TRUE, mean.point = TRUE, #' star.plot = TRUE) #' #' #' # Textual annotation #' # +++++++++++++++++ #' df$name <- rownames(df) #' ggscatter(df, x = "wt", y = "mpg", #' color = "cyl", palette = c("#00AFBB", "#E7B800", "#FC4E07"), #' label = "name", repel = TRUE) #' #' #' @export ggscatter <- function(data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "lightgray", palette = NULL, shape = 19, size = 2, point = TRUE, rug = FALSE, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, add = c("none", "reg.line", "loess"), add.params = list(), conf.int = FALSE, conf.int.level = 0.95, fullrange = FALSE, ellipse = FALSE, ellipse.level = 0.95, ellipse.type = "norm", ellipse.alpha = 0.1, ellipse.border.remove = FALSE, mean.point = FALSE, mean.point.size = ifelse(is.numeric(size), 2*size, size), star.plot = FALSE, star.plot.lty = 1, star.plot.lwd = NULL, label = NULL, font.label = c(12, "plain"), font.family = "", label.select = NULL, repel = FALSE, label.rectangle = FALSE, parse = FALSE, cor.coef = FALSE, cor.coeff.args = list(), cor.method = "pearson", cor.coef.coord = c(NULL, NULL), cor.coef.size = 4, ggp = NULL, show.legend.text = NA, ggtheme = theme_pubr(), ...){ add <- match.arg(add) # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( combine = combine, merge = merge, color = color, fill = fill, palette = palette, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, shape = shape, size = size, point = point, rug = rug, add = add, add.params = add.params, conf.int = conf.int, conf.int.level = conf.int.level, fullrange = fullrange, ellipse = ellipse, ellipse.level = ellipse.level, ellipse.type = ellipse.type, ellipse.alpha = ellipse.alpha, ellipse.border.remove = ellipse.border.remove, mean.point = mean.point, mean.point.size = mean.point.size, star.plot = star.plot, star.plot.lty = star.plot.lty, star.plot.lwd = star.plot.lwd, label = label, font.label = font.label, font.family = font.family, label.select = label.select, repel = repel, label.rectangle = label.rectangle, parse = parse, cor.coef = cor.coef, cor.coeff.args = cor.coeff.args, cor.method = cor.method, cor.coef.coord = cor.coef.coord, cor.coef.size = cor.coef.size, ggp = ggp, show.legend.text = show.legend.text, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x if(!missing(y)) .opts$y <- y # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } font.label <- .parse_font(font.label) %>% .compact() font.label$color <- ifelse(is.null(font.label$color), color, font.label$color) .opts$font.label <- font.label .opts$fun <- ggscatter_core if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggscatter_core <- function(data, x, y, color = "black", fill = "lightgray", palette = NULL, shape = 19, size = 2, point = TRUE, rug = FALSE, title = NULL, xlab = NULL, ylab = NULL, add = c("none", "reg.line", "loess"), add.params = list(), conf.int = FALSE, conf.int.level = 0.95, fullrange = FALSE, ellipse = FALSE, ellipse.level = 0.95, ellipse.type = "norm", ellipse.alpha = 0.1, ellipse.border.remove = FALSE, mean.point = FALSE, mean.point.size = ifelse(is.numeric(size), 2*size, size), star.plot = FALSE, star.plot.lty = 1, star.plot.lwd = NULL, label = NULL, font.label = c(12, "plain"), font.family = "", label.select = NULL, repel = FALSE, label.rectangle = FALSE, parse = FALSE, cor.coef = FALSE, cor.coeff.args = list(), cor.method = "pearson", cor.coef.coord = c(NULL, NULL), cor.coef.size = 4, ggp = NULL, show.legend.text = NA, ggtheme = theme_classic(), ...) { add <- match.arg(add) add.params <- .check_add.params(add, add.params, error.plot = "", data, color, fill, ...) if(length(label) >1){ if(length(label) != nrow(data)) stop("The argument label should be a column name or a vector of length = nrow(data). ", "It seems that length(label) != nrow(data)") else data$label.xx <- label label <- "label.xx" } # label font font.label <- .parse_font(font.label) font.label$size <- ifelse(is.null(font.label$size), 12, font.label$size) font.label$color <- ifelse(is.null(font.label$color), color, font.label$color) font.label$face <- ifelse(is.null(font.label$face), "plain", font.label$face) if(is.null(ggp)) p <- ggplot(data, create_aes(list(x = x, y = y))) else p <- ggp if(point) p <- p + .geom_exec(geom_point, data = data, x = x, y = y, color = color, fill = fill, size = size, shape = shape, ...) # Adjust shape when ngroups > 6, to avoid ggplot warnings if(shape %in% colnames(data)){ ngroups <- length(levels(data[[shape]])) if(ngroups > 6) p <- p + scale_shape_manual(values=1:ngroups, labels = levels(data[[shape]])) } # Add marginal rug # +++++++++++ if(rug) p <- p + .geom_exec(geom_rug, data = data, color = color, size = size/2) # Add reg line or loess # ++++++++++++ if(add %in% c("reg.line", "loess")){ add <- ifelse(add == "reg.line", stats::lm, stats::loess) if(is.null(add.params$linetype)) add.params$linetype <- "solid" if(conf.int == FALSE) add.params$fill <- "lightgray" .args <- .geom_exec(NULL, data = data, se = conf.int, level = conf.int.level, color = add.params$color, fill = add.params$fill, linetype = add.params$linetype, size = add.params$size, fullrange = fullrange) mapping <- .args$mapping option <- .args$option option[["method"]] <- add option[["formula"]] <- y ~ x option[["mapping"]] <- create_aes(mapping) p <- p + do.call(geom_smooth, option) } # Add ellipses # +++++++++++ if(ellipse){ grp <- intersect(unique(c(color, fill, shape)), colnames(data))[1] # NO grouping variable if(is.na(grp)) { grp <- factor(rep(1, nrow(data))) grp_name <- "group" data$group <- grp } # Case of grouping variable else { grp_name <- grp data[[grp_name]] <- as.factor(data[[grp_name]]) } if (ellipse.type == 'convex') p <- p + .convex_ellipse(data, x, y, grp_name, color, fill, ellipse.alpha, ellipse.border.remove = ellipse.border.remove) else if(ellipse.type == "confidence") p <- p + .confidence_ellipse(data, x, y, grp_name, color, fill, alpha = ellipse.alpha, level = ellipse.level, ellipse.border.remove = ellipse.border.remove) else if (ellipse.type %in% c('t', 'norm', 'euclid')) p <- p + .stat_ellipse(data, x, y, grp_name, color = color, fill = fill, alpha = ellipse.alpha, type = ellipse.type, level = ellipse.level, ellipse.border.remove = ellipse.border.remove) } # /ellipse # Add mean points # +++++++++ if(mean.point) { p <- p + .geom_exec(stat_mean, data = data, color = color, shape = shape, fill = fill, size = mean.point.size) } # Star plots # ++++++++++++ if(star.plot){ p <- p + .geom_exec(stat_stars, data = data, color = color, linetype = star.plot.lty, size = star.plot.lwd) } #/ star plots # Add textual annotation # ++++++ alpha <- 1 if(!is.null(list(...)$alpha)) alpha <- list(...)$alpha if(!is.null(label)) { lab_data <- data # Select some labels to show if(!is.null(label.select)) lab_data <- subset(lab_data, lab_data[[label]] %in% label.select, drop = FALSE) if(repel){ max.overlaps = getOption("ggrepel.max.overlaps", default = Inf) ggfunc <- ggrepel::geom_text_repel if(label.rectangle) ggfunc <- ggrepel::geom_label_repel p <- p + .geom_exec(ggfunc, data = lab_data, x = x, y = y, label = label, fontface = font.label$face, parse = parse, size = font.label$size/3, color = font.label$color, alpha = alpha, family = font.family, box.padding = unit(0.35, "lines"), point.padding = unit(0.3, "lines"), force = 1, show.legend = show.legend.text, seed=123, max.overlaps = max.overlaps) } else{ ggfunc <- geom_text vjust <- -0.7 if(label.rectangle) { ggfunc <- geom_label vjust <- -0.4 } p <- p + .geom_exec(ggfunc, data = lab_data, x = x, y = y, color = color, label = label, fontface = font.label$face, family = font.family, parse = parse, size = font.label$size/3, color = font.label$color, vjust = vjust, alpha = alpha, show.legend = show.legend.text) } } # Add correlation coefficient if(cor.coef){ if(!missing(cor.method)) cor.coeff.args$method <- cor.method if(!missing(cor.coef.size)) cor.coeff.args$size <- cor.coef.size if(!missing(cor.coef.coord)){ cor.coeff.args$label.x <- cor.coef.coord[1] cor.coeff.args$label.y <- cor.coef.coord[2] } p <- p + do.call(stat_cor, cor.coeff.args) } p <- ggpar(p, palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab,...) if(font.family != "") p <- p + theme(text = element_text(family = font.family)) p } # Add convex ellipse # data a data frame # x,y: x and y variables # grp_name: grp variable .convex_ellipse <- function(data, x, y, grp_name, color = "black", fill = "lightgray", alpha = 0.1, ellipse.border.remove = FALSE ){ grp_levels <- levels(data[[grp_name]]) if(length(grp_levels) == 1) .geom_exec(geomfunc = stat_chull, data = data, color = color, fill = fill, alpha = alpha, geom = "polygon") else { if( ellipse.border.remove) color <- NULL else color = grp_name .geom_exec(geomfunc = stat_chull, data = data, color = color, fill = grp_name, alpha = alpha, geom = "polygon") } } # Confidence ellipse .confidence_ellipse <- function(data, x, y, grp_name, color = "black", fill = "lightgray", alpha = 0.1, level = 0.95, ellipse.border.remove = FALSE){ grp_levels <- levels(data[[grp_name]]) if(length(grp_levels) == 1) { mapping <- create_aes(list(x = x, y = y)) stat_conf_ellipse(mapping = mapping, data = data, color = color, fill = fill, alpha = alpha, level = level, geom = "polygon") } else { mapping = create_aes(list(x = x, y = y, colour = grp_name, fill = grp_name)) if(ellipse.border.remove ) mapping = create_aes(list(x = x, y = y, colour = NULL, fill = grp_name)) stat_conf_ellipse(mapping = mapping, data = data, level = level, alpha = alpha, geom = 'polygon') } } # Add ggplot2 stat ellipse .stat_ellipse <- function(data, x, y, grp_name, color = "black", fill = "lightgray", alpha = 0.1, type = "norm", level = 0.95, ellipse.border.remove = FALSE) { grp_levels <- levels(data[[grp_name]]) if(length(grp_levels) == 1){ mapping <- create_aes(list(x = x, y = y)) ggplot2::stat_ellipse(mapping = mapping, data = data, level = level, type = type, colour = color, fill = fill, alpha = alpha, geom = 'polygon') } else{ mapping = create_aes(list(x = x, y = y, colour = grp_name, group = grp_name, fill = grp_name)) if(ellipse.border.remove) mapping = create_aes(list(x = x, y = y, group = grp_name, fill = grp_name)) ggplot2::stat_ellipse(mapping = mapping, data = data, level = level, type = type, alpha = alpha, geom = 'polygon') } } ggpubr/R/border.R0000644000176200001440000000131114332553655013350 0ustar liggesusers#'Set ggplot Panel Border Line #' #'@description Change or set ggplot panel border. #'@param color border line color. #'@param size numeric value specifying border line size. #'@param linetype line type. An integer (0:8), a name (blank, solid, dashed, #' dotted, dotdash, longdash, twodash). Sess \code{\link{show_line_types}}. #' #' #'@examples #'# Load data #'data("ToothGrowth") #'df <- ToothGrowth #' #'# Basic plot #'p <- ggboxplot(df, x = "dose", y = "len") #'p #' #'# Add border #' p + border() #'@export border <- function(color = "black", size = 0.8, linetype = NULL){ theme(panel.background = element_rect(color = color, size = size, linetype = linetype), axis.line = element_blank()) } ggpubr/R/desc_statby.R0000644000176200001440000000524514337240660014403 0ustar liggesusers#' Descriptive statistics by groups #' #' @description Computes descriptive statistics by groups for a measure variable. #' #' @param data a data frame. #' @param measure.var the name of a column containing the variable to be summarized. #' @param grps a character vector containing grouping variables; e.g.: grps = c("grp1", "grp2") #' @param ci the percent range of the confidence interval (default is 0.95). #' #' @return #' A data frame containing descriptive statistics, such as: #' \itemize{ #' \item \strong{length}: the number of elements in each group #' \item \strong{min}: minimum #' \item \strong{max}: maximum #' \item \strong{median}: median #' \item \strong{mean}: mean #' \item \strong{iqr}: interquartile range #' \item \strong{mad}: median absolute deviation (see ?MAD) #' \item \strong{sd}: standard deviation of the sample #' \item \strong{se}: standard error of the mean. It's calculated as the sample standard deviation divided by the root of the sample size. #' \item \strong{ci}: confidence interval of the mean #' \item \strong{range}: the range = max - min #' \item \strong{cv}: coefficient of variation, sd/mean #' \item \strong{var}: variance, sd^2 #' } #' #' @examples #' # Load data #'data("ToothGrowth") #' #'# Descriptive statistics #'res <- desc_statby(ToothGrowth, measure.var = "len", #' grps = c("dose", "supp")) #' head(res[, 1:10]) #' #' @export desc_statby <- function(data, measure.var, grps, ci = 0.95){ if(!inherits(data, "data.frame")) stop("data must be a data.frame.") . <- NULL data %>% as.data.frame() %>% df_group_by(vars = grps) %>% do(.summary(.[, measure.var], ci = ci)) %>% as.data.frame() } # Helper function to compute summary statistics .summary <- function(x, ci = 0.95){ if(is.data.frame(x)){ if(ncol(x) == 1) x <- .select_vec(x, 1) } if(!is.numeric(x)) stop("x should be a numeric vector or a data frame with one numeric column") data_sum <- data.frame( length = base::sum(!is.na(x)), min = base::min(x, na.rm=TRUE), max = base::max(x, na.rm=TRUE), median = stats::median(x, na.rm=TRUE), mean = base::mean(x, na.rm=TRUE), iqr = stats::IQR(x, na.rm=TRUE), mad = stats::mad(x, na.rm=TRUE), sd = stats::sd(x, na.rm=TRUE) ) data_sum$se <- data_sum$sd / sqrt(data_sum$length) # standard error # Confidence interval from t-distribution # e.g., if conf.interval is .95, use .975 (above/below), and use df=N-1 data_sum$ci <- stats::qt(ci/2 + .5, data_sum$length-1)*data_sum$se data_sum$range <- data_sum$max - data_sum$min data_sum$cv <- data_sum$sd/data_sum$mean data_sum$var <- data_sum$sd^2 data_sum[, 2:ncol(data_sum)] <- data_sum[, 2:ncol(data_sum)] return(data_sum) } ggpubr/R/utils-geom-signif.R0000644000176200001440000000037014332553655015441 0ustar liggesusers#' geom_signif exported from ggsignif package #' #' See \code{ggsignif::\link[ggsignif:stat_signif]{geom_signif}} for details. #' #' @name geom_signif #' @rdname geom_signif #' @keywords internal #' @export #' @importFrom ggsignif geom_signif NULL ggpubr/R/stat_mean.R0000644000176200001440000000267714332553655014066 0ustar liggesusers#' @include utilities.R NULL #' Draw group mean points #' @description Draw the mean point of each group. #' @inheritParams ggplot2::layer #' @param ... other arguments to pass to \code{\link[ggplot2]{geom_point}}. #' @param na.rm If FALSE (the default), removes missing values with a warning. #' If TRUE silently removes missing values. #' @seealso \code{\link{stat_conf_ellipse}}, \code{\link{stat_chull}} and #' \code{\link{ggscatter}} #' @examples #' # Load data #' data("mtcars") #' df <- mtcars #' df$cyl <- as.factor(df$cyl) #' #' # Scatter plot with ellipses and group mean points #' ggscatter(df, x = "wt", y = "mpg", #' color = "cyl", shape = "cyl", ellipse = TRUE)+ #' stat_mean(aes(color = cyl, shape = cyl), size = 4) #' #' @export stat_mean <- function(mapping = NULL, data = NULL, geom = "point", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ...) { layer( stat = StatMean, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(na.rm = na.rm, ...) ) } StatMean<- ggproto("StatMean", Stat, required_aes = c("x", "y"), compute_group = function(data, scales) { res <- data.frame(x = mean(data$x, na.rm = TRUE), y = mean(data$y, na.rm = TRUE)) res } ) ggpubr/R/ggecdf.R0000644000176200001440000000667014332553655013327 0ustar liggesusers#' @include utilities.R ggpar.R NULL #' Empirical cumulative density function #' @description Empirical Cumulative Density Function (ECDF). #' @inheritParams ggboxplot #' @param x variable to be drawn. #' @param color line and point color. #' @param linetype line type. See \code{\link{show_line_types}}. #' @param size line and point size. #' @param ... other arguments to be passed to #' \code{\link[ggplot2]{stat_ecdf}} and \code{\link{ggpar}}. #' @details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" \item plot orientation : orientation #' = c("vertical", "horizontal", "reverse") } #' @seealso \code{\link{ggpar}} #' #' @examples #' # Create some data format #' set.seed(1234) #' wdata = data.frame( #' sex = factor(rep(c("F", "M"), each=200)), #' weight = c(rnorm(200, 55), rnorm(200, 58))) #' #' head(wdata, 4) #' #' # Basic ECDF plot #' ggecdf(wdata, x = "weight") #' #' # Change colors and linetype by groups ("sex") #' # Use custom palette #' ggecdf(wdata, x = "weight", #' color = "sex", linetype = "sex", #' palette = c("#00AFBB", "#E7B800")) #' #' @export ggecdf <- function(data, x, combine = FALSE, merge = FALSE, color = "black", palette = NULL, size = NULL, linetype = "solid", title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, ggtheme = theme_pubr(), ...){ # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( combine = combine, merge = merge, color = color, palette = palette, linetype = linetype, size = size, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$fun <- ggecdf_core .opts$y <- "..ecdf.." if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggecdf_core <- function(data, x, y = "..ecdf..", color = "black", palette = NULL, size = NULL, linetype = "solid", title = NULL, xlab = NULL, ylab = NULL, ggtheme = theme_classic(), ...) { p <- ggplot(data, create_aes(list(x = x))) p <- p + geom_exec(stat_ecdf, data = data, color = color, size = size, linetype = linetype)+ labs(y = paste0("F(", x, ")")) p <- ggpar(p, palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab,...) p } ggpubr/R/stat_cor.R0000644000176200001440000002601714332553655013723 0ustar liggesusers#' @include utilities.R utilities_label.R NULL #'Add Correlation Coefficients with P-values to a Scatter Plot #'@description Add correlation coefficients with p-values to a scatter plot. Can #' be also used to add `R2`. #'@inheritParams ggplot2::layer #'@param method a character string indicating which correlation coefficient (or #' covariance) is to be computed. One of "pearson" (default), "kendall", or #' "spearman". #'@param alternative a character string specifying the alternative hypothesis, #' must be one of "two.sided" (default), "greater" or "less". You can specify #' just the initial letter. #'@param cor.coef.name character. Can be one of \code{"R"} (pearson coef), #' \code{"rho"} (spearman coef) and \code{"tau"} (kendall coef). Uppercase and #' lowercase are allowed. #'@param label.sep a character string to separate the terms. Default is ", ", to #' separate the correlation coefficient and the p.value. #'@param label.x.npc,label.y.npc can be \code{numeric} or \code{character} #' vector of the same length as the number of groups and/or panels. If too #' short they will be recycled. \itemize{ \item If \code{numeric}, value should #' be between 0 and 1. Coordinates to be used for positioning the label, #' expressed in "normalized parent coordinates". \item If \code{character}, #' allowed values include: i) one of c('right', 'left', 'center', 'centre', #' 'middle') for x-axis; ii) and one of c( 'bottom', 'top', 'center', 'centre', #' 'middle') for y-axis.} #' #' If too short they will be recycled. #'@param label.x,label.y \code{numeric} Coordinates (in data units) to be used #' for absolute positioning of the label. If too short they will be recycled. #'@param output.type character One of "expression", "latex", "tex" or "text". #'@param digits,r.digits,p.digits integer indicating the number of decimal #' places (round) or significant digits (signif) to be used for the correlation #' coefficient and the p-value, respectively.. #'@param r.accuracy a real value specifying the number of decimal places of #' precision for the correlation coefficient. Default is NULL. Use (e.g.) 0.01 #' to show 2 decimal places of precision. If specified, then \code{r.digits} is #' ignored. #'@param p.accuracy a real value specifying the number of decimal places of #' precision for the p-value. Default is NULL. Use (e.g.) 0.0001 to show 4 #' decimal places of precision. If specified, then \code{p.digits} is ignored. #'@param ... other arguments to pass to \code{\link[ggplot2]{geom_text}} or #' \code{\link[ggplot2:geom_text]{geom_label}}. #'@param na.rm If FALSE (the default), removes missing values with a warning. If #' TRUE silently removes missing values. #'@seealso \code{\link{ggscatter}} #'@section Computed variables: \describe{ \item{r}{correlation coefficient} #' \item{rr}{correlation coefficient squared} \item{r.label}{formatted label #' for the correlation coefficient} \item{rr.label}{formatted label for the #' squared correlation coefficient} \item{p.label}{label for the p-value} #' \item{label}{default labeldisplayed by \code{stat_cor()}} } #' #' @examples #' # Load data #' data("mtcars") #' df <- mtcars #' df$cyl <- as.factor(df$cyl) #' #' # Scatter plot with correlation coefficient #' #::::::::::::::::::::::::::::::::::::::::::::::::: #' sp <- ggscatter(df, x = "wt", y = "mpg", #' add = "reg.line", # Add regressin line #' add.params = list(color = "blue", fill = "lightgray"), # Customize reg. line #' conf.int = TRUE # Add confidence interval #' ) #' # Add correlation coefficient #' sp + stat_cor(method = "pearson", label.x = 3, label.y = 30) #' #' # Specify the number of decimal places of precision for p and r #' # Using 3 decimal places for the p-value and #' # 2 decimal places for the correlation coefficient (r) #' sp + stat_cor(p.accuracy = 0.001, r.accuracy = 0.01) #' #' # Show only the r.label but not the p.label #' sp + stat_cor(aes(label = ..r.label..), label.x = 3) #' #'# Use R2 instead of R #'ggscatter(df, x = "wt", y = "mpg", add = "reg.line") + #' stat_cor( #' aes(label = paste(..rr.label.., ..p.label.., sep = "~`,`~")), #' label.x = 3 #' ) #' #' # Color by groups and facet #' #:::::::::::::::::::::::::::::::::::::::::::::::::::: #' sp <- ggscatter(df, x = "wt", y = "mpg", #' color = "cyl", palette = "jco", #' add = "reg.line", conf.int = TRUE) #' sp + stat_cor(aes(color = cyl), label.x = 3) #' #'@export stat_cor <- function(mapping = NULL, data = NULL, method = "pearson", alternative = "two.sided", cor.coef.name = c("R", "rho", "tau"), label.sep = ", ", label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, output.type = "expression", digits = 2, r.digits = digits, p.digits = digits, r.accuracy = NULL, p.accuracy = NULL, geom = "text", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ...) { parse <- ifelse(output.type == "expression", TRUE, FALSE) cor.coef.name = cor.coef.name[1] layer( stat = StatCor, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(label.x.npc = label.x.npc , label.y.npc = label.y.npc, label.x = label.x, label.y = label.y, label.sep = label.sep, method = method, alternative = alternative, output.type = output.type, digits = digits, r.digits = r.digits, p.digits = p.digits, r.accuracy = r.accuracy, p.accuracy = p.accuracy, cor.coef.name = cor.coef.name, parse = parse, na.rm = na.rm, ...) ) } StatCor<- ggproto("StatCor", Stat, required_aes = c("x", "y"), default_aes = aes(hjust = ..hjust.., vjust = ..vjust..), compute_group = function(data, scales, method, alternative, label.x.npc, label.y.npc, label.x, label.y, label.sep, output.type, digits, r.digits, p.digits, r.accuracy, p.accuracy, cor.coef.name) { if (length(unique(data$x)) < 2) { # Not enough data to perform test return(data.frame()) } # Returns a data frame with estimate, p.value, label, method .test <- .cor_test( data$x, data$y, method = method, alternative = alternative, label.sep = label.sep, output.type = output.type, digits = digits, r.digits = r.digits, p.digits = p.digits, r.accuracy = r.accuracy, p.accuracy = p.accuracy, cor.coef.name = cor.coef.name ) # Returns a data frame with label: x, y, hjust, vjust .label.pms <- .label_params(data = data, scales = scales, label.x.npc = label.x.npc, label.y.npc = label.y.npc, label.x = label.x, label.y = label.y ) %>% mutate(hjust = 0) cbind(.test, .label.pms) } ) # Correlation test #:::::::::::::::::::::::::::::::::::::::: # Returns a data frame: estimatel|p.value|method|label .cor_test <- function(x, y, method = "pearson", alternative = "two.sided", label.sep = ", ", output.type = "expression", digits = 2, r.digits = digits, p.digits = digits, r.accuracy = NULL, p.accuracy = NULL, cor.coef.name = "R"){ # Overwritting digits by accuracy, if specified if(!is.null(p.accuracy)){ nb_decimal_places <- round(abs(log10(p.accuracy))) p.digits <- nb_decimal_places } if(!is.null(r.accuracy)){ nb_decimal_places <- round(abs(log10(r.accuracy))) r.digits <- nb_decimal_places } # Correlation analyses .cor <- suppressWarnings(stats::cor.test( x, y, method = method, alternative = alternative, use = "complete.obs" )) estimate <- p.value <- p <- r <- rr <- NULL z <- data.frame(estimate = .cor$estimate, p.value = .cor$p.value, method = method) %>% mutate( r = signif(estimate, r.digits), rr = signif(estimate^2, r.digits), p = signif(p.value, p.digits) ) # Defining p and r labels pval <- .cor$p.value z <- z %>% dplyr::mutate( r.label = get_corcoef_label( r, accuracy = r.accuracy, prefix = "R", cor.coef.name = cor.coef.name, type = output.type ), rr.label = get_corcoef_label( rr, accuracy = r.accuracy, prefix = "R2", cor.coef.name = cor.coef.name, type = output.type ), p.label = get_p_label( p, accuracy = p.accuracy, type = output.type ) ) # Defining correlation labels if(output.type == "expression"){ if(label.sep == "\n"){ # Line break at each comma cortxt <- paste0("atop(", z$r.label, ",", z$p.label, ")") } else{ label.sep <- trimws(label.sep) if(label.sep == "") label.sep <- "~" # Using "*" to avoid the space between the R2 value and comma else label.sep <- paste0("*`", label.sep, "`~") cortxt <- paste0(z$r.label, label.sep, z$p.label) } } else if (output.type %in% c("latex", "tex", "text")){ cortxt <- paste0(z$r.label, label.sep, z$p.label) } z$label <- cortxt z } # Formatting R and P ---------------------- get_p_label <- function(x, accuracy = 0.0001, type = "expression"){ if(is.null(accuracy)){ label <- ifelse(x < 2.2e-16, "p < 2.2e-16", paste0("p = ", x)) } else if (!(accuracy < 1)){ stop( "Accuracy should be < 1; For example use 0.01, 0.001, 0.0001, etc.", call. = FALSE ) } else{ label <- scales::pvalue(x, accuracy = accuracy, add_p = TRUE) # Add space before and after: = or < label <- gsub(pattern = "(=|<)", replacement = " \\1 ", x = label) } if(type == "expression"){ label <- gsub(pattern = "p = ", replacement = "italic(p)~`=`~", x = label, fixed = TRUE) label <- gsub(pattern = "p < ", replacement = "italic(p)~`<`~", x = label, fixed = TRUE) } label } # Prefix can be R or R^2. # cor.coef.name: R, rho, tau get_corcoef_label <- function(x, accuracy = 0.01, prefix = "R", cor.coef.name = "R", type = "expression"){ if(is.null(accuracy)){ label <- paste0(prefix, " = ", x) } else if(!(accuracy < 1)){ stop( "Accuracy should be < 1; For example use 0.01, 0.001, 0.0001, etc.", call. = FALSE ) } else{ nb_decimal_places <- round(abs(log10(accuracy))) label <- formatC(x, digits = nb_decimal_places, format = "f") label <- paste0(prefix, " = ", label) } if(type == "expression"){ label <- gsub(pattern = "R2 = ", replacement = "italic(R)^2~`=`~", x = label, fixed = TRUE) label <- gsub(pattern = "R = ", replacement = "italic(R)~`=`~", x = label, fixed = TRUE) } label <- gsub(pattern = "R", cor.coef.name, x = label, fixed = TRUE) label } ggpubr/R/theme_transparent.R0000644000176200001440000000221514332553655015622 0ustar liggesusers#' @include utilities.R #' @import ggplot2 NULL #'Create a ggplot with Transparent Background #' #'@description Create a ggplot with transparent background. #'@param base_size base font size #'@param base_family base font family #'@seealso \code{\link{theme_pubr}} #' @examples #'# Create a scatter plot #'sp <- ggscatter(iris, x = "Sepal.Length", y = "Sepal.Width", #' color = "Species", palette = "jco", #' size = 3, alpha = 0.6) #'sp #' #'# Transparent theme #'sp + theme_transparent() #' #'@export theme_transparent <- function (base_size = 12, base_family = "") { theme_classic(base_size = base_size, base_family = base_family) + theme( panel.background = element_rect(fill = "transparent", colour = NA), plot.background = element_rect(fill = "transparent", colour = NA), legend.background = element_rect(fill = "transparent", colour = NA), legend.box.background = element_rect(fill = "transparent", colour = NA), axis.line = element_blank(), axis.title = element_blank(), plot.title = element_blank(), axis.text = element_blank(), axis.ticks = element_blank() ) } ggpubr/R/utils-tidyr.R0000644000176200001440000000076414336762430014374 0ustar liggesusers# Transform data into long format-------------------- # Replacement of deprecated tidyr::gather_() # wrapper around tidyr::pivot_longer() but using `cols_vary = "slowest"` as default # instead of `cols_vary = "fastest"` df_gather <- function(data, cols, cols_vary = "slowest", names_to = "name", values_to = "value", ...){ data %>% tidyr::pivot_longer( cols = dplyr::all_of(cols), names_to = names_to, values_to = values_to, cols_vary = cols_vary, ... ) } ggpubr/R/text_grob.R0000644000176200001440000000306014332553655014073 0ustar liggesusers#' @include utilities.R NULL #' Create a Text Graphical object #' @description Create easily a customized text grob (graphical object). Wrapper around #' \code{\link[grid:grid.text]{textGrob}}. #' @inheritParams grid::grid.text #' @param color text font color. #' @param face font face. Allowed values include one of \code{"plain", "bold", #' "italic", "bold.italic"}. #' @param size font size (e.g.: size = 12) #' @param lineheight line height (e.g.: lineheight = 2). #' @param family font family. #' @param ... other arguments passed to \link[grid:grid.text]{textGrob}. #' @return a text grob. #' @examples #'text <- paste("iris data set gives the measurements in cm", #' "of the variables sepal length and width", #' "and petal length and width, respectively,", #' "for 50 flowers from each of 3 species of iris.", #' "The species are Iris setosa, versicolor, and virginica.", sep = "\n") #' #'# Create a text grob #'tgrob <- text_grob(text, face = "italic", color = "steelblue") #'# Draw the text #'as_ggplot(tgrob) #' #' @export text_grob <- function(label, just = "centre", hjust = NULL, vjust = NULL, rot = 0, color = "black", face = "plain", size = NULL, lineheight = NULL, family = NULL, ...) { gp <- grid::gpar(col = color, fontface = face, fontsize = size, lineheight = lineheight, fontfamily = family) tgrob <- grid::textGrob(label = label, just = just, hjust = hjust, vjust = vjust, rot = rot, gp = gp, ...) tgrob } ggpubr/R/utilities_color.R0000644000176200001440000001475714332553655015326 0ustar liggesusers .brewerpal <- function(){ c( # sequential 'Blues', 'BuGn', 'BuPu', 'GnBu', 'Greens', 'Greys', 'Oranges', 'OrRd', 'PuBu', 'PuBuGn', 'PuRd', 'Purples', 'RdPu', 'Reds', 'YlGn', 'YlGnBu YlOrBr', 'YlOrRd', #Divergent 'BrBG', 'PiYG', 'PRGn', 'PuOr', 'RdBu', 'RdGy', 'RdYlBu', 'RdYlGn', 'Spectral', # Qualitative 'Accent', 'Dark2', 'Paired', 'Pastel1', 'Pastel2', 'Set1', 'Set2', 'Set3' ) } .ggscipal <- function(){ # Scientific Journal and Sci-Fi Themed Color Palettes for ggplot2 # ggsci package: https://cran.r-project.org/web/packages/ggsci/vignettes/ggsci.html c("npg", "aaas", "nejm", "lancet", "jama", "jco", "ucscgb", "d3", "locuszoom", "igv", "uchicago", "startrek", "tron", "futurama", "rickandmorty", "simpsons") } # Check if color palette or default hue .is_col_palette <- function(pal){ if(is.null(pal)) return(FALSE) else return(length(pal)==1 & pal[1] %in% c(.brewerpal(), .ggscipal(), "default", "hue", "grey_pal", "gray_pal")) } .is_color_palette <- .is_col_palette # alias # Change color manually # possible value for palette: brewer palette, "grey" or a vector of colors .ggcolor <- function(palette = NULL, ...) { color_palette(palette = palette, ...) } # Change fill color manually # possible value for palette: brewer palette, "grey" or a vector of colors .ggfill <- function(palette = NULL, ...) { fill_palette(palette = palette, ...) } # Helper function to use palette from ggsci package # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% .scale_color_ggsci <- function(palette = c("npg", "aaas", "nejm", "lancet", "jama", "jco", "ucscgb", "d3", "locuszoom", "igv", "uchicago", "startrek", "tron", "futurama", "rickandmorty", "simpsons")) { pal <- match.arg(palette) functs <- list( npg = ggsci::scale_color_npg(), aaas = ggsci::scale_color_aaas(), nejm = ggsci::scale_color_nejm(), lancet = ggsci::scale_color_lancet(), jama = ggsci::scale_color_jama(), jco = ggsci::scale_color_jco(), ucscgb = ggsci::scale_color_ucscgb(), d3 = ggsci::scale_color_d3(), locuszoom = ggsci::scale_color_locuszoom(), igv = ggsci::scale_color_igv(), uchicago = ggsci::scale_color_uchicago(), startrek = ggsci::scale_color_startrek(), tron = ggsci::scale_color_tron(), futurama = ggsci::scale_color_futurama(), rickandmorty = ggsci::scale_color_rickandmorty(), simpsons = ggsci::scale_color_simpsons() ) functs[[pal]] } .scale_fill_ggsci <- function(palette = c("npg", "aaas", "nejm", "lancet", "jama", "jco", "ucscgb", "d3", "locuszoom", "igv", "uchicago", "startrek", "tron", "futurama", "rickandmorty", "simpsons")) { pal <- match.arg(palette) functs <- list( npg = ggsci::scale_fill_npg(), aaas = ggsci::scale_fill_aaas(), nejm = ggsci::scale_fill_nejm(), lancet = ggsci::scale_fill_lancet(), jama = ggsci::scale_fill_jama(), jco = ggsci::scale_fill_jco(), ucscgb = ggsci::scale_fill_ucscgb(), d3 = ggsci::scale_fill_d3(), locuszoom = ggsci::scale_fill_locuszoom(), igv = ggsci::scale_fill_igv(), uchicago = ggsci::scale_fill_uchicago(), startrek = ggsci::scale_fill_startrek(), tron = ggsci::scale_fill_tron(), futurama = ggsci::scale_fill_futurama(), rickandmorty = ggsci::scale_fill_rickandmorty(), simpsons = ggsci::scale_fill_simpsons() ) functs[[pal]] } # Generate color palette from ggsci or Rcolorbrewer #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # pal could be a brewer or ggsci palette .get_pal <- function(pal = "default", k){ if(pal %in% .brewerpal()) .get_brewer_pal(pal, k) else if(pal %in% .ggscipal()) .get_ggsci_pal(pal, k) else if(pal %in% c("default", "hue")){ hues <- seq(15, 375, length = k + 1) grDevices::hcl(h = hues, l = 65, c = 100, alpha = 1)[1:k] } } .get_palette <- .get_pal # alias # Generate color palette from ggsci # k the number of color .get_ggsci_pal <- function(palette = c("npg", "aaas", "nejm", "lancet", "jama", "jco", "ucscgb", "d3", "locuszoom", "igv", "uchicago", "startrek", "tron", "futurama", "rickandmorty", "simpsons"), k) { pal <- match.arg(palette) if(pal %in% c("npg", "aaas", "jco", "d3")) max_k <- 10 else if (pal %in% c("nejm")) max_k <- 8 else if (pal %in% c("jama", "locuszoom", "startrek", "tron")) max_k <- 7 else if (pal %in% c("igv")) max_k <- 51 else if (pal %in% c("lancet", "uchicago")) max_k <- 9 else if (pal %in% c("ucscgb")) max_k <- 26 else if (pal %in% c("futurama", "rickandmorty")) max_k <- 12 else if (pal %in% c("simpsons")) max_k <- 16 else stop("Don't support palette name: ", pal) functs <- list( npg = ggsci::pal_npg(), aaas = ggsci::pal_aaas(), nejm = ggsci::pal_nejm(), lancet = ggsci::pal_lancet(), jama = ggsci::pal_jama(), jco = ggsci::pal_jco(), ucscgb = ggsci::pal_ucscgb(), d3 = ggsci::pal_d3(), locuszoom = ggsci::pal_locuszoom(), igv = ggsci::pal_igv(), uchicago = ggsci::pal_uchicago(), startrek = ggsci::pal_startrek(), tron = ggsci::pal_tron(), futurama = ggsci::pal_futurama(), rickandmorty = ggsci::pal_rickandmorty(), simpsons = ggsci::pal_simpsons() ) if(k <= max_k) functs[[pal]](k) else grDevices::colorRampPalette(functs[[pal]](max_k))(k) } # Generate a color palette from brewer .get_brewer_pal <- function(palette, k){ if (!requireNamespace("RColorBrewer", quietly = TRUE)) { stop("RColorBrewer package needed. Please install it using install.packages('RColorBrewer').") } initial.k <- k k <- max(c(k, 3)) # Kshoud be at least 3 pal <- palette[1] sequential <- c('Blues', 'BuGn', 'BuPu', 'GnBu', 'Greens', 'Greys', 'Oranges', 'OrRd', 'PuBu', 'PuBuGn', 'PuRd', 'Purples', 'RdPu', 'Reds','YlGn', 'YlGnBu YlOrBr', 'YlOrRd') divergent <- c('BrBG', 'PiYG', 'PRGn', 'PuOr', 'RdBu', 'RdGy', 'RdYlBu', 'RdYlGn', 'Spectral') if(pal %in% sequential) max_k <- 9 else if(pal %in% divergent) max_k <- 11 else if(pal %in% c('Accent','Dark2','Pastel2', 'Set2')) max_k <- 8 else if(pal %in% c('Pastel1', 'Set1')) max_k <- 9 else if(pal %in% c('Paired', 'Set3')) max_k <- 12 else stop("Don't support palette name: ", pal) if(k <= max_k) { cols <- RColorBrewer::brewer.pal(k, palette) if(initial.k == 2) cols <- cols[c(1,3)] else if(initial.k == 1) cols <- cols[1] cols } else grDevices::colorRampPalette(RColorBrewer::brewer.pal(max_k, palette))(k) } # Set gradient colors # cols a vector of colors .gradient_col <- function (cols){ gradient_color(cols) } ggpubr/R/rotate_axis_text.R0000644000176200001440000000265314332553655015473 0ustar liggesusers#'Rotate Axes Text #' #'@description Rotate the x-axis text (tick mark labels). #'\itemize{ #'\item \code{rotate_x_text}(): Rotate x axis text. #'\item \code{rotate_y_text}(): Rotate y axis text. #'} #' #'@param angle numeric value specifying the rotation angle. Default is 90 for vertical x-axis text. #'@param hjust horizontal justification (in [0, 1]). #'@param vjust vertical justification (in [0, 1]). #'@param ... other arguments to pass to the function #' \code{\link[ggplot2:element]{element_text}()}. #' #'@examples #'# Load data #'data("ToothGrowth") #'df <- ToothGrowth #' #'# Basic plot #'p <- ggboxplot(df, x = "dose", y = "len") #'p #'# Vertical x axis text #'p + rotate_x_text() #'# Set rotation angle to 45 #'p + rotate_x_text(45) #'p + rotate_y_text(45) #' #'@name rotate_axis_text #'@rdname rotate_axis_text #'@export rotate_x_text <- function(angle = 90, hjust = NULL, vjust = NULL, ...){ if(missing(hjust) & angle > 5) hjust <- 1 if(missing(vjust) & angle == 90) vjust <- 0.5 theme( axis.text.x = element_text(angle = angle, hjust = hjust, vjust = vjust, ...) ) } #'@name rotate_axis_text #'@rdname rotate_axis_text #'@export rotate_y_text <- function(angle = 90, hjust = NULL, vjust = NULL, ...){ if(missing(hjust) & angle == 90) hjust <- 0.5 else if(missing(hjust) & angle > 5) hjust <- 1 theme( axis.text.y = element_text(angle = angle, hjust = hjust, vjust = vjust, ...) ) } ggpubr/R/as_ggplot.R0000644000176200001440000000267614343207173014062 0ustar liggesusers#' @include utilities.R NULL #'Storing grid.arrange() arrangeGrob() and plots #' #'@description Transform the output of #' \code{\link[gridExtra:arrangeGrob]{arrangeGrob}()} and #' \code{\link[gridExtra:arrangeGrob]{grid.arrange}()} to a an object of class #' ggplot. #'@param x an object of class gtable or grob as returned by the functions #' \code{\link[gridExtra:arrangeGrob]{arrangeGrob}()} and #' \code{\link[gridExtra:arrangeGrob]{grid.arrange}()}. #'@return an object of class ggplot. #' #' @examples #' # Creat some plots #'bxp <- ggboxplot(iris, x = "Species", y = "Sepal.Length") #'vp <- ggviolin(iris, x = "Species", y = "Sepal.Length", #' add = "mean_sd") #' #'# Arrange the plots in one page #'# Returns a gtable (grob) object #'library(gridExtra) #'gt <- arrangeGrob(bxp, vp, ncol = 2) #' #'# Transform to a ggplot and print #'as_ggplot(gt) #' #'@export as_ggplot <- function(x){ # Open null device to avoid blank page before plot------ # see cowplot:::as_grob.ggplot null_device <- base::getOption( "ggpubr.null_device", default = cowplot::pdf_null_device ) cur_dev <- grDevices::dev.cur() # Open null device to avoid blank page before plot null_device(width = 6, height = 6) null_dev <- grDevices::dev.cur() on.exit({ grDevices::dev.off(null_dev) if (cur_dev > 1) grDevices::dev.set(cur_dev) }) # Convert to ggplot------------- cowplot::ggdraw() + cowplot::draw_grob(grid::grobTree(x)) } ggpubr/R/get_breaks.R0000644000176200001440000000466414332553655014217 0ustar liggesusers#' Easy Break Creation for Numeric Axes #' #' @description Creates breaks for numeric axes to be used in the functions #' \code{\link[ggplot2:scale_continuous]{scale_x_continuous}()} and #' \code{\link[ggplot2:scale_continuous]{scale_y_continuous}()}. Can be used to increase the #' number of x and y ticks by specifying the option \code{n}. It's also #' possible to control axis breaks by specifying a step between ticks. For #' example, if \code{by = 5}, a tick mark is shown on every 5. #' @param n number of breaks. #' @param by number: the step between breaks. #' @param from the starting value of breaks. By default, 0 is used for positive #' variables #' @param to the end values of breaks. This corresponds generally to the maximum #' limit of the axis. #' @return a break function #' #' @examples #' #' # Generate 5 breaks for a variable x #' get_breaks(n = 5)(x = 1:100) #' #' # Generate breaks using an increasing step #' get_breaks(by = 10)(x = 1:100) #' #' # Combine with ggplot scale_xx functions #' library(ggplot2) #' #' # Create a basic plot #' p <- ggscatter(mtcars, x = "wt", y = "mpg") #' p #' #' # Increase the number of ticks #' p + #' scale_x_continuous(breaks = get_breaks(n = 10)) + #' scale_y_continuous(breaks = get_breaks(n = 10)) #' #' # Set ticks according to a specific step, starting from 0 #' p + scale_x_continuous( #' breaks = get_breaks(by = 1.5, from = 0), #' limits = c(0, 6) #' ) + #' scale_y_continuous( #' breaks = get_breaks(by = 10, from = 0), #' limits = c(0, 40) #' ) #' #' @export get_breaks <- function(n = NULL, by = NULL, from = NULL, to = NULL){ breaks <- ggplot2::waiver() if(!is.null(n)){ breaks <- get_breaks_number(n = n) } else if(is.numeric(by)){ breaks <- get_breaks_position(by = by, from = from, to = to) } breaks } # Set the number of breaks get_breaks_number <- function(n){ scales::breaks_extended(n = n) } # Set breaks using increasing step # Adapted from scales::breaks_extended get_breaks_position <- function(by, from = NULL, to = NULL){ by_default <- by from_default <- from to_default <- to function(x, by = by_default, from = from_default, to = to_default) { x <- x[is.finite(x)] if (length(x) == 0) { return(numeric()) } rng <- range(x) if( rng[1] > 0 & is.null(from)) from <- 0 xmin <- ifelse(is.null(from), floor(rng[1]), from) xmax <- ifelse(is.null(to), rng[2], to) seq(from = xmin, to = xmax, by = by) } } ggpubr/R/compare_means.R0000644000176200001440000003447214342652146014716 0ustar liggesusers#' @include utilities.R NULL #'Comparison of Means #'@description Performs one or multiple mean comparisons. #'@param formula a formula of the form \code{x ~ group} where \code{x} is a #' numeric variable giving the data values and \code{group} is a factor with #' one or multiple levels giving the corresponding groups. For example, #' \code{formula = TP53 ~ cancer_group}. #' #' It's also possible to perform the test for multiple response variables at #' the same time. For example, \code{formula = c(TP53, PTEN) ~ cancer_group}. #'@param data a data.frame containing the variables in the formula. #'@param method the type of test. Default is \link[stats]{wilcox.test}. Allowed #' values include: \itemize{ \item \code{\link[stats]{t.test}} (parametric) and #' \code{\link[stats]{wilcox.test}} (non-parametric). Perform comparison #' between two groups of samples. If the grouping variable contains more than #' two levels, then a pairwise comparison is performed. \item #' \code{\link[stats]{anova}} (parametric) and #' \code{\link[stats]{kruskal.test}} (non-parametric). Perform one-way ANOVA #' test comparing multiple groups. } #'@param paired a logical indicating whether you want a paired test. Used only #' in \code{\link[stats]{t.test}} and in \link[stats]{wilcox.test}. #'@param group.by a character vector containing the name of grouping variables. #'@param ref.group a character string specifying the reference group. If #' specified, for a given grouping variable, each of the group levels will be #' compared to the reference group (i.e. control group). #' #' \code{ref.group} can be also \code{".all."}. In this case, each of the #' grouping variable levels is compared to all (i.e. basemean). #'@param symnum.args a list of arguments to pass to the function #' \code{\link[stats]{symnum}} for symbolic number coding of p-values. For #' example, \code{symnum.args <- list(cutpoints = c(0, 0.0001, 0.001, #' 0.01, 0.05, Inf), symbols = c("****", "***", "**", "*", "ns"))}. #' #' In other words, we use the following convention for symbols indicating #' statistical significance: \itemize{ \item \code{ns}: p > 0.05 \item #' \code{*}: p <= 0.05 \item \code{**}: p <= 0.01 \item \code{***}: p <= 0.001 \item \code{****}: p <= 0.0001 } #'@param p.adjust.method method for adjusting p values (see #' \code{\link[stats]{p.adjust}}). Has impact only in a situation, where #' multiple pairwise tests are performed; or when there are multiple grouping #' variables. Allowed values include "holm", "hochberg", "hommel", #' "bonferroni", "BH", "BY", "fdr", "none". If you don't want to adjust the p #' value (not recommended), use p.adjust.method = "none". #' #' Note that, when the \code{formula} contains multiple variables, the p-value #' adjustment is done independently for each variable. #'@return return a data frame with the following columns: #'\itemize{ #'\item \code{.y.}: the y variable used in the test. #'\item \code{group1,group2}: the compared groups in the pairwise tests. #'Available only when \code{method = "t.test"} or \code{method = "wilcox.test"}. #'\item \code{p}: the p-value. #'\item \code{p.adj}: the adjusted p-value. Default for \code{p.adjust.method = "holm"}. #'\item \code{p.format}: the formatted p-value. #'\item \code{p.signif}: the significance level. #'\item \code{method}: the statistical test used to compare groups. #' #' #'} #'@param ... Other arguments to be passed to the test function. #' @examples #' # Load data #' #::::::::::::::::::::::::::::::::::::::: #' data("ToothGrowth") #' df <- ToothGrowth #' #' # One-sample test #' #::::::::::::::::::::::::::::::::::::::::: #' compare_means(len ~ 1, df, mu = 0) #' #' # Two-samples unpaired test #' #::::::::::::::::::::::::::::::::::::::::: #' compare_means(len ~ supp, df) #' #' # Two-samples paired test #' #::::::::::::::::::::::::::::::::::::::::: #' compare_means(len ~ supp, df, paired = TRUE) #' #' # Compare supp levels after grouping the data by "dose" #' #:::::::::::::::::::::::::::::::::::::::: #' compare_means(len ~ supp, df, group.by = "dose") #' #' # pairwise comparisons #' #:::::::::::::::::::::::::::::::::::::::: #' # As dose contains more thant two levels ==> #' # pairwise test is automatically performed. #' compare_means(len ~ dose, df) #' #' # Comparison against reference group #' #:::::::::::::::::::::::::::::::::::::::: #' compare_means(len ~ dose, df, ref.group = "0.5") #' #' # Comparison against all #' #:::::::::::::::::::::::::::::::::::::::: #' compare_means(len ~ dose, df, ref.group = ".all.") #' #' # Anova and kruskal.test #' #:::::::::::::::::::::::::::::::::::::::: #' compare_means(len ~ dose, df, method = "anova") #' compare_means(len ~ dose, df, method = "kruskal.test") #' @rdname compare_means #' @export compare_means <- function(formula, data, method = "wilcox.test", paired = FALSE, group.by = NULL, ref.group = NULL, symnum.args = list(), p.adjust.method = "holm", ...) { . <- NULL method.info <- .method_info(method) method <- method.info$method method.name <- method.info$name if(.is_empty(symnum.args)) symnum.args <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, 0.05, 1), symbols = c("****", "***", "**", "*", "ns")) if(!inherits(data, "data.frame")) stop("data must be a data.frame.") variables <- response.var <- .formula_left_variables(formula) group <- .formula_right_variables(formula) if(group == "1") group <- NULL # NULL model if(!.is_empty(group)){ group.vals <- .select_vec(data, group) if(!is.factor(group.vals)) data[[group]] <- factor(group.vals, levels = unique(group.vals)) } # Keep only variables of interest data <- data %>% df_select(vars = c(group.by, group, variables)) # Case of formula with multiple variables # 1. Gather the data # 2. group by variable # 3. Perform pairwise test between levels of each grouing variable #::::::::::::::::::::::::::::::::::::::::::::::::::::: # ex: formula = c(GATA3, XBP1, DEPDC1) ~ group if(.is_multi_formula(formula)){ data <- df_gather(data, cols = variables, names_to = ".y.", values_to = ".value.") %>% dplyr::mutate(.y. = factor(.data$.y., levels = unique(.data$.y.))) response.var <- ".value." group.by = c(group.by, ".y.") formula <- .collapse(response.var, group, sep = " ~ ") %>% stats::as.formula() } # Check if comparisons should be done against a reference group #::::::::::::::::::::::::::::::::::::::::::::::::::::: if(!is.null(ref.group)){ group.vals <- .select_vec(data, group) if(is.factor(group.vals)) group.levs <- levels(group.vals) else group.levs <- unique(group.vals) if(ref.group %in% group.levs){ data[[group]] <- stats::relevel(group.vals, ref.group) } if(ref.group == ".all."){ data <- data %>% mutate(.group. = as.character(group.vals), .all. = ".all.") # Add 'all' column # Create a new grouping column gathering group and the .all. columns .group.name. <- NULL data <- data %>% df_gather(cols = c(".group.", ".all."), names_to = ".group.name.", values_to = ".group.") %>% dplyr::select(-.group.name.) data[[".group."]] <- factor(data[[".group."]], levels = c(".all.", group.levs)) group <- ".group." formula <- .collapse(response.var, group, sep = " ~ ") %>% stats::as.formula() } else if(!(ref.group %in% group.levs)){ stop("Can't find specified reference group: ", ref.group, ". ", "Allowed values include one of: ", .collapse(group.levs, sep = ", "), call. = FALSE) } } # Peform the test #::::::::::::::::::::::::::::::::::::::::::::::::::::: test.func <- .test_pairwise if(method %in% c("anova", "kruskal.test")) test.func <- .test_multigroups if(is.null(group.by)){ res <- test.func(formula = formula, data = data, method = method, paired = paired, p.adjust.method = "none", ...) } else{ grouped.d <- .group_by(data, group.by) res <- grouped.d %>% mutate(p = purrr::map( data, test.func, formula = formula, method = method, paired = paired, p.adjust.method = "none",...) ) %>% df_select(vars = c(group.by, "p")) %>% unnest(cols = "p") } # Add response variables to the result #::::::::::::::::::::::::::::::::::::::::::::::::::::: if(!c(".y." %in% colnames(res))) res <- res %>% dplyr::mutate(.y. = variables) %>% dplyr::select(!!!syms(c(group.by, ".y.")), dplyr::everything()) # Select only reference groups if any #:::::::::::::::::::::::::::::::::::::::::::::::::::::::: if(!is.null(ref.group)){ group.levs <- .select_vec(data, group) %>% .levels() group1 <- NULL res <- res %>% dplyr::filter(group1 == ref.group | group2 == ref.group) # ref.group should be always in group1 column # swap group1 and group2 if group2 contains ref.group group2 <- res$group2 res <- transform(res, group1 = ifelse(group2 == ref.group, group2, group1), group2 = ifelse(group2 == ref.group, group1, group2)) } # Formatting and adjusting pvalues, and adding significance symbols #::::::::::::::::::::::::::::::::::::::::::::::::::::: symnum.args$x <- res$p pvalue.signif <- do.call(stats::symnum, symnum.args) %>% as.character() pvalue.format <- format.pval(res$p, digits = 2) .y. <- p.adj <- NULL .p.adjust <- function(d, ...) {data.frame(p.adj = stats::p.adjust(d$p, ...))} by_y <- res %>% group_by(.y.) pvalue.adj <- do(by_y, .p.adjust(., method = p.adjust.method)) res <- res %>% dplyr::ungroup() %>% mutate(p.adj = pvalue.adj$p.adj, p.format = pvalue.format, p.signif = pvalue.signif, method = method.name) res %>% mutate(p.adj = signif(p.adj, digits = 2)) %>% tibble::as_tibble() } # Check and get test method info #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # return a list(method, name) .method_info <- function(method){ if(is.null(method)) method = "wilcox.test" allowed.methods <- list( t = "t.test", t.test = "t.test", student = "t.test", wiloxon = "wilcox.test", wilcox = "wilcox.test", wilcox.test = "wilcox.test", anova = "anova", aov = "anova", kruskal = "kruskal.test", kruskal.test = "kruskal.test") method.names <- list( t.test = "T-test", wilcox.test = "Wilcoxon", anova = "Anova", kruskal.test = "Kruskal-Wallis") if(!(method %in% names(allowed.methods))) stop("Non-supported method specified. Allowed methods are one of: ", .collapse(allowed.methods, sep =", ")) method <- allowed.methods[[method]] method.name <- method.names[[method]] list(method = method, name = method.name) } # Comparing two groups #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .test <- function(data, formula, method = "t.test", ...) { test <- match.fun(method) x <- deparse(formula[[2]]) group <- attr(stats::terms(formula), "term.labels") if(.is_empty(group)) # Case of null model test.opts <- list(x = .select_vec(data, x), ...) else test.opts <- list(formula = formula, data = data, ...) res <- data.frame(p = suppressWarnings(do.call(test, test.opts)$p.value)) group1 <- group2 <- NULL if(!.is_empty(group)){ group.lev <- .select_vec(data, group) %>% levels() res <- res %>% dplyr::mutate( group1 = group.lev[1], group2 = group.lev[2] ) %>% dplyr::select(group1,group2, dplyr::everything()) } else res <- res %>% dplyr::mutate(group1 = 1, group2 = "null model") %>% dplyr::select(group1, group2, everything()) res } # pairwise test #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .test_pairwise <- function(data, formula, method = "wilcox.test", paired = FALSE, pool.sd = !paired, ...) { x <- deparse(formula[[2]]) group <- attr(stats::terms(formula), "term.labels") # One sample test if(.is_empty(group)){ res <- .test(data, formula, method = method, ...) return(res) } # Pairwise test method <- switch(method, t.test = "pairwise.t.test", wilcox.test = "pairwise.wilcox.test") test <- match.fun(method) test.opts <- list(x = .select_vec(data, x), g = .select_vec(data, group), paired = paired, ...) # if(method == "pairwise.wilcox.test") test.opts$exact <- FALSE if(method == "pairwise.t.test"){ if(missing(pool.sd)){ if(!paired) pool.sd <- FALSE } test.opts$pool.sd <- pool.sd } pvalues <- suppressWarnings(do.call(test, test.opts)$p.value) %>% as.data.frame() ..group1.. <- ..group2.. <- p <- NULL pvalues$..group2.. <- rownames(pvalues) pvalues <- pvalues %>% tidyr::gather(key = "..group1..", value = "p", -..group2..) %>% dplyr::select(group1 = ..group1.., group2 = ..group2.., p) %>% dplyr::filter(!is.na(p)) pvalues } # Compare multiple groups #:::::::::::::::::::::::::::::::::::::::::::::::::: .test_multigroups <- function(data, formula, method = c("anova", "kruskal.test"), ...){ method <- match.arg(method) . <- NULL if(method == "anova") pvalue <- stats::lm(formula, data = data) %>% stats::anova(.) %>% .$`Pr(>F)` %>% .[1] else if(method == "kruskal.test"){ pvalue <- stats::kruskal.test(formula, data = data)$p.value } data.frame(p = pvalue) } # Formula with multiple response variables #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # ex formula = c(GATA3, XBP1, DEPDC1) ~ group .is_multi_formula <- function(formula){ x <- grep(",", formula) !.is_empty(x) } # Get formula variables .formula_left_variables <- function(formula){ . <- NULL x <- deparse(formula[[2]]) %>% gsub("c\\(|\\)|\\s", "", .) %>% strsplit(",") %>% unlist() x } .formula_right_variables <- function(formula){ group <- attr(stats::terms(formula), "term.labels") if(.is_empty(group)) group <- "1" group } .update_test_arguments <- function(formula, data, group.by){ variables <- .formula_left_variables(formula) group <- .formula_right_variables(formula) data <- data %>% df_gather(cols = variables, names_to = ".y.", values_to = ".value.") %>% dplyr::mutate(.y. = factor(.data$.y., levels = unique(.data$.y.))) formula <- .collapse(".value.", group, sep = " ~ ") %>% stats::as.formula() group.by = c(group.by, ".y.") } ggpubr/R/ggdotplot.R0000644000176200001440000001371514342705267014110 0ustar liggesusers#' @include utilities.R ggpar.R NULL #' Dot plot #' @description Create a dot plot. #' @inheritParams ggboxplot #' @param binwidth numeric value specifying bin width. use value between 0 and 1 #' when you have a strong dense dotplot. For example binwidth = 0.2. #' @param ... other arguments to be passed to #' \code{\link[ggplot2]{geom_dotplot}}, \code{\link{ggpar}} and #' \code{\link{facet}}. #' @details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" \item plot orientation : orientation #' = c("vertical", "horizontal", "reverse") } #'@seealso \code{\link{ggpar}}, \code{\link{ggviolin}}, \code{\link{ggboxplot}} #' and \code{\link{ggstripchart}}. #' @examples #' # Load data #' data("ToothGrowth") #' df <- ToothGrowth #' #' # Basic plot with summary statistics : mean_sd #' # +++++++++++++++++++++++++++ #' ggdotplot(df, x = "dose", y = "len", #' add = "mean_sd") #' #' # Change error.plot to "crossbar" #' ggdotplot(df, x = "dose", y = "len", #' add = "mean_sd", add.params = list(width = 0.5), #' error.plot = "crossbar") #' #' #' # Add box plot #' ggdotplot(df, x = "dose", y = "len", #' add = "boxplot") #' #' # Add violin + mean_sd #' ggdotplot(df, x = "dose", y = "len", #' add = c("violin", "mean_sd")) #' #' #' # Change colors #' # +++++++++++++++++++++++++++ #' # Change fill and outline colors by groups: dose #' # Use custom color palette #' ggdotplot(df, "dose", "len", #' add = "boxplot", #' color = "dose", fill = "dose", #' palette = c("#00AFBB", "#E7B800", "#FC4E07")) #' #' #' # Plot with multiple groups #' # +++++++++++++++++++++ #' # Change color by a second group : "supp" #' ggdotplot(df, "dose", "len", fill = "supp", color = "supp", #' palette = c("#00AFBB", "#E7B800")) #' #' #' @export ggdotplot <- function(data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "lightgray", palette = NULL, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, size = NULL, binwidth = NULL, select = NULL, remove = NULL, order = NULL, add = "mean_se", add.params = list(), error.plot = "pointrange", label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, ggtheme = theme_pubr(), ...) { # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( combine = combine, merge = merge, color = color, fill = fill, palette = palette, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, size = size, binwidth = binwidth, select = select , remove = remove, order = order, add = add, add.params = add.params, error.plot = error.plot, label = label, font.label = font.label, label.select = label.select, repel = repel, label.rectangle = label.rectangle, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x if(!missing(y)) .opts$y <- y # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$fun <- ggdotplot_core if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggdotplot_core <- function(data, x, y, color = "black", fill = "lightgray", palette = NULL, title = NULL, xlab = NULL, ylab = NULL, size = NULL, dotsize = size, binwidth = NULL, add = "mean_se", add.params = list(), error.plot = "pointrange", position = position_dodge(0.8), ggtheme = theme_pubr(), ...) { if(!is.factor(data[[x]])) data[[x]] <- as.factor(data[[x]]) . <- NULL p <- ggplot(data, create_aes(list(x = x, y = y))) if("none" %in% add) add <- "none" if(is.null(add.params$fill)) add.params$fill <- "white" add.params <- .check_add.params(add, add.params, error.plot, data, color, fill, ...) # plot boxplot | violin | crossbar before jitter if( any( c("boxplot", "violin") %in% add)){ p <- add.params %>% .add_item(p = p, add = intersect(add, c("boxplot", "violin") )) %>% do.call(ggadd, .) } if(error.plot == "crossbar"){ p <- add.params %>% .add_item(p = p, error.plot = error.plot, add = setdiff(add, c("boxplot", "violin", "jitter"))) %>% do.call(ggadd, .) } # Plot jitter p <- p + geom_exec(geom_dotplot, data = data, binaxis = "y", stackdir = "center", color = color, fill = fill, position = position, stackratio = 1, dotsize = dotsize, binwidth = binwidth, ...) # Add errors if(error.plot == "crossbar"){} else p <- add.params %>% .add_item(p = p, error.plot = error.plot, add = setdiff(add, c("boxplot", "violin", "jitter"))) %>% do.call(ggadd, .) p <- ggpar(p, palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab,...) p } ggpubr/R/geom_bracket.R0000644000176200001440000004030314332553655014521 0ustar liggesusers#' @include utilities.R NULL StatBracket <- ggplot2::ggproto("StatBracket", ggplot2::Stat, required_aes = c("x", "y", "group"), setup_params = function(data, params) { if(length(params$tip.length) == 1) params$tip.length <- rep(params$tip.length, max(length(params$xmin), 1) * 2) if(length(params$tip.length) == length(params$xmin)) params$tip.length <- rep(params$tip.length, each=2) return(params) }, compute_group = function(data, scales, tip.length) { yrange <- scales$y$range$range y.scale.range <- yrange[2] - yrange[1] bracket.shorten <- data$bracket.shorten/2 xmin <- data$xmin + bracket.shorten xmax <- data$xmax - bracket.shorten y.position <- data$y.position + (y.scale.range*data$step.increase) + data$bracket.nudge.y label <- data$label if(is.character(xmin)){ xmin <- scales$x$map(xmin) } if(is.character(xmax)){ xmax <- scales$x$map(xmax) } if("tip.length" %in% colnames(data)){ tip.length <- rep(data$tip.length, each=2) } # Preparing bracket data data <- dplyr::bind_rows(data, data, data) data$x <- c(xmin, xmin, xmax) data$xend = c(xmin, xmax, xmax) data$y <- c(y.position - y.scale.range*tip.length[seq_len(length(tip.length))%% 2 == 1], y.position, y.position) data$yend <- c(y.position, y.position, y.position-y.scale.range*tip.length[seq_len(length(tip.length))%% 2 == 0]) data$annotation <- rep(label, 3) data } ) #' Add Brackets with Labels to a GGPlot #' @description add brackets with label annotation to a ggplot. Helpers for #' adding p-value or significance levels to a plot. #' @param label character vector with alternative label, if not null test is #' ignored #' @param type the label type. Can be one of "text" and "expression" (for #' parsing plotmath expression). #' @param xmin numeric vector with the positions of the left sides of the #' brackets #' @param xmax numeric vector with the positions of the right sides of the #' brackets #' @param y.position numeric vector with the y positions of the brackets #' @param size change the width of the lines of the bracket #' @param label.size change the size of the label text #' @param family change the font used for the text #' @param vjust move the text up or down relative to the bracket #' @param step.increase numeric vector with the increase in fraction of total #' height for every additional comparison to minimize overlap. #' @param bracket.nudge.y Vertical adjustment to nudge brackets by. Useful to #' move up or move down the bracket. If positive value, brackets will be moved #' up; if negative value, brackets are moved down. #' @param bracket.shorten a small numeric value in [0-1] for shortening the with #' of bracket. #' @param step.group.by a variable name for grouping brackets before adding #' step.increase. Useful to group bracket by facet panel. #' @param tip.length numeric vector with the fraction of total height that the #' bar goes down to indicate the precise column #' @param na.rm If \code{FALSE} (the default), removes missing values with a #' warning. If \code{TRUE} silently removes missing values. #' @param coord.flip logical. If \code{TRUE}, flip x and y coordinates so that #' horizontal becomes vertical, and vertical, horizontal. When adding the #' p-values to a horizontal ggplot (generated using #' \code{\link[ggplot2]{coord_flip}()}), you need to specify the option #' \code{coord.flip = TRUE}. #' @param ... other arguments passed on to \code{\link{layer}}. These are often #' aesthetics, used to set an aesthetic to a fixed value, like \code{color = #' "red"} or \code{size = 3}. They may also be parameters to the paired #' geom/stat. #' @inheritParams ggplot2::layer #' @examples #' df <- ToothGrowth #' df$dose <- factor(df$dose) #' #' # Add bracket with labels #' ggboxplot(df, x = "dose", y = "len") + #' geom_bracket( #' xmin = "0.5", xmax = "1", y.position = 30, #' label = "t-test, p < 0.05" #' ) #' #' # Customize bracket tip.length tip.length #' ggboxplot(df, x = "dose", y = "len") + #' geom_bracket( #' xmin = "0.5", xmax = "1", y.position = 30, #' label = "t-test, p < 0.05", tip.length = c(0.2, 0.02) #' ) #' #' #Using plotmath expression #' ggboxplot(df, x = "dose", y = "len") + #' geom_bracket( #' xmin = "0.5", xmax = "1", y.position = 30, #' label = "list(~italic(p)<=0.001)", type = "expression", #' tip.length = c(0.2, 0.02) #' ) #' #' # Specify multiple brackets manually #' ggboxplot(df, x = "dose", y = "len") + #' geom_bracket( #' xmin = c("0.5", "1"), xmax = c("1", "2"), #' y.position = c(30, 35), label = c("***", "**"), #' tip.length = 0.01 #' ) #' #' # Compute statistical tests and add p-values #' stat.test <- compare_means(len ~ dose, ToothGrowth, method = "t.test") #' ggboxplot(df, x = "dose", y = "len") + #' geom_bracket( #' aes(xmin = group1, xmax = group2, label = signif(p, 2)), #' data = stat.test, y.position = 35 #' ) #' #' # Increase step length between brackets #' ggboxplot(df, x = "dose", y = "len") + #' geom_bracket( #' aes(xmin = group1, xmax = group2, label = signif(p, 2)), #' data = stat.test, y.position = 35, step.increase = 0.1 #' ) #' #' # Or specify the positions of each comparison #' ggboxplot(df, x = "dose", y = "len") + #' geom_bracket( #' aes(xmin = group1, xmax = group2, label = signif(p, 2)), #' data = stat.test, y.position = c(32, 35, 38) #' ) #' @rdname geom_bracket #' @export stat_bracket <- function(mapping = NULL, data = NULL, position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, label = NULL, type = c("text", "expression"), y.position=NULL, xmin = NULL, xmax = NULL, step.increase = 0, step.group.by = NULL, tip.length = 0.03, bracket.nudge.y = 0, bracket.shorten = 0, size = 0.3, label.size = 3.88, family="", vjust = 0, ...) { if(! is.null(data) & ! is.null(mapping)){ if(! "x" %in% names(data)) mapping$x <- 1 if(! "y" %in% names(data)) mapping$y <- 1 } type <- match.arg(type) ggplot2::layer( stat = StatBracket, data = data, mapping = mapping, geom = "bracket", position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list( label=label, type = type, y.position=y.position,xmin=xmin, xmax=xmax, step.increase=step.increase, bracket.nudge.y = bracket.nudge.y, bracket.shorten = bracket.shorten, step.group.by = step.group.by, tip.length=tip.length, size=size, label.size=label.size, family=family, vjust=vjust, na.rm = na.rm, ...) ) } GeomBracket <- ggplot2::ggproto("GeomBracket", ggplot2::Geom, required_aes = c("x", "xend", "y", "yend", "annotation"), default_aes = ggplot2::aes( shape = 19, colour = "black", label.size = 3.88, angle = NULL, hjust = 0.5, vjust = 0, alpha = NA, family = "", fontface = 1, lineheight = 1.2, linetype=1, size = 0.3, xmin = NULL, xmax = NULL, label = NULL, y.position = NULL, step.increase = 0, bracket.nudge.y = 0, bracket.shorten = 0 # Added to avoid aesthetics warning ), # draw_key = function(...){grid::nullGrob()}, # for legend: draw_key = draw_key_path, draw_group = function(data, panel_params, coord, type = "text", coord.flip = FALSE) { lab <- as.character(data$annotation) if(type == "expression"){ lab <- parse_as_expression(lab) } coords <- coord$transform(data, panel_params) label.x <- mean(c(coords$x[1], tail(coords$xend, n=1))) label.y <- max(c(coords$y, coords$yend))+0.01 label.angle <- coords$angle if(coord.flip){ label.y <- mean(c(coords$y[1], tail(coords$yend, n=1))) label.x <- max(c(coords$x, coords$xend))+0.01 if(is.null(label.angle)) label.angle <- -90 } if(is.null(label.angle)) label.angle <- 0 grid::gList( grid::textGrob( label = lab, x = label.x, y = label.y, default.units = "native", hjust = coords$hjust, vjust = coords$vjust, rot = label.angle, gp = grid::gpar( col = scales::alpha(coords$colour, coords$alpha), fontsize = coords$label.size * ggplot2::.pt, fontfamily = coords$family, fontface = coords$fontface, lineheight = coords$lineheight ) ), grid::segmentsGrob( coords$x, coords$y, default.units = "native", coords$xend, coords$yend, gp = grid::gpar( col = scales::alpha(coords$colour, coords$alpha), lty = coords$linetype, lwd = coords$size * ggplot2::.pt ) ) ) } ) #' @rdname geom_bracket #' @export geom_bracket <- function(mapping = NULL, data = NULL, stat = "bracket", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, label = NULL, type = c("text", "expression"), y.position = NULL, xmin = NULL, xmax = NULL, step.increase = 0, step.group.by = NULL, tip.length = 0.03, bracket.nudge.y = 0, bracket.shorten = 0, size = 0.3, label.size = 3.88, family="", vjust = 0, coord.flip = FALSE, ...) { type <- match.arg(type) data <- build_signif_data( data = data, label = label, y.position = y.position, xmin = xmin, xmax = xmax, step.increase = step.increase, bracket.nudge.y = bracket.nudge.y, bracket.shorten = bracket.shorten, step.group.by = step.group.by, vjust = vjust ) mapping <- build_signif_mapping(mapping, data) ggplot2::layer( stat = stat, geom = GeomBracket, mapping = mapping, data = data, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list( type = type, tip.length = tip.length, size = size, label.size = label.size, family = family, na.rm = na.rm, coord.flip = coord.flip, ... ) ) } # Guess column to be used as significance labem guess_signif_label_column <- function(data){ potential.label <- c( "label", "labels", "p.adj.signif", "p.adj", "padj", "p.signif", "p.value", "pval", "p.val", "p" ) res <- intersect(potential.label, colnames(data)) if(length(res) > 0){ res <- res[1] } else{ stop("label is missing") } res } build_signif_data <- function(data = NULL, label = NULL, y.position = NULL, xmin = NULL, xmax = NULL, step.increase = 0, bracket.nudge.y = 0, bracket.shorten = 0, step.group.by = NULL, vjust = 0){ add_step_increase <- function(data, step.increase){ comparisons.number <- 0:(nrow(data)-1) step.increase <- step.increase*comparisons.number data <- data %>% mutate(step.increase = !!step.increase) data } if(is.null(data)){ data <- data.frame( label = label, y.position = y.position, xmin = xmin, xmax = xmax ) %>% mutate(vjust = !!vjust) } else{ if(!is.null(label)) data <- data %>% mutate(label = !!label) if(!is.null(y.position)) data <- data %>% mutate(y.position = !!y.position) if(!is.null(xmin)) data <- data %>% mutate(xmin = !!xmin) if(!is.null(xmax)) data <- data %>% mutate(xmax = !!xmax) if(!identical(vjust, 0)) data <- data %>% mutate(vjust = !!vjust) } # add vjust column if doesn't exist if(!("vjust" %in% colnames(data))) data <- data %>% mutate(vjust = !!vjust) if(!("bracket.nudge.y" %in% colnames(data))) data <- data %>% mutate(bracket.nudge.y = !!bracket.nudge.y) if(!("bracket.shorten" %in% colnames(data))) data <- data %>% mutate(bracket.shorten= !!bracket.shorten) if(is.null(step.group.by)){ data <- data %>% add_step_increase(step.increase) } else{ data <- data %>% dplyr::arrange(!!!syms(c(step.group.by, "y.position"))) %>% group_by(!!!syms(step.group.by)) %>% tidyr::nest() %>% dplyr::mutate(step.increase = purrr::map(data, add_step_increase, !!step.increase)) %>% dplyr::select(-data) %>% unnest(cols = "step.increase") } data } build_signif_mapping <- function(mapping, data){ if(is.null(mapping)){ # Check if required variables are present in data required.vars <- c("xmin", "xmax", "y.position") missing.required.vars <- setdiff(required.vars, colnames(data)) if(length(missing.required.vars) > 0){ stop( "Required variables are missing in the data: ", paste(missing.required.vars, collapse = ", ") ) } mapping <- ggplot2::aes() } if(is.null(mapping$label)){ label.col <- guess_signif_label_column(data) data$label <- data %>% dplyr::pull(!!label.col) mapping$label <- data$label } if(is.null(mapping$xmin)) mapping$xmin <- data$xmin if(is.null(mapping$xmax)) mapping$xmax <- data$xmax if(is.null(mapping$y.position)) mapping$y.position <- data$y.position if(is.null(mapping$group)) mapping$group <- 1:nrow(data) if(is.null(mapping$step.increase)) mapping$step.increase <- data$step.increase if(is.null(mapping$vjust)) mapping$vjust <- data$vjust if(is.null(mapping$bracket.nudge.y)) mapping$bracket.nudge.y <- data$bracket.nudge.y if(is.null(mapping$bracket.shorten)) mapping$bracket.shorten <- data$bracket.shorten if(! "x" %in% names(mapping)){ mapping$x <- mapping$xmin } if(! "y" %in% names(mapping)){ mapping$y <- mapping$y.position } mapping } # Source: https://github.com/tidyverse/ggplot2/issues/2864 parse_as_expression <- function(text) { stopifnot(is.character(text)) out <- vector("expression", length(text)) for (i in seq_along(text)) { expr <- parse(text = text[[i]]) out[[i]] <- if (length(expr) == 0) NA else expr[[1]] } out } ggpubr/R/utils-aes.R0000644000176200001440000000031214332576562014003 0ustar liggesusers# Extract group name from mapping, aes aes_get_group <- function(mapping){ group <- NULL if(!is.null(mapping)){ if(!is.null(mapping$group)) group <- rlang::as_label(mapping$group) } group } ggpubr/R/ggdotchart.R0000644000176200001440000002311314342704672014223 0ustar liggesusers#' @include utilities.R ggpar.R stat_chull.R stat_conf_ellipse.R NULL #' Cleveland's Dot Plots #' @description Draw a Cleveland dot plot. #' @inheritParams ggboxplot #' @inheritParams ggpar #' @param data a data frame #' @param x,y x and y variables for drawing. #' @param color,size points color and size. #' @param dot.size numeric value specifying the dot size. #' @param shape point shape. See \code{\link{show_point_shapes}}. #' @param label the name of the column containing point labels. #' @param group an optional column name indicating how the elements of x are #' grouped. #' @param sorting a character vector for sorting into ascending or descending #' order. Allowed values are one of "descending", "ascending" and "none". Partial #' match are allowed (e.g. sorting = "desc" or "asc"). Default is #' "descending". #' @param x.text.col logical. If TRUE (default), x axis texts are colored by #' groups. #' @param position Position adjustment, either as a string, or the result of a #' call to a position adjustment function. #' @param ... other arguments to be passed to \code{\link[ggplot2]{geom_point}} #' and \code{\link{ggpar}}. #' @details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" \item plot orientation : orientation #' = c("vertical", "horizontal", "reverse") } #' @seealso \code{\link{ggpar}} #' @examples #' # Load data #' data("mtcars") #' df <- mtcars #' df$cyl <- as.factor(df$cyl) #' df$name <- rownames(df) #' head(df[, c("wt", "mpg", "cyl")], 3) #' #' # Basic plot #' ggdotchart(df, x = "name", y ="mpg", #' ggtheme = theme_bw()) #' #' # Change colors by group cyl #' ggdotchart(df, x = "name", y = "mpg", #' group = "cyl", color = "cyl", #' palette = c('#999999','#E69F00','#56B4E9'), #' rotate = TRUE, #' sorting = "descending", #' ggtheme = theme_bw(), #' y.text.col = TRUE ) #' #' #'# Plot with multiple groups #'# +++++++++++++++++++++ #'# Create some data #'df2 <- data.frame(supp=rep(c("VC", "OJ"), each=3), #' dose=rep(c("D0.5", "D1", "D2"),2), #' len=c(6.8, 15, 33, 4.2, 10, 29.5)) #'print(df2) #' #'ggdotchart(df2, x = "dose", y = "len", #' color = "supp", size = 3, #' add = "segment", #' add.params = list(color = "lightgray", size = 1.5), #' position = position_dodge(0.3), #' palette = "jco", #' ggtheme = theme_pubclean() #') #' #' #' @export ggdotchart <- function(data, x, y, group = NULL, combine = FALSE, color = "black", palette = NULL, shape = 19, size = NULL, dot.size = size, sorting = c("ascending", "descending", "none"), add = c("none", "segment"), add.params = list(), x.text.col = TRUE, rotate = FALSE, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, select = NULL, remove = NULL, order = NULL, label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, position = "identity", ggtheme = theme_pubr(), ...){ # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( data = data, x = x, y = y, group = group, combine = combine, color = color, palette = palette, shape = shape, size = size, dot.size = dot.size, sorting = sorting, x.text.col = x.text.col, rotate = rotate, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, select = select , remove = remove, order = order, add = add, add.params = add.params, label = label, font.label = font.label, label.select = label.select, repel = repel, label.rectangle = label.rectangle, position = position, ggtheme = ggtheme, ...) # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$fun <- ggdotchart_core .opts$fun_name <- "ggdotchart" if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggdotchart_core <- function(data, x, y, group = NULL, color = "black", palette = NULL, shape = 19, size = NULL, dot.size = size, sorting = c("ascending", "descending", "none"), add = c("none", "segments"), add.params = list(), x.text.col = FALSE, rotate = FALSE, title = NULL, xlab = NULL, ylab = NULL, ggtheme = theme_bw(), position = "identity", ...) { add <- match.arg(add) if(!is.null(group)){ if(group == 1) group <- NULL } # if(is.null(group) & color[1] %in% names(data)){ # group <- color[1] # } .dots <- list(...) sorting <- match.arg(sorting) decreasing <- ifelse(sorting == "descending", FALSE, TRUE) x.text.angle <- ifelse(rotate, 0, 90) if(!is.null(.dots$y.text.col)) x.text.col <- .dots$y.text.col data <- as.data.frame(data) label <- .select_vec(data, x) . <- NULL if(rotate & sorting == "descending") sorting <- "ascending" else if(rotate & sorting == "ascending") sorting <- "descending" if(sorting != "none"){ if(is.null(group)){ if(sorting == "descending") data <- arrange(data, desc(!!sym(y))) else if(sorting == "ascending") data <- arrange(data, !!sym(y)) } else if(group != 1){ if(sorting == "descending") data <- arrange(data, !!sym(group), desc(!!sym(y))) else if(sorting == "ascending") data <- arrange(data, !!!syms(c(group, y))) } data[[x]] <- factor(data[[x]], levels = unique(as.vector(data[[x]]))) } if(!is.factor(data[[x]])) data[[x]] <- as.factor(data[[x]]) p <- ggplot(data, create_aes(list(x = x, y = y))) if(add == "segments"){ seg.opts <- geom_exec(data = data, color = color, size = size, position = position) mapping <- seg.opts$mapping %>% .add_item(x = x, ymin = 0, ymax = y, group = group) option <- seg.opts$option # mapping <- seg.opts$mapping %>% # .add_item(y = 0, x = x, yend = y, xend = x) # option <- seg.opts$option seg.col <- "lightgray" if(!is.null(add.params$color)) seg.col <- add.params$color else if(!is.null(add.params$colour)) seg.col <- add.params$colour if(seg.col %in% names(data)) mapping$color <- seg.col else option$color <- seg.col if(!is.null(add.params$size)) option$size <- add.params$size # if(!is.null(add.params$color)) # option$color <- add.params$color # else if(!is.null(add.params$colour)) # option$color <- add.params$colour # if(!is.null(add.params$size)) # option$size <- add.params$size option[["mapping"]] <- create_aes(mapping) p <- p + do.call(geom_linerange, option) } p <- p + geom_exec(geom_point, data = data, shape = shape, color = color, size = dot.size, position = position) p <- ggpar(p, palette = palette, ggtheme = ggtheme, x.text.angle = x.text.angle, title = title, xlab = xlab, ylab = ylab, ...) # Change x axis text colors if(x.text.col){ if(!rotate) p <- .set_x_text_col(p, label, x.text.angle) else p <- .set_y_text_col(p, label, x.text.angle) } if(x.text.angle == 90 & !rotate){ p <- p + theme(axis.text.x = element_text(vjust = 0.5)) } if(rotate) p <- p + coord_flip() p } # Set x text color .set_x_text_col <- function(p, label, angle){ g <- ggplot2::ggplot_build(p) cols <- unlist(g$data[[1]]["colour"]) names(cols) <- as.vector(label) # Give every color an appropriate name p + theme(axis.text.x = element_text(colour = cols, angle = angle, hjust = 1)) } # Set y text color .set_y_text_col <- function(p, label, angle){ g <- ggplot2::ggplot_build(p) cols <- unlist(g$data[[1]]["colour"]) names(cols) <- as.vector(label) # Give every color an appropriate name p + theme(axis.text.y = element_text(colour = cols)) } # Helper functions # +++++++++++++++++++++++++ #' @export #' @rdname ggdotchart theme_cleveland <- function(rotate = TRUE){ if(rotate){ theme(panel.grid.major.x = element_blank(), panel.grid.minor.x = element_blank(), panel.grid.major.y = element_line(colour = "grey70", linetype = "dashed"), axis.title.y = element_blank(), axis.ticks.y = element_blank()) } else{ theme(panel.grid.major.x = element_line(colour = "grey70", linetype = "dashed"), panel.grid.major.y = element_blank(), panel.grid.minor.y = element_blank(), axis.title.x = element_blank(), axis.ticks.x = element_blank()) } } ggpubr/R/utilities.R0000644000176200001440000007162314370060226014110 0ustar liggesusers#' @include desc_statby.R utilities_base.R utilities_color.R NULL #' @import ggplot2 #' @importFrom magrittr %>% #' @importFrom rstatix df_group_by df_nest_by df_select df_arrange #' @importFrom tibble as_tibble #' @importFrom dplyr group_by mutate mutate_if group_nest arrange desc #' @importFrom purrr map2 map #' @importFrom tidyr unite #' @importFrom dplyr do select distinct #' @importFrom dplyr summarise #' @importFrom dplyr everything #' @importFrom grid drawDetails #' @importFrom rlang !! #' @importFrom rlang !!! #' @importFrom rlang syms .data required_package <- function(pkg){ if (!requireNamespace(pkg, quietly = TRUE)) { stop( pkg, " package needed to be installed before using this function. ", "Type this in R: install.packages('", pkg, "')" ) } } # Unnesting, adapt to tidyr 1.0.0 unnest <- function(data, cols = "data", ...){ if(is_pkg_version_sup("tidyr", "0.8.3")){ results <- tidyr::unnest(data, cols = cols, ...) } else {results <- tidyr::unnest(data, ...)} results } # Check if an installed package version is superior to a specified version # Version, pkg: character vector is_pkg_version_sup<- function(pkg, version){ vv <- as.character(utils::packageVersion(pkg)) cc <- utils::compareVersion(vv, version) > 0 cc } keep_only_tbl_df_classes <- function(x){ toremove <- setdiff(class(x), c("tbl_df", "tbl", "data.frame")) if(length(toremove) > 0){ class(x) <- setdiff(class(x), toremove) } x } #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # Execute a geom_* function from ggplot2 #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # geomfunc : gem_*() functions # data data for mapping # ... argument accepeted by the function # return a plot if geomfunc!=Null or a list(option, mapping) if geomfunc = NULL .geom_exec <- function (geomfunc = NULL, data = NULL, position = NULL, ...) { geom_exec(geomfunc = geomfunc, data = data, position = position, ...) } # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # Official argument from ggplot2 # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # bar plot arguments .barplot_params <- function(...){ x <- list(...) res <- list() res$width <- x$width res$binwidth <- x$binwidth res$na.rm <- ifelse(!is.null(x$na.rm), x$na.rm, FALSE) res$show.legend <- ifelse(!is.null(x$show.legend), x$show.legend, NA) res$inherit.aes <- ifelse(!is.null(x$inherit.aes), x$inherit.aes, TRUE) return(res) } # box plot arguments .boxplot_params <- function(...){ x <- list(...) res <- list() res$outlier.colour <- x$outlier.colour res$outlier.shape <- ifelse(!is.null(x$outlier.shape), x$outlier.shape, 19) res$outlier.size <- ifelse(!is.null(x$outlier.size), x$outlier.size, 1.5) res$outlier.stroke <- ifelse(!is.null(x$outlier.stroke), x$outlier.stroke, 0.5) res$notch <- ifelse(!is.null(x$notch), x$notch, FALSE) res$notchwidth <- ifelse(!is.null(x$notchwidth), x$notchwidth, 0.5) res$varwidth <- ifelse(!is.null(x$varwidth), x$varwidth, FALSE) res$na.rm <- ifelse(!is.null(x$na.rm), x$na.rm, FALSE) res$show.legend <- ifelse(!is.null(x$show.legend), x$show.legend, NA) res$inherit.aes <- ifelse(!is.null(x$inherit.aes), x$inherit.aes, TRUE) return(res) } .dotplot_params <- function(...){ x <- list(...) res <- list() res$stackratio <- ifelse(!is.null(x$stackratio ), x$stackratio, 1) res$width <- ifelse(!is.null(x$width), x$width, 0.9) return(res) } .violin_params <- function(...){ x <- list(...) res <- list() res$stat <- ifelse(!is.null(x$stat ), x$stat, "ydensity") res$draw_quantiles <- x$draw_quantiles res$scale <- ifelse(!is.null(x$scale), x$scale, "area") res$trim <- ifelse(!is.null(x$trim), x$trim, TRUE) return(res) } .hist_params <- function(...){ x <- list(...) res <- list() res$binwidth <- x$binwidth res$bins <- x$bins return(res) } .standard_params <- function(...){ x <- list(...) res <- list() res$color <- ifelse(!is.null(x$color), x$color, "black") res$color <- ifelse(!is.null(x$colour), x$colour, res$color) res$linetype <- ifelse(!is.null(x$linetype), x$linetype, "solid") res$size <- ifelse(!is.null(x$size), x$size, 1) res$fill <- ifelse(!is.null(x$fill), x$fill, "black") res$shape <- ifelse(!is.null(x$shape), x$shape, 19) res } #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # Graphical parameters #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # Set plot orientation # %%%%%%%%%%%%%%%%%%%%%%%%%%%%% .set_orientation <- function(p, orientation = c("vertical", "horizontal", "reverse")) { ori <- match.arg(orientation) if (ori == "horizontal") p + coord_flip() else if (ori == "reverse") p + scale_y_reverse() else p } # Change title and labels # %%%%%%%%%%%%%%%%%%%%%%%%%%%%% .labs <- function(p, main = NULL, xlab = NULL, ylab = NULL, font.main = NULL, font.x = NULL, font.y = NULL, submain = NULL, caption = NULL, font.submain = NULL, font.caption = NULL) { font.main <- .parse_font(font.main) font.x <- .parse_font(font.x) font.y <- .parse_font(font.y) font.submain <- .parse_font(font.submain) font.caption <- .parse_font(font.caption) if(is.logical(main)){ if(!main) main <- NULL } if(is.logical(submain)){ if(!submain) submain <- NULL } if(is.logical(caption)){ if(!caption) caption <- NULL } if (!is.null(main)) { p <- p + labs(title = main) } if (!is.null(submain)) { p <- p + labs(subtitle = submain) } if (!is.null(caption)) { p <- p + labs(caption = caption) } if (!is.null(xlab)) { if (xlab == FALSE) p <- p + theme(axis.title.x = element_blank()) else p <- p + labs(x = xlab) } if (!is.null(ylab)) { if (ylab == FALSE) p <- p + theme(axis.title.y = element_blank()) else p <- p + labs(y = ylab) } if (!is.null(font.main)) p <- p + theme( plot.title = element_text( size = font.main$size, lineheight = 1.0, face = font.main$face, colour = font.main$color ) ) if (!is.null(font.submain)) p <- p + theme( plot.subtitle = element_text( size = font.submain$size, lineheight = 1.0, face = font.submain$face, colour = font.submain$color ) ) if (!is.null(font.caption)) p <- p + theme( plot.caption = element_text( size = font.caption$size, lineheight = 1.0, face = font.caption$face, colour = font.caption$color ) ) if (!is.null(font.x)) p <- p + theme(axis.title.x = element_text( size = font.x$size, face = font.x$face, colour = font.x$color )) if (!is.null(font.y)) p <- p + theme(axis.title.y = element_text( size = font.y$size, face = font.y$face, colour = font.y$color )) p } # ticks # %%%%%%%%%%%%%%%%%%%%%%%%%%%%% .set_ticks <- function(ticks = TRUE, tickslab = TRUE, font.tickslab = NULL, xtickslab.rt = NULL, ytickslab.rt = NULL, font.xtickslab = font.tickslab, font.ytickslab = font.tickslab) { . <- xhjust <- xvjust <- NULL if(!is.null(xtickslab.rt)) { if(xtickslab.rt > 5) xhjust <- 1 if(xtickslab.rt == 90) xvjust <- 0.5 } else xhjust <- NULL if (ticks) ticks <- element_line(colour = "black") else ticks <- element_blank() if (is.null(font.xtickslab)) font.x <- list() else font.x <- .parse_font(font.xtickslab) if (is.null(font.ytickslab)) font.y <- list() else font.y <- .parse_font(font.ytickslab) if (tickslab) { xtickslab <- font.x %>% .add_item(hjust = xhjust, vjust = xvjust, angle = xtickslab.rt) %>% do.call(element_text, .) ytickslab <- font.y %>% .add_item(angle = ytickslab.rt) %>% do.call(element_text, .) } else { xtickslab <- element_blank() ytickslab <- element_blank() } theme( axis.ticks = ticks, axis.text.x = xtickslab, axis.text.y = ytickslab ) } # Change Axis limits # %%%%%%%%%%%%%%%%%%%%%%%%%%%%% .set_axis_limits <- function(xlim = NULL, ylim = NULL){ if(!is.null(xlim) | !is.null(ylim)) coord_cartesian(xlim, ylim) } # Axis scales # %%%%%%%%%%%%%%%%%%%%%%%%%%%%% .set_scale <- function (p, xscale = c("none", "log2", "log10", "sqrt"), yscale = c("none", "log2", "log10", "sqrt"), format.scale = FALSE) { xscale <- match.arg(xscale) yscale <- match.arg(yscale) .x <- ".x" if(format.scale){ if(!requireNamespace("scales")) stop("The R package 'scales' is required.") if(yscale == "log2"){ p <- p + scale_y_continuous(trans = scales::log2_trans(), breaks = scales::trans_breaks("log2", function(x) 2^x), labels = scales::trans_format("log2", scales::math_format(2^.x))) } else if(yscale == "log10"){ p <- p + scale_y_continuous(trans = scales::log10_trans(), breaks = scales::trans_breaks("log10", function(x) 10^x), labels = scales::trans_format("log10", scales::math_format(10^.x))) } if(xscale == "log2"){ p <- p + scale_x_continuous(trans = scales::log2_trans(), breaks = scales::trans_breaks("log2", function(x) 2^x), labels = scales::trans_format("log2", scales::math_format(2^.x))) } else if(xscale == "log10"){ p <- p + scale_x_continuous(trans = scales::log10_trans(), breaks = scales::trans_breaks("log10", function(x) 10^x), labels = scales::trans_format("log10", scales::math_format(10^.x))) } } else{ if(xscale != "none") p <- p + scale_x_continuous(trans = xscale) if(yscale != "none") p <- p + scale_y_continuous(trans = yscale) } p } # Legends # %%%%%%%%%%%%%%%%%%%%%%%%%%%%% .set_legend <- function(p, legend = NULL, legend.title = NULL, font.legend = NULL) { if(is.null(legend.title)) legend.title = waiver() font <- .parse_font(font.legend) if(!is.null(legend)) p <- p + theme(legend.position = legend) if(!.is_empty(legend.title)){ if(.is_list(legend.title)) p <- p + do.call(ggplot2::labs, legend.title) else p <- p + labs(color = legend.title, fill = legend.title, linetype = legend.title, shape = legend.title) } if(!is.null(font)){ p <- p + theme( legend.text = element_text(size = font$size, face = font$face, colour = font$color), legend.title = element_text(size = font$size, face = font$face, colour = font$color) ) } p } # Set ticks by # %%%%%%%%%%%%%%%%%%%%%%%%%%%%% .set_ticksby <- function(p, xticks.by = NULL, yticks.by = NULL) { if(!is.null(yticks.by)) { # Forcing ymin to start at 0 when distribution plot gg_mapping <- .get_gg_xy_variables(p) is_density_plot <- gg_mapping["y"] %in% c("..count..", "..density..", "..ecdf..") ymin <- NULL if(is_density_plot) ymin <- 0 p <- p + scale_y_continuous(breaks = get_breaks(by = yticks.by, from = ymin)) } else if(!is.null(xticks.by)) { p <- p + scale_x_continuous(breaks = get_breaks(by = xticks.by)) } p } # %%%%%%%%%%%%%%%%%%%%%%%%%%%%% # Add stat # %%%%%%%%%%%%%%%%%%%%%%%%%%%%% .check_add.params <- function(add, add.params, error.plot, data, color, fill, ...){ if(color %in% names(data) & is.null(add.params$color)) add.params$color <- color if(fill %in% names(data) & is.null(add.params$fill)) add.params$fill <- fill if(is.null(add.params$color)) add.params$color <- color if(is.null(add.params$fill) & ("crossbar" %in% error.plot | "boxplot" %in% add | "violin" %in% add)) add.params$fill <- fill if(is.null(add.params$fill)) add.params$fill <- add.params$color #else add.params$fill <- add.params$color if(!is.null(list(...)$shape) & is.null(add.params$shape)) add.params$shape <- list(...)$shape add.params } # Calculate the mean and the SD in each group #+++++++++++++++++++++++++ # data : a data frame # varname : the name of the variable to be summariezed # grps : column names to be used as grouping variables # .mean_sd <- function(data, varname, grps){ # summary_func <- function(x, col){ # c(mean = base::mean(x[[col]], na.rm=TRUE), # sd = stats::sd(x[[col]], na.rm=TRUE)) # } # data_sum <- plyr::ddply(data, grps, .fun=summary_func, varname) # data_sum$ymin <- data_sum$mean-data_sum$sd # data_sum$ymax <- data_sum$mean+data_sum$sd # names(data_sum)[ncol(data_sum)-3] <- varname # # data_sum <- plyr::rename(data_sum, c("mean" = varname)) # return(data_sum) # } # Summary functions .summary_functions <- function(){ c("mean", "mean_se", "mean_se_", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", "median_hilow_", "median_q1q3", "median_mad", "median_range") } .errorbar_functions <- function(){ setdiff(.summary_functions(), c("mean", "median")) } # parse font # %%%%%%%%%%%%%%%%%%%%%%%%%%%%% .parse_font <- function(font){ if(is.null(font)) res <- NULL else if(inherits(font, "list")) res <- font else{ # matching size and face size <- grep("^[0-9]+$", font, perl = TRUE) face <- grep("plain|bold|italic|bold.italic", font, perl = TRUE) if(length(size) == 0) size <- NULL else size <- as.numeric(font[size]) if(length(face) == 0) face <- NULL else face <- font[face] color <- setdiff(font, c(size, face)) if(length(color) == 0) color <- NULL res <- list(size=size, face = face, color = color) } res } # Add annotation to a plot # label: text to be added to a plot # size: text size # coord: x and coordinates .ggannotate <- function (label, size = 12, coord = c(NULL, NULL)){ if(is.null(unique(coord))){ grob <- grid::grobTree(grid::textGrob(label, x = 0.3, y = 0.80, hjust=0, gp = grid::gpar(col = "black", fontsize = size, fontface = "plain"))) ggplot2::annotation_custom(grob) } else{ ggplot2::annotate("text", x = coord[1], y = coord[2], label = label, size = size/3) } } #::::::::::::::::::::::::::::::::::::::::: # Check the data provided by user #::::::::::::::::::::::::::::::::::::::::: # combine: if TRUE, gather y variables # return a list(data, x, y) .check_data <- function(data, x, y, combine = FALSE) { if(missing(x) & missing(y)){ if(!is.numeric(data)) stop("x and y are missing. In this case data should be a numeric vector.") else{ data <- data.frame(y = data, x = rep(1, length(data))) x <- "x" y <- "y" } } else if(missing(x)) { x <- "x" if(is.numeric(data)) data <- data.frame(x = data) else data$x <- rep("1", nrow(data)) } # A list of y elements to plot else if(length(y) > 1){ if(!all(y %in% colnames(data))){ not_found <- setdiff(y , colnames(data)) y <- intersect(y, colnames(data)) if(.is_empty(y)) stop("Can't find the y elements in the data.") else if(!.is_empty(not_found)) warning("Can't find the following element in the data: ", .collapse(not_found)) } } if(inherits(data, c("tbl_df", "tbl"))) data <- as.data.frame(data) # Combining y variables #...................................................... if(is.null(y)) y <- "" if(combine & length(y) > 1){ data <- data %>% df_gather(cols = y, names_to = ".y.", values_to = ".value.") %>% dplyr::mutate(.y. = factor(.data$.y., levels = unique(.data$.y.))) y <- ".value." } # Combining x variables: Case of density plot or histograms #...................................................... else if(combine & length(x) > 1 & y[1] %in% c("..density..", "..count..", "..ecdf..", "..qq..")){ data <- data %>% df_gather(cols = x, names_to = ".y.", values_to = ".value.") %>% dplyr::mutate(.y. = factor(.data$.y., levels = unique(.data$.y.))) x <- ".value." } # If not factor, x elements on the plot should # appear in the same order as in the data if(is.character(data[[x]])) data[[x]] <- factor(data[[x]], levels = unique(data[[x]])) y <- unique(y) names(y) <- y x <- unique(x) names(x) <- x if(y[1] %in% c("..density..", "..count..", "..ecdf..", "..qq..")) list(x = x, data = data, y = y) # The name of plots are x variables else list(y = y, data = data, x = x) # The name of plots will be y variables } # Adjust shape when ngroups > 6, to avoid ggplot warnings .scale_point_shape <- function(p, data, shape){ if(shape %in% colnames(data)){ grp <- data[[shape]] if(!inherits(grp, "factor")) grp <- as.factor(grp) ngroups <- length(levels(data[[shape]])) if(ngroups > 6) p <- p + scale_shape_manual(values=1:ngroups, labels = levels(data[[shape]])) } p } # Get not numeric columns in a data.frame .get_not_numeric_vars <- function(data_frame){ is_numeric <- sapply(data_frame, is.numeric) if(sum(!is_numeric) == 0) res = NULL else res <- colnames(data_frame[, !is_numeric, drop = FALSE]) res } # Get the current color used in ggplot .get_ggplot_ncolors <- function(p){ g <- ggplot_build(p) gdata <- g$data[[1]] cols <- fills <- 1 if("colour" %in% names(gdata)) cols <- unique(unlist(gdata["colour"])) if("fills" %in% names(gdata)) fills <- unique(unlist(gdata["fill"])) max(length(cols), length(fills)) } # Check if character string is a valid color representation .is_color <- function(x) { sapply(x, function(X) { tryCatch(is.matrix(grDevices::col2rgb(X)), error = function(e) FALSE) }) } # Collapse one or two vectors #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .collapse <- function(x, y = NULL, sep = "."){ if(missing(y)) paste(x, collapse = sep) else if(is.null(x) & is.null(y)) return(NULL) else if(is.null(x)) return (as.character(y)) else if(is.null(y)) return(as.character(x)) else paste0(x, sep, y) } # Check if en object is empty #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .is_empty <- function(x){ length(x) == 0 } # Remove NULL items in a vector or list # # x a vector or list .compact <- function(x){Filter(Negate(is.null), x)} # Check if is a list #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .is_list <- function(x){ inherits(x, "list") } # Returns the levels of a factor variable #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .levels <- function(x){ if(!is.factor(x)) x <- as.factor(x) levels(x) } # Remove items from a list #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .remove_item <- function(.list, items){ for(item in items) .list[[item]] <- NULL .list } # Additems in a list #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .add_item <- function(.list, ...){ pms <- list(...) for(pms.names in names(pms)){ .list[[pms.names]] <- pms[[pms.names]] } .list } # Select a colun as vector from tiblle data frame .select_vec <- function(df, column){ dplyr::pull(df, column) } # Select the top up or down rows of a data frame sorted by variables #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # - df: data frame # - x: x axis variables (grouping variables) # - y: y axis variables (sorting variables) # - n the number of rows # - grps: other grouping variables .top_up <- function(df, x, y, n, grouping.vars = NULL){ . <- NULL grouping.vars <- c(x, grouping.vars) %>% unique() df %>% df_arrange(vars = c(grouping.vars, y)) %>% df_group_by(vars = grouping.vars) %>% do(utils::tail(., n)) } .top_down <- function(df, x, y, n, grouping.vars = NULL){ . <- NULL grouping.vars <- c(x, grouping.vars) %>% unique() df %>% df_arrange(vars = c(grouping.vars, y)) %>% df_group_by(vars = grouping.vars) %>% do(utils::head(., n)) } #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Apply ggpubr functions on a data #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # fun: function, can be ggboxplot, ggdotplot, ggstripchart, ... .plotter <- function(fun, data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "white", title = NULL, xlab = NULL, ylab = NULL, legend = NULL, legend.title = NULL, facet.by = NULL, select = NULL, remove = NULL, order = NULL, add = "none", add.params = list(), label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, font.family = "", parse = FALSE, ggtheme = theme_pubr(), fun_name = "", group = 1, # used only by ggline show.legend.text = NA, ...) { if(is.logical(merge)){ if(merge) merge = "asis" else merge = "none" } if(combine & merge != "none") stop("You should use either combine = TRUE or merge = TRUE, but not both together.") font.label <- .parse_font(font.label) if(is.null(label) & fun_name == "barplot") label <- FALSE .lab <- label if(fun_name != "barplot") .lab <- NULL if(!missing(x) & !missing(y)){ if(length(y) == 1 & length(x) == 1){ combine <- FALSE merge <- "none" } } # Check data #::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # - returns a list of updated main options: # list(y, data, x) opts <- .check_data(data, x, y, combine = combine | merge != "none") data <- opts$data x <- opts$x y <- opts$y is_density_plot <- y[1] %in% c("..count..", "..density..", "..ecdf..", "..qq..") if(combine) facet.by <- ".y." # Faceting by y variables if(merge != "none"){ if(!is_density_plot) facet.by <- NULL if(is.null(legend.title)) legend.title <- "" # remove .y. in the legend } # Updating parameters after merging #::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Special case for density and histograms: # x are variables and y is ..count.. or ..density.. # after merging ggpubr add a new column .y. which hold x variables # User might want to color by x variables as follow color = ".x." and # he aren't aware that the column is ".y." --> so we should translate this (see from line 1055) user.add.color <- add.params$color geom.text.position <- "identity" if(merge == "asis" ){ .grouping.var <- ".y." # y variables become grouping variable } else if(merge == "flip"){ .grouping.var <- opts$x # x variable becomes grouping variable opts$x <- ".y." # y variables become x tick labels if(is.null(xlab)) xlab <- FALSE } if(merge == "asis" | merge == "flip"){ if(is_density_plot){ color <- ifelse(color == ".x.", ".y.", color) fill <- ifelse(fill == ".x.", ".y.", fill) } if(any(c(color, fill) %in% names(data))){ add.params$color <- font.label$color <- ifelse(color %in% names(data), color, fill) } else if(!all(c(color, fill) %in% names(data))){ color <- add.params$color <- font.label$color <- .grouping.var #fill <- "white" } group <- .grouping.var geom.text.position <- position_dodge(0.8) } if(!combine & merge == "none" & length(opts$y) > 1 & is.null(title)) title <- opts$y if(!combine & merge == "none" & is.null(title)){ if(length(opts$y) > 1) title <- opts$y else if (length(opts$x) > 1 & is_density_plot) # case of density plot title <- opts$x } # Item to display x <- opts$data[[opts$x]] %>% as.vector() if(!is.null(select)) opts$data <- subset(opts$data, x %in% select) if(!is.null(remove)) opts$data <- subset(opts$data, !(x %in% remove)) if(!is.null(order)) opts$data[[opts$x]] <- factor(opts$data[[opts$x]], levels = order) # Add additional options, which can be potentially vectorized # when multiple plots opts <- opts %>% c(list(title = title, xlab = xlab, ylab = ylab)) %>% .compact() data <- opts$data opts$data <- list(opts$data) if(fun_name %in% c("ggline", "ggdotchart")) opts$group <- group # Plotting #:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Apply function to each y variables p <- purrr::pmap(opts, fun, color = color, fill = fill, legend = legend, legend.title = legend.title, ggtheme = ggtheme, facet.by = facet.by, add = add, add.params = add.params , # group = group, # for line plot user.add.color = user.add.color, label = .lab, # used only in ggbarplot font.label = font.label, repel = repel, label.rectangle = label.rectangle, ...) # Faceting if(!is.null(facet.by)) p <-purrr::map(p, facet, facet.by = facet.by, ...) # Add labels if(!is.null(label) & fun_name != "barplot"){ if(is.logical(label)){ if(label) label <- opts$y } grouping.vars <- intersect(c(facet.by, color, fill), colnames(data)) label.opts <- font.label %>% .add_item(data = data, x = opts$x, y = opts$y, label = label, label.select = label.select, repel = repel, label.rectangle = label.rectangle, family = font.family, parse = parse, ggtheme = NULL, grouping.vars = grouping.vars, facet.by = facet.by, position = geom.text.position, show.legend = show.legend.text) p <- purrr::map(p, function(p, label.opts){ . <- NULL label.opts %>% .add_item(ggp = p) %>% do.call(ggtext, .) }, label.opts ) } # Take into account the legend argument, when the main plot has no legend and ggtext has legend p <-purrr::map(p, ggpar, legend = legend, legend.title = legend.title) if(.is_list(p) & length(p) == 1) p <- p[[1]] p } # get the geometry of the first layer #::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .geom <- function(p, .layer = 1){ . <- NULL if(is.null(p) | .is_empty(p$layers)) return("") class(p$layers[[.layer]]$geom)[1] %>% tolower() %>% gsub("geom", "", .) } # Get the mapping variables of the first layer #::::::::::::::::::::::::::::::::::::::::::::::::: .mapping <- function(p){ if(is.null(p)) return(list()) . <- NULL layer0.mapping <- as.character(p$mapping) %>% gsub("~", "", .) layer0.mapping.labels <- p$mapping %>% names() names(layer0.mapping) <- layer0.mapping.labels layer1.mapping <- NULL if(!.is_empty(p$layers)){ layer1.mapping <- p$layers[[1]]$mapping %>% as.character() %>% gsub("~", "", .) layer1.mapping.labels <- p$layers[[1]]$mapping %>% names() names(layer1.mapping) <- layer1.mapping.labels } c(layer0.mapping, layer1.mapping) %>% as.list() } # Call geom_exec function to update a plot #::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .update_plot <- function(opts, p){ p + do.call(geom_exec, opts) } # Get ggplot2 x and y variable # :::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .get_gg_xy_variables <- function(p){ . <- NULL x <- p$mapping['x'] %>% as.character() %>% gsub("~", "", .) y <- p$mapping['y'] %>% as.character() %>% gsub("~", "", .) xy <- c(x, y) names(xy) <- c("x", "y") return(xy) } # Add mean or median line # used by ggdensity and gghistogram #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # p: main plot # data: data frame # x: measure variables # add: center to add # grouping.vars: grouping variables .add_center_line <- function(p, add = c("none", "mean", "median"), grouping.vars = NULL, color = "black", linetype = "dashed", size = NULL) { add <- match.arg(add) data <- p$data # x <- .mapping(p)$x .mapping <- .get_gg_xy_variables(p) x <- .mapping["x"] if(!(add %in% c("mean", "median"))) return(p) compute_center <- switch(add, mean = mean, median = stats::median) # NO grouping variable if(.is_empty(grouping.vars)) { m <- ifelse(add == "mean", mean(data[[x]], na.rm = TRUE), stats::median(data[[x]], na.rm = TRUE)) p <- p + geom_exec(geom_vline, data = data, xintercept = m, color = color, linetype = linetype, size = size) } # Case of grouping variable else { data_sum <- data %>% group_by(!!!syms(grouping.vars)) %>% summarise(.center = compute_center(!!sym(x), na.rm = TRUE)) p <- p + geom_exec(geom_vline, data = data_sum, xintercept = ".center", color = color, linetype = linetype, size = size) } p } # Check legend argument .check_legend <- function(legend){ allowed.values <- c("top", "bottom", "left", "right", "none") if(is.null(legend) | is.numeric(legend)) return(legend) else if(is.logical(legend)){ if(legend) legend <- "top" else legend <- "none" } else if(is.character(legend)){ legend <- legend[1] if(!legend %in% allowed.values) stop("Argument legend should be one of ", .collapse(allowed.values, sep = ", ")) } return (legend) } ggpubr/R/annotate_figure.R0000644000176200001440000000577014344267673015267 0ustar liggesusers#' @include utilities.R NULL #'Annotate Arranged Figure #' #'@description Annotate figures including: i) ggplots, ii) arranged ggplots from #' \code{\link{ggarrange}()}, \code{\link[gridExtra:arrangeGrob]{grid.arrange}()} and #' \code{\link[cowplot]{plot_grid}()}. #'@param p (arranged) ggplots. #'@param top,bottom,left,right optional string, or grob. #'@param fig.lab figure label (e.g.: "Figure 1"). #'@param fig.lab.pos position of the figure label, can be one of "top.left", #' "top", "top.right", "bottom.left", "bottom", "bottom.right". Default is #' "top.left". #'@param fig.lab.size optional size of the figure label. #'@param fig.lab.face optional font face of the figure label. Allowed values #' include: "plain", "bold", "italic", "bold.italic". #'@author Alboukadel Kassambara \email{alboukadel.kassambara@@gmail.com} #'@seealso \code{\link{ggarrange}()} #' @examples #' data("ToothGrowth") #' df <- ToothGrowth #' df$dose <- as.factor(df$dose) #' #' # Create some plots #' # :::::::::::::::::::::::::::::::::::::::::::::::::: #' # Box plot #' bxp <- ggboxplot(df, x = "dose", y = "len", #' color = "dose", palette = "jco") #' # Dot plot #' dp <- ggdotplot(df, x = "dose", y = "len", #' color = "dose", palette = "jco") #' # Density plot #' dens <- ggdensity(df, x = "len", fill = "dose", palette = "jco") #' #' # Arrange and annotate #' # :::::::::::::::::::::::::::::::::::::::::::::::::: #' figure <- ggarrange(bxp, dp, dens, ncol = 2, nrow = 2) #'annotate_figure(figure, #' top = text_grob("Visualizing Tooth Growth", color = "red", face = "bold", size = 14), #' bottom = text_grob("Data source: \n ToothGrowth data set", color = "blue", #' hjust = 1, x = 1, face = "italic", size = 10), #' left = text_grob("Figure arranged using ggpubr", color = "green", rot = 90), #' right = text_grob(bquote("Superscript: ("*kg~NH[3]~ha^-1~yr^-1*")"), rot = 90), #' fig.lab = "Figure 1", fig.lab.face = "bold" #') #' #' #'@export annotate_figure <- function(p, top = NULL, bottom = NULL, left = NULL, right = NULL, fig.lab = NULL, fig.lab.pos = c("top.left", "top", "top.right", "bottom.left", "bottom", "bottom.right"), fig.lab.size, fig.lab.face ) { fig.lab.pos <- match.arg(fig.lab.pos) annot.args <- list(top = top, bottom = bottom, left = left,right = right) %>% .compact() lab.args <- list(label = fig.lab, position = fig.lab.pos) %>% .compact() if(!missing(fig.lab.size)) lab.args$size <- fig.lab.size if(!missing(fig.lab.face)) lab.args$fontface <- fig.lab.face if(!.is_empty(annot.args)){ p <- gridExtra::arrangeGrob(p, top = top, bottom = bottom, left = left,right = right) %>% as_ggplot() } if(!is.null(fig.lab)){ p <- cowplot::ggdraw(p) + do.call(cowplot::draw_figure_label, lab.args) } p } ggpubr/R/bgcolor.R0000644000176200001440000000074714332553655013536 0ustar liggesusers#'Change ggplot Panel Background Color #' #' @description Change ggplot panel background color. #' @param color background color. #' #' @seealso \link{border}(). #' #'@examples #'# Load data #'data("ToothGrowth") #'df <- ToothGrowth #' #'# Basic plot #'p <- ggboxplot(df, x = "dose", y = "len") #'p #' #'# Change panel background color #' p + #' bgcolor("#BFD5E3")+ #' border("#BFD5E3") #'@export bgcolor <- function(color){ theme(panel.background = element_rect(fill = color)) } ggpubr/R/utilities_label.R0000644000176200001440000001064314332553655015255 0ustar liggesusers#:::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Helper function for adding annotation to a ggplot #:::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Get label parameters for each group #::::::::::::::::::::::::::::::::::::::::::::::::::::::::: # Returns a data frame with x, y, hjust, vjust # group.id is the index position of the group in a boxplot for example .label_params <- function(data, scales, label.x.npc = "left", label.y.npc = "right", label.x = NULL, label.y = NULL, .by = c("group", "panel"), group.id = NULL, ...) { .by <- match.arg(.by) # Check label coordinates for each group #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: if(is.null(group.id)) group.id <- group.id <- abs(data$group[1]) label.x.npc <- .group_coord(label.x.npc, group.id) label.y.npc <- .group_coord(label.y.npc, group.id) label.x <- .group_coord(label.x, group.id) label.y <- .group_coord(label.y, group.id) .check_npc_coord(label.x.npc, axis = "x") .check_npc_coord(label.y.npc, axis = "y") if (length(label.x) > 0) { x <- label.x hjust <- 0.5 } else if (length(label.x.npc) > 0) { if (is.numeric(label.x.npc)) { x <- scales$x$dimension()[1] + label.x.npc * diff(scales$x$dimension()) hjust <- 0.5 } else if (is.character(label.x.npc)) { if (label.x.npc == "right") { x <- scales$x$dimension()[2] hjust <- 1 } else if (label.x.npc %in% c("center", "centre", "middle")) { x <- mean(scales$x$dimension()) hjust <- 0.5 } else if (label.x.npc == "left") { x <- scales$x$dimension()[1] hjust <- 0 } } } if (length(label.y) > 0) { y <- label.y vjust <- 0.5 } else if (length(label.y.npc) > 0) { if (is.numeric(label.y.npc)) { y <- scales$y$dimension()[1] + label.y.npc * diff(scales$y$dimension()) vjust <- 1.4 * group.id - (0.7 * length(group.id)) } else if (is.character(label.y.npc)) { if (label.y.npc == "bottom") { y <- scales$y$dimension()[1] vjust <- -1.4 * group.id } else if (label.y.npc %in% c("center", "centre", "middle")) { y <- mean(scales$y$dimension()) vjust <- 1.4 * group.id - (0.7 * length(group.id)) } else if (label.y.npc == "top") { y <- scales$y$dimension()[2] vjust <- 1.4 * group.id } } } if(.by == "panel"){ hjust <- 0.5 vjust = 0.5 } data.frame(x = x, y = y, hjust = hjust, vjust = vjust) } # Get label parameters by group # Useful in boxplot, where group.ids is the index of the group: 1, 2, 3, etc # Useful only when computation is done by panel .label_params_by_group <- function(..., group.ids){ purrr::map(group.ids, function(group.id, ...){.label_params(..., group.id = group.id)}, ...) %>% dplyr::bind_rows() #%>% #dplyr::mutate(x = group.ids) } # Check label coordinates for each group #::::::::::::::::::::::::::::::::::::::::: # coord.values: label coordinate for each group. If too short, they are recycled. # group.id the id of groups as returned by ggplot_build() .group_coord <- function(coord.values, group.id){ if(!.is_empty(coord.values)){ coord.values <- ifelse(length(coord.values) >= group.id, coord.values[group.id], coord.values[1]) } coord.values } # Check NPC coord #::::::::::::::::::::::::::::::::::::::::: # npc: Normalised Parent Coordinates. # The origin of the viewport is (0, 0) and the viewport has a width and height of 1 unit. # For example, (0.5, 0.5) is the centre of the viewport. # coord: should be between 0 and 1 # axis: should be "x" or "y" .check_npc_coord <- function(.coord, axis = c("x", "y")){ axis <- match.arg(axis) if(axis == "x") allowed.values <- c('right', 'left', 'center', 'centre', 'middle') else if(axis == "y") allowed.values <- c( 'bottom', 'top', 'center', 'centre', 'middle') .message <- paste0("'*.npc coord for ", axis, " axis should be either a numeric value in [0-1] ", "or a character strings including one of ", .collapse(allowed.values, sep = ", ")) if(!is.null(.coord)){ if(is.numeric(.coord)){ if (any(.coord < 0 | .coord > 1)) { stop(.message) } } else if(is.character(.coord)){ if(!(.coord %in% allowed.values)) stop(.message) } else stop(.message) } } ggpubr/R/ggscatterhist.R0000644000176200001440000002350214344271270014745 0ustar liggesusers#' @include utilities.R NULL #'Scatter Plot with Marginal Histograms #'@description Create a scatter plot with marginal histograms, density plots or #' box plots. #'@inheritParams ggscatter #'@param main.plot.size the width of the main plot. Default is 2. #'@param margin.plot.size the width of the marginal plot. Default is 1. #'@param group a grouping variable. Change points color and shape by groups if #' the options \code{color} and \code{shape} are missing. Should be also #' specified when you want to create a marginal box plot that is grouped. #'@param margin.plot the type of the marginal plot. Default is "hist". #'@param margin.params parameters to be applied to the marginal plots. #'@param margin.ggtheme the theme of the marginal plot. Default is #' \code{\link[ggplot2:ggtheme]{theme_void}()}. #'@param margin.space logical value. If TRUE, adds space between the main plot #' and the marginal plot. #'@param bins Number of histogram bins. Defaults to 30. Pick a better value that #' fit to your data. #'@param linetype line type ("solid", "dashed", ...) #'@param legend specify the legend position. Allowed values include: "top", #' "bottom", "left", "right". #'@param ggtheme the theme to be used for the scatter plot. Default is #' \code{\link{theme_pubr}()}. #'@param print logical value. If \code{TRUE} (default), print the plot. #'@param ... other arguments passed to the function \code{\link{ggscatter}()}. #'@return an object of class \code{ggscatterhist}, which is list of ggplots, #' including the following elements: \itemize{\item sp: main scatter plot; #' \item xplot: marginal x-axis plot; \item yplot: marginal y-axis plot. }. #' #' User can modify each of plot before printing. #' #' @examples #' # Basic scatter plot with marginal density plot #' ggscatterhist(iris, x = "Sepal.Length", y = "Sepal.Width", #' color = "#00AFBB", #' margin.params = list(fill = "lightgray")) #' #' #' # Grouped data #'ggscatterhist( #' iris, x = "Sepal.Length", y = "Sepal.Width", #' color = "Species", size = 3, alpha = 0.6, #' palette = c("#00AFBB", "#E7B800", "#FC4E07"), #' margin.params = list(fill = "Species", color = "black", size = 0.2) #') #' #'# Use boxplot as marginal #'ggscatterhist( #' iris, x = "Sepal.Length", y = "Sepal.Width", #' color = "Species", size = 3, alpha = 0.6, #' palette = c("#00AFBB", "#E7B800", "#FC4E07"), #' margin.plot = "boxplot", #' ggtheme = theme_bw() #') #' #'# Add vertical and horizontal line to a ggscatterhist #'plots <- ggscatterhist(iris, x = "Sepal.Length", y = "Sepal.Width", print = FALSE) #'plots$sp <- plots$sp + #' geom_hline(yintercept = 3, linetype = "dashed", color = "blue") + #' geom_vline(xintercept = 6, linetype = "dashed", color = "red") #'plots #' #'@export ggscatterhist <- function( data, x, y, group = NULL, color = "black", fill = NA, palette = NULL, shape = 19, size = 2, linetype = "solid", bins = 30, margin.plot = c("density", "histogram", "boxplot"), margin.params = list(), margin.ggtheme = theme_void(), margin.space = FALSE, main.plot.size = 2, margin.plot.size = 1, title = NULL, xlab = NULL, ylab = NULL, legend = "top", ggtheme = theme_pubr(), print = TRUE, ... ) { if(!has_cowplot_v0.9()){ warning("Install the latest developmental version of cowplot on github ", "to fully use all the feature of ggscatterhist", .call = FALSE) # margin.space = TRUE } margin.plot <- match.arg(margin.plot) margin.params <- .check_margin_params( margin.params, data, color, fill, linetype ) if(margin.plot == "histogram") { if(is.null(margin.params$position)){ margin.params$position <- "identity" } margin.params <- margin.params %>% .add_item(bins = bins) } if(!is.null(group)){ if(missing(color)) color = group if(missing(shape)) shape = group } . <- NULL sp <- ggscatter( data, x, y, color = color, fill = fill, palette = palette, shape = shape, size = size, xlab = xlab, ylab = ylab, ggtheme = ggtheme, title = title, legend = legend, ... ) # Type of graphics to be added in the margins geomfunc <- switch (margin.plot, histogram = geom_histogram, density = geom_density, boxplot = geom_boxplot, geom_histogram ) # Define the x and the y variables depending on # the geometry used in margins if(margin.plot %in% c("density", "histogram")){ xplot.x <- x xplot.y <- NULL yplot.x <- y yplot.y <- NULL } else if(margin.plot %in% c("boxplot")){ if(is.null(group)) { data <- data %>% mutate(.xgroupx. = factor(1)) group = ".xgroupx." } xplot.x <- group xplot.y <- x yplot.x <- group yplot.y <- y } # Create the different marginal plot xplot <- ggplot() + margin.params %>% .add_item(geomfunc = geomfunc, data = data, x = xplot.x, y = xplot.y, alpha = 0.7) %>% do.call(geom_exec, .) xplot <- set_palette(xplot, palette) yplot <- ggplot() + margin.params %>% .add_item(geomfunc = geomfunc, data = data, x = yplot.x, y = yplot.y, alpha = 0.7) %>% do.call(geom_exec, .) yplot <- set_palette(yplot, palette) # Flip the marginal plots if(margin.plot %in% c("density", "histogram")) yplot <- yplot + coord_flip() else if(margin.plot %in% c("boxplot")) xplot <- xplot + coord_flip() # Cleaning the plot .legend <- get_legend(sp) sp <- sp + theme(plot.margin = grid::unit(c(0,0,0.25,0.25), "cm")) xplot <- xplot + margin.ggtheme + clean_theme() + rremove("legend") + theme( plot.margin = grid::unit(c(0,0,0,0), "cm")) yplot <- yplot + margin.ggtheme + clean_theme() + rremove("legend") + theme(plot.margin = grid::unit(c(0,0,0,0), "cm")) plots <- list(sp = sp, xplot = xplot, yplot = yplot) class(plots) <- c("ggscatterhist", "list") if(print){ res <- print( plots, margin.space = margin.space, main.plot.size = main.plot.size, margin.plot.size = margin.plot.size, title = title, legend = legend ) } invisible(plots) } #' @method print ggscatterhist #' @param x an object of class \code{ggscatterhist}. #' @rdname ggscatterhist #' @export print.ggscatterhist <- function(x, margin.space = FALSE, main.plot.size = 2, margin.plot.size = 1, title = NULL, legend = "top", ...){ sp <- x$sp xplot <- x$xplot yplot <- x$yplot .legend <- get_legend(sp) if(margin.space){ common.legend <- FALSE if(!is.null(.legend)) common.legend = TRUE sp <- sp + theme( plot.title = element_blank(), plot.subtitle = element_blank() ) fig <- ggarrange( xplot, NULL, sp, yplot, ncol = 2, nrow = 2, align = "hv", widths = c(main.plot.size, margin.plot.size), heights = c(margin.plot.size, main.plot.size), common.legend = common.legend, legend = legend ) if(!is.null(title)){ fig <- annotate_figure( fig, top = text_grob(title, color = "black", size = 13, face = "bold") ) } } else{ if(!is.null(title)) sp <- sp + ggtitle(title) fig <- .insert_xaxis_grob(sp, xplot, grid::unit(margin.plot.size/5, "null"), position = "top") fig <- .insert_yaxis_grob(fig, yplot, grid::unit(margin.plot.size/5, "null"), position = "right") fig <- cowplot::ggdraw(fig) } print(fig) invisible(fig) } has_cowplot_v0.9 <- function(){ vv <- as.character(utils::packageVersion("cowplot")) cc <- utils::compareVersion(vv, "0.8.0.8") > 0 cc } .check_margin_params <- function(params, data, color = "black", fill = NA, linetype = "slid"){ if(is.null(params$color)) { if(color %in% colnames(data)){ col.val <- dplyr::pull(data, color) if(!is.factor(col.val)) params$color <- "black" else params$color <- color } } if(is.null(params$fill)) { if(fill %in% colnames(data)){ fill.val <- .select_vec(data, fill) if(!is.factor(fill.val)) params$fill <- "black" else params$fill <- fill } } if(is.null(params$linetype)) params$linetype <- linetype params } # Helper functions to insert marginal plots #:::::::::::::::::::::::::::::::::::::::::::::::::::: # Use cowplot::insert_xaxis_grob and cowplot::insert_yaxis_grob, # when 0.9 stable version released .insert_xaxis_grob <- function ( plot, grob, height = grid::unit(0.2, "null"), position = c("top", "bottom") ) { if(inherits(grob, "ggplot")) grob <- .get_panel(grob) gt <- .plot_to_gtable(plot) pp <- gt$layout[gt$layout$name == "panel", ] if (position[1] == "top") { g <- gtable::gtable_add_rows(gt, height, pp$t - 1) g <- gtable::gtable_add_grob( g, grob, pp$t, pp$l, pp$t, pp$r, clip = "inherit", name = "xaxis-grob-t" ) } else { g <- gtable::gtable_add_rows(gt, height, pp$b) g <- gtable::gtable_add_grob( g, grob, pp$b + 1, pp$l, pp$b + 1, pp$r, clip = "inherit", name = "xaxis-grob-b" ) } } .insert_yaxis_grob <- function ( plot, grob, width = grid::unit(0.2, "null"), position = c("right", "left")) { if(inherits(grob, "ggplot")) grob <- .get_panel(grob) gt <- .plot_to_gtable(plot) pp <- gt$layout[gt$layout$name == "panel", ] if (position[1] == "right") { g <- gtable::gtable_add_cols(gt, width, pp$r) g <- gtable::gtable_add_grob( g, grob, pp$t, pp$r + 1, pp$b, pp$r + 1, clip = "inherit", name = "yaxis-grob-r" ) } else { g <- gtable::gtable_add_cols(gt, width, pp$l - 1) g <- gtable::gtable_add_grob( g, grob, pp$t, pp$l, pp$b, pp$l, clip = "inherit", name = "yaxis-grob-l" ) } } .plot_to_gtable <- function (plot) { if(inherits(plot, "gtable")) return(plot) else ggplot2::ggplotGrob(plot) } .get_panel <- function (plot) { gt <- .plot_to_gtable(plot) panelIndex <- which(gt$layout$name == "panel") panel <- gt$grobs[[panelIndex]] } ggpubr/R/ggbarplot.R0000644000176200001440000004023414342651420014051 0ustar liggesusers#' @include utilities.R ggpar.R NULL #' Bar plot #' @description Create a bar plot. #' @inheritParams ggboxplot #' @inheritParams ggplot2::geom_bar #' @param x,y x and y variables for drawing. #' @param color,fill outline and fill colors. #' @param sort.val a string specifying whether the value should be sorted. #' Allowed values are "none" (no sorting), "asc" (for ascending) or "desc" (for descending). #' @param sort.by.groups logical value. If TRUE the data are sorted by groups. #' Used only when sort.val != "none". #' @param top a numeric value specifying the number of top elements to be shown. #' @param label specify whether to add labels on the bar plot. Allowed values #' are: \itemize{ \item \strong{logical value}: If TRUE, y values is added as #' labels on the bar plot \item \strong{character vector}: Used as text #' labels; must be the same length as y. } #' @param lab.col,lab.size text color and size for labels. #' @param lab.pos character specifying the position for labels. Allowed values #' are "out" (for outside) or "in" (for inside). Ignored when lab.vjust != #' NULL. #' @param lab.vjust numeric, vertical justification of labels. Provide negative #' value (e.g.: -0.4) to put labels outside the bars or positive value to put #' labels inside (e.g.: 2). #' @param lab.hjust numeric, horizontal justification of labels. #' @param lab.nb.digits integer indicating the number of decimal places (round) to be used. #' @param ... other arguments to be passed to be passed to ggpar(). #' @details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" \item plot orientation : orientation #' = c("vertical", "horizontal", "reverse") } #' @seealso \code{\link{ggpar}}, \code{\link{ggline}} #' @examples #' # Data #' df <- data.frame(dose=c("D0.5", "D1", "D2"), #' len=c(4.2, 10, 29.5)) #' print(df) #' #' # Basic plot with label outsite #' # +++++++++++++++++++++++++++ #' ggbarplot(df, x = "dose", y = "len", #' label = TRUE, label.pos = "out") #' #' # Change width #' ggbarplot(df, x = "dose", y = "len", width = 0.5) #' #' # Change the plot orientation: horizontal #' ggbarplot(df, "dose", "len", orientation = "horiz") #' #' # Change the default order of items #' ggbarplot(df, "dose", "len", #' order = c("D2", "D1", "D0.5")) #' #' #' # Change colors #' # +++++++++++++++++++++++++++ #' #' # Change fill and outline color #' # add labels inside bars #' ggbarplot(df, "dose", "len", #' fill = "steelblue", color = "steelblue", #' label = TRUE, lab.pos = "in", lab.col = "white") #' #' # Change colors by groups: dose #' # Use custom color palette #' ggbarplot(df, "dose", "len", color = "dose", #' palette = c("#00AFBB", "#E7B800", "#FC4E07")) #' #' # Change fill and outline colors by groups #' ggbarplot(df, "dose", "len", #' fill = "dose", color = "dose", #' palette = c("#00AFBB", "#E7B800", "#FC4E07")) #' #' #' # Plot with multiple groups #' # +++++++++++++++++++++ #' #' # Create some data #' df2 <- data.frame(supp=rep(c("VC", "OJ"), each=3), #' dose=rep(c("D0.5", "D1", "D2"),2), #' len=c(6.8, 15, 33, 4.2, 10, 29.5)) #' print(df2) #' #' # Plot "len" by "dose" and change color by a second group: "supp" #' # Add labels inside bars #' ggbarplot(df2, "dose", "len", #' fill = "supp", color = "supp", palette = "Paired", #' label = TRUE, lab.col = "white", lab.pos = "in") #' #' # Change position: Interleaved (dodged) bar plot #' ggbarplot(df2, "dose", "len", #' fill = "supp", color = "supp", palette = "Paired", #' label = TRUE, #' position = position_dodge(0.9)) #' #' # Add points and errors #' # ++++++++++++++++++++++++++ #' #' # Data: ToothGrowth data set we'll be used. #' df3 <- ToothGrowth #' head(df3, 10) #' #' # It can be seen that for each group we have #' # different values #' ggbarplot(df3, x = "dose", y = "len") #' #' # Visualize the mean of each group #' ggbarplot(df3, x = "dose", y = "len", #' add = "mean") #' #' # Add error bars: mean_se #' # (other values include: mean_sd, mean_ci, median_iqr, ....) #' # Add labels #' ggbarplot(df3, x = "dose", y = "len", #' add = "mean_se", label = TRUE, lab.vjust = -1.6) #' #' # Use only "upper_errorbar" #' ggbarplot(df3, x = "dose", y = "len", #' add = "mean_se", error.plot = "upper_errorbar") #' #' # Change error.plot to "pointrange" #' ggbarplot(df3, x = "dose", y = "len", #' add = "mean_se", error.plot = "pointrange") #' #' # Add jitter points and errors (mean_se) #' ggbarplot(df3, x = "dose", y = "len", #' add = c("mean_se", "jitter")) #' #' # Add dot and errors (mean_se) #' ggbarplot(df3, x = "dose", y = "len", #' add = c("mean_se", "dotplot")) #' #' # Multiple groups with error bars and jitter point #' ggbarplot(df3, x = "dose", y = "len", color = "supp", #' add = "mean_se", palette = c("#00AFBB", "#E7B800"), #' position = position_dodge()) # #' #' #' @export ggbarplot <- function(data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "white", palette = NULL, size = NULL, width = NULL, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, select = NULL, remove = NULL, order = NULL, add = "none", add.params = list(), error.plot = "errorbar", label = FALSE, lab.col = "black", lab.size = 4, lab.pos = c("out", "in"), lab.vjust = NULL, lab.hjust = NULL, lab.nb.digits = NULL, sort.val = c("none", "desc", "asc"), sort.by.groups = TRUE, top = Inf, position = position_stack(), ggtheme = theme_pubr(), ...) { # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( combine = combine, merge = merge, color = color, fill = fill, palette = palette, size = size, width = width, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, select = select , remove = remove, order = order, add = add, add.params = add.params, error.plot = error.plot, label = label, lab.col = lab.col, lab.size = lab.size, lab.pos = lab.pos, lab.vjust = lab.vjust, lab.hjust = lab.hjust, lab.nb.digits = lab.nb.digits, sort.val = sort.val, sort.by.groups = sort.by.groups, top = top, position = position, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x if(!missing(y)) .opts$y <- y # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } if(is.logical(merge)){ if(merge & missing(position)) .opts$position <- position_dodge(0.8) if(merge & missing(lab.col)) .opts$lab.col <- ".y." } else if(is.character(merge)){ .opts$position <- position_dodge(0.8) } .opts$fun <- ggbarplot_core .opts$fun_name <- "barplot" if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggbarplot_core <- function(data, x, y, color = "black", fill = "white", palette = NULL, size = NULL, width = 0.7, title = NULL, xlab = NULL, ylab = NULL, label = FALSE, lab.col = "black", lab.size = 4, lab.pos = c("out", "in"), lab.vjust = NULL, lab.hjust = NULL, lab.nb.digits = NULL, select = NULL, order = NULL, facet.by = NULL, sort.val = c("none", "desc", "asc"), sort.by.groups = TRUE, merge = FALSE, top = Inf, add = "none", add.params = list(), error.plot = "errorbar", position = position_stack(), ggtheme = theme_pubr(), ...) { sort.val <- match.arg(sort.val) if(!is.null(order)) data[[x]] <- factor(data[[x]], levels = order) else { xx <- .select_vec(data, x) if(inherits(xx, c("character", "numeric"))) data[[x]] <- as.factor(data[[x]]) } error.plot = error.plot[1] lab.pos <- match.arg(lab.pos) label <- as.vector(label) if("none" %in% add) add <- "none" grouping.vars <- intersect(c(x, color, fill, facet.by), names(data)) . <- NULL # static summaries for computing mean/median and adding errors if(is.null(add.params$fill)) add.params$fill <- "white" if(is.null(add.params$group)){ if(fill %in% names(data)) add.params$group <- fill else if(color %in% names(data)) add.params$group <- color } add.params <- .check_add.params(add, add.params, error.plot, data, color, fill, ...) if(any(.summary_functions() %in% add)) { data_sum <- desc_statby(data, measure.var = y, grps = grouping.vars) summary.funcs <- intersect(.summary_functions(), add) if(length(summary.funcs) > 1) stop("Only one summary function is allowed. ", "Choose one of ", .collapse(.summary_functions(), sep = ", ")) .center <- .get_errorbar_center_func(summary.funcs) add <- setdiff(add, .center) names(data_sum)[which(names(data_sum) == .center)] <- y if(inherits(xx, c("character", "numeric"))) data_sum[, x] <- .select_vec(data_sum, x) %>% as.factor() } else data_sum <- data # Sorting #%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if(top !=Inf & sort.val == "none") sort.val = "desc" if(top !=Inf) { data_sum <- data_sum[order(-data_sum[, y]), ] data_sum <- utils::head(data_sum, n = top) } grps <- unique(intersect(c(color, fill), names(data))) if(length(grps) > 0) grps <- .get_not_numeric_vars(data[, grps, drop = FALSE]) ngrps <- length(grps) if(!sort.by.groups) ngrps <- 0 # Variables for ordering if(ngrps > 0) dd <- data_sum[, c(grps, y)] else dd <- data_sum[, y, drop = FALSE] if(sort.val == "desc") dd[, y] <- -dd[, y] # Sorting if(sort.val != "none") { if(ngrps == 0) data_sum <- data_sum[order(dd[, y]),] else if(ngrps == 1) data_sum <- data_sum[order(dd[, 1], dd[, y]),] else if(ngrps == 2) data_sum <- data_sum[order(dd[, 1], dd[, 2], dd[, y]),] data_sum[, x] <- factor(data_sum[, x], levels = data_sum[, x]) } # Main plot #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if(inherits(position, "PositionDodge") & is.null(position$width)) position$width = 0.95 p <- ggplot(data, create_aes(list(x = x, y = y))) p <- p + geom_exec(geom_bar, data = data_sum, stat = "identity", color = color, fill = fill, position = position, size = size, width = width, ...) # Add errors add.params <- add.params %>% .add_item(p = p, error.plot = error.plot) is.stacked.position <- inherits(position, "PositionStack") stack.groups <- unique(c(x, facet.by)) nb.bars.by.xposition <- data_sum %>% group_by(!!!syms(stack.groups)) %>% dplyr::count() %>% dplyr::pull(.data$n) %>% max() if(is.stacked.position) add.position <- "identity" else add.position <- position if(is.stacked.position & nb.bars.by.xposition >=2) { p <- add.params %>% .add_item(add = .remove_errorbar_func(add), position = add.position) %>% do.call(ggadd, .) if(any(.errorbar_functions() %in% add)){ p <- p + .geom_stacked_errorbar( data_sum, x, y, color = add.params$color, fill = add.params$fill, group = add.params$group, facet.by = facet.by, func = .get_summary_func(add), error.plot = error.plot ) } } else { p <- add.params %>% .add_item(add = add, position = add.position) %>% do.call(ggadd, .) } # Add labels add.label <- FALSE if(is.logical(label)){ .lab <- y add.label <- label } else { # Add user specified labels as data column data_sum$.ulabel. <- label .lab <- ".ulabel." add.label <- TRUE } if(add.label) { if(is.null(lab.vjust)) lab.vjust <- ifelse(lab.pos == "out", -0.4, 2 ) if(is.null(lab.hjust)) lab.hjust <- 0.5 if(!is.null(lab.nb.digits)){ if(is.numeric(.lab)) .lab <- round(.lab, digits = lab.nb.digits) else if(.lab[1] %in% colnames(data_sum)) data_sum[, .lab] <- dplyr::pull(data_sum, .lab) %>% round(digits = lab.nb.digits) } # pos <- "identity" # if color or fill by groups .cols <- unique(c(color, fill)) if(any(.cols %in% names(data))){ .in <- which(.cols %in% names(data)) lab.fill <- color.var <- .cols[.in] data_sum <- data_sum %>% dplyr::arrange(!!!syms(x), desc(!!!syms(color.var))) group <- intersect(.cols, names(data))[1]# You should specify group for dodging text p <- p + geom_exec(geom_text, data = data_sum, label = .lab, #fill = lab.fill vjust = lab.vjust, hjust = lab.hjust, size = lab.size, color = lab.col, fontface = "plain", position = position, group = group) } else{ p <- p + geom_exec(geom_text, data = data_sum, label = .lab, vjust = lab.vjust, hjust = lab.hjust, size = lab.size, color = lab.col, fontface = "plain", position = position) } } # To do # top10, visualizing error p <- ggpar(p, palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab,...) p } # Stacked error bar ---------------------------- .geom_stacked_errorbar <- function(data_sum, x, y, color = NULL, fill = NULL, facet.by = NULL, group = NULL, func = "mean_se", error.plot = "errorbar"){ stack.groups <- unique(c(x, facet.by)) legend.var <- intersect(unique(c(color, fill, group)), colnames(data_sum)) error <- .get_errorbar_error_func(func) error.value <- data_sum %>% dplyr::pull(!!error) desc <- dplyr::desc errorbar.position <- data_sum %>% group_by(!!!syms(stack.groups)) %>% dplyr::arrange(!!sym(x), desc(!!sym(legend.var))) %>% dplyr::mutate( y = cumsum(!!sym(y)), ymin = .data$y - !!sym(error), ymax = .data$y + !!sym(error) ) %>% dplyr::ungroup() geom_error <- .get_geom_error_function(error.plot) args <- geom_exec( data = errorbar.position, color = color, group = group, x = x, ymin = "ymin", ymax = "ymax" ) mapping <- args$mapping option <- args$option if(error.plot == "errorbar") option$width <- 0.15 option[["mapping"]] <- create_aes(mapping) do.call(geom_error, option) } .get_geom_error_function <- function(error.plot = "errorbar"){ error.plot <- error.plot[1] geom_func <- ggplot2::geom_errorbar if(error.plot %in% c("pointrange", "lower_pointrange", "upper_pointrange")) geom_func <- ggplot2::geom_pointrange else if(error.plot %in% c("linerange", "lower_linerange", "upper_linerange")) geom_func <- ggplot2::geom_linerange else if(error.plot %in% c("errorbar", "lower_errorbar", "upper_errorbar")) geom_func <- ggplot2::geom_errorbar geom_func } .is_stacked <- function(p){ inherits(p$layers[[1]]$position, "PositionStack") } # remove "mean_se", "mean_sd", etc .remove_errorbar_func <- function(add){ setdiff(add, .errorbar_functions()) } # return "mean_se" .get_summary_func <- function(add){ intersect(.errorbar_functions(), add) } # Returns: mean or median .get_errorbar_center_func <- function(func = "mean_se"){ . <- NULL func %>% strsplit("_", fixed = TRUE) %>% unlist() %>% .[1] } # Returns se, sd, iqr .get_errorbar_error_func <- function(func = "mean_se"){ res <- func %>% strsplit("_", fixed = TRUE) %>% unlist() if(length(res) >= 2){ res <- res[2] } else res <- NULL res } ggpubr/R/diff_express.R0000644000176200001440000000277514332553655014573 0ustar liggesusers#' Differential gene expression analysis results #' #' @description Differential gene expression analysis results obtained from #' comparing the RNAseq data of two different cell populations using DESeq2 #' @name diff_express #' @docType data #' @usage data("diff_express") #' @format A data frame with 36028 rows and 5 columns. \describe{ #' \item{\code{name}}{gene names} \item{\code{baseMean}}{mean expression #' signal across all samples} \item{\code{log2FoldChange}}{log2 fold change} #' \item{\code{padj}}{Adjusted p-value}\item{\code{detection_call}}{a numeric #' vector specifying whether the genes is expressed (value = 1) or not (value = 0).}} #' #' @examples #' data(diff_express) #' #' # Default plot #'ggmaplot(diff_express, main = expression("Group 1" %->% "Group 2"), #' fdr = 0.05, fc = 2, size = 0.4, #' palette = c("#B31B21", "#1465AC", "darkgray"), #' genenames = as.vector(diff_express$name), #' legend = "top", top = 20, #' font.label = c("bold", 11), #' font.legend = "bold", #' font.main = "bold", #' ggtheme = ggplot2::theme_minimal()) #' #' # Add rectangle around labesl #'ggmaplot(diff_express, main = expression("Group 1" %->% "Group 2"), #' fdr = 0.05, fc = 2, size = 0.4, #' palette = c("#B31B21", "#1465AC", "darkgray"), #' genenames = as.vector(diff_express$name), #' legend = "top", top = 20, #' font.label = c("bold", 11), label.rectangle = TRUE, #' font.legend = "bold", #' font.main = "bold", #' ggtheme = ggplot2::theme_minimal()) #' NULL ggpubr/R/ggstripchart.R0000644000176200001440000001577614342652232014610 0ustar liggesusers#' @include utilities.R ggpar.R NULL #' Stripcharts #' @description Create a stripchart, also known as one dimensional scatter #' plots. These plots are suitable compared to box plots when sample sizes are #' small. #' @inheritParams ggboxplot #' @param shape point shape #' @param jitter the amount of jitter. #' @param position position adjustment, either as a string, or the result of a #' call to a position adjustment function. Used to adjust position for #' multiple groups. #' @param ... other arguments to be passed to #' \code{\link[ggplot2]{geom_jitter}}, \code{\link{ggpar}} and #' \code{\link{facet}}. #' @details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" \item plot orientation : orientation #' = c("vertical", "horizontal", "reverse") } #'@seealso \code{\link{ggpar}}, \code{\link{ggviolin}}, \code{\link{ggdotplot}} #' and \code{\link{ggboxplot}}. #' @examples #' # Load data #' data("ToothGrowth") #' df <- ToothGrowth #' #' # Basic plot with summary statistics: mean_se #' # +++++++++++++++++++++++++++ #' # Change point shapes by groups: "dose" #' ggstripchart(df, x = "dose", y = "len", #' shape = "dose", size = 3, #' add = "mean_se") #' #' # Use mean_sd #' # Change error.plot to "crossbar" #' ggstripchart(df, x = "dose", y = "len", #' shape = "dose", size = 3, #' add = "mean_sd", add.params = list(width = 0.5), #' error.plot = "crossbar") #' #' #' #' # Add summary statistics #' # ++++++++++++++++++++++++++ #' #' # Add box plot #' ggstripchart(df, x = "dose", y = "len", #' shape = "dose", add = "boxplot") #' #' # Add violin + mean_sd #' ggstripchart(df, x = "dose", y = "len", #' shape = "dose", add = c("violin", "mean_sd")) #' #' #' # Change colors #' # +++++++++++++++++++++++++++ #' # Change colors by groups: dose #' # Use custom color palette #' ggstripchart(df, "dose", "len", shape = "dose", #' color = "dose", palette = c("#00AFBB", "#E7B800", "#FC4E07"), #' add = "mean_sd") #' #' #' #' # Plot with multiple groups #' # +++++++++++++++++++++ #' # Change shape and color by a second group : "supp" #' ggstripchart(df, "dose", "len", shape = "supp", #' color = "supp", palette = c("#00AFBB", "#E7B800")) #' #' # Adjust point position #' ggstripchart(df, "dose", "len", shape = "supp", #' color = "supp", palette = c("#00AFBB", "#E7B800"), #' position = position_dodge(0.8) ) #' #' # You can also use position_jitterdodge() #' # but fill aesthetic is required #' ggstripchart(df, "dose", "len", shape = "supp", #' color = "supp", palette = c("#00AFBB", "#E7B800"), #' position = position_jitterdodge() ) #' #' # Add boxplot #' ggstripchart(df, "dose", "len", shape = "supp", #' color = "supp", palette = c("#00AFBB", "#E7B800"), #' add = "boxplot", add.params = list(color = "black") ) #' #' @export ggstripchart <- function(data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "white", palette = NULL, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, shape = 19, size = NULL, select = NULL, remove = NULL, order = NULL, add = "mean_se", add.params = list(), error.plot = "pointrange", label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, jitter = 0.2, position = position_jitter(jitter, seed = 123), ggtheme = theme_pubr(), ...) { # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( combine = combine, merge = merge, color = color, fill = fill, palette = palette, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, shape = shape, size = size, select = select , remove = remove, order = order, add = add, add.params = add.params, error.plot = error.plot, label = label, font.label = font.label, label.select = label.select, repel = repel, label.rectangle = label.rectangle, jitter = jitter, position = position, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x if(!missing(y)) .opts$y <- y # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$fun <- ggstripchart_core if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggstripchart_core <- function(data, x, y, color = "black", fill = "white", palette = NULL, title = NULL, xlab = NULL, ylab = NULL, shape = 19, size = NULL, add = "mean_se", add.params = list(), error.plot = "pointrange", jitter = 0.2, position = position_jitter(jitter, seed = 123), ggtheme = theme_pubr(), ...) { if(!is.factor(data[[x]])) data[[x]] <- as.factor(data[[x]]) . <- NULL p <- ggplot(data, create_aes(list(x = x, y = y))) if("none" %in% add) add <- "none" add.params <- .check_add.params(add, add.params, error.plot, data, color, fill, ...) # plot boxplot | violin | crossbar before jitter if( any( c("boxplot", "violin") %in% add)){ p <- add.params %>% .add_item(p = p, add = intersect(add, c("boxplot", "violin") )) %>% do.call(ggadd, .) } if(error.plot == "crossbar"){ p <- add.params %>% .add_item(p = p, error.plot = error.plot, add = setdiff(add, c("boxplot", "violin", "jitter"))) %>% do.call(ggadd, .) } # Plot jitter p <- p + geom_exec(geom_jitter, data = data, color = color, fill = fill, shape = shape, position = position, size = size, ...) # Add errors if(error.plot == "crossbar"){} else p <- add.params %>% .add_item(p = p, error.plot = error.plot, add = setdiff(add, c("boxplot", "violin", "jitter"))) %>% do.call(ggadd, .) p <- ggpar(p, palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab,...) p } ggpubr/R/get_legend.R0000644000176200001440000000271414332553655014200 0ustar liggesusers#' @include utilities.R NULL #' Extract Legends from a ggplot object #' @description Extract the legend labels from a ggplot object. #' @param p an object of class ggplot or a list of ggplots. If p is a list, only the first legend is returned. #' @param position character specifying legend position. Allowed values are one of #' c("top", "bottom", "left", "right", "none"). To remove the legend use #' legend = "none". #' @return an object of class gtable. #' @examples #' # Create a scatter plot #' p <- ggscatter(iris, x = "Sepal.Length", y = "Sepal.Width", #' color = "Species", palette = "jco", #' ggtheme = theme_minimal()) #' p #' #' # Extract the legend. Returns a gtable #' leg <- get_legend(p) #' #' # Convert to a ggplot and print #' as_ggplot(leg) #' #' @export get_legend <- function(p, position = NULL){ if(.is_list(p)){ continue <- TRUE i <- 1 while(i <= length(p) & continue){ leg <- .get_legend(p[[i]], position = position) if(!is.null(leg)) continue <- FALSE i <- i+1 } } else{ leg <- .get_legend(p, position = position) } leg } # Return legend for one plot .get_legend <- function(p, position = NULL){ if(is.null(p)) return(NULL) if(!is.null(position)){ p <- p + theme(legend.position = position) } tmp <- ggplot_gtable(ggplot_build(p)) leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box") if(length(leg) > 0) leg <- tmp$grobs[[leg]] else leg <- NULL leg } ggpubr/R/gghistogram.R0000644000176200001440000002044514334523053014406 0ustar liggesusers#' @include utilities.R ggpar.R NULL #' Histogram plot #' @description Create a histogram plot. #' @inheritParams ggboxplot #' @param x variable to be drawn. #' @param y one of "density" or "count". #' @param weight a variable name available in the input data for creating a weighted histogram. #' @param color,fill histogram line color and fill color. #' @param linetype line type. See \code{\link{show_line_types}}. #' @param alpha numeric value specifying fill color transparency. Value should #' be in [0, 1], where 0 is full transparency and 1 is no transparency. #' @param bins Number of bins. Defaults to 30. #' @param binwidth numeric value specifying bin width. use value between 0 and 1 #' when you have a strong dense dotplot. For example binwidth = 0.2. #' @param add allowed values are one of "mean" or "median" (for adding mean or #' median line, respectively). #' @param add.params parameters (color, size, linetype) for the argument 'add'; #' e.g.: add.params = list(color = "red"). #' @param rug logical value. If TRUE, add marginal rug. #' @param add_density logical value. If TRUE, add density curves. #' @param position Position adjustment, either as a string, or the result of a #' call to a position adjustment function. Allowed values include "identity", #' "stack", "dodge". #' @param ... other arguments to be passed to #' \code{\link[ggplot2]{geom_histogram}} and \code{\link{ggpar}}. #' @details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" \item plot orientation : orientation #' = c("vertical", "horizontal", "reverse") } #' @seealso \code{\link{ggdensity}} and \code{\link{ggpar}} #' #' @examples #' # Create some data format #' set.seed(1234) #' wdata = data.frame( #' sex = factor(rep(c("F", "M"), each=200)), #' weight = c(rnorm(200, 55), rnorm(200, 58))) #' #' head(wdata, 4) #' #' # Basic density plot #' # Add mean line and marginal rug #' gghistogram(wdata, x = "weight", fill = "lightgray", #' add = "mean", rug = TRUE) #' #' # Change outline colors by groups ("sex") #' # Use custom color palette #' gghistogram(wdata, x = "weight", #' add = "mean", rug = TRUE, #' color = "sex", palette = c("#00AFBB", "#E7B800")) #' #' # Change outline and fill colors by groups ("sex") #' # Use custom color palette #' gghistogram(wdata, x = "weight", #' add = "mean", rug = TRUE, #' color = "sex", fill = "sex", #' palette = c("#00AFBB", "#E7B800")) #' #' #' #' # Combine histogram and density plots #' gghistogram(wdata, x = "weight", #' add = "mean", rug = TRUE, #' fill = "sex", palette = c("#00AFBB", "#E7B800"), #' add_density = TRUE) #' #' # Weighted histogram #' gghistogram(iris, x = "Sepal.Length", weight = "Petal.Length") #' @export gghistogram <- function(data, x, y = "count", combine = FALSE, merge = FALSE, weight = NULL, color = "black", fill = NA, palette = NULL, size = NULL, linetype = "solid", alpha = 0.5, bins = NULL, binwidth = NULL, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, add = c("none", "mean", "median"), add.params = list(linetype = "dashed"), rug = FALSE, add_density = FALSE, label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, position = position_identity(), ggtheme = theme_pubr(), ...) { # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( combine = combine, merge = merge, color = color, fill = fill, palette = palette, linetype = linetype, size = size, alpha = alpha, bins = bins, binwidth = binwidth, weight = weight, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, add = add, add.params = add.params, rug = rug, add_density = add_density, label = label, font.label = font.label, label.select = label.select, repel = repel, label.rectangle = label.rectangle, position = position, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x if(!missing(y)) .opts$y <- y # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$fun <- gghistogram_core if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) if(missing(y)) .opts$y <- y if(missing(add.params)) .opts$add.params <- add.params p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } gghistogram_core <- function(data, x, y = "count", weight = NULL, color = "black", fill = NA, palette = NULL, size = NULL, linetype = "solid", alpha = 0.5, bins = NULL, binwidth = NULL, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, add = c("none", "mean", "median"), add.params = list(linetype = "dashed"), rug = FALSE, add_density = FALSE, position = position_identity(), ggtheme = theme_classic(), ...) { grouping.vars <- grp <- c(color, fill, linetype, size, alpha, facet.by) %>% unique() %>% intersect(colnames(data)) color2 <- c(color, fill) %>% unique() %>% intersect(colnames(data)) if(.is_empty(color2)) color2 <- color # Check bins if(is.null(bins) & is.null(binwidth)){ bins <- 30 warning("Using `bins = 30` by default. Pick better value with the argument `bins`.", call.= FALSE) } add <- match.arg(add) if(is.null(add.params$color)){ if(!.is_empty(color2)) add.params$color <- color2 } add.params <- .check_add.params(add, add.params, error.plot = "", data, color, fill, ...) if(is.null(add.params$size)) add.params$size <- size if(is.null(add.params$linetype)) add.params$linetype <- linetype # if(add_density) y <- "..density.." if (y %in% c("..density..", "density")) y <- "after_stat(density)" else if (y %in% c("..count..", "count")) y <- "after_stat(count)" p <- ggplot(data, create_aes(list(x = x, y = y))) p <- p + geom_exec(geom_histogram, data = data, color = color, fill = fill, size = size, linetype = linetype, alpha = alpha, bins = bins, binwidth = binwidth, weight = weight, position = position, ...) # Add mean/median if(add %in% c("mean", "median")){ p <- p %>% .add_center_line(add = add, grouping.vars = grouping.vars, color = add.params$color, linetype = add.params$linetype, size = add.params$size) } # Add marginal rug if(rug) { grps <- c(color, fill, linetype, size, alpha) %>% unique() %>% intersect(colnames(data)) alpha <- ifelse(.is_empty(grps), 1, alpha) .args <- geom_exec(NULL, data = data, color = color2, sides = "b", alpha = alpha) mapping <- .args$mapping mapping[["y"]] <- 0 option <- .args$option option[["mapping"]] <- create_aes(mapping) p <- p + do.call(geom_rug, option) } # Add density curve if(add_density) p <- p + geom_exec(geom_density, data = data, color = add.params$color, linetype = linetype, alpha = alpha, size = add.params$size) p <- ggpar(p, palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab,...) p } ggpubr/R/ggqqplot.R0000644000176200001440000002042514341737601013733 0ustar liggesusers#' @include utilities.R ggpar.R NULL #' QQ Plots #' @description Quantile-Quantile plot. #' @inheritParams ggboxplot #' @param x variable to be drawn. #' @param color point color. #' @param size point size. #' @param shape point shape. #' @param add character vector. Allowed values are one of "none" and "qqline" #' (for adding qqline). #' @param add.params parameters (color, size, linetype) for the #' argument 'add'; e.g.: add.params = list(color = "red"). #' @param conf.int logical value. If TRUE, confidence interval is added. #' @param conf.int.level the confidence level. Default value is 0.95. #' @param ... other arguments to be passed to \code{\link{ggpar}}. #' @details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" \item plot orientation : orientation #' = c("vertical", "horizontal", "reverse") } #' @seealso \code{\link{ggpar}} #' #' @examples #' # Create some data format #' set.seed(1234) #' wdata = data.frame( #' sex = factor(rep(c("F", "M"), each=200)), #' weight = c(rnorm(200, 55), rnorm(200, 58))) #' #' head(wdata, 4) #' #' # Basic QQ plot #' ggqqplot(wdata, x = "weight") #' #' # Change colors and shape by groups ("sex") #' # Use custom palette #' ggqqplot(wdata, x = "weight", #' color = "sex", palette = c("#00AFBB", "#E7B800")) #' #' @export ggqqplot <- function(data, x, combine = FALSE, merge = FALSE, color = "black", palette = NULL, size = NULL, shape = NULL, add = c( "qqline", "none"), add.params = list(linetype = "solid"), conf.int = TRUE, conf.int.level = 0.95, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, ggtheme = theme_pubr(), ...) { # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( combine = combine, merge = merge, color = color, palette = palette, size = size, shape = shape, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, conf.int = conf.int, conf.int.level = conf.int.level, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$fun <- ggqqplot_core .opts$y <- "..qq.." if(is.null(.opts$xlab)) .opts$xlab <- "Theoretical" if(is.null(.opts$ylab)) .opts$ylab <- "Sample" if(is.null(.opts$add)) .opts$add <- "qqline" if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggqqplot_core <- function(data, x, y = "..qq..", color = "black", palette = NULL, size = NULL, shape = NULL, fill = "white", add = c( "qqline", "none"), add.params = list(linetype = "solid"), conf.int = TRUE, conf.int.level = 0.95, title = NULL, xlab = NULL, ylab = NULL, ggtheme = theme_pubr(), ...) { # Check data .dd <- .check_data(data, x, y=NULL) data <- .dd$data x <- .dd$x y <- .dd$y group <- c(shape, color) %>% unique() %>% intersect(colnames(data)) group <- ifelse(.is_empty(group), 1, group[1]) add <- match.arg(add) add.params <- .check_add.params(add, add.params, error.plot = "", data, color, fill = fill, ...) if(is.null(add.params$size)) add.params$size <- size if(is.null(add.params$linetype)) add.params$linetype <- "solid" p <- ggplot(data, create_aes(list(sample = x))) p <- p + geom_exec(stat_qq, data = data, color = color, size = size, shape = shape) if ("qqline" %in% add) p <- p + geom_exec(.stat_qqline, data = data, color = add.params$color, size = add.params$size, linetype = add.params$linetype, group = group) # Confidence interval if(conf.int){ p <- p + geom_exec(.stat_qq_confint, data = data, fill = color, alpha = 0.2, conf.int.level = conf.int.level, group = group) } p <- ggpar(p, palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab,...) p } # Helper functions ######################## # from: http://stackoverflow.com/questions/4357031/qqnorm-and-qqline-in-ggplot2 # qf : qfunction (e.g.: qnorm) .qq_line <- function(data, qf, na.rm) { q.sample <- stats::quantile(data, c(0.25, 0.75), na.rm = na.rm) q.theory <- qf(c(0.25, 0.75)) slope <- diff(q.sample) / diff(q.theory) intercept <- q.sample[1] - slope * q.theory[1] list(slope = slope, intercept = intercept) } StatQQLine <- ggproto("StatQQLine", Stat, # http://docs.ggplot2.org/current/vignettes/extending-ggplot2.html # https://github.com/hadley/ggplot2/blob/master/R/stat-qq.r required_aes = c('sample'), compute_group = function(data, scales, distribution = stats::qnorm, dparams = list(), conf.int.level = 0.95, na.rm = FALSE) { qf <- function(p) do.call(distribution, c(list(p = p), dparams)) n <- length(data$sample) P <- stats::ppoints(n) theoretical <- qf(P) qq <- .qq_line(data$sample, qf = qf, na.rm = na.rm) line <- qq$intercept + theoretical * qq$slope # Confidence interval zz <- stats::qnorm(1 - (1 - conf.int.level)/2) SE <- (qq$slope/stats::dnorm(theoretical)) * sqrt(P * (1 - P)/n) fit.value <- qq$intercept + qq$slope * theoretical ymax <- fit.value + zz * SE ymin <- fit.value - zz * SE data.frame(sample = line, x = theoretical, y = line, ymin = ymin, ymax = ymax) } ) .stat_qqline <- function(mapping = NULL, data = NULL, geom = "line", position = "identity", ..., distribution = stats::qnorm, dparams = list(), na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, conf.int.level = 0.95) { layer(stat = StatQQLine, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(distribution = distribution, dparams = dparams, na.rm = na.rm, conf.int.level = conf.int.level, ...)) } .stat_qq_confint <- function(mapping = NULL, data = NULL, geom = "ribbon", position = "identity", ..., distribution = stats::qnorm, dparams = list(), na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, conf.int.level = 0.95) { layer(stat = StatQQLine, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(distribution = distribution, dparams = dparams, na.rm = na.rm, conf.int.level = conf.int.level, ...)) } ggpubr/R/utilities_base.R0000644000176200001440000000624214344547604015110 0ustar liggesusers#:::::::::::::::::::::::::::::::::::::::::::::::::::: # General helper functions #:::::::::::::::::::::::::::::::::::::::::::::::::::: # Get random string .random_string <-function(.length = 7){ index <- sample(1:26, .length) paste(letters[index], collapse = "") } # get file extension .file_ext <- function(x){ pos <- regexpr("\\.([[:alnum:]]+)$", x) ifelse(pos > -1L, substring(x, pos + 1L), "") } # extract device name from file name .device <- function (filename) { device <- .file_ext(filename) devices <- list(eps = grDevices::postscript, ps = grDevices::postscript, pdf = grDevices::pdf, svg = grDevices::svg, png = grDevices::png, jpg = grDevices::jpeg, jpeg = grDevices::jpeg, bmp = grDevices::bmp, tiff = grDevices::tiff) dev <- devices[[device]] if (is.null(dev)) { stop("Unknown graphics device '", device, "'", call. = FALSE) } dev } # Grouping data by variables #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .group_by <- function(data, grouping.vars){ . <- NULL # used in pipes # Grouping the data ==> list of data sets grouped.d <- data %>% df_nest_by(vars = grouping.vars) # Defining names for the list of data sets. # names = combination of the levels of the grouping variables .names.df <- grouped.d[, grouping.vars, drop = FALSE] .names <- .paste_colnames(.names.df, sep = ":") %>% apply(1, paste, collapse = ", ") names(grouped.d$data) <- .names return(grouped.d) } # Pasting the column name to each value of a dataframe #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .paste_colnames <- function(data, sep = "."){ data <- as.data.frame(data) if(ncol(data) == 1){ res <- paste0(colnames(data), ".", data[[1]]) res <- data.frame(x = res, stringsAsFactors = FALSE) colnames(res) <- colnames(data) return(res) } res <- apply(data, 1, function(row, cname){paste(cname, row, sep = sep)}, colnames(data) ) %>% t() %>% as.data.frame(stringsAsFactors = FALSE) colnames(res) <- colnames(data) res } # Setting seed with possibility to restore initial random state #::::::::::::::::::::::::::::::::::::::::::::::: # Ref: https://github.com/florianhartig/DHARMa/blob/master/DHARMa/R/random.R # seed numeric value to be used for setting seed # return a function named restore_random_state() # for restoring intitial random state # # Examples: # seed <- set_seed(123) # Restore back initial state # seed$restore_random_state() set_seed <- function(seed){ # Record current random state current <- mget(".Random.seed", envir = .GlobalEnv, ifnotfound = list(NULL))[[1]] restore_random_state <- function(){ if(is.null(current)) rm(".Random.seed", envir = .GlobalEnv) else assign(".Random.seed", current , envir = .GlobalEnv) } # Setting seed if(is.numeric(seed)) set.seed(seed) # ensuring that RNG has been initialized if (is.null(current)) stats::runif(1) # Returning function for restoring state invisible(list(restore_random_state = restore_random_state)) } ggpubr/R/ggdensity.R0000644000176200001440000001442114334523134014065 0ustar liggesusers#' @include utilities.R ggpar.R NULL #' Density plot #' @description Create a density plot. #' @inheritParams ggboxplot #' @param x variable to be drawn. #' @param y one of "density" or "count". #' @param color,fill density line color and fill color. #' @param linetype line type. See \code{\link{show_line_types}}. #' @param alpha numeric value specifying fill color transparency. Value should #' be in [0, 1], where 0 is full transparency and 1 is no transparency. #' @param add allowed values are one of "mean" or "median" (for adding mean or #' median line, respectively). #' @param add.params parameters (color, size, linetype) for the argument 'add'; #' e.g.: add.params = list(color = "red"). #' @param rug logical value. If TRUE, add marginal rug. #' @param ... other arguments to be passed to #' \code{\link[ggplot2]{geom_density}} and \code{\link{ggpar}}. #' @details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" \item plot orientation : orientation #' = c("vertical", "horizontal", "reverse") } #' @seealso \code{\link{gghistogram}} and \code{\link{ggpar}}. #' #' @examples #' # Create some data format #' set.seed(1234) #' wdata = data.frame( #' sex = factor(rep(c("F", "M"), each=200)), #' weight = c(rnorm(200, 55), rnorm(200, 58))) #' #' head(wdata, 4) #' #' # Basic density plot #' # Add mean line and marginal rug #' ggdensity(wdata, x = "weight", fill = "lightgray", #' add = "mean", rug = TRUE) #' #' # Change outline colors by groups ("sex") #' # Use custom palette #' ggdensity(wdata, x = "weight", #' add = "mean", rug = TRUE, #' color = "sex", palette = c("#00AFBB", "#E7B800")) #' #' #' # Change outline and fill colors by groups ("sex") #' # Use custom palette #' ggdensity(wdata, x = "weight", #' add = "mean", rug = TRUE, #' color = "sex", fill = "sex", #' palette = c("#00AFBB", "#E7B800")) #' #' #' @export ggdensity <- function(data, x, y = "density", combine = FALSE, merge = FALSE, color = "black", fill = NA, palette = NULL, size = NULL, linetype = "solid", alpha = 0.5, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, add = c("none", "mean", "median"), add.params = list(linetype = "dashed"), rug = FALSE, label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, ggtheme = theme_pubr(), ...){ # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( combine = combine, merge = merge, color = color, fill = fill, palette = palette, linetype = linetype, size = size, alpha = alpha, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, add = add, add.params = add.params, rug = rug, label = label, font.label = font.label, label.select = label.select, repel = repel, label.rectangle = label.rectangle, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x if(!missing(y)) .opts$y <- y # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$fun <- ggdensity_core if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) if(missing(y)) .opts$y <- y if(missing(add.params)) .opts$add.params <- add.params p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggdensity_core <- function(data, x, y = "density", color = "black", fill = NA, palette = NULL, size = NULL, linetype = "solid", alpha = 0.5, title = NULL, xlab = NULL, ylab = NULL, add = c("none", "mean", "median"), add.params = list(linetype = "dashed"), rug = FALSE, facet.by = NULL, ggtheme = theme_classic(), ...) { grouping.vars <- grp <- c(color, fill, linetype, size, alpha, facet.by) %>% unique() %>% intersect(colnames(data)) add <- match.arg(add) add.params <- .check_add.params(add, add.params, error.plot = "", data, color, fill, ...) if(is.null(add.params$size)) add.params$size <- size if(is.null(add.params$linetype)) add.params$linetype <- linetype if (y %in% c("..density..", "density")) y <- "after_stat(density)" else if (y %in% c("..count..", "count")) y <- "after_stat(count)" p <- ggplot(data, create_aes(list(x = x, y = y))) p <- p + geom_exec(geom_density, data = data, color = color, fill = fill, size = size, linetype = linetype, alpha = alpha, ...) # Add mean/median if(add %in% c("mean", "median")){ p <- p %>% .add_center_line(add = add, grouping.vars = grouping.vars, color = add.params$color, linetype = add.params$linetype, size = add.params$size) } # Add marginal rug if(rug) { grps <- c(color, fill, linetype, size, alpha) %>% unique() %>% intersect(colnames(data)) alpha <- ifelse(.is_empty(grps), 1, alpha) .args <- geom_exec(NULL, data = data, color = color, sides = "b", alpha = alpha) mapping <- .args$mapping mapping[["y"]] <- 0 option <- .args$option option[["mapping"]] <- create_aes(mapping) p <- p + do.call(geom_rug, option) } p <- ggpar(p, palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab,...) p } ggpubr/R/ggmaplot.R0000644000176200001440000002256014340446656013717 0ustar liggesusers#' @include utilities.R ggpar.R NULL #'MA-plot from means and log fold changes #'@description Make MA-plot which is a scatter plot of log2 fold changes (M, on #' the y-axis) versus the average expression signal (A, on the x-axis). \code{M #' = log2(x/y)} and \code{A = (log2(x) + log2(y))/2 = log2(xy)*1/2}, where x #' and y are respectively the mean of the two groups being compared. #'@inheritParams ggboxplot #'@inheritParams ggpar #'@param data an object of class DESeqResults, get_diff, DE_Results, matrix or #' data frame containing the columns baseMean (or baseMeanLog2), #' log2FoldChange, and padj. Rows are genes. #' #' Two possible formats are accepted for the input data: \itemize{ \item 1/ #' \code{baseMean | log2FoldChange | padj}. This is a typical output from #' DESeq2 pipeline. Here, we'll use log2(baseMean) as the x-axis variable. #' \item 2/ \code{baseMeanLog2 | log2FoldChange | padj}. Here, baseMeanLog2 is #' assumed to be the mean of logged values; so we'll use it as the x-axis #' variable without any transformation. This is the real A in MA plot. In other #' words, it is the average of two log-scales values: \code{A = (log2(x) + #' log2(y))/2 = log2(xy)*1/2} } #' #' Terminology: #' #' \itemize{ \item baseMean: the mean expression of genes in the two groups. #' \item log2FoldChange: the log2 fold changes of group 2 compared to group 1 #' \item padj: the adjusted p-value of the used statiscal test. } #'@param fdr Accepted false discovery rate for considering genes as #' differentially expressed. #'@param fc the fold change threshold. Only genes with a fold change >= fc and #' padj <= fdr are considered as significantly differentially expressed. #'@param genenames a character vector of length nrow(data) specifying gene names #' corresponding to each row. Used for point labels. #'@param detection_call a numeric vector with length = nrow(data), specifying if #' the genes is expressed (value = 1) or not (value = 0). For example #' detection_call = c(1, 1, 0, 1, 0, 1). Default is NULL. If detection_call #' column is available in data, it will be used. #'@param size points size. #'@param alpha numeric value betwenn 0 an 1 specifying point alpha for #' controlling transparency. For example, use alpha = 0.5. #'@param seed Random seed passed to \code{set.seed}. if #' \code{NA}, set.seed will not be called. Default is 42 for reproducibility. #'@param font.label a vector of length 3 indicating respectively the size (e.g.: #' 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the #' color (e.g.: "red") of point labels. For example \emph{font.label = c(14, #' "bold", "red")}. #'@param label.rectangle logical value. If TRUE, add rectangle underneath the #' text, making it easier to read. #'@param top the number of top genes to be shown on the plot. Use top = 0 to #' hide to gene labels. #'@param select.top.method methods to be used for selecting top genes. Allowed #' values include "padj" and "fc" for selecting by adjusted p values or fold #' changes, respectively. #'@param label.select character vector specifying some labels to show. #'@param ... other arguments to be passed to \code{\link{ggpar}}. #'@return returns a ggplot. #' @examples #' data(diff_express) #' #' # Default plot #'ggmaplot(diff_express, main = expression("Group 1" %->% "Group 2"), #' fdr = 0.05, fc = 2, size = 0.4, #' palette = c("#B31B21", "#1465AC", "darkgray"), #' genenames = as.vector(diff_express$name), #' legend = "top", top = 20, #' font.label = c("bold", 11), #' font.legend = "bold", #' font.main = "bold", #' ggtheme = ggplot2::theme_minimal()) #' #' # Add rectangle around labels #'ggmaplot(diff_express, main = expression("Group 1" %->% "Group 2"), #' fdr = 0.05, fc = 2, size = 0.4, #' palette = c("#B31B21", "#1465AC", "darkgray"), #' genenames = as.vector(diff_express$name), #' legend = "top", top = 20, #' font.label = c("bold", 11), label.rectangle = TRUE, #' font.legend = "bold", #' font.main = "bold", #' ggtheme = ggplot2::theme_minimal()) #' #' # Select specific genes to show #' # set top = 0, then specify genes using label.select argument #' ggmaplot(diff_express, main = expression("Group 1" %->% "Group 2"), #' fdr = 0.05, fc = 2, size = 0.4, #' genenames = as.vector(diff_express$name), #' ggtheme = ggplot2::theme_minimal(), #' top = 0, label.select = c("BUB1", "CD83") #' ) #' #'@export ggmaplot <- function (data, fdr = 0.05, fc = 1.5, genenames = NULL, detection_call = NULL, size = NULL, alpha = 1, seed = 42, font.label = c(12, "plain", "black"), label.rectangle = FALSE, palette = c("#B31B21", "#1465AC", "darkgray"), top = 15, select.top.method = c("padj", "fc"), label.select = NULL, main = NULL, xlab = "Log2 mean expression", ylab = "Log2 fold change", ggtheme = theme_classic(),...) { if(!base::inherits(data, c("matrix", "data.frame", "DataFrame", "DE_Results", "DESeqResults"))) stop("data must be an object of class matrix, data.frame, DataFrame, DE_Results or DESeqResults") if(!is.null(detection_call)){ if(nrow(data)!=length(detection_call)) stop("detection_call must be a numeric vector of length = nrow(data)") } else if("detection_call" %in% colnames(data)){ detection_call <- as.vector(data$detection_call) } else detection_call = rep(1, nrow(data)) # Legend position if(is.null(list(...)$legend)) legend <- c(0.12, 0.9) # If basemean logged, we'll leave it as is, otherwise log2 transform is.basemean.logged <- "baseMeanLog2" %in% colnames(data) if(is.basemean.logged){ data$baseMean <- data$baseMeanLog2 } else if("baseMean" %in% colnames(data)){ data$baseMean <- log2(data$baseMean +1) } # Check data format ss <- base::setdiff(c("baseMean", "log2FoldChange", "padj"), colnames(data)) if(length(ss)>0) stop("The colnames of data must contain: ", paste(ss, collapse = ", ")) if(is.null(genenames)) genenames <- rownames(data) else if(length(genenames)!=nrow(data)) stop("genenames should be of length nrow(data).") sig <- rep(3, nrow(data)) sig[which(data$padj <= fdr & data$log2FoldChange < 0 & abs(data$log2FoldChange) >= log2(fc) & detection_call ==1)] = 2 sig[which(data$padj <= fdr & data$log2FoldChange > 0 & abs(data$log2FoldChange) >= log2(fc) & detection_call ==1)] = 1 data <- data.frame(name = genenames, mean = data$baseMean, lfc = data$log2FoldChange, padj = data$padj, sig = sig) # Change level labels . <- NULL data$sig <- as.factor(data$sig) .lev <- .levels(data$sig) %>% as.numeric() palette <- palette[.lev] new.levels <- c( paste0("Up: ", sum(sig == 1)), paste0("Down: ", sum(sig == 2)), "NS" ) %>% .[.lev] data$sig <- factor(data$sig, labels = new.levels) # Ordering for selecting top gene select.top.method <- match.arg(select.top.method) if(select.top.method == "padj") data <- data[order(data$padj), ] else if(select.top.method == "fc") data <- data[order(abs(data$lfc), decreasing = TRUE), ] # select data for top genes complete_data <- stats::na.omit(data) labs_data <- subset(complete_data, padj <= fdr & name!="" & abs(lfc) >= log2(fc)) labs_data <- utils::head(labs_data, top) # Select some specific labels to show if(!is.null(label.select)){ selected_labels <- complete_data %>% subset(complete_data$name %in% label.select, drop = FALSE) labs_data <- dplyr::bind_rows(labs_data, selected_labels) %>% dplyr::distinct(.data$name, .keep_all = TRUE) } font.label <- .parse_font(font.label) font.label$size <- ifelse(is.null(font.label$size), 12, font.label$size) font.label$color <- ifelse(is.null(font.label$color), "black", font.label$color) font.label$face <- ifelse(is.null(font.label$face), "plain", font.label$face) # Plot mean <- lfc <- sig <- name <- padj <- NULL p <- ggplot(data, aes(x = mean, y = lfc)) + geom_point(aes(color = sig), size = size, alpha = alpha) max.overlaps = getOption("ggrepel.max.overlaps", default = Inf) if(label.rectangle){ p <- p + ggrepel::geom_label_repel(data = labs_data, mapping = aes(label = name), box.padding = unit(0.35, "lines"), point.padding = unit(0.3, "lines"), force = 1, seed = seed, fontface = font.label$face, size = font.label$size/3, color = font.label$color, max.overlaps = max.overlaps) } else{ p <- p + ggrepel::geom_text_repel(data = labs_data, mapping = aes(label = name), box.padding = unit(0.35, "lines"), point.padding = unit(0.3, "lines"), force = 1, seed = seed, fontface = font.label$face, size = font.label$size/3, color = font.label$color, max.overlaps = max.overlaps) } p <- p + scale_x_continuous(breaks=seq(0, max(data$mean), 2))+ labs(x = xlab, y = ylab, title = main, color = "")+ # to remove legend title use color = "" geom_hline(yintercept = c(0, -log2(fc), log2(fc)), linetype = c(1, 2, 2), color = c("black", "black", "black")) p <- ggpar(p, palette = palette, ggtheme = ggtheme, ...) p } ggpubr/R/stat_overlay_normal_density.R0000644000176200001440000000427314332553655017730 0ustar liggesusers#' @include utilities.R NULL #' Overlay Normal Density Plot #' #' @description Overlay normal density plot (with the same mean and SD) to the #' density distribution of 'x'. This is useful for visually inspecting the #' degree of deviance from normality. #' @inheritParams ggplot2::layer #' @param ... other arguments to pass to \code{\link[ggplot2:geom_path]{geom_line}}. #' @param na.rm If FALSE (the default), removes missing values with a warning. #' If TRUE silently removes missing values. #' @seealso \code{\link{ggdensity}} #' @examples #' # Simpledensity plot #' data("mtcars") #' ggdensity(mtcars, x = "mpg", fill = "red") + #' scale_x_continuous(limits = c(-1, 50)) + #' stat_overlay_normal_density(color = "red", linetype = "dashed") #' #' # Color by groups #' data(iris) #' ggdensity(iris, "Sepal.Length", color = "Species") + #' stat_overlay_normal_density(aes(color = Species), linetype = "dashed") #' #' #' # Facet #' ggdensity(iris, "Sepal.Length", facet.by = "Species") + #' stat_overlay_normal_density(color = "red", linetype = "dashed") #' #' @export stat_overlay_normal_density <- function(mapping = NULL, data = NULL, geom = "line", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ...) { if(is.null(mapping)){ mapping <- ggplot2::aes(y = NULL) }else{ mapping["y"] <- list(NULL) } layer( stat = StatOverlayNormalDensity, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(na.rm = na.rm, ...) ) } StatOverlayNormalDensity<- ggproto("StatOverlayNormalDensity", Stat, required_aes = c("x"), compute_group = function(data, scales) { x <- data$x .mean <- mean(x, na.rm = TRUE) .sd <- stats::sd(x, na.rm = TRUE) probability.points <- stats::ppoints(length(x[!(is.na(x))])) res.density <- stats::density(stats::qnorm(probability.points, .mean, .sd)) res.density <- data.frame(x = res.density$x, y = res.density$y) res.density } ) ggpubr/R/add_summary.R0000644000176200001440000002353114334273471014405 0ustar liggesusers#' @include utilities.R NULL #'Add Summary Statistics onto a ggplot. #'@description add summary statistics onto a ggplot. #'@param p a ggplot on which you want to add summary statistics. #'@param fun a function that is given the complete data and should return a data #' frame with variables ymin, y, and ymax. Allowed values are one of: "mean", #' "mean_se", "mean_sd", "mean_ci", "mean_range", "median", "median_iqr", #' "median_hilow", "median_q1q3", "median_mad", "median_range". #'@param error.plot plot type used to visualize error. Allowed values are one of #' \code{c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", #' "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", #' "lower_linerange")}. Default value is "pointrange". #'@param color point or outline color. #'@param fill fill color. Used only whne \code{error.plot = "crossbar"}. #'@param group grouping variable. Allowed values are 1 (for one group) or a #' character vector specifying the name of the grouping variable. Used only for #' adding statistical summary per group. #'@param width numeric value between 0 and 1 specifying bar or box width. #' Example width = 0.8. Used only when \code{error.plot} is one of #' c("crossbar", "errorbar"). #'@param shape point shape. Allowed values can be displayed using the function #' \code{\link{show_point_shapes}()}. #'@param size numeric value in [0-1] specifying point and line size. #'@param linetype line type. #'@param show.legend logical. Should this layer be included in the legends? NA, #' the default, includes if any aesthetics are mapped. \code{FALSE} never includes, #' and TRUE always includes. It can also be a named logical vector to finely #' select the aesthetics to display. #'@param data a \code{data.frame} to be displayed. If \code{NULL}, the default, #' the data is inherited from the plot data as specified in the call to #' \link[ggplot2]{ggplot}. #'@param position position adjustment, either as a string, or the result of a #' call to a position adjustment function. Used to adjust position for multiple #' groups. #'@param x a numeric vector. #'@param ci the percent range of the confidence interval (default is 0.95). #'@param error.limit allowed values are one of ("both", "lower", "upper", #' "none") specifying whether to plot the lower and/or the upper limits of #' error interval. #'@examples #' #'# Basic violin plot #'p <- ggviolin(ToothGrowth, x = "dose", y = "len", add = "none") #'p #' #'# Add mean_sd #'add_summary(p, "mean_sd") #' #' #'@describeIn add_summary add summary statistics onto a ggplot. #'@export add_summary <- function(p, fun = "mean_se", error.plot = "pointrange", color = "black", fill = "white", group = 1, width = NULL, shape = 19, size = 1, linetype = 1, show.legend = NA, ci = 0.95, data = NULL, position = position_dodge(0.8)) { if(is.null(data)) data <- p$data if(fun == "mean_se") fun <- "mean_se_" else if(fun == "median_hilow") fun <- "median_hilow_" allowed.fun <- .summary_functions() if(!(fun %in% allowed.fun)) stop("Don't support ", fun, ". Possibilities for the argument fun are: ", .collapse(allowed.fun, sep = ", ")) allowed.error.plot = c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", "lower_linerange") if(!(error.plot %in% allowed.error.plot)) stop("Don't support ", error.plot, ". Possibilities for the argument error.plot are: ", .collapse(allowed.error.plot, sep = ", ")) if(missing(width)) width <- 0.8 .map <- .mapping(p) if(missing(color) & !is.null(.map$colour)) color <- .map$colour if(missing(fill) & !is.null(.map$fill)) fill <- .map$fill # Error limits #:::::::::::::::::::::::::::::::::::::::::::::::::: . <- NULL error.limit <- strsplit(error.plot, "_") %>% unlist() %>% .[1] if(!(error.limit %in% c("upper", "lower"))) error.limit <- "both" if(fun %in% c("mean", "median")) error.limit <- "none" # Defining plot geometry #:::::::::::::::::::::::::::::::::::::::::::::::::: geom <- error.plot if(error.plot %in% c("pointrange", "lower_pointrange", "upper_pointrange")) geom <- "pointrange" else if(error.plot %in% c("linerange", "lower_linerange", "upper_linerange")) geom <- "linerange" else if(error.plot %in% c("errorbar", "lower_errorbar", "upper_errorbar")) geom <- "errorbar" fun.data <- fun.y <- fun.ymin <- fun.ymax <- NULL if(fun %in% c("mean", "median")){ fun.y <- fun.ymin <- fun.ymax <- fun } else fun.data <- fun # General option #:::::::::::::::::::::::::::::::::::::::::::::::::: opts <- list(geomfunc = "stat_summary", fun.data = fun.data, fun.y = fun.y, fun.ymin = fun.ymin, fun.ymax = fun.ymax, color = color, geom = geom, size = size, linetype = linetype, show.legend = show.legend, data = data, position = position, fun.args = list(error.limit = error.limit), group = group) if(fun %in% c("mean_ci", "median_hilow_")){ opts$fun.args$ci <- ci } # Specific option #:::::::::::::::::::::::::::::::::::::::::::::::::: if(geom == "crossbar") opts <- opts %>% .add_item(fill = fill, width = width) else if(geom == "errorbar"){ if(missing(width)) opts$width = 0.1 else opts$width = width } opts %>% .update_plot(p) } #' @describeIn add_summary returns the \code{mean} and the error limits defined by the #' \code{standard error}. We used the name \code{mean_se_}() to avoid masking \code{\link[ggplot2]{mean_se}}(). #' @export mean_se_ <- function(x, error.limit = "both") { length <- base::sum(!is.na(x)) sd = stats::sd(x, na.rm=TRUE) se <- sd / sqrt(length) .mean <- base::mean(x, na.rm = TRUE) data.frame( y = .mean, ymin = .mean - se, ymax = .mean + se ) %>% .format_error(error.limit) } #' @describeIn add_summary returns the \code{mean} and the error limits defined by the #' \code{standard deviation}. #' @export mean_sd <- function(x, error.limit = "both"){ sd = stats::sd(x, na.rm=TRUE) .mean <- base::mean(x, na.rm = TRUE) data.frame( y = .mean, ymin = .mean - sd, ymax = .mean + sd ) %>% .format_error(error.limit) } #' @describeIn add_summary returns the \code{mean} and the error limits defined by the #' \code{confidence interval}. #' @export mean_ci <- function(x, ci = 0.95, error.limit = "both"){ length <- base::sum(!is.na(x)) sd = stats::sd(x, na.rm=TRUE) se <- sd / sqrt(length) .mean <- base::mean(x, na.rm = TRUE) ci <- stats::qt(ci/2 + .5, length-1)*se data.frame( y = .mean, ymin = .mean - ci, ymax = .mean + ci ) %>% .format_error(error.limit) } #' @describeIn add_summary returns the \code{mean} and the error limits defined by the #' \code{range = max - min}. #' @export mean_range <- function(x, error.limit = "both"){ .mean <- base::mean(x, na.rm = TRUE) .min <- base::min(x, na.rm=TRUE) .max <- base::max(x, na.rm=TRUE) .range <- .max - .min data.frame( y = .mean, ymin = .mean - .range, ymax = .mean + .range ) %>% .format_error(error.limit) } #' @describeIn add_summary returns the \code{median} and the error limits #' defined by the \code{interquartile range}. #' @export median_iqr <- function(x, error.limit = "both"){ .median = stats::median(x, na.rm=TRUE) .iqr <- stats::IQR(x, na.rm=TRUE) data.frame( y = .median, ymin = .median - .iqr, ymax = .median + .iqr ) %>% .format_error(error.limit) } #' @describeIn add_summary computes the sample median and a selected pair of #' outer quantiles having equal tail areas. This function is a reformatted #' version of \code{Hmisc::smedian.hilow()}. The confidence limits are computed #' as follow: \code{lower.limits = (1-ci)/2} percentiles; \code{upper.limits = #' (1+ci)/2} percentiles. By default (\code{ci = 0.95}), the 2.5th and the #' 97.5th percentiles are used as the lower and the upper confidence limits, #' respectively. If you want to use the 25th and the 75th percentiles as the #' confidence limits, then specify \code{ci = 0.5} or use the function #' \code{median_q1q3()}. #' @export median_hilow_ <- function(x, ci = 0.95, error.limit = "both"){ quant <- stats::quantile( x, probs = c(0.5, (1 - ci)/2, (1 + ci)/2), na.rm = TRUE ) names(quant) <- c("median", "lower", "upper") data.frame( y = quant["median"], ymin = quant["lower"], ymax = quant["upper"] ) %>% .format_error(error.limit) } #' @describeIn add_summary computes the sample median and, the 25th and 75th #' percentiles. Wrapper around the function \code{median_hilow_()} using #' \code{ci = 0.5}. #' @export median_q1q3 <- function(x, error.limit = "both"){ median_hilow_(x, ci = 0.5, error.limit = error.limit) } #' @describeIn add_summary returns the \code{median} and the error limits #' defined by the \code{median absolute deviation}. #' @export median_mad <- function(x, error.limit = "both"){ .median = stats::median(x, na.rm=TRUE) .mad = stats::mad(x, na.rm=TRUE) data.frame( y = .median, ymin = .median - .mad, ymax = .median + .mad ) %>% .format_error(error.limit) } #' @describeIn add_summary returns the \code{median} and the error limits #' defined by the \code{range = max - min}. #' @export median_range <- function(x, error.limit = "both"){ .median = stats::median(x, na.rm=TRUE) .min <- base::min(x, na.rm=TRUE) .max <- base::max(x, na.rm=TRUE) .range <- .max - .min data.frame( y = .median, ymin = .median - .range, ymax = .median + .range ) %>% .format_error(error.limit) } # Format error .format_error <- function(d, error.limit = "both"){ if(error.limit == "upper") d$ymin <- d$y else if(error.limit == "lower") d$ymax <- d$y else if(error.limit == "none") d$ymin <- d$ymax <- d$y d } ggpubr/R/ggadd.R0000644000176200001440000001533114340445172013141 0ustar liggesusers#' @include utilities.R NULL #'Add Summary Statistics or a Geom onto a ggplot #'@description Add summary statistics or a geometry onto a ggplot. #'@inheritParams add_summary #'@param p a ggplot #'@param add character vector specifying other plot elements to be added. #' Allowed values are one or the combination of: "none", "dotplot", "jitter", #' "boxplot", "point", "mean", "mean_se", "mean_sd", "mean_ci", "mean_range", #' "median", "median_iqr", "median_hilow", "median_q1q3", "median_mad", #' "median_range". #'@param color point or outline color. #'@param fill fill color. Used only when \code{error.plot = "crossbar"}. #'@param group grouping variable. Allowed values are 1 (for one group) or a #' character vector specifying the name of the grouping variable. Used only for #' adding statistical summary per group. #'@param width numeric value between 0 and 1 specifying bar or box width. #' Example width = 0.8. Used only when \code{error.plot} is one of #' c("crossbar", "errorbar"). #'@param shape point shape. Allowed values can be displayed using the function #' \code{\link{show_point_shapes}()}. #'@param size numeric value in [0-1] specifying point and line size. #'@param linetype line type. #'@param show.legend logical. Should this layer be included in the legends? NA, #' the default, includes if any aesthetics are mapped. \code{FALSE} never #' includes, and TRUE always includes. It can also be a named logical vector to #' finely select the aesthetics to display. #'@param alpha numeric value specifying fill color transparency. Value should be #' in [0, 1], where 0 is full transparency and 1 is no transparency. #'@param jitter a numeric value specifying the amount of jittering. Used only #' when \code{add} contains "jitter". #'@param seed A random seed to make the jitter reproducible. Default is `123`. Useful if you need #' to apply the same jitter twice, e.g., for a point and a corresponding label. #' The random seed is reset after jittering. If `NA`, the #' seed is initialized with a random value; this makes sure that two subsequent #' calls start with a different seed. Use NULL to use the current random seed #' and also avoid resetting (the behaviour of ggplot 2.2.1 and earlier). #'@param binwidth numeric value specifying bin width. use value between 0 and 1 #' when you have a strong dense dotplot. For example binwidth = 0.2. Used only #' when \code{add} contains "dotplot". #'@param dotsize as \code{size} but applied only to dotplot. #'@param p_geom the geometry of the main plot. Ex: p_geom = "geom_line". If #' NULL, the geometry is extracted from p. Used only by \link{ggline}(). #' @examples #'# Basic violin plot #'data("ToothGrowth") #'p <- ggviolin(ToothGrowth, x = "dose", y = "len", add = "none") #' #'# Add mean +/- SD and jitter points #'p %>% ggadd(c("mean_sd", "jitter"), color = "dose") #' #'# Add box plot #'p %>% ggadd(c("boxplot", "jitter"), color = "dose") #' #'@export ggadd <- function(p, add = NULL, color = "black", fill = "white", group = 1, width = 1, shape = 19, size = NULL, alpha = 1, jitter = 0.2, seed = 123, binwidth = NULL, dotsize = size, linetype = 1, show.legend = NA, error.plot = "pointrange", ci = 0.95, data = NULL, position = position_dodge(0.8), p_geom = "" ) { . <- NULL if(missing(group)) group <- NULL # Checkpoints #::::::::::::::::::::::::::::::::::::::::::: if("none" %in% add) add <- "none" # Adding mean or median point center <- intersect(c("mean", "median"), add) if(length(center) == 2) stop("Use mean or mdedian, but not both at the same time.") # Adding error bars errors <- intersect(.errorbar_functions(), add) if(length(errors) > 1) stop("Choose only one of these: ", .collapse(errors, sep = ", ")) if(is.null(dotsize)) dotsize =1 # Data and mapping #::::::::::::::::::::::::::::::::::::::::::: if(is.null(data)) data <- p$data .map <- .mapping(p) x <- .map$x y <- .map$y if(missing(color) & !is.null(.map$colour)) color <- .map$colour if(missing(fill) & !is.null(.map$fill)) fill <- .map$fill ngrps <- intersect(names(data), c(.map$x, fill, color, group)) %>% length() # number of grouping variables # Amount of jittering when add = "jitter" #::::::::::::::::::::::::::::::::::::::::::: .jitter <- jitter if(is.numeric(jitter)) jitter <- position_jitter(jitter, seed = seed) if(p_geom == "geom_line" & ngrps > 1){} else if(ngrps > 1) jitter <- position_jitterdodge(jitter.width = .jitter, dodge.width = 0.8, seed = seed) common.opts <- opts <- list(data = data, color = color, fill = fill, size = size, position = position, alpha = alpha, show.legend = show.legend) if ("boxplot" %in% add) { if(.geom(p) == "violin" & missing(width)) width = 0.2 else if(missing(width)) width = 0.7 p <- common.opts %>% .add_item(geomfunc = geom_boxplot, width = width) %>% .update_plot(p) } if ("violin" %in% add) { if(missing(width)) width = 1 p <- common.opts %>% .add_item(geomfunc = geom_violin, width = width, trim = FALSE) %>% .update_plot(p) } if ( "dotplot" %in% add ) { p <- common.opts %>% .add_item(geomfunc = geom_dotplot, binaxis = 'y', stackdir = 'center', dotsize = dotsize, stackratio = 1, binwidth = binwidth) %>% .update_plot(p) } if ( "jitter" %in% add ){ jitter.opts <- common.opts if(!(shape %in% 21:25)) jitter.opts$fill <- NULL p <- jitter.opts %>% .add_item(geomfunc = geom_jitter, position = jitter, shape = shape) %>% .update_plot(p) } if ( "point" %in% add ) { p <- common.opts %>% .remove_item("fill") %>% .add_item(geomfunc = geom_point, group = group) %>% .update_plot(p) } if ( "line" %in% add ) { p <- common.opts %>% .remove_item("fill") %>% .add_item(geomfunc = geom_line, group = 1) %>% .update_plot(p) } # Add mean or median #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: if(!.is_empty(center)) p <- p %>% add_summary(fun = center, color = color, shape = shape, position = position, size = size, group = group) # Add erors #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: if(!.is_empty(errors)){ if(missing(width)){ if(error.plot %in% c("errorbar", "lower_errorbar", "upper_errorbar")) width <- 0.1 else if(error.plot == "crossbar" & .geom(p) == "violin") width = 0.2 } p <- p %>% add_summary(errors, error.plot = error.plot, color = color, shape = shape, position = position, size = size, width = width, ci = ci, group = group, linetype = linetype, show.legend = show.legend) } p } ggpubr/R/show_line_types.R0000644000176200001440000000142214332553655015311 0ustar liggesusers#' @include utilities.R ggpar.R NULL #' Line types available in R #' @description Show line types available in R. #' @return a ggplot. #' #' @seealso \code{\link{ggpar}} and \code{\link{ggline}}. #' @examples #' show_line_types()+ #' theme_minimal() #' @export show_line_types <- function() { lt <- c("blank", "solid", "dashed", "dotted", "dotdash", "longdash", "twodash") d <- data.frame(lt = factor(lt, levels = lt)) ggplot() + scale_x_continuous(name="", limits=c(0,1), breaks=NULL) + scale_linetype_identity() + geom_segment(data=d, mapping=aes(x=0, xend=1, y=lt, yend=lt, linetype=lt))+ labs(title = "Line types available in R", y = "")+ theme(axis.text.y = element_text(face="bold", color="black")) } ggpubr/R/stat_kruskal_test.R0000644000176200001440000001077614332576562015662 0ustar liggesusers#' @include utilities.R utils_stat_test_label.R stat_anova_test.R NULL #'Add Kruskal-Wallis Test P-values to a GGPlot #'@description Add Kruskal-Wallis test p-values to a ggplot, such as #' box blots, dot plots and stripcharts. #'@inheritParams ggplot2::layer #'@inheritParams stat_pvalue_manual #'@inheritParams stat_anova_test #' #'@section Computed variables: \itemize{ #' \item{statistic}: the Kruskal-Wallis rank sum chi-squared statistic used to compute the p-value. #' \item{p}: p-value. #' \item{p.adj}: Adjusted p-values. #' \item{p.signif}: P-value significance. #' \item{p.adj.signif}: Adjusted p-value significance. #' \item{p.format}: Formated p-value. #' \item{p.adj.format}: Formated adjusted p-value. #' \item{n}: number of samples. #' } #' #' @examples #' # Data preparation #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Transform `dose` into factor variable #' df <- ToothGrowth #' df$dose <- as.factor(df$dose) #' # Add a random grouping variable #' set.seed(123) #' df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) #' df$len <- ifelse(df$group == "grp2", df$len+2, df$len) #' df$len <- ifelse(df$group == "grp3", df$len+7, df$len) #' head(df, 3) #' #' #' # Basic boxplot #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Create a basic boxplot #' # Add 5% and 10% space to the plot bottom and the top, respectively #' bxp <- ggboxplot(df, x = "dose", y = "len") + #' scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) #' #' # Add the p-value to the boxplot #' bxp + stat_kruskal_test() #' #' # Change the label position #' # Using coordinates in data units #' bxp + stat_kruskal_test(label.x = "1", label.y = 10, hjust = 0) #' #' # Format the p-value differently #' custom_p_format <- function(p) { #' rstatix::p_format(p, accuracy = 0.0001, digits = 3, leading.zero = FALSE) #' } #' bxp + stat_kruskal_test( #' label = "Kruskal-Wallis, italic(p) = {custom_p_format(p)}{p.signif}" #' ) #' #' # Show a detailed label in italic #' bxp + stat_kruskal_test(label = "as_detailed_italic") #' #' #' # Faceted plots #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Create a ggplot facet #' bxp <- ggboxplot(df, x = "dose", y = "len", facet.by = "supp") + #' scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) #' # Add p-values #' bxp + stat_kruskal_test() #' #' #' # Grouped plots #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' bxp2 <- ggboxplot(df, x = "group", y = "len", color = "dose", palette = "npg") #' #' # For each x-position, computes tests between legend groups #' bxp2 + stat_kruskal_test(aes(group = dose), label = "p = {p.format}{p.signif}") #' #' # For each legend group, computes tests between x variable groups #' bxp2 + stat_kruskal_test(aes(group = dose, color = dose), group.by = "legend.var") #' #' @export stat_kruskal_test <- function(mapping = NULL, data = NULL, group.by = NULL, label = "{method}, p = {p.format}", label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, step.increase = 0.1, p.adjust.method = "holm", significance = list(), geom = "text", position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, parse = FALSE, ...) { label <- get_kruskal_test_label_template(label) if(missing(parse) & is_plotmath_expression(label)){ parse <- TRUE } layer( stat = StatCompareMultipleMeans, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list( method = "kruskal_test", group.by = group.by, method.args = list(), correction = "none", na.rm = na.rm, stat.label = label, label.x.npc = label.x.npc , label.y.npc = label.y.npc, label.x = label.x, label.y = label.y, parse = parse, is.group.specified = is_group_aes_specified(mapping), step.increase = step.increase, p.adjust.method = p.adjust.method, significance = fortify_signif_symbols_encoding(significance), ... ) ) } get_kruskal_test_label_template <- function(label){ switch( label, as_italic = "{method}, italic(p) = {p.format}", as_detailed = "{method}, X2({df}) = {statistic}, p = {p.format}, n = {n}", as_detailed_italic = "{method}, italic(chi)^2 ({df}) = {statistic}, italic(p) = {p.format}, italic(n) = {n}", as_detailed_expression = "{method}, italic(chi)^2({df}) = {statistic}, italic(p) = {p.format}, italic(n) = {n}", label ) } ggpubr/R/utils-pipe.R0000644000176200001440000000031714332553655014173 0ustar liggesusers#' Pipe operator #' #' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. #' #' @name %>% #' @rdname pipe #' @keywords internal #' @export #' @importFrom magrittr %>% #' @usage lhs \%>\% rhs NULL ggpubr/R/show_point_shapes.R0000644000176200001440000000137514332553655015641 0ustar liggesusers#' @include utilities.R NULL #' Point shapes available in R #' @description Show point shapes available in R. #' @return a ggplot. #' #' @seealso \code{\link{ggpar}} and \code{\link{ggline}}. #' @examples #' show_point_shapes()+ #' theme_minimal() #' @export show_point_shapes <- function() { d=data.frame(p=c(0:25)) p <- ggplot() + scale_y_continuous(name="") + scale_x_continuous(name="") + scale_shape_identity() + geom_point(data=d, mapping=aes(x=p%%6, y=p%/%6, shape=p), size=5, fill="blue") + geom_text(data=d, mapping=aes(x=p%%6, y=p%/%6+0.25, label=p), size=3)+ scale_y_reverse() + theme( axis.title = element_blank() ) ggpar(p, ticks = FALSE, tickslab = FALSE, main = "Point shapes available in R") } ggpubr/R/stat_pvalue_manual.R0000644000176200001440000003204214332576562015766 0ustar liggesusers#' @include utilities.R geom_bracket.R #' @importFrom dplyr pull #' @importFrom glue glue NULL #'Add Manually P-values to a ggplot #' #'@description Add manually p-values to a ggplot, such as box blots, dot plots #' and stripcharts. Frequently asked questions are available on \href{https://www.datanovia.com/en/blog/tag/ggpubr/}{Datanovia ggpubr FAQ page}, for example: #' \itemize{ #' \item \href{https://www.datanovia.com/en/blog/how-to-add-p-values-onto-basic-ggplots/}{How to Add P-Values onto Basic GGPLOTS} #' \item \href{https://www.datanovia.com/en/blog/ggpubr-how-to-add-adjusted-p-values-to-a-multi-panel-ggplot/}{How to Add Adjusted P-values to a Multi-Panel GGPlot} #' \item \href{https://www.datanovia.com/en/blog/how-to-add-p-values-to-ggplot-facets/}{How to Add P-values to GGPLOT Facets} #' \item \href{https://www.datanovia.com/en/blog/ggpubr-how-to-add-p-values-generated-elsewhere-to-a-ggplot/}{How to Add P-Values Generated Elsewhere to a GGPLOT} #' \item \href{https://www.datanovia.com/en/blog/how-to-add-p-values-onto-a-grouped-ggplot-using-the-ggpubr-r-package/}{How to Add P-Values onto a Grouped GGPLOT using the GGPUBR R Package} #' \item \href{https://www.datanovia.com/en/blog/how-to-create-stacked-bar-plots-with-error-bars-and-p-values/}{How to Create Stacked Bar Plots with Error Bars and P-values} #' \item \href{https://www.datanovia.com/en/blog/how-to-add-p-values-onto-horizontal-ggplots/}{How to Add P-Values onto Horizontal GGPLOTS} #' } #'@inheritParams geom_bracket #'@param data a data frame containing statitistical test results. The expected #' default format should contain the following columns: \code{group1 | group2 | #' p | y.position | etc}. \code{group1} and \code{group2} are the groups that #' have been compared. \code{p} is the resulting p-value. \code{y.position} is #' the y coordinates of the p-values in the plot. #'@param label the column containing the label (e.g.: label = "p" or label = #' "p.adj"), where \code{p} is the p-value. Can be also an expression that can #' be formatted by the \code{\link[glue]{glue}()} package. For example, when #' specifying label = "t-test, p = \{p\}", the expression \{p\} will be #' replaced by its value. #'@param y.position column containing the coordinates (in data units) to be used #' for absolute positioning of the label. Default value is "y.position". Can be #' also a numeric vector. #'@param xmin column containing the position of the left sides of the brackets. #' Default value is "group1". #'@param xmax (optional) column containing the position of the right sides of #' the brackets. Default value is "group2". If NULL, the p-values are plotted #' as a simple text. #'@param x x position of the p-value. Should be used only when you want plot the #' p-value as text (without brackets). #'@param size,label.size size of label text. #'@param bracket.size Width of the lines of the bracket. #'@param color text and line color. Can be variable name in the data for coloring by groups. #'@param linetype linetype. Can be variable name in the data for changing linetype by groups. #'@param tip.length numeric vector with the fraction of total height that the #' bar goes down to indicate the precise column. Default is 0.03. #'@param remove.bracket logical, if \code{TRUE}, brackets are removed from the #' plot. Considered only in the situation, where comparisons are performed #' against reference group or against "all". #'@param hide.ns can be logical value or a character vector. #'\itemize{ #' \item Case when logical value. If TRUE, hide ns symbol when displaying #' significance levels. Filter is done by checking the column #' \code{p.adj.signif}, \code{p.signif}, \code{p.adj} and \code{p}. #' \item Case when character value. Possible values are "p" or "p.adj", for filtering out non significant. #' } #'@param vjust move the text up or down relative to the bracket. Can be also a #' column name available in the data. #'@param position position adjustment, either as a string, or the result of a #' call to a position adjustment function. #'@param ... other arguments passed to the function \code{geom_bracket()} or #' \code{geom_text()} #'@seealso \code{\link{stat_compare_means}} #'@examples #' #'# T-test #'stat.test <- compare_means( #' len ~ dose, data = ToothGrowth, #' method = "t.test" #') #'stat.test #' #'# Create a simple box plot #'p <- ggboxplot(ToothGrowth, x = "dose", y = "len") #'p #' #'# Perform a t-test between groups #'stat.test <- compare_means( #' len ~ dose, data = ToothGrowth, #' method = "t.test" #') #'stat.test #' #'# Add manually p-values from stat.test data #'# First specify the y.position of each comparison #'stat.test <- stat.test %>% #' mutate(y.position = c(29, 35, 39)) #'p + stat_pvalue_manual(stat.test, label = "p.adj") #' #'# Customize the label with glue expression #'# (https://github.com/tidyverse/glue) #'p + stat_pvalue_manual(stat.test, label = "p = {p.adj}") #' #' #' # Grouped bar plots #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' ToothGrowth$dose <- as.factor(ToothGrowth$dose) #' # Comparisons against reference #' stat.test <- compare_means( #' len ~ dose, data = ToothGrowth, group.by = "supp", #' method = "t.test", ref.group = "0.5" #' ) #' stat.test #' # Plot #' bp <- ggbarplot(ToothGrowth, x = "supp", y = "len", #' fill = "dose", palette = "jco", #' add = "mean_sd", add.params = list(group = "dose"), #' position = position_dodge(0.8)) #' bp + stat_pvalue_manual( #' stat.test, x = "supp", y.position = 33, #' label = "p.signif", #' position = position_dodge(0.8) #' ) #' #'@export stat_pvalue_manual <- function( data, label = NULL, y.position = "y.position", xmin = "group1", xmax = "group2", x = NULL, size = 3.88, label.size = size, bracket.size = 0.3, bracket.nudge.y = 0, bracket.shorten = 0, color = "black", linetype = 1, tip.length = 0.03, remove.bracket = FALSE, step.increase = 0, step.group.by = NULL, hide.ns = FALSE, vjust = 0, coord.flip = FALSE, position = "identity", ... ) { if(is.null(label)){ label <- guess_signif_label_column(data) } # Hide NS if(is.logical(hide.ns)){ if(hide.ns) data <- remove_ns(data) } else if (is.character(hide.ns)){ filter <- dplyr::filter if(hide.ns == "p") data <- data %>% filter(.data$p <= 0.05) else if(hide.ns == "p.adj") data <- data %>% filter(.data$p.adj <= 0.05) } data <- asserttat_group_columns_exists(data) comparison <- detect_comparison_type(data) all.x.is.missing <- is.null(x) & missing(xmin) & missing(xmax) if(all(data$group1 == "all") & all.x.is.missing){ is.grouped <- length(data$group2) > length(unique(data$group2)) if(!is.grouped) x <- "group2" # labels will be plotted at x = "group2" } # Detect automatically if xmin and xmax exists in the data. if(all.x.is.missing){ if(all(c("xmin", "xmax") %in% colnames(data))){ xmin <- "xmin" xmax <- "xmax" } } # should stay before (!is.null(x)) if(remove.bracket){ group1.length <- unique(data$group1) %>% length() if(group1.length == 1) { xmin <- xmax xmax <- NULL } } # P-value displayed as text (without brackets) if(!is.null(x)){ xmin <- x xmax <- NULL } # If label is a glue package expression if(.contains_curlybracket(label)){ data <- data %>% mutate(label = glue(label)) label <- "label" } available.variables <- colnames(data) if(!(label %in% available.variables)) stop("can't find the label variable '", label, "' in the data") if(!(xmin %in% available.variables)) stop("can't find the xmin variable '", xmin, "' in the data") y.position <- .valide_y_position(y.position, data) if(is.numeric(y.position)){ data$y.position <- y.position y.position <- "y.position" } # If xmax is null, pvalue is drawn as text if(!is.null(xmax)) { xmax <- data %>% pull(!!xmax) pvalue.geom <- "bracket" } else { xmax <- NA pvalue.geom <- "text" } if(!is.null(xmin)){ xmin <- data %>% pull(!!xmin) } else{ xmin <- NA } # Build the statistical table for plotting xxmax <-xmax # so that mutate will avoid re-using an existing xmax in the data xxmin <- xmin data <- data %>% dplyr::mutate( label = as.character(data %>% pull(!!label)), y.position = data %>% pull(!!y.position), xmin = xxmin, xmax = xxmax ) # vjust if(is.character(vjust)){ vjust <- data %>% pull(!!vjust) } else if(missing(vjust)){ vjust <- guess_labels_default_vjust(data$label) } data <- data %>% mutate(vjust = !!vjust) if(pvalue.geom == "bracket"){ if(identical(data$xmin, data$xmax) | remove.bracket){ # case when ref.group = "all" bracket.size = 0 } geom_exec( geom_bracket, data = data, xmin = "xmin", xmax = "xmax", label = "label", y.position = "y.position", vjust = "vjust", group = 1:nrow(data), tip.length = tip.length, label.size = label.size, size = bracket.size, bracket.nudge.y = bracket.nudge.y, bracket.shorten = bracket.shorten, color = color, linetype = linetype, step.increase = step.increase, step.group.by = step.group.by, coord.flip = coord.flip, position = position, ... ) } else{ if(comparison == "each_vs_ref"){ ref.group <- unique(data$group1) group2 <- NULL data <- add_ctr_rows(data, ref.group = ref.group) mapping <- aes(x = xmin, y = y.position, vjust = vjust, label = label, group = group2) if(missing(position) & !missing(x)){ if (is_grouping_variable(x)) position <- position_dodge(0.8) } } else{ mapping <- aes(x = xmin, y = y.position, vjust = vjust, label = label) } option <- list(data = data, size = label.size, position = position, ...) if(color %in% colnames(data)) mapping$colour <- rlang::ensym(color) else option$color <- color option[["mapping"]] <- mapping do.call(geom_text, option) } } asserttat_group_columns_exists <- function(data){ groups.exist <- all(c("group1", "group2") %in% colnames(data)) if(!groups.exist){ if(inherits(data, "rstatix_test") & "group" %in% colnames(data)){ data$group1 <- "all" data$group2 <- data$group } else{ stop("data should contain group1 and group2 columns") } } invisible(data) } # get validate p-value y-position .valide_y_position <- function(y.position, data){ if(is.numeric(y.position)){ number.of.test <- nrow(data) number.of.ycoord <- length(y.position) xtimes <- number.of.test/number.of.ycoord if(number.of.ycoord < number.of.test) y.position <- rep(y.position, xtimes) } else if(is.character(y.position)){ if(!(y.position %in% colnames(data))) stop("can't find the y.position variable '", y.position, "' in the data") } return(y.position) } # Check if a string contains curly bracket .contains_curlybracket <- function(x){ grepl("\\{|\\}", x, perl = TRUE) } # For ctr rows: the comparaison of ctr against itself # useful only when positionning the label of grouped bars add_ctr_rows <- function(data, ref.group){ xmin <- NULL data <- keep_only_tbl_df_classes(data) ctr <- data %>% dplyr::distinct(xmin, .keep_all = TRUE) %>% mutate(group2 = ref.group) %>% mutate(label = " ") dplyr::bind_rows(ctr, data) } # Returns the type of comparisons: one_group, two_groups, each_vs_ref, pairwise detect_comparison_type <- function(data){ ngroup1 <- unique(data$group1) %>% length() ngroup2 <- unique(data$group2) %>% length() if(is_null_model(data)){ type = "one_group" } else if(ngroup1 == 1 & ngroup2 >= 2){ type = "each_vs_ref" } else if(ngroup1 == 1 & ngroup2 == 1){ type = "two_groups" } else if (ngroup1 >= 2 & ngroup2 >= 2){ type = "pairwise" } else if(all(c("group1", "group2") %in% colnames(data))){ # filtered data type = "pairwise" } else{ stop("Make sure that group1 and group2 columns exist in the data.") } type } is_null_model <- function(data){ group2 <- unique(data$group2) .diff <- setdiff(group2, "null model") length(.diff) == 0 } is_grouping_variable <- function(x){ !(x %in% c("group1", "group2")) } # Check if label column contains stars contains_signif_stars <- function(data, label.col){ result <- FALSE if(label.col[1] %in% colnames(data)){ labels <- data %>% pull(!!label.col) stars <- c("****", "***", "**", "*") result <- any(labels %in% stars) } result } # guess label default vjust guess_label_default_vjust <- function(label){ if(label %in% c("****", "***", "**", "*")) vjust <- 0.5 else vjust <- 0 vjust } guess_labels_default_vjust <- function(labels){ labels %>% purrr::map(guess_label_default_vjust) %>% unlist() } # remove non significant remove_ns <- function(data){ filter <- dplyr::filter columns <- colnames(data) if("p.adj.signif" %in% columns){ data <- data %>% filter(.data$p.adj.signif != "ns") } else if("p.adj" %in% columns){ data <- data %>% filter(.data$p.adj <= 0.05) } else if("p.signif" %in% columns){ data <- data %>% filter(.data$p.signif != "ns") } else if("p" %in% columns){ data <- data %>% filter(.data$p <= 0.05) } data } ggpubr/R/rotate.R0000644000176200001440000000076014332553655013400 0ustar liggesusers#'Rotate a ggplot Horizontally #' #'@description Rotate a ggplot to create horizontal plots. Wrapper around #' \code{\link[ggplot2]{coord_flip}}. #'@param ... other arguments to pass to \code{\link[ggplot2]{coord_flip}}. #' #'@examples #'# Load data #'data("ToothGrowth") #'df <- ToothGrowth #' #'# Basic plot #'p <- ggboxplot(df, x = "dose", y = "len", #' color = "dose", palette = "jco") #'p #'# Create horizontal plots #'p + rotate() #'@export rotate <- function(...){ coord_flip(...) } ggpubr/R/ggpar.R0000644000176200001440000002113714367732414013203 0ustar liggesusers#' @include utilities.R NULL #' Graphical parameters #' #' @param p an object of class ggplot or a list of ggplots #' #' @param palette the color palette to be used for coloring or filling by #' groups. Allowed values include "grey" for grey color palettes; brewer #' palettes e.g. "RdBu", "Blues", ...; or custom color palette e.g. c("blue", #' "red"); and scientific journal palettes from ggsci R package, e.g.: "npg", #' "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and #' "rickandmorty". Can be also a numeric vector of length(groups); in this #' case a basic color palette is created using the function #' \link[grDevices]{palette}. #' @param gradient.cols vector of colors to use for n-colour gradient. Allowed #' values include brewer and ggsci color palettes. #' @param main plot main title. #' @param title plot main title. #' @param submain,subtitle plot subtitle. #' @param caption plot caption. #' @param xlab character vector specifying x axis labels. Use xlab = FALSE to #' hide xlab. #' @param ylab character vector specifying y axis labels. Use ylab = FALSE to #' hide ylab. #' @param font.main,font.submain,font.caption,font.x,font.y a vector of length 3 #' indicating respectively the size (e.g.: 14), the style (e.g.: "plain", #' "bold", "italic", "bold.italic") and the color (e.g.: "red") of main title, #' subtitle, caption, xlab and ylab, respectively. For example \emph{font.x = #' c(14, "bold", "red")}. Use font.x = 14, to change only font size; or use #' font.x = "bold", to change only font face. #' @param font.title,font.subtitle alias of font.submain and font.submain, #' respectively. #' @param font.family character vector specifying font family. #' @param xlim,ylim a numeric vector of length 2, specifying x and y axis #' limits (minimum and maximum), respectively. e.g.: ylim = c(0, 50). #' @param xscale,yscale x and y axis scale, respectively. Allowed values are one #' of c("none", "log2", "log10", "sqrt"); e.g.: yscale="log2". #' @param format.scale logical value. If TRUE, axis tick mark labels will be #' formatted when xscale or yscale = "log2" or "log10". #' @param legend character specifying legend position. Allowed values are one of #' c("top", "bottom", "left", "right", "none"). To remove the legend use #' legend = "none". Legend position can be also specified using a numeric #' vector c(x, y); see details section. #' @param legend.title legend title, e.g.: \code{legend.title = "Species"}. Can #' be also a list, \code{legend.title = list(color = "Species", linetype = "Species", #' shape = "Species")}. #' @param font.legend legend text font style; e.g.: font.legend = c(10, "plain", #' "black"). #' @param ticks logical value. Default is TRUE. If FALSE, hide axis tick marks. #' @param tickslab logical value. Default is TRUE. If FALSE, hide axis tick #' labels. #' @param font.tickslab,font.xtickslab,font.ytickslab Font style (size, face, #' color) for tick labels, e.g.: c(14, "bold", "red"). #' @param x.text.angle,y.text.angle Numeric value specifying the rotation angle #' of x and y axis tick labels, respectively. Default value is NULL. For #' vertical x axis texts use x.text.angle = 90. #' @param xtickslab.rt,ytickslab.rt Same as x.text.angle and y.text.angle, #' respectively. Will be deprecated in the near future. #' @param xticks.by,yticks.by numeric value controlling x and y axis breaks, #' respectively. For example, if yticks.by = 5, a tick mark is shown on every #' 5. Default value is NULL. #' @param rotate logical value. If TRUE, rotate the graph by setting the plot #' orientation to horizontal. #' @param orientation change the orientation of the plot. Allowed values are one #' of c( "vertical", "horizontal", "reverse"). Partial match is allowed. #' @param ggtheme function, ggplot2 theme name. Default value is theme_pubr(). #' Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), #' theme_minimal(), theme_classic(), theme_void(), .... #' @param ... not used #' @examples #' # Load data #' data("ToothGrowth") #' df <- ToothGrowth #' #' # Basic box plot #' # +++++++++++++++++++++++++++ #' #' p <- ggboxplot(df, x = "dose", y = "len") #' #' # Change the plot orientation: horizontal #' ggpar(p, orientation = "horiz") #' #' #' # Change main title and axis labels #' # ++++++++++++++++++++++++++++ #' #' ggpar(p, #' main = "Plot of length \n by dose", #' xlab = "Dose (mg)", ylab = "Length") #' #' # Title font styles: 'plain', 'italic', 'bold', 'bold.italic' #' ggpar(p, #' main = "Length by dose", #' font.main = c(14,"bold.italic", "red"), #' font.x = c(14, "bold", "#2E9FDF"), #' font.y = c(14, "bold", "#E7B800")) #' #' # Hide axis labels #' ggpar(p, xlab = FALSE, ylab = FALSE) #' #' #' # Change colors #' # ++++++++++++++++++++++ #' #' # Change outline colors by groups: dose #' p2 <- ggboxplot(df, "dose", "len", color = "dose") #' p2 #' #' # Use custom color palette #' ggpar(p2, palette = c("#00AFBB", "#E7B800", "#FC4E07")) #' #' # Use brewer palette #' ggpar(p2, palette = "Dark2" ) #' #' # Use grey palette #' ggpar(p2, palette = "grey") #' #' # Use scientific journal palette from ggsci package #' ggpar(p2, palette = "npg") # nature #' #' # Axis ticks, limits, scales #' # +++++++++++++++++++++++++ #' #' # Axis ticks labels and rotation #' ggpar(p, #' font.tickslab = c(14,"bold", "#993333"), #' xtickslab.rt = 45, ytickslab.rt = 45) #' # Hide axis ticks and tick labels #' ggpar(p, ticks = FALSE, tickslab = FALSE) #' #' # Axis limits #' ggpar(p, ylim = c(0, 50)) #' #' # Axis scale #' ggpar(p, yscale = "log2") #' #' # Format axis scale #' ggpar(p, yscale = "log2", format.scale = TRUE) #' #' # Legends #' # ++++++++++++++++++ #' # Change legend position and title #' ggpar(p2, #' legend = "right", legend.title = "Dose (mg)", #' font.legend = c(10, "bold", "red")) #' #' @export ggpar <- function(p, palette = NULL, gradient.cols = NULL, main = NULL, submain = NULL, caption = NULL, xlab = NULL, ylab = NULL, title = NULL, subtitle = NULL, font.main = NULL, font.submain = NULL, font.x = NULL, font.y = NULL, font.caption = NULL, font.title = NULL, font.subtitle = NULL, font.family = "", xlim = NULL, ylim = NULL, xscale = c("none", "log2", "log10", "sqrt"), yscale = c("none", "log2", "log10", "sqrt"), format.scale = FALSE, legend = NULL, legend.title = NULL, font.legend = NULL, ticks = TRUE, tickslab = TRUE, font.tickslab = NULL, font.xtickslab = font.tickslab, font.ytickslab = font.tickslab, x.text.angle = NULL, y.text.angle = NULL, xtickslab.rt = x.text.angle, ytickslab.rt = y.text.angle, xticks.by = NULL, yticks.by = NULL, rotate = FALSE, orientation = c("vertical", "horizontal", "reverse"), ggtheme = NULL, ...) { original.p <- p if(rotate) orientation <- "horizontal" if(is.ggplot(original.p)) list.plots <- list(original.p) else if(is.list(original.p)) list.plots <- original.p else stop("Can't handle an object of class ", class (original.p)) if(!is.null(title)) main <- title if(!is.null(subtitle)) submain <- subtitle if(!is.null(font.title)) font.main <- font.title if(!is.null(font.subtitle)) font.submain <- font.subtitle if(is.numeric(palette)) palette <- grDevices::palette()[palette] for(i in 1:length(list.plots)){ p <- list.plots[[i]] if(is.ggplot(p)){ p <- p + .ggcolor(palette)+ .ggfill(palette) if(!is.null(ggtheme)) p <- p + ggtheme # labs_pubr() + if(!is.null(gradient.cols)) p <- p + .gradient_col(gradient.cols) p <- p +.set_ticks(ticks, tickslab, font.tickslab, xtickslab.rt, ytickslab.rt, font.xtickslab = font.xtickslab, font.ytickslab = font.ytickslab) p <- .set_ticksby(p, xticks.by, yticks.by) p <- p + .set_axis_limits(xlim, ylim) p <-.set_legend(p, legend, legend.title, font.legend) p <- .set_scale(p, xscale = xscale, yscale = yscale, format.scale = format.scale) p <- .labs(p, main, xlab, ylab, font.main, font.x, font.y, submain = submain, caption = caption, font.submain = font.submain, font.caption = font.caption) p <- .set_orientation(p, orientation) if(font.family != "") p <- p + theme(text = element_text(family = font.family)) list.plots[[i]] <- p } } if(is.ggplot(original.p)) list.plots[[1]] else list.plots } ggpubr/R/ggpaired.R0000644000176200001440000001214614342650175013661 0ustar liggesusers#'@include utilities.R ggpar.R NULL #'Plot Paired Data #'@description Plot paired data. #'@inheritParams ggboxplot #'@param cond1 variable name corresponding to the first condition. #'@param cond2 variable name corresponding to the second condition. #'@param x,y x and y variables, where x is a grouping variable and y contains #' values for each group. Considered only when \code{cond1} and \code{cond2} #' are missing. #'@param id variable name corresponding to paired samples' id. Used to connect #' paired points with lines. #'@param color points and box plot colors. To color by conditions, use color = #' "condition". #'@param fill box plot fill color. To change fill color by conditions, use fill #' = "condition". #'@param line.color line color. #'@param linetype line type. #'@param point.size,line.size point and line size, respectively. #'@param width box plot width. #'@param ... other arguments to be passed to be passed to \link{ggpar}(). #' @examples #' #'# Example 1 #'#:::::::::::::::::::::::::::::::::::::::::: #' before <-c(200.1, 190.9, 192.7, 213, 241.4, 196.9, 172.2, 185.5, 205.2, 193.7) #' after <-c(392.9, 393.2, 345.1, 393, 434, 427.9, 422, 383.9, 392.3, 352.2) #' #' d <- data.frame(before = before, after = after) #' ggpaired(d, cond1 = "before", cond2 = "after", #' fill = "condition", palette = "jco") #' #'# Example 2 #'#:::::::::::::::::::::::::::::::::::::::::: #'ggpaired(ToothGrowth, x = "supp", y = "len", #' color = "supp", line.color = "gray", line.size = 0.4, #' palette = "npg") #' #'@export ggpaired <- function(data, cond1, cond2, x = NULL, y = NULL, id = NULL, color = "black", fill = "white", palette = NULL, width = 0.5, point.size = 1.2, line.size = 0.5, line.color = "black", linetype = "solid", title = NULL, xlab = "Condition", ylab = "Value", facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, ggtheme = theme_pubr(), ...){ grouping.vars <- c(x, color, fill) %>% unique() %>% intersect(colnames(data)) if(!missing(cond1) & !missing(cond2)){ data <- data %>% df_gather( cols = c(cond1, cond2), names_to = "condition", values_to = "val" ) data$condition<- factor(data$condition, levels = c(cond1, cond2)) x <- "condition" y <- "val" } else if(!is.null(x) & !is.null(y)){ if(missing(xlab)) xlab <- x if(missing(ylab)) ylab <- y } # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( id = id, color = color, fill = fill, palette = palette, width = width, point.size = point.size, line.size = line.size, line.color = line.color, linetype = linetype, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, label = label, font.label = font.label, label.select = label.select, repel = repel, label.rectangle = label.rectangle, ggtheme = ggtheme, ...) # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$data <- data .opts$x <- x .opts$y <- y .opts$fun <- ggpaired_core if(missing(ggtheme) & (!is.null(facet.by))) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggpaired_core <- function(data, x = NULL, y = NULL, id = NULL, color = "black", fill = "white", palette = NULL, width = 0.5, point.size = 1.2, line.size = 0.5, line.color = "black", linetype = "solid", title = NULL, xlab = "Condition", ylab = "Value", ggtheme = theme_pubr(), ...) { if(!is.factor(data[[x]])) data[[x]] <- as.factor(data[[x]]) grouping.vars <- c(x, color, fill) %>% unique() %>% intersect(colnames(data)) # Add paired sample ids if(!is.null(id)) id <- .select_vec(data, id) else id <- rep(1:(nrow(data)/2), 2) data$id <- id position <- "identity" # if(length(grouping.vars) > 1) # position <- position_dodge(0.8) condition <- val <- id <- NULL p <- ggplot(data, create_aes(list(x = x, y = y))) + geom_exec(geom_boxplot, data = data, color = color, fill = fill, width = width, position = position)+ geom_exec(geom_line, data = data, group = "id", color = line.color, size = line.size, linetype = linetype, position = position) + geom_exec(geom_point, data = data, color = color, size = point.size, position = position) p <- ggpar(p, palette = palette, ggtheme = ggtheme, xlab = xlab, ylab = ylab, title = title, ...) p } ggpubr/R/ggballoonplot.R0000644000176200001440000002157614342705520014744 0ustar liggesusers#' Ballon plot #' #' @description Plot a graphical matrix where each cell contains a dot whose #' size reflects the relative magnitude of the corresponding component. Useful #' to visualize contingency table formed by two categorical variables. #' #' @inheritParams ggpar #' @param data a data frame. Can be: \itemize{ \item \bold{a standard #' contingency table} formed by two categorical variables: a data frame with #' row names and column names. The categories of the first variable are #' columns and the categories of the second variable are rows. \item \bold{a #' streched contingency table}: a data frame containing at least three columns #' corresponding, respectively, to (1) the categories of the first variable, #' (2) the categories of the second varible, (3) the frequency value. In this #' case, you should specify the argument x and y in the function #' \code{ggballoonplot()}}. #' @param x,y the column names specifying, respectively, the first and the #' second variable forming the contingency table. Required only when the data #' is a stretched contingency table. #' @param color point border line color. #' @param fill point fill color. Default is "lightgray". Considered only for #' points 21 to 25. #' @param shape points shape. The default value is 21. Alternaive values include #' 22, 23, 24, 25. #' @param size point size. By default, the points size reflects the relative #' magnitude of the value of the corresponding cell (\code{size = "value"}). #' Can be also numeric (\code{size = 4}). #' @param size.range a numeric vector of length 2 that specifies the minimum and #' maximum size of the plotting symbol. Default values are \code{size.range = #' c(1, 10)}. #' @param facet.by character vector, of length 1 or 2, specifying grouping variables for #' faceting the plot into multiple panels. Should be in the data. #' @param show.label logical. If TRUE, show the data cell values as point #' labels. #' @param font.label a vector of length 3 indicating respectively the size #' (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and #' the color (e.g.: "red") of point labels. For example font.label = c(14, #' "bold", "red"). To specify only the size and the style, use font.label = #' c(14, "plain"). #' @param rotate.x.text logica. If TRUE (default), rotate the x axis text. #' @param ... other arguments passed to the function \code{\link{ggpar}} #' #' @examples #' # Define color palette #' my_cols <- c("#0D0887FF", "#6A00A8FF", "#B12A90FF", #' "#E16462FF", "#FCA636FF", "#F0F921FF") #' #' # Standard contingency table #' #::::::::::::::::::::::::::::::::::::::::::::::::::::::::: #' # Read a contingency table: housetasks #' # Repartition of 13 housetasks in the couple #' data <- read.delim( #' system.file("demo-data/housetasks.txt", package = "ggpubr"), #' row.names = 1 #' ) #' data #' #' # Basic ballon plot #' ggballoonplot(data) #' #' # Change color and fill #' ggballoonplot(data, color = "#0073C2FF", fill = "#0073C2FF") #' #' #' # Change color according to the value of table cells #' ggballoonplot(data, fill = "value")+ #' scale_fill_gradientn(colors = my_cols) #' #' # Change the plotting symbol shape #' ggballoonplot(data, fill = "value", shape = 23)+ #' gradient_fill(c("blue", "white", "red")) #' #' #' # Set points size to 8, but change fill color by values #' # Sow labels #' ggballoonplot(data, fill = "value", color = "lightgray", #' size = 10, show.label = TRUE)+ #' gradient_fill(c("blue", "white", "red")) #' #' # Streched contingency table #' #::::::::::::::::::::::::::::::::::::::::::::::::::::::::: #' #' # Create an Example Data Frame Containing Car x Color data #' carnames <- c("bmw","renault","mercedes","seat") #' carcolors <- c("red","white","silver","green") #' datavals <- round(rnorm(16, mean=100, sd=60),1) #' car_data <- data.frame(Car = rep(carnames,4), #' Color = rep(carcolors, c(4,4,4,4) ), #' Value=datavals ) #' #' car_data #' #' ggballoonplot(car_data, x = "Car", y = "Color", #' size = "Value", fill = "Value") + #' scale_fill_gradientn(colors = my_cols) + #' guides(size = FALSE) #' #' #' # Grouped frequency table #' #::::::::::::::::::::::::::::::::::::::::::::::::::::::::: #'data("Titanic") #'dframe <- as.data.frame(Titanic) #'head(dframe) #'ggballoonplot( #' dframe, x = "Class", y = "Sex", #' size = "Freq", fill = "Freq", #' facet.by = c("Survived", "Age"), #' ggtheme = theme_bw() #')+ #' scale_fill_gradientn(colors = my_cols) #' #'# Hair and Eye Color of Statistics Students #'data(HairEyeColor) #'ggballoonplot( as.data.frame(HairEyeColor), #' x = "Hair", y = "Eye", size = "Freq", #' ggtheme = theme_gray()) %>% #' facet("Sex") #' #' #' @export ggballoonplot <- function( data, x = NULL, y = NULL, size = "value", facet.by = NULL, size.range = c(1, 10), shape = 21, color = "black", fill = "gray", show.label = FALSE, font.label = list(size = 12, color = "black"), rotate.x.text = TRUE, ggtheme = theme_minimal(), ... ) { if(inherits(data, "matrix")) data <- as.data.frame(data) # Check the data #:::::::::::::::::::::::::::::::::::::::::::::::::::::: # case 1: x and y specified. we assume that the data is streched # if size not specified, then take the third column as size values # detect fill variable if misspecified if(!is.null(x) & !is.null(y)){ if(missing(size)) size <- colnames(data)[3] if(fill == "value" & !("value" %in% colnames(data))) fill <- colnames(data)[3] label <- colnames(data)[3] } # case 2: x and y are not specified # - check if the data is streched: # If yes, then consider the first 3 columns as x, y and size values # If no, then strech the data and continu else if(is.null(x) | is.null(y)){ if(.is_streched(data)){ .cnames <- colnames(data) x <- .cnames[1] y <- .cnames[2] if(missing(size)) size <- .cnames[3] if(fill == "value" & !("value" %in% .cnames)) fill <- .cnames[3] label <- .cnames[3] # Reverse y levels so that it appears in the right order on the plot y.val <- dplyr::pull(data, 2) data[[2]] <- y.val %>% factor(levels = rev(.levels(y.val))) } else { data <- .df_strech(data) # Strech the data into 3 columns: .row|.col|.value x <- ".col" y <- ".row" if(missing(size)) size <- "value" label <- "value" } } p <- ggplot(data, create_aes(list(x = x, y = y))) + geom_exec( geom_point, data = data, size = size, fill = fill, shape = shape, color = color ) p <- p + scale_size(range = size.range)+ guides( size = guide_legend(reverse=TRUE))+ ggtheme + theme( axis.title.x = ggplot2::element_blank(), axis.title.y = ggplot2::element_blank() ) if (show.label){ font.label <- .check_lab_font(font.label) text.args <- font.label %>% .add_item( geomfunc = geom_text, data = data, x = x, y = y, label = label ) p <- p + do.call(geom_exec, text.args) } if(rotate.x.text) p <- p + rotate_x_text(45, hjust = 1, vjust = 1) if(!is.null(facet.by)) p <- facet(p, facet.by) ggpar(p, ...) } # Font label .check_lab_font <- function(font.label){ font.label <- .parse_font(font.label) font.label$size <- ifelse(is.null(font.label$size), 4, font.label$size/3) font.label$color <- ifelse(is.null(font.label$color), "black", font.label$color) font.label$face <- ifelse(is.null(font.label$face), "plain", font.label$face) font.label } # strech a data frame with row names # returns a data frame with 3 columns .row, .col, value .df_strech <- function(data){ .col.names <- colnames(data) .row.names <- rownames(data) data <- data %>% dplyr::mutate(.row = .row.names) %>% dplyr::select(.row, dplyr::everything()) # Sretch the data into three columns .col <- .row <- NULL data <- data %>% tidyr::gather( key= ".col", value = "value", -.row ) %>% dplyr::mutate( .col = factor(.col, levels = .col.names), .row = factor(.row, levels = rev(.row.names)) ) data } # Check if the contingency table is in the streched format .is_streched <- function(data, x = NULL, y = NULL){ streched <- TRUE if(is.null(x) | is.null(y)){ if(.is_numeric_data(data)) streched <- FALSE else{ x <- dplyr::pull(data, 1) y <- dplyr::pull(data, 2) z <- dplyr::pull(data, 3) streched <- ( (is.character(x) | is.factor(x)) & (is.character(y) | is.factor(y)) & is.numeric(z) ) } } streched } # Check if a data matrix is numeric .is_numeric_data <- function(x){ all(apply(x, 2, is.numeric)) } # For tible data. The first column should be row names .is_correct_tbl <- function(x){ ok <- FALSE if(inherits(x,"tbl_df" )) ok <- TRUE if(ok){ .rows <- dplyr::pull(x, 1) ok <- is.character(.rows) & .is_numeric_data(x[,-1]) } ok } ggpubr/R/as_npc.R0000644000176200001440000000765714332576562013363 0ustar liggesusers#' Convert Character Coordinates into Normalized Parent Coordinates (NPC) #' #' Convert character coordinates to npc units and shift postions to avoid #' overlaps when grouping is active. If numeric validate npc values. #' #' @param value numeric (in [0-1]) or character vector of coordinates. If #' character, should be one of \code{c('right', 'left', 'bottom', 'top', #' 'center', 'centre', 'middle')}. #' @param group integer ggplot's group id. Used to shift coordinates to avoid #' overlaps. #' @param step numeric value in [0-1]. The step size for shifting coordinates #' in npc units. Considered as horizontal step for x-axis and vertical step #' for y-axis. For y-axis, the step value can be negative to reverse the order of groups. #' @param margin.npc numeric [0-1] The margin added towards the nearest #' plotting area edge when converting character coordinates into npc. #' @param axis the concerned axis . Should be one of \code{c("xy", "x", "y")}. #' #' @return A numeric vector with values in the range [0-1] representing npc #' coordinates. #' @seealso \code{\link{npc_to_data_coord}}, \code{\link{get_coord}}. #' @details the \code{as_npc()} function is an adaptation from #' \code{ggpmisc::compute_npc()}. #' #' @examples #' as_npc(c("left", "right")) #' as_npc(c("top", "right")) #' #' @describeIn as_npc converts x or y coordinate values into npc. Input values #' should be numeric or one of the following values \code{c('right', 'left', #' 'bottom', 'top', 'center', 'centre', 'middle')}. #' @export as_npc <- function(value, group = 1L, step = 0.1, margin.npc = 0.05, axis = c("xy", "x", "y")) { group <- abs(group) axis <- match.arg(axis) if (is.factor(value)) { value <- as.character(value) } assertthat_coord_is_valid(value, axis = axis) if (is.character(value)) { map <- c(right = 1 - margin.npc, left = 0 + margin.npc, top = 1 - margin.npc, bottom = 0 + margin.npc, centre = 0.5, center = 0.5, middle = 0.5, NA_real_) value <- unname(map[value]) } if (any(group > 1L) & step != 0) { value <- value + (group - 1L) * step * ifelse(value < 0.5, 1, -1) } #value <- ifelse(value > 1, 1, value) #value <- ifelse(value < 0, 0, value) value } #' @describeIn as_npc converts x coordinate values into npc. Input values should #' be numeric or one of the following values \code{c('right', 'left', #' 'center', 'centre', 'middle')}. Wrapper around \code{as_npc(axis = "x")}. #' @export as_npcx <- function(value, group = 1L, step = 0.1, margin.npc = 0.05) { as_npc(value, group = group, step = step, margin.npc = margin.npc, axis = "x" ) } #' @describeIn as_npc converts y coordinate values into npc. Input values should #' be numeric or one of the following values \code{c( 'bottom', 'top', #' 'center', 'centre', 'middle')}. Wrapper around \code{as_npc(axis = "y")}. #' @export as_npcy <- function(value, group = 1L, step = 0.1, margin.npc = 0.05) { as_npc(value, group = group, step = step, margin.npc = margin.npc, axis = "y" ) } # Check NPC coord----------------------------------------- # coord: should be between 0 and 1 or a character # axis: should be "x" or "y" assertthat_coord_is_valid <- function(.coord, axis = c("x", "y", "xy")){ axis <- match.arg(axis) allowed.values <- switch (axis, x = c('right', 'left', 'center', 'centre', 'middle'), y = c( 'bottom', 'top', 'center', 'centre', 'middle'), xy = c('right', 'left', 'bottom', 'top', 'center', 'centre', 'middle') ) .message <- paste0( "'*.npc coord for ", axis, " axis should be either a numeric value in [0-1] ", "or a character strings including one of: ", paste(allowed.values, collapse = ", ") ) if(is.numeric(.coord)){ if (any(.coord < 0 | .coord > 1)) { stop(.message, call. = FALSE) } } else if(is.character(.coord)){ if(!all(.coord %in% allowed.values)) stop(.message, call. = FALSE) } } ggpubr/R/gene_expression.R0000644000176200001440000000162514336762430015275 0ustar liggesusers#'Gene Expression Data #' #'@description Gene expression data extracted from TCGA using the `RTCGA` and #' `RTCGA.mRNA` R packages. It contains the mRNA expression for 3 genes - #' GATA3, PTEN and XBP1- from 3 different datasets: Breast invasive carcinoma #' (BRCA), Ovarian serous cystadenocarcinoma (OV) and Lung squamous cell #' carcinoma (LUSC) #'@name gene_expression #'@docType data #'@usage data("gene_expression") #'@format A data frame with 1305 rows and 5 columns. \describe{ #' \item{\code{bcr_patient_barcode}}{sample ID} \item{\code{dataset}}{cance type} \item{\code{GATA3}}{GATA3 gene expression} #' \item{\code{PTEN}}{PTEN gene expression}\item{\code{XBP1}}{XBP1 gene expression.}} #' #' @examples #' data(gene_expression) #' #' ggboxplot(gene_expression, x = "dataset", #' y = c("GATA3", "PTEN", "XBP1"), #' combine = TRUE, #' ylab = "Expression", #' color = "dataset", palette = "jco") #' NULL ggpubr/R/theme_pubr.R0000644000176200001440000001343314332553655014235 0ustar liggesusers#' @include utilities.R #' @import ggplot2 NULL #'Publication ready theme #' #'@description \itemize{ \item \strong{theme_pubr()}: Create a publication ready #' theme \item \strong{theme_pubclean()}: a clean theme without axis lines, to #' direct more attention to the data. \item \strong{labs_pubr()}: Format only #' plot labels to a publication ready style \item \strong{theme_classic2()}: #' Create a classic theme with axis lines. \item \strong{clean_theme()}: Remove #' axis lines, ticks, texts and titles. \item \strong{clean_table_theme()}: #' Clean the the theme of a table, such as those created by #' \code{\link{ggsummarytable}()}}. #'@param base_size base font size #'@param base_family base font family #'@param border logical value. Default is FALSE. If TRUE, add panel border. #'@param margin logical value. Default is TRUE. If FALSE, reduce plot margin. #'@param legend character specifying legend position. Allowed values are one of #' c("top", "bottom", "left", "right", "none"). Default is "top" side position. #' to remove the legend use legend = "none". Legend position can be also #' specified using a numeric vector c(x, y). In this case it is possible to #' position the legend inside the plotting area. x and y are the coordinates of #' the legend box. Their values should be between 0 and 1. c(0,0) corresponds #' to the "bottom left" and c(1,1) corresponds to the "top right" position. For #' instance use legend = c(0.8, 0.2). #'@param x.text.angle Rotation angle of x axis tick labels. Default value is 0. #' Use 90 for vertical text. #'@param flip logical. If TRUE, grid lines are added to y axis instead of x #' axis. #' @examples #' p <- ggplot(mtcars, aes(x = wt, y = mpg)) + #' geom_point(aes(color = gear)) #' #' # Default plot #' p #' #' # Use theme_pubr() #' p + theme_pubr() #' #' # Format labels #' p + labs_pubr() #' #'@name theme_pubr #'@rdname theme_pubr #'@export theme_pubr <- function (base_size = 12, base_family = "", border = FALSE, margin = TRUE, legend = c("top", "bottom", "left", "right", "none"), x.text.angle = 0) { half_line <- base_size/2 if(!is.numeric(legend)) legend <- match.arg(legend) if(x.text.angle > 5) xhjust <- 1 else xhjust <- NULL if(border){ panel.border <- element_rect(fill = NA, colour = "black", size = 0.7) axis.line <- element_blank() } else{ panel.border <- element_blank() axis.line = element_line(colour = "black", size = 0.5) } if(margin) plot.margin <- margin(half_line, half_line, half_line, half_line) else plot.margin <- unit(c(0.5,0.3,0.3,0.3),"mm") .theme <- theme_bw(base_size = base_size, base_family = base_family) %+replace% theme(panel.border = panel.border, panel.grid.major = element_blank(), panel.grid.minor = element_blank(), axis.line = axis.line, axis.text = element_text(color = "black"), legend.key = element_blank(), strip.background = element_rect(fill = "#F2F2F2", colour = "black", size = 0.7), plot.margin = plot.margin, legend.position = legend, complete = TRUE) if(x.text.angle!=0) .theme <- .theme + theme(axis.text.x = element_text(angle = x.text.angle, hjust = xhjust)) .theme } #' @rdname theme_pubr #' @export theme_pubclean <- function (base_size = 12, base_family = "", flip = FALSE) { res <- theme_grey(base_size = base_size, base_family = base_family) + theme( panel.background = element_rect(fill = "white"), legend.background = element_rect(fill = "white"), legend.position = "top" ) if(flip){ res <- res + theme( panel.grid.major.x = element_line(linetype = "dotted", color = "grey"), axis.line.y = element_line(color = "black") ) } else{ res <- res + theme( panel.grid.major.y = element_line(linetype = "dotted", color = "grey") ) } res } #' @rdname theme_pubr #' @export labs_pubr <- function(base_size = 14, base_family = ""){ theme( text = element_text(family = base_family, face = "plain", colour = "black", size = base_size, lineheight = 0.9, hjust = 0.5, vjust = 0.5, angle = 0, margin = margin(), debug = FALSE), # Tick labels axis.text.x = element_text(size = rel(0.86), colour = "black", face = "bold"), axis.text.y = element_text(size = rel(0.86), colour = "black", face = "bold"), # Axis labels axis.title = element_text(size = rel(1), colour = "black", face = "bold"), # Main title plot.title = element_text(size = rel(1), colour = "black" , lineheight=1.0, face = "bold"), legend.title = element_text(size = rel(0.7), face = "bold", colour = "black"), legend.text = element_text(size = rel(0.7), face = "plain", colour = "black") ) } #' @rdname theme_pubr #' @export theme_classic2 <- function (base_size = 12, base_family = "") { theme_classic(base_size = base_size, base_family = base_family) %+replace% theme( axis.line.x = element_line(), axis.line.y = element_line() ) } #' @export #' @rdname theme_pubr clean_theme <- function() { theme( axis.line.x = element_blank(), axis.line.y = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank(), axis.ticks.x = element_blank(), axis.ticks.y = element_blank(), axis.title.x = element_blank(), axis.title.y = element_blank() ) } #' @export #' @rdname theme_pubr clean_table_theme <- function () { theme(axis.line.x = element_blank(), axis.line.y = element_blank(), axis.text.x = element_blank(), axis.ticks.x = element_blank(), axis.ticks.y = element_blank(), axis.title.x = element_blank(), axis.title.y = element_blank()) } ggpubr/R/ggboxplot.R0000644000176200001440000002445114340223022014067 0ustar liggesusers#' @include utilities.R ggpar.R NULL #'Box plot #'@description Create a box plot with points. Box plots display a group of #' numerical data through their quartiles. #'@param data a data frame #'@param x character string containing the name of x variable. #'@param y character vector containing one or more variables to plot #'@param combine logical value. Default is FALSE. Used only when y is a vector #' containing multiple variables to plot. If TRUE, create a multi-panel plot by #' combining the plot of y variables. #'@param merge logical or character value. Default is FALSE. Used only when y is #' a vector containing multiple variables to plot. If TRUE, merge multiple y #' variables in the same plotting area. Allowed values include also "asis" #' (TRUE) and "flip". If merge = "flip", then y variables are used as x tick #' labels and the x variable is used as grouping variable. #'@param color outline color. #'@param fill fill color. #'@param palette the color palette to be used for coloring or filling by groups. #' Allowed values include "grey" for grey color palettes; brewer palettes e.g. #' "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and #' scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", #' "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty". #'@param bxp.errorbar logical value. If TRUE, shows error bars of box plots. #'@param bxp.errorbar.width numeric value specifying the width of box plot error #' bars. Default is 0.4. #'@param linetype line types. #'@param size Numeric value (e.g.: size = 1). change the size of points and #' outlines. #'@param width numeric value between 0 and 1 specifying box width. #'@inheritParams ggplot2::geom_boxplot #'@param outlier.shape point shape of outlier. Default is 19. To hide outlier, #' specify \code{outlier.shape = NA}. When jitter is added, then outliers will #' be automatically hidden. #'@inheritParams facet #'@inheritParams ggpar #'@inheritParams ggtext #'@param select character vector specifying which items to display. #'@param remove character vector specifying which items to remove from the plot. #'@param order character vector specifying the order of items. #'@param add character vector for adding another plot element (e.g.: dot plot or #' error bars). Allowed values are one or the combination of: "none", #' "dotplot", "jitter", "boxplot", "point", "mean", "mean_se", "mean_sd", #' "mean_ci", "mean_range", "median", "median_iqr", "median_hilow", #' "median_q1q3", "median_mad", "median_range"; see ?desc_statby for more #' details. #'@param add.params parameters (color, shape, size, fill, linetype) for the #' argument 'add'; e.g.: add.params = list(color = "red"). #'@param error.plot plot type used to visualize error. Allowed values are one of #' c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", #' "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", #' "lower_linerange"). Default value is "pointrange" or "errorbar". Used only #' when add != "none" and add contains one "mean_*" or "med_*" where "*" = sd, #' se, .... #'@param font.label a list which can contain the combination of the following #' elements: the size (e.g.: 14), the style (e.g.: "plain", "bold", "italic", #' "bold.italic") and the color (e.g.: "red") of labels. For example font.label #' = list(size = 14, face = "bold", color ="red"). To specify only the size and #' the style, use font.label = list(size = 14, face = "plain"). #'@param ggtheme function, ggplot2 theme name. Default value is theme_pubr(). #' Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), #' theme_minimal(), theme_classic(), theme_void(), .... #'@param ... other arguments to be passed to #' \code{\link[ggplot2]{geom_boxplot}}, \code{\link{ggpar}} and #' \code{\link{facet}}. #'@details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, #' ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette #' = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels #' and position: legend = "right" \item plot orientation : orientation = #' c("vertical", "horizontal", "reverse") } #' #'@section Suggestions for the argument "add": Suggested values are one of #' c("dotplot", "jitter"). #' #'@seealso \code{\link{ggpar}}, \code{\link{ggviolin}}, \code{\link{ggdotplot}} #' and \code{\link{ggstripchart}}. #' @examples #' # Load data #' data("ToothGrowth") #' df <- ToothGrowth #' #' # Basic plot #' # +++++++++++++++++++++++++++ #' # width: change box plots width #' ggboxplot(df, x = "dose", y = "len", width = 0.8) #' #' # Change orientation: horizontal #' ggboxplot(df, "dose", "len", orientation = "horizontal") #' #' # Notched box plot #' ggboxplot(df, x = "dose", y = "len", #' notch = TRUE) #' #' # Add dots #' # ++++++++++++++++++++++++++ #' ggboxplot(df, x = "dose", y = "len", #' add = "dotplot") #' #' # Add jitter points and change the shape by groups #' ggboxplot(df, x = "dose", y = "len", #' add = "jitter", shape = "dose") #' #' #' # Select and order items #' # ++++++++++++++++++++++++++++++ #' #' # Select which items to display: "0.5" and "2" #' ggboxplot(df, "dose", "len", #' select = c("0.5", "2")) #' #' # Change the default order of items #' ggboxplot(df, "dose", "len", #' order = c("2", "1", "0.5")) #' #' #' # Change colors #' # +++++++++++++++++++++++++++ #' # Change outline and fill colors #' ggboxplot(df, "dose", "len", #' color = "black", fill = "gray") #' #' # Change outline colors by groups: dose #' # Use custom color palette #' # Add jitter points and change the shape by groups #' ggboxplot(df, "dose", "len", #' color = "dose", palette =c("#00AFBB", "#E7B800", "#FC4E07"), #' add = "jitter", shape = "dose") #' #' # Change fill color by groups: dose #' ggboxplot(df, "dose", "len", #' fill = "dose", palette = c("#00AFBB", "#E7B800", "#FC4E07")) #' #' #' # Box plot with multiple groups #' # +++++++++++++++++++++ #' # fill or color box plot by a second group : "supp" #' ggboxplot(df, "dose", "len", color = "supp", #' palette = c("#00AFBB", "#E7B800")) #' #'@export ggboxplot <- function(data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "white", palette = NULL, title = NULL, xlab = NULL, ylab = NULL, bxp.errorbar = FALSE, bxp.errorbar.width = 0.4, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, linetype = "solid", size = NULL, width = 0.7, notch = FALSE, outlier.shape = 19, select = NULL, remove = NULL, order = NULL, add = "none", add.params = list(), error.plot = "pointrange", label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, ggtheme = theme_pubr(),...) { # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( combine = combine, merge = merge, color = color, fill = fill, palette = palette, title = title, xlab = xlab, ylab = ylab, bxp.errorbar = bxp.errorbar, bxp.errorbar.width = bxp.errorbar.width, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, linetype = linetype, size = size, width = width, notch = notch, outlier.shape = outlier.shape, select = select , remove = remove, order = order, add = add, add.params = add.params, error.plot = error.plot, label = label, font.label = font.label, label.select = label.select, repel = repel, label.rectangle = label.rectangle, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x if(!missing(y)) .opts$y <- y # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$fun <- ggboxplot_core if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggboxplot_core <- function(data, x, y, color = "black", fill = "white", palette = NULL, linetype = "solid", size = NULL, width = 0.7, notch = FALSE, outlier.shape = 19, title = NULL, xlab = NULL, ylab = NULL, bxp.errorbar = FALSE, bxp.errorbar.width = 0.4, add = "none", add.params = list(), error.plot = "pointrange", ggtheme = theme_pubr(), ...) { if(!is.factor(data[[x]])) data[[x]] <- as.factor(data[[x]]) if("jitter" %in% add) outlier.shape <- NA p <- ggplot(data, create_aes(list(x = x, y = y))) if(bxp.errorbar){ if(fill %in% colnames(data)){ # Important, so that the fill grouping is taken into account in the errorbar p <- p + geom_exec( geomfunc = stat_boxplot, data = data, geom = "errorbar", width = bxp.errorbar.width, color = color, fill = fill, linetype = linetype, position = position_dodge(0.8) ) } else{ p <- p + geom_exec( geomfunc = stat_boxplot, data = data, geom = "errorbar", width = bxp.errorbar.width, color = color, linetype = linetype, position = position_dodge(0.8) ) } } p <- p + geom_exec(geom_boxplot, data = data, color = color, fill = fill, linetype = linetype, size = size, width = width, notch = notch, outlier.shape = outlier.shape, position = position_dodge(0.8), size = size,...) # Add add.params <- .check_add.params(add, add.params, error.plot, data, color, fill, ...) %>% .add_item(p = p, add = add, error.plot = error.plot) p <- do.call(ggadd, add.params) %>% ggpar(palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab, ...) p } ggpubr/R/rremove.R0000644000176200001440000000530514332553655013561 0ustar liggesusers#'Remove a ggplot Component #' #' @description Remove a specific component from a ggplot. #' #'@param object character string specifying the plot components. Allowed values #' include: \itemize{ #' \item \code{"grid"} for both x and y grids #' \item \code{"x.grid"} for x axis grids #' \item \code{"y.grid"} for y axis grids #' \item \code{"axis"} for both x and y axes #' \item \code{"x.axis"} for x axis #' \item \code{"y.axis"} for y axis #' #' \item \code{"xlab", or "x.title"} #' for x axis label #' \item \code{"ylab", or "y.title"} for y axis label #' \item \code{"xylab", "xy.title" or "axis.title"} for both x and y axis #' labels #' \item \code{"x.text"} for x axis texts (x axis tick labels) #' \item \code{"y.text"} for y axis texts (y axis tick labels) #' \item \code{"xy.text"} or \code{"axis.text"} for both x and y axis texts #' #' \item \code{"ticks"} for both x and y ticks #' \item \code{"x.ticks"} for x ticks #' \item \code{"y.ticks"} for y ticks #' #' \item \code{"legend.title"} for the legend title #' \item \code{"legend"} for the legend #' } #' #'@examples #'# Load data #'data("ToothGrowth") #' #'# Basic plot #'p <- ggboxplot(ToothGrowth, x = "dose", y = "len", #' ggtheme = theme_gray()) #'p #' #'# Remove all grids #' p + rremove("grid") #' #' # Remove only x grids #' p + rremove("x.grid") #'@export rremove <- function(object){ blank <- element_blank() switch(object, grid = theme(panel.grid.minor = blank, panel.grid.major = blank), x.grid = theme(panel.grid.minor.x = blank, panel.grid.major.x = blank), y.grid = theme(panel.grid.minor.y = blank, panel.grid.major.y = blank), axis = theme(axis.line = blank), x.axis = theme(axis.line.x = blank), y.axis = theme(axis.line.y = blank), xlab = theme(axis.title.x = blank), x.title = theme(axis.title.x = blank), ylab = theme(axis.title.y = blank), y.title = theme(axis.title.y = blank), xy.title = theme(axis.title.x = blank, axis.title.y = blank), xylab = theme(axis.title.x = blank, axis.title.y = blank), axis.title = theme(axis.title.x = blank, axis.title.y = blank), x.ticks = theme(axis.ticks.x = blank), y.ticks = theme(axis.ticks.y = blank), ticks = theme(axis.ticks.x = blank, axis.ticks.y = blank), x.text = theme(axis.text.x = blank), y.text = theme(axis.text.y = blank), xy.text = theme(axis.text.x = blank, axis.text.y = blank), axis.text = theme(axis.text.x = blank, axis.text.y = blank), legend.title = theme(legend.title = blank), legend = theme(legend.position = "none"), stop("Don't support ", object) ) } ggpubr/R/ggarrange.R0000644000176200001440000001742214343207173014033 0ustar liggesusers#' @include utilities.R NULL #' Arrange Multiple ggplots #' #' @description Arrange multiple ggplots on the same page. Wrapper around #' \code{\link[cowplot]{plot_grid}()}. Can arrange multiple ggplots over #' multiple pages, compared to the standard #' \code{\link[cowplot]{plot_grid}()}. Can also create a common unique legend #' for multiple plots. #' @inheritParams cowplot::plot_grid #' @param ... list of plots to be arranged into the grid. The plots can be #' either ggplot2 plot objects or arbitrary gtables. #' @param plotlist (optional) list of plots to display. #' @param ncol (optional) number of columns in the plot grid. #' @param nrow (optional) number of rows in the plot grid. #' @param labels (optional) list of labels to be added to the plots. You can #' also set labels="AUTO" to auto-generate upper-case labels or labels="auto" #' to auto-generate lower-case labels. #' @param font.label a list of arguments for customizing labels. Allowed values #' are the combination of the following elements: size (e.g.: 14), face (e.g.: #' "plain", "bold", "italic", "bold.italic"), color (e.g.: "red") and family. #' For example font.label = list(size = 14, face = "bold", color ="red"). #' @param label.x (optional) Single value or vector of x positions for plot #' labels, relative to each subplot. Defaults to 0 for all labels. (Each label #' is placed all the way to the left of each plot.) #' @param label.y (optional) Single value or vector of y positions for plot #' labels, relative to each subplot. Defaults to 1 for all labels. (Each label #' is placed all the way to the top of each plot.) #' @param widths (optional) numerical vector of relative columns widths. For #' example, in a two-column grid, widths = c(2, 1) would make the first column #' twice as wide as the second column. #' @param heights same as \code{widths} but for column heights. #' @param legend character specifying legend position. Allowed values are one of #' c("top", "bottom", "left", "right", "none"). To remove the legend use #' legend = "none". #' @param common.legend logical value. Default is FALSE. If TRUE, a common #' unique legend will be created for arranged plots. #' @param legend.grob a legend grob as returned by the function #' \code{\link{get_legend}()}. If provided, it will be used as the common #' legend. #' @return return an object of class \code{ggarrange}, which is a ggplot or a #' list of ggplot. #' @author Alboukadel Kassambara \email{alboukadel.kassambara@@gmail.com} #' @seealso \code{\link{annotate_figure}()} #' @examples #' data("ToothGrowth") #' df <- ToothGrowth #' df$dose <- as.factor(df$dose) #' #' # Create some plots #' # :::::::::::::::::::::::::::::::::::::::::::::::::: #' # Box plot #' bxp <- ggboxplot(df, x = "dose", y = "len", #' color = "dose", palette = "jco") #' # Dot plot #' dp <- ggdotplot(df, x = "dose", y = "len", #' color = "dose", palette = "jco") #' # Density plot #' dens <- ggdensity(df, x = "len", fill = "dose", palette = "jco") #' #' # Arrange #' # :::::::::::::::::::::::::::::::::::::::::::::::::: #' ggarrange(bxp, dp, dens, ncol = 2, nrow = 2) #' # Use a common legend for multiple plots #' ggarrange(bxp, dp, common.legend = TRUE) #' #' #' @export ggarrange <- function(..., plotlist = NULL, ncol = NULL, nrow = NULL, labels = NULL, label.x = 0, label.y = 1, hjust = -0.5, vjust = 1.5, font.label = list(size = 14, color = "black", face = "bold", family = NULL), align = c("none", "h", "v", "hv"), widths = 1, heights = 1, legend = NULL, common.legend = FALSE, legend.grob = NULL ) { # Open null device to avoid blank page before plot------ # see cowplot:::as_grob.ggplot null_device <- base::getOption("ggpubr.null_device", default = cowplot::pdf_null_device) cur_dev <- grDevices::dev.cur() # Open null device to avoid blank page before plot null_device(width = 6, height = 6) null_dev <- grDevices::dev.cur() on.exit({ grDevices::dev.off(null_dev) if (cur_dev > 1) grDevices::dev.set(cur_dev) }) plots <- c(list(...), plotlist) align <- match.arg(align) nb.plots <- length(plots) page.layout <- .get_layout(ncol, nrow, nb.plots) ncol <- page.layout$ncol nrow <- page.layout$nrow nb.plots.per.page <- .nbplots_per_page(ncol, nrow) if(!is.null(legend.grob)) common.legend <- TRUE if(is.null(legend) & common.legend) legend <- "top" legend <- .check_legend(legend) if(!is.null(legend)) plots <- purrr::map( plots, function(x) {if(!is.null(x)) x + theme(legend.position = legend) else x} ) if(common.legend){ if(is.null(legend.grob)) legend.grob <- get_legend(plots) plots <- purrr::map( plots, function(x) {if(!is.null(x)) x + theme(legend.position = "none") else x} ) } # Split plots over multiple pages if(nb.plots > nb.plots.per.page){ plots <- split(plots, ceiling(seq_along(plots)/nb.plots.per.page)) } # One unique page else plots <- list(plots) # label arguments .lab <- .update_label_pms(font.label, label.x = label.x, label.y = label.y, hjust = hjust, vjust = vjust) res <- purrr::map(plots, .plot_grid, ncol = ncol, nrow = nrow, labels = labels, label_size = .lab$size, label_fontfamily = .lab$family, label_fontface = .lab$face, label_colour = .lab$color, label_x = .lab$label.x, label_y = .lab$label.y, hjust = .lab$hjust, vjust = .lab$vjust, align = align, rel_widths = widths, rel_heights = heights, legend = legend, common.legend.grob = legend.grob ) if(length(res) == 1) res <- res[[1]] class(res) <- c(class(res), "ggarrange") res } .get_layout <- function(ncol, nrow, nb.plots){ if(!is.null(ncol) & !is.null(nrow)){} else if(!is.null(ncol)){ if(ncol == 1) nrow = nb.plots } else if(!is.null(nrow)){ if(nrow == 1) ncol = nb.plots } list(ncol = ncol, nrow = nrow) } # Compute number of plots per page .nbplots_per_page <- function(ncol = NULL, nrow = NULL){ if(!is.null(ncol) & !is.null(nrow)) ncol * nrow else if(!is.null(ncol)) ncol else if(!is.null(nrow)) nrow else Inf } .plot_grid <- function(plotlist, legend = "top", common.legend.grob = NULL, ... ){ res <- cowplot::plot_grid(plotlist = plotlist, ...) if(is.null(common.legend.grob)) return(res) else { leg <- common.legend.grob lheight <- sum(leg$height) lwidth <- sum(leg$width) } arrangeGrob <- gridExtra::arrangeGrob unit.c <- grid::unit.c .unit <- grid::unit(1, "npc") res <- switch(legend, top = arrangeGrob(leg, res, ncol = 1, heights = unit.c(lheight, .unit - lheight)), bottom = arrangeGrob(res, leg, ncol = 1, heights = unit.c(unit(1, "npc") - lheight, lheight)), left = arrangeGrob(leg, res, ncol = 2, widths = unit.c(lwidth, .unit - lwidth)), right = arrangeGrob(res, leg, ncol = 2, widths = unit.c(.unit - lwidth, lwidth)) ) p <- cowplot::ggdraw() + cowplot::draw_grob(grid::grobTree(res)) p } # update label parameters for cowplot::plot_grid() .update_label_pms <- function(font.label, label.x = 0, label.y = 1, hjust = -0.5, vjust = 1.5) { .font <- list(size = 14, color = "black", face = "bold", family = NULL) new.font.names <- names(font.label) for(i in new.font.names) .font[[i]] <- font.label[[i]] pms <- .font list( size = pms$size, family = pms$family, face = pms$face, color = pms$color, label.x = label.x, label.y = label.y, hjust = hjust, vjust = vjust ) } ggpubr/R/npc_to_data_coord.R0000644000176200001440000000131214332576562015537 0ustar liggesusers#' Convert NPC to Data Coordinates #' @description Convert NPC (Normalized Parent Coordinates) into data coordinates. #' @param npc a numeric vector. Each value should be in [0-1] #' @param data.ranges a numeric vector of length 2 containing the data ranges (minimum and the maximum) #' @return a numeric vector representing data coordinates. #' @seealso \code{\link{as_npc}}, \code{\link{get_coord}}. #' @examples #' npc_to_data_coord(npc = c(0.2, 0.95), data.ranges = c(1, 20)) #' as_npc(c("top", "right")) %>% #' npc_to_data_coord(data.ranges = c(1, 20)) #' #' @rdname npc_to_data_coord #' @export npc_to_data_coord <- function(npc, data.ranges){ data.ranges[1] + npc * (data.ranges[2] - data.ranges[1]) } ggpubr/R/ggadjust_pvalue.R0000644000176200001440000000767114343207173015267 0ustar liggesusers#' @include utilities.R geom_pwc.R NULL #'Adjust p-values Displayed on a GGPlot #'@description Adjust p-values produced by \code{\link{geom_pwc}()} on a ggplot. #' This is mainly useful when using facet, where p-values are generally #' computed and adjusted by panel without taking into account the other panels. #' In this case, one might want to adjust after the p-values of all panels together. #'@inheritParams geom_pwc #'@param p a ggplot #'@param layer An integer indicating the statistical layer rank in the ggplot #' (in the order added to the plot). #'@param output character. Possible values are one of \code{c("plot", #' "stat_test")}. Default is "plot". #'@examples #' # Data preparation #' #::::::::::::::::::::::::::::::::::::::: #' df <- ToothGrowth #' df$dose <- as.factor(df$dose) #' # Add a random grouping variable #' df$group <- factor(rep(c("grp1", "grp2"), 30)) #' head(df, 3) #' #' # Boxplot: Two groups by panel #' #::::::::::::::::::::::::::::::::::::::: #' # Create a box plot #' bxp <- ggboxplot( #' df, x = "supp", y = "len", fill = "#00AFBB", #' facet.by = "dose" #' ) #' # Make facet and add p-values #' bxp <- bxp + geom_pwc(method = "t_test") #' bxp #' # Adjust all p-values together after #' ggadjust_pvalue( #' bxp, p.adjust.method = "bonferroni", #' label = "{p.adj.format}{p.adj.signif}", hide.ns = TRUE #' ) #' #' #' # Boxplot: Three groups by panel #' #::::::::::::::::::::::::::::::::::::::: #' # Create a box plot #' bxp <- ggboxplot( #' df, x = "dose", y = "len", fill = "#00AFBB", #' facet.by = "supp" #' ) #' # Make facet and add p-values #' bxp <- bxp + geom_pwc(method = "t_test") #' bxp #' # Adjust all p-values together after #' ggadjust_pvalue( #' bxp, p.adjust.method = "bonferroni", #' label = "{p.adj.format}{p.adj.signif}" #' ) #'@export ggadjust_pvalue <- function(p, layer = NULL, p.adjust.method = "holm", label = "p.adj", hide.ns = NULL, symnum.args = list(), output = c("plot", "stat_test")){ output <- match.arg(output) .build <- ggplot_build(p) .build_data <- .build$data # Pairwise comparison-------------------------- # Find layer containing statistical test data key_columns <- c("group1", "group2", "p") if(is.null(layer)){ for(i in 1:length(.build_data)){ if(all( key_columns %in% colnames(.build_data[[i]]))){ layer <- i break } } } if(is.null(layer)){ stop("Can't find any layer containing statiscal tests") } stat_test <- .build$data[[layer]] sy <- fortify_signif_symbols_encoding(symnum.args) if(all(is.na(stat_test$p))){ warning( "p-values can't be adjusted for the specified stat method.\n", "The result of the method doesn't contain the p column.\n", "Note that, tests such as tukey_hsd or games_howell_test handle p-value adjustement ", "internally; they only return the p.adj.", call. = FALSE ) label <- gsub(pattern = "p.format", replacement = "p.adj.format", label) } else{ padjusted <- stat_test %>% dplyr::select(dplyr::all_of(c("PANEL", "group", "group1", "group2", "p"))) %>% dplyr::distinct(.keep_all = TRUE) %>% rstatix::adjust_pvalue(method = p.adjust.method) # Hide NS if hide.ns not null if(!is.null(hide.ns)) padjusted <- rstatix::remove_ns(padjusted, col = hide.ns) p <- p.adj <- NULL stat_test <- stat_test %>% dplyr::select(-dplyr::one_of(c("p", "p.adj", "p.format", "p.adj.format", "label"))) %>% dplyr::inner_join(padjusted, by = c("PANEL", "group", "group1", "group2")) %>% rstatix::p_format(p, p.adj, new.col = TRUE, accuracy = 1e-4) %>% rstatix::add_significance(p.col = "p", cutpoints = sy$cutpoints, symbols = sy$symbols) %>% rstatix::add_significance(p.col = "p.adj", cutpoints = sy$cutpoints, symbols = sy$symbols) %>% add_stat_label(label = label) .build$data[[layer]] <- stat_test } if(output == "stat_test"){ return(stat_test) } as_ggplot(ggplot_gtable(.build)) } ggpubr/R/stat_regline_equation.R0000644000176200001440000001674014332553655016474 0ustar liggesusers#' @include utilities.R utilities_label.R #' @importFrom dplyr everything #' @importFrom dplyr select NULL #'Add Regression Line Equation and R-Square to a GGPLOT. #'@description Add regression line equation and R^2 to a ggplot. Regression #' model is fitted using the function \code{\link[stats]{lm}}. #'@inheritParams ggplot2::layer #'@param formula a formula object #'@param label.x.npc,label.y.npc can be \code{numeric} or \code{character} #' vector of the same length as the number of groups and/or panels. If too #' short they will be recycled. \itemize{ \item If \code{numeric}, value should #' be between 0 and 1. Coordinates to be used for positioning the label, #' expressed in "normalized parent coordinates". \item If \code{character}, #' allowed values include: i) one of c('right', 'left', 'center', 'centre', #' 'middle') for x-axis; ii) and one of c( 'bottom', 'top', 'center', 'centre', #' 'middle') for y-axis.} #' #' If too short they will be recycled. #'@param label.x,label.y \code{numeric} Coordinates (in data units) to be used #' for absolute positioning of the label. If too short they will be recycled. #'@param output.type character One of "expression", "latex" or "text". #'@param ... other arguments to pass to \code{\link[ggplot2]{geom_text}} or #' \code{\link[ggplot2:geom_text]{geom_label}}. #'@param na.rm If FALSE (the default), removes missing values with a warning. If #' TRUE silently removes missing values. #'@seealso \code{\link{ggscatter}} #'@references the source code of the function \code{stat_regline_equation()} is #' inspired from the code of the function \code{stat_poly_eq()} (in ggpmisc #' package). #' #' @section Computed variables: #' \describe{ \item{x}{x position for left edge} #' \item{y}{y position near upper edge} #' \item{eq.label}{equation for the #' fitted polynomial as a character string to be parsed} #' \item{rr.label}{\eqn{R^2} of the fitted model as a character string to be parsed} #' \item{adj.rr.label}{Adjusted \eqn{R^2} of the fitted model as a character string #' to be parsed} #' \item{AIC.label}{AIC for the fitted model.} #' \item{BIC.label}{BIC for the fitted model.} #' \item{hjust}{Set to zero to override the default of the "text" geom.}} #' @examples #' #' # Simple scatter plot with correlation coefficient and #' # regression line #' #:::::::::::::::::::::::::::::::::::::::::::::::::::: #' ggscatter(mtcars, x = "wt", y = "mpg", add = "reg.line") + #' stat_cor(label.x = 3, label.y = 34) + #' stat_regline_equation(label.x = 3, label.y = 32) #' #' #' # Groupped scatter plot #' #:::::::::::::::::::::::::::::::::::::::::::::::::::: #' ggscatter( #' iris, x = "Sepal.Length", y = "Sepal.Width", #' color = "Species", palette = "jco", #' add = "reg.line" #' ) + #' facet_wrap(~Species) + #' stat_cor(label.y = 4.4) + #' stat_regline_equation(label.y = 4.2) #' #' # Polynomial equation #' #:::::::::::::::::::::::::::::::::::::::::::::::::::: #' #' # Demo data #' set.seed(4321) #' x <- 1:100 #' y <- (x + x^2 + x^3) + rnorm(length(x), mean = 0, sd = mean(x^3) / 4) #' my.data <- data.frame(x, y, group = c("A", "B"), #' y2 = y * c(0.5,2), block = c("a", "a", "b", "b")) #' #' # Fit polynomial regression line and add labels #' formula <- y ~ poly(x, 3, raw = TRUE) #' p <- ggplot(my.data, aes(x, y2, color = group)) + #' geom_point() + #' stat_smooth(aes(fill = group, color = group), method = "lm", formula = formula) + #' stat_regline_equation( #' aes(label = paste(..eq.label.., ..adj.rr.label.., sep = "~~~~")), #' formula = formula #' ) + #' theme_bw() #' ggpar(p, palette = "jco") #' #'@export stat_regline_equation <- function( mapping = NULL, data = NULL, formula = y~x, label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, output.type = "expression", geom = "text", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ... ) { parse <- ifelse(output.type == "expression", TRUE, FALSE) layer( stat = StatReglineEquation, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(formula = formula, label.x.npc = label.x.npc , label.y.npc = label.y.npc, label.x = label.x, label.y = label.y, output.type = output.type, parse = parse, na.rm = na.rm, ...) ) } StatReglineEquation<- ggproto("StatReglineEquation", Stat, required_aes = c("x", "y"), default_aes = aes(label = ..eq.label.., hjust = ..hjust.., vjust = ..vjust..), compute_group = function(data, scales, formula, label.x.npc, label.y.npc, label.x, label.y, output.type) { force(data) if (length(unique(data$x)) < 2) { return(data.frame()) # Not enough data to perform test } .test <- .stat_lm(formula, data, output.type = output.type) # Returns a data frame with label: x, y, hjust, vjust .label.pms <- .label_params(data = data, scales = scales, label.x.npc = label.x.npc, label.y.npc = label.y.npc, label.x = label.x, label.y = label.y ) %>% mutate(hjust = 0) cbind(.test, .label.pms) } ) # Compute regression line equation .stat_lm <- function(formula, data, output.type = "expression"){ res.lm <- stats::lm(formula, data) coefs <- stats::coef(res.lm) formula.rhs.chr <- as.character(formula)[3] if (grepl("-1", formula.rhs.chr) || grepl("- 1", formula.rhs.chr)) { coefs <- c(0, coefs) } rr <- summary(res.lm)$r.squared %>% signif(2) adj.rr <- summary(res.lm)$adj.r.squared %>% signif(2) AIC <- stats::AIC(res.lm) %>% signif(2) BIC <- stats::BIC(res.lm) %>% signif(2) # Build model equation eq.char <- as.character(signif(polynom::as.polynomial(coefs), 2)) eq.char <- gsub("e([+-]?[0-9]*)", "%*%10^\\1", eq.char) if (output.type %in% c("latex", "tex", "tikz")) { eq.char <- gsub("*", " ", eq.char, fixed = TRUE) } # Add y if (output.type == "expression") { lhs <- "italic(y)~`=`~" } else if (output.type %in% c("latex", "tex", "tikz", "text")) { lhs <- "y = " } eq.char <- paste(lhs, eq.char, sep = "") # Build data frame with the output if (output.type == "expression") { eq.x.rhs = "~italic(x)" } else { eq.x.rhs = " x" } if (output.type == "expression") { z <- data.frame(eq.label = gsub("x", eq.x.rhs, eq.char, fixed = TRUE), rr.label = paste("italic(R)^2", rr, sep = "~`=`~"), adj.rr.label = paste("italic(R)[adj]^2", adj.rr, sep = "~`=`~"), AIC.label = paste("AIC", AIC, sep = "~`=`~"), BIC.label = paste("BIC", BIC, sep = "~`=`~")) } else if (output.type %in% c("latex", "tex", "text")) { z <- data.frame(eq.label = gsub("x", eq.x.rhs, eq.char, fixed = TRUE), rr.label = paste("R^2", rr, sep = " = "), adj.rr.label = paste("R_{adj}^2",adj.rr, sep = " = "), AIC.label = paste("AIC", AIC, sep = " = "), BIC.label = paste("BIC", BIC, sep = " = ")) } z <- z %>% mutate(rr = rr, adj.rr = adj.rr, AIC = AIC, BIC = BIC) %>% dplyr::select(rr, adj.rr, AIC, BIC, everything()) z } ggpubr/R/geom_pwc.R0000644000176200001440000010374514343207173013702 0ustar liggesusers#' @include utilities.R utils_stat_test_label.R utils-aes.R NULL #'Add Pairwise Comparisons P-values to a GGPlot #'@description add pairwise comparison p-values to a ggplot such as box plots, #' dot plots and stripcharts. #'@param method a character string indicating which method to be used for #' pairwise comparisons. Default is \code{"wilcox_test"}. Allowed methods #' include pairwise comparisons methods implemented in the \code{rstatix} R #' package. These methods are: \code{"wilcox_test", "t_test", "sign_test", #' "dunn_test", "emmeans_test", "tukey_hsd", "games_howell_test"}. #'@param method.args a list of additional arguments used for the test method. #' For example one might use \code{method.args = list(alternative = "greater")} #' for wilcoxon test. #'@param ref.group a character string or a numeric value specifying the #' reference group. If specified, for a given grouping variable, each of the #' group levels will be compared to the reference group (i.e. control group). #' #' \code{ref.group} can be also \code{"all"}. In this case, each of the #' grouping variable levels is compared to all (i.e. basemean). #' #' Allowed values can be: \itemize{ \item \strong{numeric value}: specifying #' the rank of the reference group. For example, use \code{ref.group = 1} when #' the first group is the reference; use \code{ref.group = 2} when the second #' group is the reference, and so on. This works for all situations, including #' i) when comparisons are performed between x-axis groups and ii) when #' comparisons are performed between legend groups. \item \strong{character #' value}: For example, you can use \code{ref.group = "ctrl"} instead of using #' the numeric rank value of the "ctrl" group. \item \strong{"all"}: In this #' case, each of the grouping variable levels is compared to all (i.e. #' basemean). } #'@param label character string specifying label. Can be: \itemize{ \item the #' column containing the label (e.g.: \code{label = "p"} or \code{label = #' "p.adj"}), where \code{p} is the p-value. Other possible values are #' \code{"p.signif", "p.adj.signif", "p.format", "p.adj.format"}. \item an #' expression that can be formatted by the \code{\link[glue]{glue}()} package. #' For example, when specifying \code{label = "Wilcoxon, p = \{p\}"}, the #' expression \{p\} will be replaced by its value. \item a combination of #' plotmath expressions and glue expressions. You may want some of the #' statistical parameter in italic; for example:\code{label = "Wilcoxon, #' italic(p)= {p}"}}. #'@param y.position numeric vector with the y positions of the brackets #'@param group.by (optional) character vector specifying the grouping variable; #' it should be used only for grouped plots. Possible values are : \itemize{ #' \item \code{"x.var"}: Group by the x-axis variable and perform the test #' between legend groups. In other words, the p-value is compute between legend #' groups at each x position \item \code{"legend.var"}: Group by the legend #' variable and perform the test between x-axis groups. In other words, the #' test is performed between the x-groups for each legend level. } #'@param dodge dodge width for grouped ggplot/test. Default is 0.8. It's used to #' dodge the brackets position when \code{group.by = "legend.var"}. #'@param stack logical value. Default is FALSE; should be set to TRUE for #' stacked bar plots or line plots. If TRUE, then the brackets are #' automatically removed and the \code{dodge} value is set to zero. #'@param bracket.nudge.y Vertical adjustment to nudge brackets by (in fraction #' of the total height). Useful to move up or move down the bracket. If #' positive value, brackets will be moved up; if negative value, brackets are #' moved down. #'@param bracket.shorten a small numeric value in [0-1] for shortening the width #' of bracket. #'@param bracket.group.by (optional); a variable name for grouping brackets #' before adding step.increase. Useful for grouped plots. Possible values #' include \code{"x.var"} and \code{"legend.var"}. #'@param step.increase numeric vector with the increase in fraction of total #' height for every additional comparison to minimize overlap. #'@param tip.length numeric vector with the fraction of total height that the #' bar goes down to indicate the precise column/ #'@param size change the width of the lines of the bracket #'@param label.size change the size of the label text #'@param family change the font used for the text #'@param vjust move the text up or down relative to the bracket. #'@param hjust move the text left or right relative to the bracket. #'@param p.adjust.method method for adjusting p values (see #' \code{\link[stats]{p.adjust}}). Has impact only in a situation, where #' multiple pairwise tests are performed; or when there are multiple grouping #' variables. Ignored when the specified method is \code{"tukey_hsd"} or #' \code{"games_howell_test"} because they come with internal p adjustment #' method. Allowed values include "holm", "hochberg", "hommel", "bonferroni", #' "BH", "BY", "fdr", "none". If you don't want to adjust the p value (not #' recommended), use p.adjust.method = "none". #'@param p.adjust.by possible value is one of \code{c("group", "panel")}. #' Default is \code{"group"}: for a grouped data, if pairwise test is #' performed, then the p-values are adjusted for each group level #' independently. P-values are adjusted by panel when \code{p.adjust.by = #' "panel"}. #'@param symnum.args a list of arguments to pass to the function #' \code{\link[stats]{symnum}} for symbolic number coding of p-values. For #' example, \code{symnum.args <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, #' 0.05, Inf), symbols = c("****", "***", "**", "*", "ns"))}. #' #' In other words, we use the following convention for symbols indicating #' statistical significance: \itemize{ \item \code{ns}: p > 0.05 \item #' \code{*}: p <= 0.05 \item \code{**}: p <= 0.01 \item \code{***}: p <= 0.001 #' \item \code{****}: p <= 0.0001 } #'@param hide.ns can be logical value (\code{TRUE} or \code{FALSE}) or a character vector (\code{"p.adj"} or \code{"p"}). #'@param remove.bracket logical, if \code{TRUE}, brackets are removed from the #' plot. \itemize{ \item Case when logical value. If TRUE, hide ns symbol when #' displaying significance levels. Filter is done by checking the column #' \code{p.adj.signif}, \code{p.signif}, \code{p.adj} and \code{p}. \item Case #' when character value. Possible values are "p" or "p.adj", for filtering out #' non significant. } #'@param na.rm If \code{FALSE} (the default), removes missing values with a #' warning. If \code{TRUE} silently removes missing values. #'@param parse logical for parsing plotmath expression. #'@param ... other arguments passed on to \code{\link{layer}}. These are often #' aesthetics, used to set an aesthetic to a fixed value, like \code{color = #' "red"} or \code{size = 3}. They may also be parameters to the paired #' geom/stat. #' @details #' \bold{Notes on adjusted p-values and facet}. When using the ggplot facet functions, the p-values are computed and adjusted by panel, without taking into account the other panels. This is by design in ggplot2. #' #' In this case, when there is only one computed p-value by panel, then using `label = "p"` or `label = "p.adj"` will give the same results using `geom_pwc()`. Again, p-value computation and adjustment in a given facet panel is done independently to the other panels. #' #' One might want to adjust the p-values of all the facet panels together. There are two solutions for that: #' #' \itemize{ #' \item Using \code{\link{ggadjust_pvalue}(p)} after creating the plot \code{p} #' \item or adding the adjusted p-value manually using \code{\link{stat_pvalue_manual}()}. Read more at: #' \itemize{ #' \item \href{https://www.datanovia.com/en/blog/how-to-add-p-values-to-ggplot-facets/}{How to Add P-values to GGPLOT Facets} #' \item \href{https://www.datanovia.com/en/blog/add-p-values-to-ggplot-facets-with-different-scales/}{Add P-values to GGPLOT Facets with Different Scales} #' } #' } #'@inheritParams ggplot2::layer #' @examples #' df <- ToothGrowth #' df$dose <- factor(df$dose) #' #'@rdname geom_pwc #' @seealso \code{\link{ggadjust_pvalue}} #'@examples #' # Data preparation #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Transform `dose` into factor variable #' df <- ToothGrowth #' df$dose <- as.factor(df$dose) #' # Add a random grouping variable #' df$group <- factor(rep(c("grp1", "grp2"), 30)) #' head(df, 3) #' #' #' # Two groups by x position #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' #' # Create a box plot #' # Add 10% spaces between the p-value labels and the plot border #' bxp <- ggboxplot( #' df, x = "dose", y = "len", #' color = "supp", palette = c("#00AFBB", "#E7B800") #' ) + #' scale_y_continuous(expand = expansion(mult = c(0.05, 0.10))) #' #' #' # Add p-values onto the box plots #' # label can be "p.format" or "p.adj.format" #' bxp + geom_pwc( #' aes(group = supp), tip.length = 0, #' method = "t_test", label = "p.format" #' ) #' #' # Show adjusted p-values and significance levels #' # Hide ns (non-significant) #' bxp + geom_pwc( #' aes(group = supp), tip.length = 0, #' method = "t_test", label = "{p.adj.format}{p.adj.signif}", #' p.adjust.method = "bonferroni", p.adjust.by = "panel", #' hide.ns = TRUE #' ) #' #' # Complex cases #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # 1. Add p-values of OJ vs VC at each dose group #' bxp.complex <- bxp + #' geom_pwc( #' aes(group = supp), tip.length = 0, #' method = "t_test", label = "p.adj.format", #' p.adjust.method = "bonferroni", p.adjust.by = "panel" #' ) #' # 2. Add pairwise comparisons between dose levels #' # Nudge up the brackets by 20% of the total height #' bxp.complex <- bxp.complex + #' geom_pwc( #' method = "t_test", label = "p.adj.format", #' p.adjust.method = "bonferroni", #' bracket.nudge.y = 0.2 #' ) #' # 3. Display the plot #' bxp.complex #' #' #' # Three groups by x position #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' #' # Simple plots #' #_____________________________________ #' #' # Box plots with p-values #' bxp <- ggboxplot( #' df, x = "supp", y = "len", fill = "dose", #' palette = "npg" #' ) #' bxp + #' geom_pwc( #' aes(group = dose), tip.length = 0, #' method = "t_test", label = "p.adj.format", #' bracket.nudge.y = -0.08 #' ) + #' scale_y_continuous(expand = expansion(mult = c(0, 0.1))) #' #' # Bar plots with p-values #' bp <- ggbarplot( #' df, x = "supp", y = "len", fill = "dose", #' palette = "npg", add = "mean_sd", #' position = position_dodge(0.8) #' ) #' bp + #' geom_pwc( #' aes(group = dose), tip.length = 0, #' method = "t_test", label = "p.adj.format", #' bracket.nudge.y = -0.08 #' ) + #' scale_y_continuous(expand = expansion(mult = c(0, 0.1))) #' #'@export stat_pwc <- function(mapping = NULL, data = NULL, method = "wilcox_test", method.args = list(), ref.group = NULL, label = "p.format", y.position = NULL, group.by = NULL, dodge = 0.8, bracket.nudge.y = 0.05, bracket.shorten = 0, bracket.group.by = c("x.var", "legend.var"), step.increase = 0.12, tip.length = 0.03, size = 0.3, label.size = 3.88, family="", vjust = 0, hjust = 0.5, p.adjust.method = "holm", p.adjust.by = c("group", "panel"), symnum.args = list(), hide.ns = FALSE, remove.bracket = FALSE, position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, parse = FALSE, ...) { p.adjust.by <- match.arg(p.adjust.by) if(missing(parse) & is_plotmath_expression(label)){ parse <- TRUE } if(is.null(group.by)) group.by <- "x.var" bracket.group.by <- match.arg(bracket.group.by) if(!is.null(ref.group)){ if(ref.group %in% c("all", ".all.")){ if(missing(step.increase)) step.increase <- 0 remove.bracket <- TRUE } } # Keep legend variable in memory, we'll be useful to guess ref.group id # related question: https://stackoverflow.com/questions/63640543/how-to-access-to-a-legend-group-id-inside-a-ggplot2-extension legend.var <- aes_get_group(mapping) if(!is.null(legend.var)) mapping$legend.var <- as.name(legend.var) ggplot2::layer( stat = StatPwc, data = data, mapping = mapping, geom = "pwc", position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list( method = method, method.args = method.args, ref.group = ref.group, stat.label = label, y.position = y.position, group.by = group.by, dodge = dodge, bracket.nudge.y = bracket.nudge.y, bracket.shorten = bracket.shorten, bracket.group.by = bracket.group.by, step.increase = step.increase, tip.length = tip.length, size=size, label.size=label.size, remove.bracket = remove.bracket, family=family, vjust=vjust, hjust = hjust, na.rm = na.rm, p.adjust.method = p.adjust.method, p.adjust.by = p.adjust.by, symnum.args = fortify_signif_symbols_encoding(symnum.args), hide.ns = hide.ns, parse = parse, ...) ) } StatPwc <- ggplot2::ggproto("StatPwc", ggplot2::Stat, required_aes = c("x", "y", "group"), setup_params = function(data, params) { if(length(params$tip.length) == 1) params$tip.length <- rep(params$tip.length, max(length(params$xmin), 1) * 2) if(length(params$tip.length) == length(params$xmin)) params$tip.length <- rep(params$tip.length, each=2) # Statistical test methods functions and arguments method <- params$method method.args <- params$method.args if(is.null(method.args$p.adjust.method)){ method.args$p.adjust.method <- params$p.adjust.method } pwc_func <- get_pwc_stat_function(method, method.args) params$method <- pwc_func$method params$method.args <- pwc_func$method.args return(params) }, compute_panel = function(self, data, scales, method, method.args, ref.group, tip.length, stat.label, y.position, step.increase, bracket.nudge.y, bracket.shorten, bracket.group.by, p.adjust.method, p.adjust.by, symnum.args, hide.ns, group.by, dodge, remove.bracket) { # Compute the statistical tests df <- data %>% mutate(x = as.factor(.data$x)) is.grouped.plots <- contains_multiple_grouping_vars(df) formula <- y ~ x grouping.var <- NULL if(is.grouped.plots){ if(group.by == "legend.var"){ grouping.var <- "group" formula <- y ~ x } else { grouping.var <- "x" formula <- y ~ group } df <- df %>% rstatix::df_group_by(vars = grouping.var) } is.comparisons.between.legend.grps <- is.grouped.plots & group.by == "x.var" # Comparison against reference group ref.group.id <- get_ref_group_id( scales = scales, data = df, ref.group = ref.group, is.comparisons.between.legend.grps = is.comparisons.between.legend.grps ) if(!is.null(ref.group.id)) { method.args <- method.args %>% .add_item(ref.group = ref.group.id) } method.args <- method.args %>% .add_item(data = df, formula = formula) stat.test <- do.call(method, method.args) # Add method name method.name <- rstatix::get_description(stat.test) if(method.name == "") { stat.label <- gsub(pattern = "\\{method\\},\\s?", replacement = "", stat.label) } stat.test$method <- method.name # P-value adjustment, formatting and significance if(!("p.adj" %in% colnames(stat.test))){ # Case of one comparison of two groups stat.test <- stat.test %>% rstatix::adjust_pvalue(method = p.adjust.method) } # Adjust all the p-values in a given panel # no matter the grouping if(p.adjust.by == "panel"){ if("p" %in% colnames(stat.test)){ stat.test <- stat.test %>% rstatix::adjust_pvalue(method = p.adjust.method) } else{ warning( "p-values can't be adjusted by panel for the specified stat method.\n", "The result of the method doesn't contain the p column.\n", "Note that, tests such as tukey_hsd or games_howell_test handle p-value adjustement ", "internally; they only return the p.adj.", call. = FALSE ) } } if(!("p" %in% colnames(stat.test))){ # Case when method is tukey or games-howel, etc # doesn't return p but p.adj stat.test <- stat.test %>% tibble::add_column(p = NA, .before = "p.adj") stat.label <- gsub(pattern = "p.format", replacement = "p.adj.format", stat.label) } sy <- symnum.args stat.test <- stat.test %>% rstatix::add_x_position(x = "x", group = "group", dodge = dodge) %>% rstatix::add_significance(p.col = "p", cutpoints = sy$cutpoints, symbols = sy$symbols) %>% rstatix::add_significance(p.col = "p.adj", cutpoints = sy$cutpoints, symbols = sy$symbols) %>% rstatix::p_format(p, p.adj, new.col = TRUE, accuracy = 1e-4) %>% add_stat_n() %>% keep_only_tbl_df_classes() %>% add_stat_label(label = stat.label) if(!is.null(ref.group)){ if(!(ref.group %in% c(".all.", "all"))){ # when comparisons is done against reference group if(remove.bracket) stat.test$xmin <- stat.test$xmax } } # Hide NS if hide.ns not null stat.test <- rstatix::remove_ns(stat.test, col = hide.ns) # Grouped bracket colors # When data is grouped by legend variable and # stat test is computed between x variable groups # labels are stacked on y-axis. labels group ids are group (legend var) if(is.grouped.plots){ if(grouping.var == "group" & "colour" %in% colnames(data)){ color.data <- data %>% select(.data$group, .data$colour) %>% distinct(.data$group, .keep_all = TRUE) stat.test <- stat.test %>% dplyr::left_join(color.data, by = "group") } } # Bracket groups, used for spacing vertically brackets bracket.group <- 1 if(nrow(stat.test) > 1) bracket.group <- 1:nrow(stat.test) if(is.grouped.plots){ if(grouping.var == "x"){ nb.comparisons.by.group <- stat.test %>% rstatix::df_group_by(vars = grouping.var) %>% dplyr::summarise(n = dplyr::n()) bracket.group <- unlist(purrr::map(nb.comparisons.by.group$n, seq)) } else if(grouping.var == "group" & bracket.group.by == "legend.var"){ stat.test <- stat.test %>% dplyr::arrange(.data$group1, .data$group2) } } # Parameters for customizing brackets group <- 1 if(nrow(stat.test) > 1) group <- 1:nrow(stat.test) stat.test <- stat.test %>% mutate( group = group, bracket.group = bracket.group, step.increase = step.increase, bracket.nudge.y = bracket.nudge.y, bracket.shorten = bracket.shorten ) # Bracket x positions bracket.shorten <- stat.test$bracket.shorten/2 xmin <- as.numeric(stat.test$xmin) + bracket.shorten xmax <- as.numeric(stat.test$xmax) - bracket.shorten # Bracket y positions yrange <- scales$y$range$range y.scale.range <- yrange[2] - yrange[1] bracket.nudge.y <- stat.test$bracket.nudge.y step.increase <- stat.test$step.increase if(is.null(y.position)){ y.position <- yrange[2] + y.scale.range * bracket.nudge.y + y.scale.range * step.increase * (bracket.group-1) } else if(length(y.position) == 1) { y.position <- y.position + y.scale.range * bracket.nudge.y + y.scale.range * step.increase * (bracket.group-1) } else if(length(y.position) >= length(stat.test$group)){ y.position <- y.position[stat.test$group] } if("tip.length" %in% colnames(stat.test)){ tip.length <- rep(stat.test$tip.length, each=2) } # Preparing bracket data stat.test <- dplyr::bind_rows(stat.test, stat.test, stat.test) stat.test$x <- c(xmin, xmin, xmax) stat.test$xend = c(xmin, xmax, xmax) stat.test$y <- c(y.position - y.scale.range*tip.length[seq_len(length(tip.length))%% 2 == 1], y.position, y.position) stat.test$yend <- c(y.position, y.position, y.position-y.scale.range*tip.length[seq_len(length(tip.length))%% 2 == 0]) stat.test %>% select(-step.increase, -bracket.nudge.y, -bracket.shorten) } ) #' @rdname geom_pwc #' @export geom_pwc <- function(mapping = NULL, data = NULL, stat = "pwc", method = "wilcox_test", method.args = list(), ref.group = NULL, label = "p.format", y.position = NULL, group.by = NULL, dodge = 0.8, stack = FALSE, step.increase = 0.12, tip.length = 0.03, bracket.nudge.y = 0.05, bracket.shorten = 0, bracket.group.by = c("x.var", "legend.var"), size = 0.3, label.size = 3.88, family="", vjust = 0, hjust = 0.5, p.adjust.method = "holm", p.adjust.by = c("group", "panel"), symnum.args = list(), hide.ns = FALSE, remove.bracket = FALSE, position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, parse = FALSE, ...) { p.adjust.by <- match.arg(p.adjust.by) if(missing(parse) & is_plotmath_expression(label)){ parse <- TRUE } bracket.group.by <- match.arg(bracket.group.by) if(is.null(group.by)) group.by <- "x.var" if(stack){ # for stacked bar plots/line plots dodge <- 0 if (group.by == "x.var") remove.bracket <- TRUE } if(!is.null(ref.group)){ if(ref.group %in% c("all", ".all.")){ if(missing(step.increase)) step.increase <- 0 remove.bracket <- TRUE } } # Keep legend variable in memory, we'll be useful to guess ref.group id # related question: https://stackoverflow.com/questions/63640543/how-to-access-to-a-legend-group-id-inside-a-ggplot2-extension legend.var <- aes_get_group(mapping) if(!is.null(legend.var)) mapping$legend.var <- as.name(legend.var) ggplot2::layer( stat = stat, geom = GeomPwc, mapping = mapping, data = data, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list( method = method, method.args = method.args, ref.group = ref.group, stat.label = label, y.position = y.position, group.by = group.by, dodge = dodge, bracket.nudge.y = bracket.nudge.y, bracket.shorten = bracket.shorten, bracket.group.by = bracket.group.by, step.increase = step.increase, tip.length = tip.length, size = size, label.size = label.size, family = family, na.rm = na.rm, hjust = hjust, vjust = vjust, p.adjust.method = p.adjust.method, p.adjust.by = p.adjust.by, symnum.args = fortify_signif_symbols_encoding(symnum.args), hide.ns = hide.ns, remove.bracket = remove.bracket, parse = parse, ... ) ) } GeomPwc <- ggplot2::ggproto("GeomPwc", ggplot2::Geom, required_aes = c("x", "xend", "y", "yend", "label"), default_aes = ggplot2::aes( shape = 19, colour = "black", label.size = 3.88, angle = NA, hjust = 0.5, vjust = 0, alpha = NA, family = "", fontface = 1, lineheight = 1.2, linetype=1, size = 0.3, legend.var = NA ), # draw_key = function(...){grid::nullGrob()}, # for legend: draw_key = draw_key_path, draw_panel = function(data, panel_params, coord, parse = FALSE, remove.bracket = FALSE) { coords <- coord$transform(data, panel_params) coord.flip <- inherits(coord, "CoordFlip") if(remove.bracket){ text_grob <- get_text_grob(data, coords, coord.flip = coord.flip, parse = parse) return(text_grob) } grid::gList( get_text_grob(data, coords, coord.flip = coord.flip, parse = parse), grid::segmentsGrob( coords$x, coords$y, default.units = "native", coords$xend, coords$yend, gp = grid::gpar( col = scales::alpha(coords$colour, coords$alpha), lty = coords$linetype, lwd = coords$size * ggplot2::.pt ) ) ) } ) # Text grob ------------------------------ get_text_grob <- function(data, coords, coord.flip = FALSE, parse = FALSE){ lab <- as.character(data$label) if(parse) lab <- parse_as_expression(lab) label_coords <- get_pwc_label_coords(coords, coord.flip = coord.flip ) grid::textGrob( lab, x = label_coords$x, y = label_coords$y, default.units = "native", hjust = coords$hjust, vjust = coords$vjust, rot = label_coords$angle, gp = grid::gpar( col = scales::alpha(coords$colour, coords$alpha), fontsize = coords$label.size * ggplot2::.pt, fontfamily = coords$family, fontface = coords$fontface, lineheight = coords$lineheight ) ) } # Source: https://github.com/tidyverse/ggplot2/issues/2864 parse_as_expression <- function(text) { stopifnot(is.character(text)) out <- vector("expression", length(text)) for (i in seq_along(text)) { expr <- parse(text = text[[i]]) out[[i]] <- if (length(expr) == 0) NA else expr[[1]] } out } # Compute the coordinates of pairwise comparison labels get_pwc_label_coords <- function(coords, coord.flip = FALSE){ get_label_x <- function(coords){mean(c(coords$x[1], utils::tail(coords$xend, n=1)))} get_label_y <- function(coords){max(c(coords$y, coords$yend))+0.01} get_label_angle <- function(coords, coord.flip = FALSE){ label.angle <- coords$angle[1] if(coord.flip & is.na(label.angle)) label.angle <- -90 if(is.na(label.angle)) label.angle <- 0 label.angle[1] } if(coord.flip){ get_label_x <- function(coords){max(c(coords$x, coords$xend))+0.01} get_label_y <- function(coords){mean(c(coords$y[1], utils::tail(coords$yend, n=1)))} } if(!("group" %in% colnames(coords))){ coords$group <- 1 } data <- NULL coords %>% rstatix::df_nest_by(vars = c("group", "bracket.group")) %>% dplyr::transmute( x = unlist(map(data, get_label_x)), y = unlist(map(data, get_label_y)), angle = unlist(map(data, get_label_angle, coord.flip = coord.flip)) ) } # Statistical tests -------------------------------------------------- # Get the pairwise comparison stat function # returns a list(method, method.args) get_pwc_stat_function <- function(method, method.args){ if(is.character(method)){ # replace t.test by t_test, etc method <- gsub(pattern = ".", replacement = "_", method, fixed = TRUE) if(method == "wilcoxon") method <- "wilcox_test" else if(method == "emmeans") method <- "emmeans_test" else if(method == "games_howell") method <- "games_howell_test" allowed.methods <- c( "wilcox_test", "wilcoxon", "t_test", "sign_test", "dunn_test", "emmeans_test", "emmeans", "tukey_hsd", "games_howell_test" ) if(!(method %in% allowed.methods)){ stop( "Unknown stat method: '", method, "'. ", "Allowed method names are: ", paste(allowed.methods, collapse = ","), call. = FALSE ) } # Ignoring p.adjust.method for tukey_hsd and games_howell # because they come with internal adjustment method if(method %in% c("tukey_hsd", "games_howell_test")) method.args$p.adjust.method <- NULL stat_func <- switch( method, wilcox_test = rstatix::wilcox_test, t_test = rstatix::t_test, sign_test = rstatix::sign_test, dunn_test = rstatix::dunn_test, emmeans_test = rstatix::emmeans_test, tukey_hsd = function(data, formula, ...){rstatix::tukey_hsd(data, formula, ...)}, games_howell_test = rstatix::games_howell_test, games_howell = rstatix::games_howell_test ) } else if(is.function(method)){ stat_func <- method } else{ stop("The argument method is required.") } list( method = stat_func, method.args = method.args ) } # Get ref group rank id for comparison against reference ------------------------------------- # param scales: ggproto scales # param data: ggproto data # param ref.group: group name # Returns 1 (for the first group), 2 for the second group get_ref_group_id <- function(scales, data, ref.group = NULL, is.comparisons.between.legend.grps = FALSE){ if(is.null(ref.group)) return(NULL) else if(ref.group %in% c(".all.", "all")) return(ref.group) # Grouped plots if(is.comparisons.between.legend.grps){ if(is.character(ref.group)){ if("legend.var" %in% colnames(data)){ ref.group <- get_group_id(data$legend.var, ref.group) if(is.na(ref.group)) stop("The ref.group ('", ref.group, "') doesn't exist.", call. = FALSE) } else{ stop( "ref.group should be a numeric value indicating the rank of the ", "legend group to be used as the reference. \n", "For example, use ref.group = 1 when the first group is the reference; \n", "use ref.group = 2 when the second group is the reference and so on.", call. = FALSE ) } } } # Basic plot: comparison between x-axis groups else if(is.character(ref.group)){ ref.group <- scales$x$map(ref.group) %>% as.character() } as.character(ref.group) } # x a factor # group a level get_group_id <- function(x, group){ ids <- x %>% as.factor() %>% as.numeric() names(ids) <- x unname(ids[group]) %>% unique() } ggpubr/R/ggpubr_args.R0000644000176200001440000000635614332553655014413 0ustar liggesusers#' ggpubr General Arguments Description #' #'@param data a data frame #'@param x character string containing the name of x variable. #'@param y character vector containing one or more variables to plot #'@param combine logical value. Default is FALSE. Used only when y is a vector #' containing multiple variables to plot. If TRUE, create a multi-panel plot by #' combining the plot of y variables. #'@param merge logical or character value. Default is FALSE. Used only when y is #' a vector containing multiple variables to plot. If TRUE, merge multiple y #' variables in the same plotting area. Allowed values include also "asis" #' (TRUE) and "flip". If merge = "flip", then y variables are used as x tick #' labels and the x variable is used as grouping variable. #'@param color outline color. #'@param fill fill color. #'@param palette the color palette to be used for coloring or filling by groups. #' Allowed values include "grey" for grey color palettes; brewer palettes e.g. #' "RdBu", "Blues", ...; or custom color palette e.g. c("blue", "red"); and #' scientific journal palettes from ggsci R package, e.g.: "npg", "aaas", #' "lancet", "jco", "ucscgb", "uchicago", "simpsons" and "rickandmorty". #'@param linetype line types. #'@param size Numeric value (e.g.: size = 1). change the size of points and #' outlines. #'@param select character vector specifying which items to display. #'@param remove character vector specifying which items to remove from the plot. #'@param order character vector specifying the order of items. #'@param add character vector for adding another plot element (e.g.: dot plot or #' error bars). Allowed values are one or the combination of: "none", #' "dotplot", "jitter", "boxplot", "point", "mean", "mean_se", "mean_sd", #' "mean_ci", "mean_range", "median", "median_iqr", "median_mad", #' "median_range"; see ?desc_statby for more details. #'@param add.params parameters (color, shape, size, fill, linetype) for the #' argument 'add'; e.g.: add.params = list(color = "red"). #'@param error.plot plot type used to visualize error. Allowed values are one of #' c("pointrange", "linerange", "crossbar", "errorbar", "upper_errorbar", #' "lower_errorbar", "upper_pointrange", "lower_pointrange", "upper_linerange", #' "lower_linerange"). Default value is "pointrange" or "errorbar". Used only #' when add != "none" and add contains one "mean_*" or "med_*" where "*" = sd, #' se, .... #'@param font.label a list which can contain the combination of the following elements: the size #' (e.g.: 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and #' the color (e.g.: "red") of labels. For example font.label = list(size = 14, #' face = "bold", color ="red"). To specify only the size and the style, use font.label = #' list(size = 14, face = "plain"). #' @param title plot main title. #' @param xlab character vector specifying x axis labels. Use xlab #' = FALSE to hide xlab. #' @param ylab character vector specifying y axis labels. Use ylab = FALSE to #' hide ylab. #'@param ggtheme function, ggplot2 theme name. Default value is theme_pubr(). #' Allowed values include ggplot2 official themes: theme_gray(), theme_bw(), #' theme_minimal(), theme_classic(), theme_void(), .... #' @name ggpubr_args #' @rdname ggpubr_args NULL ggpubr/R/ggline.R0000644000176200001440000002623214342705003013334 0ustar liggesusers#' @include utilities.R ggpar.R NULL #' Line plot #' @description Create a line plot. #' @inheritParams ggboxplot #' @inheritParams ggplot2::geom_line #' @param x,y x and y variables for drawing. #' @param group grouping variable to connect points by line. #' Allowed values are 1 (for one line, one group) or a character vector specifying #' the name of the grouping variable (case of multiple lines). #' @param numeric.x.axis logical. If TRUE, x axis will be treated as numeric. Default is FALSE. #' @param color line colors. #' @param linetype line type. #' @param plot_type plot type. Allowed values are one of "b" for both line and point; #' "l" for line only; and "p" for point only. Default is "b". #' @param shape point shapes. #' @param stroke point stroke. Used only for shapes 21-24 to control the thickness of points border. #' @param show.line.label logical value. If TRUE, shows line labels. #' @param point.size point size. #' @param point.color point color. #' @param ... other arguments to be passed to geom_dotplot. #' #' #' @details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" \item plot orientation : orientation #' = c("vertical", "horizontal", "reverse") } #' @seealso \code{\link{ggpar}}, \code{\link{ggbarplot}} #' @examples #' # Data #' df <- data.frame(dose=c("D0.5", "D1", "D2"), #' len=c(4.2, 10, 29.5)) #' print(df) #' #' # Basic plot #' # +++++++++++++++++++++++++++ #' ggline(df, x = "dose", y = "len") #' #' #' # Plot with multiple groups #' # +++++++++++++++++++++ #' #' # Create some data #' df2 <- data.frame(supp=rep(c("VC", "OJ"), each=3), #' dose=rep(c("D0.5", "D1", "D2"),2), #' len=c(6.8, 15, 33, 4.2, 10, 29.5)) #' print(df2) #' #' # Plot "len" by "dose" and #' # Change line types and point shapes by a second groups: "supp" #' ggline(df2, "dose", "len", #' linetype = "supp", shape = "supp") #' #' #' # Change colors #' # +++++++++++++++++++++ #' #' # Change color by group: "supp" #' # Use custom color palette #' ggline(df2, "dose", "len", #' linetype = "supp", shape = "supp", #' color = "supp", palette = c("#00AFBB", "#E7B800")) #' #' #' # Add points and errors #' # ++++++++++++++++++++++++++ #' #' # Data: ToothGrowth data set we'll be used. #' df3 <- ToothGrowth #' head(df3, 10) #' #' # It can be seen that for each group we have #' # different values #' ggline(df3, x = "dose", y = "len") #' #' # Visualize the mean of each group #' ggline(df3, x = "dose", y = "len", #' add = "mean") #' #' # Add error bars: mean_se #' # (other values include: mean_sd, mean_ci, median_iqr, ....) #' # Add labels #' ggline(df3, x = "dose", y = "len", add = "mean_se") #' #' # Change error.plot to "pointrange" #' ggline(df3, x = "dose", y = "len", #' add = "mean_se", error.plot = "pointrange") #' #' # Add jitter points and errors (mean_se) #' ggline(df3, x = "dose", y = "len", #' add = c("mean_se", "jitter")) #' #' # Add dot and errors (mean_se) #' ggline(df3, x = "dose", y = "len", #' add = c("mean_se", "dotplot"), color = "steelblue") #' #' # Add violin and errors (mean_se) #' ggline(df3, x = "dose", y = "len", #' add = c("mean_se", "violin"), color = "steelblue") #' #' # Multiple groups with error bars #' # ++++++++++++++++++++++ #' #' ggline(df3, x = "dose", y = "len", color = "supp", #' add = "mean_se", palette = c("#00AFBB", "#E7B800")) #' #' # Add jitter #' ggline(df3, x = "dose", y = "len", color = "supp", #' add = c("mean_se", "jitter"), palette = c("#00AFBB", "#E7B800")) #' #' # Add dot plot #' ggline(df3, x = "dose", y = "len", color = "supp", #' add = c("mean_se", "dotplot"), palette = c("#00AFBB", "#E7B800")) # #' #' #' @export ggline<- function(data, x, y, group = 1, numeric.x.axis = FALSE, combine = FALSE, merge = FALSE, color = "black", palette = NULL, linetype = "solid", plot_type = c("b", "l", "p"), size = 0.5, shape = 19, stroke = NULL, point.size = size, point.color = color, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, select = NULL, remove = NULL, order = NULL, add = "none", add.params = list(), error.plot = "errorbar", label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, show.line.label = FALSE, position = "identity", ggtheme = theme_pubr(), ...) { # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( group = group, numeric.x.axis = numeric.x.axis, combine = combine, merge = merge, color = color, palette = palette, linetype = linetype, plot_type = plot_type, size = size, shape = shape, stroke = stroke, point.size = point.size, point.color = point.color, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, select = select , remove = remove, order = order, add = add, add.params = add.params, error.plot = error.plot, label = label, font.label = font.label, label.select = label.select, repel = repel, label.rectangle = label.rectangle, show.line.label = show.line.label, position = position, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x if(!missing(y)) .opts$y <- y # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$fun <- ggline_core .opts$fun_name <- "ggline" if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggline_core <- function(data, x, y, group = 1, numeric.x.axis = FALSE, color = "black", fill = "white", palette = NULL, linetype = "solid", plot_type = c("b", "l", "p"), size = 0.5, shape = 19, stroke = NULL, point.size = size, point.color = color, title = NULL, xlab = NULL, ylab = NULL, select = NULL, order = NULL, facet.by = NULL, add = "none", add.params = list(), error.plot = "errorbar", show.line.label = FALSE, font.label = list(size = 11, color = "black"), repel = FALSE, label.rectangle = FALSE, position = "identity", ggtheme = theme_pubr(), ...) { xx <- .select_vec(data, x) if(inherits(xx, c("character", "numeric")) & !numeric.x.axis) data[[x]] <- .select_vec(data, x) %>% as.factor() error.plot = error.plot[1] plot_type <- match.arg(plot_type) if("none" %in% add) add <- "none" grouping.vars <- intersect(c(x, color, linetype, group, facet.by), names(data)) . <- NULL # static summaries for computing mean/median and adding errors if(is.null(add.params$fill)) add.params$fill <- "white" add.params <- .check_add.params(add, add.params, error.plot, data, color, fill = "white", ...) if(any(.summary_functions() %in% add)) { data_sum <- desc_statby(data, measure.var = y, grps = grouping.vars) summary.funcs <- intersect(.summary_functions(), add) if(length(summary.funcs) > 1) stop("Only one summary function is allowed. ", "Choose one of ", .collapse(.summary_functions(), sep = ", ")) .center <- summary.funcs %>% strsplit("_", fixed = TRUE) %>% unlist() %>% .[1] add <- setdiff(add, .center) names(data_sum)[which(names(data_sum) == .center)] <- y # data_sum[, x] <- as.factor(data_sum[, x]) if(inherits(xx, c("character", "numeric")) & !numeric.x.axis) data_sum[, x] <- .select_vec(data_sum, x) %>% as.factor() } else data_sum <- data .cols <- unique(c(color, linetype, group)) if(any(.cols %in% names(data))){ .in <- which(.cols %in% names(data)) group <- .cols[.in] if(is.null(add.params$group)) add.params$group <- group[1] } p <- ggplot(data, create_aes(list(x = x, y = y))) # Add other geom or summary #::::::::::::::::::::::::::::::::::::::: add.params <- add.params %>% .add_item(error.plot = error.plot, position = position, p_geom = "geom_line") # First add geom if any p <- add.params %>% .add_item(p = p, add = setdiff(add, .summary_functions())) %>% do.call(ggadd, .) # Then add summary statistics p <- add.params %>% .add_item(p = p, size = size, add = intersect(add, .summary_functions())) %>% do.call(ggadd, .) # add.params <- add.params %>% # .add_item(p = p, add = add, error.plot = error.plot, # position = "identity", p_geom = "geom_line") # p <- do.call(ggadd, add.params) # Main plot if(plot_type %in% c("b", "l")){ line_args <- geom_exec(NULL, data = data_sum, stat = "identity", color = color, linetype = linetype, position = position, size = size) mapping <- line_args$mapping mapping[["group"]] <- group option <- line_args$option option[["mapping"]] <- create_aes(mapping) p <- p + do.call(geom_line, option) } if(plot_type %in% c("p", "b")){ p <- p + geom_exec(geom_point, data = data_sum, color = point.color, shape = shape, size = 1.2+point.size, stroke = stroke, position = position) # Adjust shape when ngroups > 6, to avoid ggplot warnings p <-.scale_point_shape(p, data_sum, shape) } # Color palette user.add.color <- list(...)$user.add.color if(is.null(user.add.color)) user.add.color <- "" if(.is_color(user.add.color) & !is.numeric(group)){ ngroup <- nlevels(.select_vec(data_sum, group)) palette <- rep(user.add.color, ngroup) } if(show.line.label & !is.numeric(group)){ xval <- .select_vec(data_sum, x) last.xval <- .levels(xval) %>% utils::tail(1) groupval <- .select_vec(data_sum, group) label.data <- subset(data_sum, xval == last.xval) font.label <- .parse_font(font.label) p <- font.label %>% .add_item(data = label.data, x = x, y = y, label = group, repel = repel, label.rectangle = label.rectangle, ggtheme = ggtheme, ggp = p) %>% do.call(ggtext, .) } p <- ggpar(p, palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab,...) p } ggpubr/R/stat_compare_means.R0000644000176200001440000003516214370060424015737 0ustar liggesusers#' @include utilities.R utilities_label.R NULL #'Add Mean Comparison P-values to a ggplot #'@description Add mean comparison p-values to a ggplot, such as box blots, dot #' plots and stripcharts. #'@inheritParams ggplot2::layer #'@inheritParams compare_means #'@param method a character string indicating which method to be used for #' comparing means. #'@param method.args a list of additional arguments used for the test method. #' For example one might use \code{method.args = list(alternative = "greater")} #' for wilcoxon test. #'@param comparisons A list of length-2 vectors. The entries in the vector are #' either the names of 2 values on the x-axis or the 2 integers that correspond #' to the index of the groups of interest, to be compared. #'@param hide.ns logical value. If TRUE, hide ns symbol when displaying #' significance levels. #'@param label character string specifying label type. Allowed values include #' "p.signif" (shows the significance levels), "p.format" (shows the formatted #' p value). #'@param label.sep a character string to separate the terms. Default is ", ", to #' separate the correlation coefficient and the p.value. #'@param label.x.npc,label.y.npc can be \code{numeric} or \code{character} #' vector of the same length as the number of groups and/or panels. If too #' short they will be recycled. \itemize{ \item If \code{numeric}, value should #' be between 0 and 1. Coordinates to be used for positioning the label, #' expressed in "normalized parent coordinates". \item If \code{character}, #' allowed values include: i) one of c('right', 'left', 'center', 'centre', #' 'middle') for x-axis; ii) and one of c( 'bottom', 'top', 'center', 'centre', #' 'middle') for y-axis.} #'@param vjust move the text up or down relative to the bracket. #'@param tip.length numeric vector with the fraction of total height that the #' bar goes down to indicate the precise column. Default is 0.03. Can be of #' same length as the number of comparisons to adjust specifically the tip #' lenth of each comparison. For example tip.length = c(0.01, 0.03). #' #' If too short they will be recycled. #'@param label.x,label.y \code{numeric} Coordinates (in data units) to be used #' for absolute positioning of the label. If too short they will be recycled. #'@param bracket.size Width of the lines of the bracket. #'@param step.increase numeric vector with the increase in fraction of total #' height for every additional comparison to minimize overlap. #'@param ... other arguments to pass to \code{\link[ggplot2]{geom_text}} or #' \code{\link[ggplot2:geom_text]{geom_label}}. #'@param na.rm If FALSE (the default), removes missing values with a warning. If #' TRUE silently removes missing values. #'@seealso \code{\link{compare_means}} #' @examples #' # Load data #' data("ToothGrowth") #' head(ToothGrowth) #' #' # Two independent groups #' #::::::::::::::::::::::::::::::::::::::::::::::::: #' p <- ggboxplot(ToothGrowth, x = "supp", y = "len", #' color = "supp", palette = "npg", add = "jitter") #' #' # Add p-value #' p + stat_compare_means() #' # Change method #' p + stat_compare_means(method = "t.test") #' #' # Paired samples #' #::::::::::::::::::::::::::::::::::::::::::::::::: #' ggpaired(ToothGrowth, x = "supp", y = "len", #' color = "supp", line.color = "gray", line.size = 0.4, #' palette = "npg")+ #' stat_compare_means(paired = TRUE) #' #' # More than two groups #' #::::::::::::::::::::::::::::::::::::::::::::::::: #' # Pairwise comparisons: Specify the comparisons you want #' my_comparisons <- list( c("0.5", "1"), c("1", "2"), c("0.5", "2") ) #' ggboxplot(ToothGrowth, x = "dose", y = "len", #' color = "dose", palette = "npg")+ #' # Add pairwise comparisons p-value #' stat_compare_means(comparisons = my_comparisons, label.y = c(29, 35, 40))+ #' stat_compare_means(label.y = 45) # Add global Anova p-value #' #' # Multiple pairwise test against a reference group #' ggboxplot(ToothGrowth, x = "dose", y = "len", #' color = "dose", palette = "npg")+ #' stat_compare_means(method = "anova", label.y = 40)+ # Add global p-value #' stat_compare_means(aes(label = after_stat(p.signif)), #' method = "t.test", ref.group = "0.5") #' #' # Multiple grouping variables #' #::::::::::::::::::::::::::::::::::::::::::::::::: #' # Box plot facetted by "dose" #'p <- ggboxplot(ToothGrowth, x = "supp", y = "len", #' color = "supp", palette = "npg", #' add = "jitter", #' facet.by = "dose", short.panel.labs = FALSE) #'# Use only p.format as label. Remove method name. #'p + stat_compare_means( #' aes(label = paste0("p = ", after_stat(p.format))) #') #' #'@export stat_compare_means <- function(mapping = NULL, data = NULL, method = NULL, paired = FALSE, method.args = list(), ref.group = NULL, comparisons = NULL, hide.ns = FALSE, label.sep = ", ", label = NULL, label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, vjust = 0, tip.length = 0.03, bracket.size = 0.3, step.increase = 0, symnum.args = list(), geom = "text", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ...) { if(!is.null(comparisons)){ method.info <- .method_info(method) method <- method.info$method method.args <- .add_item(method.args, paired = paired) pms <- list(...) size <- ifelse(is.null(pms$size), 3.88, pms$size) color <- ifelse(is.null(pms$color), "black", pms$color) map_signif_level <- FALSE if(is.null(label)) label <- "p.format" if(.is_p.signif_in_mapping(mapping) | (label %in% "p.signif")) { map_signif_level <- c("****"=0.0001, "***"=0.001, "**"=0.01, "*"=0.05, "ns"=Inf) if(hide.ns) map_signif_level <- .hide_ns(map_signif_level) } if(!.is_empty(symnum.args)){ symnum.args.isok <- length(symnum.args$cutpoints == length(symnum.args$symbols)) if(!symnum.args.isok) stop("Incorrect format detected in symnum.args. ", "Check the documentation.") map_signif_level <- symnum.args$cutpoints[-1] # the first element is 0 (the minimum p-value) names(map_signif_level) <- symnum.args$symbols if(hide.ns) map_signif_level <- .hide_ns(map_signif_level) } if(missing(step.increase)){ step.increase <- ifelse(is.null(label.y), 0.12, 0) } ggsignif::geom_signif(comparisons = comparisons, y_position = label.y, test = method, test.args = method.args, step_increase = step.increase, size = bracket.size, textsize = size, color = color, map_signif_level = map_signif_level, tip_length = tip.length, data = data, vjust = vjust) } else{ mapping <- .update_mapping(mapping, label) layer( stat = StatCompareMeans, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(label.x.npc = label.x.npc , label.y.npc = label.y.npc, label.x = label.x, label.y = label.y, label.sep = label.sep, method = method, method.args = method.args, paired = paired, ref.group = ref.group, symnum.args = symnum.args, hide.ns = hide.ns, na.rm = na.rm, vjust = vjust,...) ) } } StatCompareMeans<- ggproto("StatCompareMeans", Stat, required_aes = c("x", "y"), default_aes = aes(hjust = ..hjust.., vjust = ..vjust..), compute_panel = function(data, scales, method, method.args, paired, ref.group, symnum.args, hide.ns, label.x.npc, label.y.npc, label.x, label.y, label.sep) { . <- x <- NULL .is.multiple.grouping.vars <- !all(data$x == data$group) if(!is.null(ref.group)) { if(ref.group != ".all.") ref.group <- scales$x$map(ref.group) } # Guess the number of group to be compared #:::::::::::::::::::::::::::::::::::::::::::::::::: if(.is.multiple.grouping.vars) x.levels <- .levels(data$group) else x.levels <- .levels(data$x) two.groups <- length(x.levels) == 2 | !is.null(ref.group) multi.groups <- length(x.levels) > 2 # Guess the test to be performed #:::::::::::::::::::::::::::::::::::::::::::::::::: if(two.groups & is.null(method)) method <- "wilcox.test" else if(multi.groups & is.null(method)) method <- "kruskal.test" # Perform group comparisons #:::::::::::::::::::::::::::::::::::::::::::::::::: if(!is.null(ref.group)) ref.group <- as.character(ref.group) method.args <- method.args %>% .add_item(data = data, method = method, paired = paired, ref.group = ref.group, symnum.args = symnum.args) if(.is.multiple.grouping.vars){ method.args <- method.args %>% .add_item(formula = y ~ group, group.by = "x") .test <- do.call(compare_means, method.args) } else{ method.args <- method.args %>% .add_item(formula = y ~ x) .test <- do.call(compare_means, method.args) } pvaltxt <- ifelse(.test$p < 2.2e-16, "p < 2.2e-16", paste("p =", signif(.test$p, 2))) .test$label <- paste(.test$method, pvaltxt, sep = label.sep) # Options for label positioning #:::::::::::::::::::::::::::::::::::::::::::::::::: label.opts <- list(data = data, scales = scales, label.x.npc = label.x.npc, label.y.npc = label.y.npc, label.x = label.x, label.y = label.y, symnum.args = symnum.args, .by = "panel" ) if(.is.multiple.grouping.vars){ if(is.null(label.x) & length(label.x.npc) == 1) label.opts$label.x <- .test$x .label.pms <- label.opts %>% .add_item(group.ids = .test$x) %>% do.call(.label_params_by_group, .) # Returns a data frame with label: x, y, hjust, vjust # .test <- dplyr::select(.test, -x) .label.pms <- dplyr::select(.label.pms, -x) } else{ .label.pms <- label.opts %>% do.call(.label_params, .) %>% # Returns a data frame with label: x, y, hjust, vjust dplyr::mutate(hjust = 0.2) } if(!is.null(ref.group)){ group.ids <- as.numeric(.test$group2) if(!is.null(label.y) & ref.group != ".all."){ if(length(label.y) == length(group.ids)) label.opts$label.y <- c(0, label.y) } .label.pms <- label.opts %>% .add_item(group.ids = group.ids) %>% do.call(.label_params_by_group, .) } res <- cbind(.test, .label.pms) if(!is.null(ref.group)){ # Set label x value to group names other.group.index <- as.numeric(res$group2) res$x <- scales$x$range$range[other.group.index ] res <- res %>% dplyr::mutate(hjust = 0.5) } if(hide.ns){ p.signif <- res$p.signif p.format <- res$p.format p.signif[p.signif == "ns"] <- " " res$p.signif <- p.signif } res } ) # Check if p.signif is in mapping .is_p.signif_in_mapping <- function(mapping){ res <- FALSE if(!is.null(mapping)){ if(!is.null(mapping$label)){ .label <- rlang::as_label(mapping$label) res <- grepl(pattern = "p\\.signif", .label) } } return(res) } # Update mapping with label .update_mapping <- function (mapping, label){ allowed.label <- list( "p.signif" = quote(ggplot2::after_stat(p.signif)), "..p.signif.." = quote(ggplot2::after_stat(p.signif)), "p.format" = quote(ggplot2::after_stat(paste0("p = ", p.format))), "..p.format.." = quote(ggplot2::after_stat(paste0("p = ", p.format))), "p" = quote(ggplot2::after_stat(paste0("p = ", p.format))), "..p.." = quote(ggplot2::after_stat(paste0("p = ", p.format))) ) if(!is.null(label)){ if(!label %in% names(allowed.label) ) stop("Allowed values for label are: ", .collapse(names(allowed.label) , sep = ", ")) } if(!is.null(mapping) & is.character(label)){ mapping$label <- allowed.label[[label]] } else if(is.character(label)){ mapping <- aes() mapping$label <- allowed.label[[label]] } convert_label_dotdot_notation_to_after_stat(mapping) } # Hide NS in map_signif_level .hide_ns <- function(x){ n <- names(x) ns.pos <- which(n == "ns" | n == "NS") if(!.is_empty(ns.pos)) n[ns.pos] = " " names(x) <- n x } # The dot-dot notation (`..p.signif..`) was deprecated in ggplot2 3.4.0. # after_stat(p.signif) should be used. This function makes automatic # conversion if user specified ..p.signif.. convert_label_dotdot_notation_to_after_stat <- function(mapping){ if(!is.null(mapping) ){ label <- mapping$label if(!is.null(mapping$label)){ label <- rlang::as_label(mapping$label) label <- gsub( pattern = "..p.signif..", replacement = "ggplot2::after_stat(p.signif)", x = label, fixed = TRUE ) label <- gsub( pattern = "..p.format..", replacement = "ggplot2::after_stat(p.format)", x = label, fixed = TRUE ) label <- gsub( pattern = "..p..", replacement = "ggplot2::after_stat(p)", x = label, fixed = TRUE ) mapping$label <- parse(text = label)[[1]] } } mapping } ggpubr/R/set_palette.R0000644000176200001440000000452314332553655014414 0ustar liggesusers#' @include utilities_color.R NULL #'Set Color Palette #' #'@description \itemize{ \item \code{change_palette(), set_palette()}: Change #'both color and fill palettes. \item \code{color_palette()}: change color #'palette only. \item \code{fill_palette()}: change fill palette only. #' #'} #'@inheritParams get_palette #'@param p a ggplot #'@param ... other arguments passed to ggplot2 scale_color_xxx() and #' scale_fill_xxx() functions. #' #'@seealso \link{get_palette}. #' #' #'@examples #'# Load data #'data("ToothGrowth") #'df <- ToothGrowth #' #'# Basic plot #'p <- ggboxplot(df, x = "dose", y = "len", #' color = "dose") #'p #' #'# Change the color palette #' set_palette(p, "jco") #'@name set_palette #'@rdname set_palette #'@export set_palette <- function(p, palette){ p + .ggcolor(palette)+ .ggfill(palette) } #'@rdname set_palette #'@export change_palette <- function(p, palette){ set_palette(p, palette) } #'@rdname set_palette #'@export color_palette <- function(palette = NULL, ...) { brewerpal <- .brewerpal() ggscipal <- .ggscipal() res <- NULL if (is.null(palette)) palette <- "" if (length(palette) == 1) { if (palette %in% brewerpal) ggplot2::scale_color_brewer(..., palette = palette) else if (palette %in% ggscipal) .scale_color_ggsci(palette = palette) else if (palette == "grey") ggplot2::scale_color_grey(..., start = 0.8, end = 0.2) else if (palette == "hue") ggplot2::scale_color_hue(...) else if(.is_color(palette)) ggplot2::scale_color_manual(..., values = palette) } else if (palette[1] != "") ggplot2::scale_color_manual(..., values = palette) } #'@rdname set_palette #'@export fill_palette <- function(palette = NULL, ...){ brewerpal <- .brewerpal() ggscipal <- .ggscipal() res <- NULL if (is.null(palette)) palette <- "" if (length(palette) == 1) { if (palette %in% brewerpal) ggplot2::scale_fill_brewer(..., palette = palette) else if (palette %in% ggscipal) .scale_fill_ggsci(palette = palette) else if (palette == "grey") ggplot2::scale_fill_grey(..., start = 0.8, end = 0.2) else if (palette == "hue") ggplot2::scale_fill_hue(...) else if(.is_color(palette)) ggplot2::scale_fill_manual(..., values = palette) } else if (palette[1] != "") ggplot2::scale_fill_manual(..., values = palette) } ggpubr/R/gene_citation.R0000644000176200001440000000245114332553655014711 0ustar liggesusers#'Gene Citation Index #' #'@description Contains the mean citation index of 66 genes obtained by #' assessing PubMed abstracts and annotations using two key words i) Gene name #' + b cell differentiation and ii) Gene name + plasma cell differentiation. #'@name gene_citation #'@docType data #'@usage data("gene_citation") #'@format A data frame with 66 rows and 2 columns. \describe{ #' \item{\code{gene}}{gene names} \item{\code{citation_index}}{mean citation index} } #' #' @examples #' data(gene_citation) #' #'# Some key genes of interest to be highlighted #'key.gns <- c("MYC", "PRDM1", "CD69", "IRF4", "CASP3", "BCL2L1", "MYB", "BACH2", "BIM1", "PTEN", #' "KRAS", "FOXP1", "IGF1R", "KLF4", "CDK6", "CCND2", "IGF1", "TNFAIP3", "SMAD3", "SMAD7", #' "BMPR2", "RB1", "IGF2R", "ARNT") #'# Density distribution #'ggdensity(gene_citation, x = "citation_index", y = "..count..", #' xlab = "Number of citation", #' ylab = "Number of genes", #' fill = "lightgray", color = "black", #' label = "gene", label.select = key.gns, repel = TRUE, #' font.label = list(color= "citation_index"), #' xticks.by = 20, # Break x ticks by 20 #' gradient.cols = c("blue", "red"), #' legend = "bottom", #' legend.title = "" # Hide legend title #' ) #' NULL ggpubr/R/reexports.R0000644000176200001440000000027514332553655014136 0ustar liggesusers#' @importFrom dplyr mutate #' @export dplyr::mutate #' @importFrom dplyr group_by #' @export dplyr::group_by #' @importFrom rstatix get_summary_stats #' @export rstatix::get_summary_stats ggpubr/R/background_image.R0000644000176200001440000000165314332553655015365 0ustar liggesusers#' @include utilities.R NULL #'Add Background Image to ggplot2 #'@description Add background image to ggplot2. #'@param raster.img raster object to display, as returned by the function #' \code{readPNG()}[in \code{png} package] and \code{readJPEG()} [in \code{jpeg} package]. #'@author Alboukadel Kassambara #' @examples #' \dontrun{ #'install.packages("png") #' #'# Import the image #'img.file <- system.file(file.path("images", "background-image.png"), #' package = "ggpubr") #'img <- png::readPNG(img.file) #' #'# Plot with background image #'ggplot(iris, aes(Species, Sepal.Length))+ #' background_image(img)+ #' geom_boxplot(aes(fill = Species), color = "white")+ #' fill_palette("jco") #' } #' #'@export background_image <- function(raster.img){ annotation_raster(raster.img, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) } ggpubr/R/ggpubr-package.R0000644000176200001440000000257014343207174014754 0ustar liggesusers#' @keywords internal #' #' @details #' #' General resources: #' #'\itemize{ #' \item \href{https://rpkgs.datanovia.com/ggpubr/}{ggpubr documentation} #' \item \href{https://www.datanovia.com/en/blog/tag/ggpubr/}{ggpubr tutorials} #'} #' #' @section Package options: #' #' \describe{ #' \item{ggpubr.parse_aes}{logical indicating whether to parse or not aesthetics variables names. #' Default is \code{TRUE}. For example, if you want \code{ggpubr} to handle non-standard column names, like \code{A-A}, #' without parsing, then set this option to \code{FALSE} using \code{options(ggpubr.parse_aes = FALSE)}.} #' \item{ggpubr.null_device}{A function that creates an appropriate null device. #' These include: \code{\link[cowplot:pdf_null_device]{cowplot::pdf_null_device}}, #' \code{\link[cowplot:png_null_device]{cowplot::png_null_device}}, #' \code{\link[cowplot:cairo_null_device]{cowplot::cairo_null_device}} and #' \code{\link[cowplot:agg_null_device]{cowplot::agg_null_device}}. Default is #' \code{\link[cowplot:pdf_null_device]{cowplot::pdf_null_device}}. This is used in #' function like \code{\link{as_ggplot}()}, which needs to open a graphics #' device to render ggplot objects into grid graphics objects. This function is #' used to open null device for avoiding the display of unnecessary blank page #' when calling \code{\link{ggarrange}()} or \code{\link{as_ggplot}()}} } #' "_PACKAGE" ggpubr/R/ggtexttable.R0000644000176200001440000011427714350533257014421 0ustar liggesusers#' @include utilities.R NULL #' Draw a Textual Table #' @description Draw a textual table. \itemize{ \item \code{ggtexttable()}: draw #' a textual table. \item \code{ttheme()}: customize table theme. \item #' \code{rownames_style(), colnames_style(), tbody_style()}: helper functions #' to customize the table row names, column names and body. #' \item \code{table_cell_font()}: access to a table cell for changing the text font (size and face). #' \item \code{table_cell_bg()}: access to a table cell for changing the background (fill, color, linewidth). #' \item \code{tab_cell_crossout()}: cross out a table cell. #' \item \code{tab_ncol(), tab_nrow()}: returns, respectively, the number of columns and rows in a ggtexttable. #' \item \code{tab_add_hline()}: Creates horizontal lines or separators at the top or the bottom side of a given specified row. #' \item \code{tab_add_vline()}: Creates vertical lines or separators at the right or the left side of a given specified column. #' \item \code{tab_add_border(), tbody_add_border(), thead_add_border()}: Add borders to table; tbody is for table body and thead is for table head. #' \item \code{tab_add_title(),tab_add_footnote()}: Add title, subtitle and footnote to a table. #' } #'@inheritParams gridExtra::tableGrob #'@param x a \code{data.frame} or \code{matrix}. #'@param theme a list, as returned by the function \code{ttheme()}, defining the #' parameters of the table theme. Allowed values include one of \code{ttheme()} #' and \code{ttheme_clean()}. #'@param base_style character string the table style/theme. The available themes #' are illustrated in the #' \href{https://rpkgs.datanovia.com/ggpubr/files/ggtexttable-theme.pdf}{ggtexttable-theme.pdf} #' file. Allowed values include one of \code{c("default", "blank", "classic", #' "minimal", "light", "lBlack", "lBlue", "lRed", "lGreen", "lViolet", "lCyan", #' "lOrange", "lBlackWhite", "lBlueWhite", "lRedWhite", "lGreenWhite", #' "lVioletWhite", "lCyanWhite", "lOrangeWhite", "mBlack", "mBlue", "mRed", #' "mGreen", "mViolet", "mCyan", "mOrange", "mBlackWhite", "mBlueWhite", #' "mRedWhite", "mGreenWhite", "mVioletWhite", "mCyanWhite", "mOrangeWhite" )}. #' Note that, l = "light"; m = "medium". #'@param colnames.style a list, as returned by the function #' \code{colnames_style()}, defining the style of the table column names. #' Considered only when \code{base_size = "default"}. #'@param rownames.style a list, as returned by the function #' \code{rownames_style()}, defining the style of the table row names. #' Considered only when \code{base_size = "default"}. #'@param tbody.style a list, as returned by the function \code{tbody_style()}, #' defining the style of the table body. Considered only when \code{base_size = #' "default"}. #'@param color,face,size text font color, face and size, respectively. Allowed #' values for face include c("plain", "bold", "italic", "bold.italic"). #'@param fill background color. #'@param linewidth,linecolor line width and color, respectively. #'@param alpha numeric value specifying fill color transparency. #' Value should be in [0, 1], where 0 is full transparency and 1 is no transparency. #' @param at.row a numeric vector of row indexes; for example \code{at.row = c(1, 2)}. #' @param row.side row side to which the horinzotal line should be added. Can be one of \code{c("bottom", "top")}. #' @param from.column integer indicating the column from which to start drawing the horizontal line. #' @param to.column integer indicating the column to which the horizontal line should end. #' @param linetype line type #' @param at.column a numeric vector of column indexes; for example \code{at.column = c(1, 2)}. #' @param column.side column side to which the vertical line should be added. Can be one of \code{c("left", "right")}. #' @param from.row integer indicating the row from which to start drawing the horizontal line. #' @param to.row integer indicating the row to which the vertical line should end. #'@param ... extra parameters for text justification, e.g.: hjust and x. Default #' is "centre" for the body and header, and "right" for the row names. Left #' justification: \code{hjust = 0, x = 0.1}. Right justification: \code{hjust = 1, x = 0.9}. #'@return an object of class ggplot. #' #' #' @examples #' # data #' df <- head(iris) #' #' # Default table #' # Remove row names using rows = NULL #' ggtexttable(df, rows = NULL) #' #' # Text justification for individual cells/rows/columns (#335) #' # First column is left justified i.e., hjust = 0 , x = 0.1 #' # Remaining columns are right justified i.e., hjust = 1 , x = 0.9 #' table_theme <- ttheme( #' tbody.style = tbody_style( #' hjust = as.vector(matrix(c(0, 1, 1, 1, 1), ncol = 5, nrow = nrow(df), byrow = TRUE)), #' x = as.vector(matrix(c(.1, .9, .9,.9, .9), ncol = 5, nrow = nrow(df), byrow = TRUE)) #' ) #' ) #' ggtexttable(df, rows = NULL, theme = table_theme) #' #' # Blank theme #' ggtexttable(df, rows = NULL, theme = ttheme("blank")) #' #' # light theme #' ggtexttable(df, rows = NULL, theme = ttheme("light")) #' #' # Column names border only #' ggtexttable(df, rows = NULL, theme = ttheme("blank")) %>% #' tab_add_hline(at.row = 1:2, row.side = "top", linewidth = 2) #' #' # classic theme #' ggtexttable(df, rows = NULL, theme = ttheme("classic")) #' #' # minimal theme #' ggtexttable(df, rows = NULL, theme = ttheme("minimal")) #' #' # Medium blue (mBlue) theme #' ggtexttable(df, rows = NULL, theme = ttheme("mBlue")) #' #' #' # Customize the table as you want #' ggtexttable(df, rows = NULL, #' theme = ttheme( #' colnames.style = colnames_style(color = "white", fill = "#8cc257"), #' tbody.style = tbody_style(color = "black", fill = c("#e8f3de", "#d3e8bb")) #' ) #' ) #' #' # Use RColorBrewer palette #' # Provide as many fill color as there are rows in the table body, here nrow = 6 #'ggtexttable(df, #' theme = ttheme( #' colnames.style = colnames_style(fill = "white"), #' tbody.style = tbody_style(fill = get_palette("RdBu", 6)) #' ) #') #' #'# Text justification #'#:::::::::::::::::::::::::::::::::::::::::::::: #'# Default is "centre" for the body and header, and "right" for the row names. #'# Left justification: hjust=0, x=0.1 #'# Right justification: hjust=1, x=0.9 #'tbody.style = tbody_style(color = "black", #' fill = c("#e8f3de", "#d3e8bb"), hjust=1, x=0.9) #'ggtexttable(head(iris), rows = NULL, #' theme = ttheme( #' colnames.style = colnames_style(color = "white", fill = "#8cc257"), #' tbody.style = tbody.style #' ) #') #' #'# Access and modify the font and #'# the background of table cells #'# ::::::::::::::::::::::::::::::::::::::::::::: #'tab <- ggtexttable(head(iris), rows = NULL, #' theme = ttheme("classic")) #'tab <- table_cell_font(tab, row = 3, column = 2, #' face = "bold") #'tab <- table_cell_bg(tab, row = 4, column = 3, linewidth = 5, #' fill="darkolivegreen1", color = "darkolivegreen4") #'tab #' #'# Change table cells background and font for column 3, #'# Spaning from row 2 to the last row in the data #'tab <- ggtexttable(df, rows = NULL, theme = ttheme("classic")) #'tab %>% #' table_cell_bg(row = 2:tab_nrow(tab), column = 3, fill = "darkblue") %>% #' table_cell_font(row = 2:tab_nrow(tab), column = 3, face = "italic", color = "white") #' #'# Add separators and borders #'# ::::::::::::::::::::::::::::::::::::::::::::::::::: #'# Table with blank theme #'tab <- ggtexttable(df, theme = ttheme("blank"), rows = NULL) #'# Add horizontal and vertical lines #'tab %>% #' tab_add_hline(at.row = c(1, 2), row.side = "top", linewidth = 3, linetype = 1) %>% #' tab_add_hline(at.row = c(7), row.side = "bottom", linewidth = 3, linetype = 1) %>% #' tab_add_vline(at.column = 2:tab_ncol(tab), column.side = "left", from.row = 2, linetype = 2) #' #'# Add borders to table body and header #'# Cross out some cells #'tab %>% #' tbody_add_border() %>% #' thead_add_border() %>% #' tab_cell_crossout( #' row = c(2, 4), column = 3, linecolor = "red", #' reduce.size.by = 0.6 #' ) #' #'# Add titles andd footnote #'# ::::::::::::::::::::::::::::::::::::::::::::::::::: #'# Add titles and footnote #'# Wrap subtitle into multiple lines using strwrap() #'main.title <- "Edgar Anderson's Iris Data" #'subtitle <- paste0( #' "This famous (Fisher's or Anderson's) iris data set gives the measurements", #' " in centimeters of the variables sepal length and width and petal length and width,", #' " respectively, for 50 flowers from each of 3 species of iris.", #' " The species are Iris setosa, versicolor, and virginica." #') %>% #' strwrap(width = 80) %>% #' paste(collapse = "\n") #' #'tab <- ggtexttable(head(iris), theme = ttheme("light")) #'tab %>% #' tab_add_title(text = subtitle, face = "plain", size = 10) %>% #' tab_add_title(text = main.title, face = "bold", padding = unit(0.1, "line")) %>% #' tab_add_footnote(text = "*Table created using ggpubr", size = 10, face = "italic") #' #' #' # Combine density plot and summary table #'#::::::::::::::::::::::::::::::::::::: #'# Density plot of "Sepal.Length" #'density.p <- ggdensity(iris, x = "Sepal.Length", #' fill = "Species", palette = "jco") #' #'# Draw the summary table of Sepal.Length #'# Descriptive statistics by groups #'stable <- desc_statby(iris, measure.var = "Sepal.Length", #' grps = "Species") #'stable <- stable[, c("Species", "length", "mean", "sd")] #'stable.p <- ggtexttable(stable, rows = NULL, #' theme = ttheme("mOrange")) #' #'# Arrange the plots on the same page #'ggarrange(density.p, stable.p, #' ncol = 1, nrow = 2, #' heights = c(1, 0.5)) #' #'@rdname ggtexttable #'@export ggtexttable <- function(x, rows = rownames(x), cols = colnames(x), vp = NULL, theme = ttheme(), ...) { style <- attr(theme, "style") res <- gridExtra::tableGrob(x, rows = rows, cols = cols, vp = vp, theme = theme, ...) if(style == "minimal"){ # minimal = blank theme + left vertical line res <- tab_add_vline( res, at.column = 2:tab_ncol(res), column.side = "left", from.row = 2, to.row = tab_nrow(res) ) } else if(style == "light"){ # light = blank theme + horizontal line res <- tab_add_hline( res, at.row = c(1, tab_nrow(res)), row.side = "bottom", linewidth = 1.5, linetype = 1, from.column = 1 ) } .grob <- res res <- as_ggplot(res) attr(res, "ggtexttableGrob") <- .grob return(res) } #' @export #' @rdname ggtexttable ttheme <- function(base_style = "default", base_size = 11, base_colour = "black", padding = unit(c(4, 4), "mm"), colnames.style = colnames_style(size = base_size), rownames.style = rownames_style(size = base_size), tbody.style = tbody_style(size = base_size) ) { style <- tstyle(base_style, size = base_size) if(!is.null(style)){ if(missing(colnames.style)) colnames.style <- style$colnames.style if(missing(rownames.style)) rownames.style <- style$rownames.style if(missing(tbody.style)) tbody.style <- style$tbody.style } .ttheme <- gridExtra::ttheme_default(base_size = base_size, base_colour = base_colour, padding = padding) .ttheme$colhead <- do.call(.add_item, c(list(.list = .ttheme$colhead), colnames.style)) .ttheme$rowhead <- do.call(.add_item, c(list(.list = .ttheme$rowhead), rownames.style)) .ttheme$core <- do.call(.add_item, c(list(.list = .ttheme$core), tbody.style)) attr(.ttheme, "style") <- base_style .ttheme } #' @export #' @rdname ggtexttable colnames_style <- function(color = "black", face = "bold", size = 12, fill = "grey80", linewidth = 1, linecolor = "white", parse = FALSE, ...) { list( fg_params = list(parse = parse, col = color, fontface = face, fontsize = size) %>% .add_item(...), # Accept extra parameters bg_params = list(fill = fill, lwd = linewidth, col = linecolor)) } #' @export #' @rdname ggtexttable rownames_style <- function(color = "black", face = "italic", size = 12, fill = NA, linewidth = 1, linecolor = "white", parse = FALSE, ...) { list( fg_params = list(parse = parse, col = color, fontface = face, fontsize = size, hjust = 1, x = 0.95) %>% .add_item(...), # Accept extra parameters bg_params = list(fill = fill, lwd = linewidth, col = linecolor)) } #' @export #' @rdname ggtexttable tbody_style <- function(color = "black", face = "plain", size = 12, fill = c("grey95", "grey90"), linewidth = 1, linecolor = "white", parse = FALSE, ...) { list( fg_params = list(parse = parse, col = color, fontface = face, fontsize = size)%>% .add_item(...), # Accept extra parameters bg_params = list(fill = fill, lwd = linewidth, col = linecolor)) } #' @export #' @rdname ggtexttable #' @param tab an object from \code{ggtexttable} or from \code{gridExtra::tableGrob()}. #' @param row,column an integer specifying the row and the column numbers for the cell of interest. table_cell_font <- function(tab, row, column, face = NULL, size = NULL, color = NULL) { tabGrob <- get_tablegrob(tab) cells <- expand.grid(row = row, column = column) for(i in 1:nrow(cells)){ tc <- .find_cell(tabGrob, cells$row[i], cells$column[i], "core-fg") tabGrob$grobs[tc][[1]][["gp"]] <- grid::gpar(fontface = face, fontsize = size, col = color) } tab_return_same_class_as_input(tabGrob, input = tab) } #' @export #' @rdname ggtexttable table_cell_bg <- function(tab, row, column, fill = NULL, color = NULL, linewidth = NULL, alpha = NULL) { tabGrob <- get_tablegrob(tab) cells <- expand.grid(row = row, column = column) for(i in 1:nrow(cells)){ tc <- .find_cell(tabGrob, cells$row[i], cells$column[i], "core-bg") tabGrob$grobs[tc][[1]][["gp"]] <- grid::gpar( fill = fill, col = color, lwd = linewidth, alpha = alpha ) } tab_return_same_class_as_input(tabGrob, input = tab) } .find_cell <- function(tab, row, column, name="core-fg"){ l <- tab$layout which(l$t==row & l$l==column & l$name==name) } #' @export #' @rdname ggtexttable #' @param reduce.size.by Numeric value in [0, 1] to reduce the size by. tab_cell_crossout <- function(tab, row, column, linetype = 1, linewidth = 1, linecolor = "black", reduce.size.by = 0){ required_package("gtable") tabgrob <- get_tablegrob(tab) crosses <- replicate( n = length(row), tab_cross(linetype = linetype, linewidth = linewidth, linecolor = linecolor, reduce.size.by = reduce.size.by), simplify = FALSE ) tabgrob <- gtable::gtable_add_grob( tabgrob, grobs = crosses, t = row, b = row, l = column, r = column ) tab_return_same_class_as_input(tabgrob, input = tab) } tab_cross <- function(linetype = 1, linewidth = 1, linecolor = "black", reduce.size.by = 0){ reduce <- reduce.size.by/2 grid::grobTree( grid::segmentsGrob( # diagonal line ul -> lr x0 = unit(0+reduce,"npc"), y0 = unit(1-reduce,"npc"), x1 = unit(1-reduce,"npc"), y1 = unit(0+reduce,"npc"), gp = grid::gpar( lty = linetype, lwd = linewidth, col = linecolor, reduce = reduce) ), grid::segmentsGrob( # diagonal line ll -> ur x0 = unit(0+reduce,"npc"), y0 = unit(0+reduce,"npc"), x1 = unit(1-reduce,"npc"), y1 = unit(1-reduce,"npc"), gp = grid::gpar( lty = linetype, lwd = linewidth, col = linecolor) ) ) } #' @export #' @rdname ggtexttable tab_ncol <- function(tab){ ncol(get_tablegrob(tab)) } #' @export #' @rdname ggtexttable tab_nrow <- function(tab){ nrow(get_tablegrob(tab)) } #' @export #' @rdname ggtexttable tab_add_hline <- function(tab, at.row = 2:tab_nrow(tab), row.side = c("bottom", "top"), from.column = 1, to.column = tab_ncol(tab), linetype = 1, linewidth = 1, linecolor = "black"){ required_package("gtable") row.side <- match.arg(row.side) tabgrob <- get_tablegrob(tab) separators <- replicate( n = length(at.row), tab_hline(row.side = row.side, linetype = linetype, linewidth = linewidth, linecolor = linecolor), simplify = FALSE ) tabgrob <- gtable::gtable_add_grob( tabgrob, grobs = separators, t = at.row, b = at.row, l = from.column, r = to.column ) tab_return_same_class_as_input(tabgrob, input = tab) } # Create hline at the top or the bottom side of a given row tab_hline <- function(row.side = c("bottom", "top"), linetype = 1, linewidth = 1, linecolor = "black"){ row.side <- match.arg(row.side) y0 <- y1 <- unit(0, "npc") if(row.side == "top") y0 <- y1 <- unit(1, "npc") grid::segmentsGrob( x0 = unit(0, "npc"), x1 = unit(1,"npc"), y0 = y0, y1 = y1, gp = grid::gpar( lty = linetype, lwd = linewidth, col = linecolor) ) } #' @export #' @rdname ggtexttable tab_add_vline <- function(tab, at.column = 2:tab_ncol(tab), column.side = c("left", "right"), from.row = 1, to.row = tab_nrow(tab), linetype = 1, linewidth = 1, linecolor = "black"){ required_package("gtable") column.side <- match.arg(column.side) tabgrob <- get_tablegrob(tab) separators <- replicate( n = length(at.column), tab_vline(column.side = column.side, linetype = linetype, linewidth = linewidth, linecolor = linecolor), simplify = FALSE ) tabgrob <- gtable::gtable_add_grob( tabgrob, grobs = separators, t = from.row, b = to.row, l = at.column, r = at.column ) tab_return_same_class_as_input(tabgrob, input = tab) } # Create vline at the left or the right side of a given column tab_vline <- function(column.side = c("left", "right"), linetype = 1, linewidth = 1, linecolor = "black"){ column.side <- match.arg(column.side) x0 <- x1 <- unit(0, "npc") if(column.side == "right") x0 <- x1 <- unit(1, "npc") grid::segmentsGrob( x0 = x0, x1 = x1, y0 = unit(0, "npc"), y1 = unit(1, "npc"), gp = grid::gpar( lty = linetype, lwd = linewidth, col = linecolor) ) } #' @export #' @rdname ggtexttable tab_add_border <- function(tab, from.row = 2, to.row = tab_nrow(tab), from.column = 1, to.column = tab_ncol(tab), linetype = 1, linewidth = 1, linecolor = "black"){ required_package("gtable") tabgrob <- get_tablegrob(tab) border <- grid::rectGrob( gp = grid::gpar(fill = NA, lty = linetype, lwd = linewidth, col = linecolor) ) tabgrob <- gtable::gtable_add_grob( tabgrob, grobs = border, t = from.row, b = to.row, l = from.column, r = to.column ) tab_return_same_class_as_input(tabgrob, input = tab) } #' @export #' @rdname ggtexttable tbody_add_border <- function(tab, from.row = 2, to.row = tab_nrow(tab), from.column = 1, to.column = tab_ncol(tab), linetype = 1, linewidth = 1, linecolor = "black"){ tab_add_border( tab, from.row = from.row, to.row = to.row, from.column = from.column, to.column = to.column, linetype = linetype, linewidth = linewidth, linecolor = linecolor ) } #' @export #' @rdname ggtexttable thead_add_border <- function(tab, from.row = 1, to.row = 1, from.column = 1, to.column = tab_ncol(tab), linetype = 1, linewidth = 1, linecolor = "black"){ tab_add_border( tab, from.row = from.row, to.row = to.row, from.column = from.column, to.column = to.column, linetype = linetype, linewidth = linewidth, linecolor = linecolor ) } #' @export #' @rdname ggtexttable #' @param text text to be added as title or footnote. tab_add_title <- function(tab, text, face = NULL, size = NULL, color = NULL, family = NULL, padding = unit(1.5,"line"), just = "left", hjust = NULL, vjust = NULL){ required_package("gtable") tabgrob <- get_tablegrob(tab) text <- grid::textGrob( text, x = 0.02, just = just, hjust = hjust, vjust = vjust, gp = grid::gpar(fontsize = size, fontface = face, fontfamily = family, col = color) ) # Add row at the top tabgrob <- gtable::gtable_add_rows( tabgrob, heights = grid::grobHeight(text) + padding, pos = 0 ) tabgrob <- gtable::gtable_add_grob( tabgrob, list(text), t = 1, b = 1, l = 1, r = ncol(tabgrob) ) tab_return_same_class_as_input(tabgrob, input = tab) } #' @export #' @rdname ggtexttable #' @param text text to be added as title or footnote. #' @param family font family #' @param just The justification of the text relative to its (x, y) location. If #' there are two values, the first value specifies horizontal justification #' and the second value specifies vertical justification. Possible string #' values are: "left", "right", "centre", "center", "bottom", and "top". For #' numeric values, 0 means left (bottom) alignment and 1 means right (top) #' alignment. #' @param hjust A numeric vector specifying horizontal justification. If #' specified, overrides the just setting. #' @param vjust A numeric vector specifying vertical justification. If #' specified, overrides the just setting. #' tab_add_footnote <- function(tab, text, face = NULL, size = NULL, color = NULL, family = NULL, padding = unit(1.5,"line"), just = "right", hjust = NULL, vjust = NULL){ required_package("gtable") tabgrob <- get_tablegrob(tab) text <- grid::textGrob( text, x = 0.95, just = just, hjust = hjust, vjust = vjust, gp = grid::gpar(fontsize = size, fontface = face, fontfamily = family, col = color) ) # Add row at the bottom tabgrob <- gtable::gtable_add_rows( tabgrob, heights = grid::grobHeight(text) + padding, pos = -1 ) tabgrob <- gtable::gtable_add_grob( tabgrob, list(text), t = nrow(tabgrob), b = nrow(tabgrob), l = 1, r = ncol(tabgrob) ) tab_return_same_class_as_input(tabgrob, input = tab) } #:::::::::::::::::::::::::::::::::::::::: # Helper function #:::::::::::::::::::::::::::::::::::::::: is_ggtexttable <- function(tab){ !is.null(attr(tab, "ggtexttableGrob")) } is_tablegrob <- function(tab){ inherits(tab, "gtable") & inherits(tab, "grob") } # Transform a table grob in ggtexttable like object as_ggtexttable <- function(tabgrob){ res <- as_ggplot(tabgrob) attr(res, "ggtexttableGrob") <- tabgrob res } # Extract tableGrob from ggtexttable() get_tablegrob <- function(tab){ if(is_ggtexttable(tab)){ tabgrob <- attr(tab, "ggtexttableGrob") } else if(is_tablegrob(tab)){ tabgrob <- tab } else{ stop("tab should be an object from either ggpubr::ggtexttable() or gridExtra::tableGrob().") } tabgrob } # Return the same class as the input data, # which can be either ggtextable or a gridExtra::tableGrob tab_return_same_class_as_input <- function(tabgrob, input){ if(is_ggtexttable(input)){ return(as_ggtexttable(tabgrob)) } else if(is_tablegrob(input)){ return(tabgrob) } tabgrob } # Define table style tstyle <- function(pal, size = 12){ allowed.palettes = c("default", "blank", "classic", "minimal", "light", "lBlack", "lBlue", "lRed", "lGreen", "lViolet", "lCyan", "lOrange", "lBlackWhite", "lBlueWhite", "lRedWhite", "lGreenWhite", "lVioletWhite", "lCyanWhite", "lOrangeWhite", "mBlack", "mBlue", "mRed", "mGreen", "mViolet", "mCyan", "mOrange", "mBlackWhite", "mBlueWhite", "mRedWhite", "mGreenWhite", "mVioletWhite", "mCyanWhite", "mOrangeWhite" ) if(!(pal %in% allowed.palettes )) stop(pal, " is not a supported palette") style <- switch(pal, blank = list( colnames.style = colnames_style(fill = NA, linecolor = NA, size = size), rownames.style = rownames_style(fill = NA, linecolor = NA, size = size), tbody.style = tbody_style(fill = NA, linecolor = NA, size = size) ), classic = list( colnames.style = colnames_style(fill = NA, linecolor = "black", size = size), rownames.style = rownames_style(fill = NA, linecolor = NA, size = size), tbody.style = tbody_style(fill = NA, linecolor = "black", size = size) ), minimal = list( colnames.style = colnames_style(fill = NA, linecolor = NA, size = size), rownames.style = rownames_style(fill = NA, linecolor = NA, size = size), tbody.style = tbody_style(fill = NA, linecolor = NA, size = size) ), light = list( colnames.style = colnames_style(fill = NA, linecolor = NA, size = size), rownames.style = rownames_style(fill = NA, linecolor = NA, size = size), tbody.style = tbody_style(fill = NA, linecolor = NA, size = size) ), lBlack = list( colnames.style = colnames_style( color = "black", fill = "white", size = size, linecolor = NA, linewidth = 1), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#D9D9D9", "white"), linecolor = NA, size = size) ), lBlue = list( colnames.style = colnames_style( color = "#2F5D94", fill = "white", linecolor = NA, linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "#2F5D94", fill = c("#DAE6F2", "white"), linecolor = NA, size = size) ), lRed = list( colnames.style = colnames_style( color = "#A3262A", fill = "white", linecolor = NA, linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "#A3262A", fill = c("#F7DBDA", "white"), linecolor = NA, size = size) ), lGreen = list( colnames.style = colnames_style( color = "#7F993A", fill = "white", linecolor = NA, linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "#7F993A", fill = c("#E8F3DE", "white"), linecolor = NA, size = size) ), lViolet = list( colnames.style = colnames_style( color = "#67417B", fill = "white", linecolor = NA, linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "#67417B", fill = c("#E6DEEC", "white"), linecolor = NA, size = size) ), lCyan = list( colnames.style = colnames_style( color = "#00889E", fill = "white", linecolor = NA, linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "#00889E", fill = c("#D5EFF4", "white"), linecolor = NA, size = size) ), lOrange = list( colnames.style = colnames_style( color = "#F15F00", fill = "white", linecolor = NA, linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "#F15F00", fill = c("#FBE5D4", "white"), linecolor = NA, size = size) ), lBlackWhite = list( colnames.style = colnames_style( color = "white", fill = "black", size = size, linecolor = "black", linewidth = 1), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = "white", linecolor = "black", size = size) ), lBlueWhite = list( colnames.style = colnames_style( color = "white", fill = "#477DC0", size = size, linecolor = "#477DC0", linewidth = 1), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = "white", linecolor = "#477DC0", size = size) ), lRedWhite = list( colnames.style = colnames_style( color = "white", fill = "#D04042", size = size, linecolor = "#D04042", linewidth = 1), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = "white", linecolor = "#D04042", size = size) ), lGreenWhite = list( colnames.style = colnames_style( color = "white", fill = "#8CC257", size = size, linecolor = "#8CC257", linewidth = 1), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = "white", linecolor = "#8CC257", size = size) ), lVioletWhite = list( colnames.style = colnames_style( color = "white", fill = "#895AA3", size = size, linecolor = "#895AA3", linewidth = 1), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = "white", linecolor = "#895AA3", size = size) ), lCyanWhite = list( colnames.style = colnames_style( color = "white", fill = "#00AEC9", size = size, linecolor = "#00AEC9", linewidth = 1), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = "white", linecolor = "#00AEC9", size = size) ), lOrangeWhite = list( colnames.style = colnames_style( color = "white", fill = "#FB8F2D", size = size, linecolor = "#FB8F2D", linewidth = 1), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = "white", linecolor = "#FB8F2D", size = size) ), mBlack = list( colnames.style = colnames_style( color = "white", fill = "black", size = size, linecolor = "white", linewidth = 1), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#A6A6A6", "#D9D9D9"), linecolor = "white", size = size) ), mBlue = list( colnames.style = colnames_style( color = "white", fill = "#477DC0", linecolor = "white", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#B5CBE5", "#DAE6F2"), linecolor = "white", size = size) ), mRed = list( colnames.style = colnames_style( color = "white", fill = "#D04042", linecolor = "white", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#EFB4B5", "#F7DBDA"), linecolor = "white", size = size) ), mGreen = list( colnames.style = colnames_style( color = "white", fill = "#8CC257", linecolor = "white", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#D3E8BB", "#E8F3DE"), linecolor = "white", size = size) ), mViolet = list( colnames.style = colnames_style( color = "white", fill = "#895AA3", linecolor = "white", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#D0BDDA", "#E6DEEC"), linecolor = "white", size = size) ), mCyan = list( colnames.style = colnames_style( color = "white", fill = "#00AEC9", linecolor = "white", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#ADDFEA", "#D5EFF4"), linecolor = "white", size = size) ), mOrange = list( colnames.style = colnames_style( color = "white", fill = "#EC8C2C", linecolor = "white", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#FDD2AF", "#FFE9D7"), linecolor = "white", size = size) ), mBlackWhite = list( colnames.style = colnames_style( color = "white", fill = "black", size = size, linecolor = "black", linewidth = 1), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#A6A6A6", "white"), linecolor = "black", size = size) ), mBlueWhite = list( colnames.style = colnames_style( color = "white", fill = "#477DC0", linecolor = "#477DC0", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#B5CBE5", "white"), linecolor = "#477DC0", size = size) ), mRedWhite = list( colnames.style = colnames_style( color = "white", fill = "#D04042", linecolor = "#D04042", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#EFB4B5", "white"), linecolor = "#D04042", size = size) ), mGreenWhite = list( colnames.style = colnames_style( color = "white", fill = "#8CC257", linecolor = "#8CC257", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#D3E8BB", "white"), linecolor = "#8CC257", size = size) ), mVioletWhite = list( colnames.style = colnames_style( color = "white", fill = "#895AA3", linecolor = "#895AA3", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#D0BDDA", "white"), linecolor = "#895AA3", size = size) ), mCyanWhite = list( colnames.style = colnames_style( color = "white", fill = "#00AEC9", linecolor = "#00AEC9", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#ADDFEA", "white"), linecolor = "#00AEC9", size = size) ), mOrangeWhite = list( colnames.style = colnames_style( color = "white", fill = "#EC8C2C", linecolor = "#EC8C2C", linewidth = 1, size = size), rownames.style = rownames_style(size = size), tbody.style = tbody_style(color = "black", fill = c("#FDD2AF", "white"), linecolor = "#EC8C2C", size = size) ) , NULL ) style } ggpubr/R/stat_stars.R0000644000176200001440000000305414332553655014270 0ustar liggesusers#' @include utilities.R NULL #' Add Stars to a Scatter Plot #' @description Create a star plot by drawing segments from group centroid to each points. #' @inheritParams ggplot2::layer #' @param ... other arguments to pass to \code{\link[ggplot2]{geom_segment}}. #' @param na.rm If FALSE (the default), removes missing values with a warning. #' If TRUE silently removes missing values. #' @seealso \code{\link{ggscatter}} #' @examples #' # Load data #' data("mtcars") #' df <- mtcars #' df$cyl <- as.factor(df$cyl) #' #' # Scatter plot with ellipses and group mean points #' ggscatter(df, x = "wt", y = "mpg", #' color = "cyl", shape = "cyl", #' mean.point = TRUE, ellipse = TRUE)+ #' stat_stars(aes(color = cyl)) #' #' @export stat_stars <- function(mapping = NULL, data = NULL, geom = "segment", position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, ...) { layer( stat = StatStars, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(na.rm = na.rm, ...) ) } StatStars<- ggproto("StatStars", Stat, required_aes = c("x", "y"), compute_group = function(data, scales) { x.mean <- mean(data$x, na.rm = TRUE) y.mean <- mean(data$y, na.rm = TRUE) res <- data %>% mutate(x = x.mean, y = y.mean) res$xend <- data$x res$yend <- data$y res } ) ggpubr/R/axis_scale.R0000644000176200001440000000531714332553655014220 0ustar liggesusers#'Change Axis Scale: log2, log10 and more #' #'@description Change axis scale. #'\itemize{ #'\item \code{xscale}: change x axis scale. #'\item \code{yscale}: change y axis scale. #'} #'@param .scale axis scale. Allowed values are one of c("none", "log2", "log10", #' "sqrt", "percent", "dollar", "scientific"); e.g.: .scale="log2". #'@param .format ogical value. If TRUE, axis tick mark labels will be formatted #' when .scale = "log2" or "log10". #' #' #'@examples #'# Basic scatter plots #'data(cars) #'p <- ggscatter(cars, x = "speed", y = "dist") #'p #' #'# Set log scale #'p + yscale("log2", .format = TRUE) #'@name axis_scale #'@rdname axis_scale #'@export xscale <- function(.scale, .format = FALSE) { .x <- NULL if(.format & .scale %in% c("percent", "dollar", "scientific")) .format <- FALSE if(.format){ if(.scale == "log2"){ scale_x_continuous(trans = scales::log2_trans(), breaks = scales::trans_breaks("log2", function(x) 2^x), labels = scales::trans_format("log2", scales::math_format(2^.x))) } else if(.scale == "log10"){ scale_x_continuous(trans = scales::log10_trans(), breaks = scales::trans_breaks("log10", function(x) 10^x), labels = scales::trans_format("log10", scales::math_format(10^.x))) } } else if(.scale %in% c("log2", "log10")){ scale_x_continuous(trans = .scale) } else{ switch(.scale, percent = scale_x_continuous(labels = scales::percent), dollar = scale_x_continuous(labels = scales::dollar), scientific = scale_x_continuous(labels = scales::scientific) ) } } #'@rdname axis_scale #'@export yscale <- function(.scale, .format = FALSE) { .x <- NULL if(.format & .scale %in% c("percent", "dollar", "scientific")) .format <- FALSE if(.format){ if(.scale == "log2"){ scale_y_continuous(trans = scales::log2_trans(), breaks = scales::trans_breaks("log2", function(x) 2^x), labels = scales::trans_format("log2", scales::math_format(2^.x))) } else if(.scale == "log10"){ scale_y_continuous(trans = scales::log10_trans(), breaks = scales::trans_breaks("log10", function(x) 10^x), labels = scales::trans_format("log10", scales::math_format(10^.x))) } } else if(.scale %in% c("log2", "log10")){ scale_y_continuous(trans = .scale) } else{ switch(.scale, percent = scale_y_continuous(labels = scales::percent), dollar = scale_y_continuous(labels = scales::dollar), scientific = scale_y_continuous(labels = scales::scientific) ) } } ggpubr/R/stat_friedman_test.R0000644000176200001440000001171614332576562015766 0ustar liggesusers#' @include utilities.R utils_stat_test_label.R stat_anova_test.R utils-aes.R NULL #'Add Friedman Test P-values to a GGPlot #'@description Add automatically Friedman test p-values to a ggplot, such as #' box blots, dot plots and stripcharts. #'@inheritParams ggplot2::layer #'@inheritParams stat_pvalue_manual #'@inheritParams stat_anova_test #' #'@section Computed variables: \itemize{ #' \item{statistic}: the value of the test statistic (Chi-squared). #' \item{df}: the degrees of freedom of the approximate chi-squared distribution of the test statistic. #' \item{p}: p-value. #' \item{p.adj}: Adjusted p-values. #' \item{p.signif}: P-value significance. #' \item{p.adj.signif}: Adjusted p-value significance. #' \item{p.format}: Formated p-value. #' \item{p.adj.format}: Formated adjusted p-value. #' \item{n}: number of samples. #' } #' #' @examples #' # Data preparation #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Transform `dose` into factor variable #' df <- ToothGrowth #' df$dose <- as.factor(df$dose) #' df$id <- as.factor(c(rep(1:10, 3), rep(11:20, 3))) #' # Add a random grouping variable #' set.seed(123) #' df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) #' df$len <- ifelse(df$group == "grp2", df$len+2, df$len) #' df$len <- ifelse(df$group == "grp3", df$len+7, df$len) #' head(df, 3) #' #' #' # Basic boxplot #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Create a basic boxplot #' # Add 5% and 10% space to the plot bottom and the top, respectively #' bxp <- ggboxplot(df, x = "dose", y = "len") + #' scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) #' #' # Add the p-value to the boxplot #' bxp + stat_friedman_test(aes(wid = id)) #' #' # Change the label position #' # Using coordinates in data units #' bxp + stat_friedman_test(aes(wid = id), label.x = "1", label.y = 10, hjust = 0) #' #' # Format the p-value differently #' custom_p_format <- function(p) { #' rstatix::p_format(p, accuracy = 0.0001, digits = 3, leading.zero = FALSE) #' } #' bxp + stat_friedman_test( #' aes(wid = id), #' label = "Friedman test, italic(p) = {custom_p_format(p)}{p.signif}" #' ) #' #' # Show a detailed label in italic #' bxp + stat_friedman_test(aes(wid = id), label = "as_detailed_italic") #' #' #' # Faceted plots #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Create a ggplot facet #' df$id <- rep(1:10,6) #' bxp <- ggboxplot(df, x = "dose", y = "len", facet.by = "supp") + #' scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) #' # Add p-values #' bxp + stat_friedman_test(aes(wid = id)) #' #' #' # Grouped plots #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' df$id <- rep(1:10,6) #' bxp <- ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") #' #' # For each legend group, computes tests within x variable groups #' bxp + stat_friedman_test(aes(wid = id, group = supp, color = supp), within = "x") #' #' # For each x-position, computes tests within legend variable groups #' bxp + stat_friedman_test( #' aes(wid = id, group = supp, color = supp), #' within = "group", label = "p = {p.format}" #' ) #' #' @export stat_friedman_test <- function(mapping = NULL, data = NULL, wid = NULL, group.by = NULL, label = "{method}, p = {p.format}", label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, step.increase = 0.1, p.adjust.method = "holm", significance = list(), geom = "text", position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, parse = FALSE, ...) { label <- get_friedman_test_label_template(label) if(missing(parse) & is_plotmath_expression(label)){ parse <- TRUE } if(!is.null(wid)){ if(!is.null(mapping)) mapping$wid <- as.name(wid) else mapping <- create_aes(list(wid = wid)) } layer( stat = StatCompareMultipleMeans, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list( method = "friedman_test", method.args = list(), group.by = group.by, correction = "none", na.rm = na.rm, stat.label = label, label.x.npc = label.x.npc , label.y.npc = label.y.npc, label.x = label.x, label.y = label.y, parse = parse, is.group.specified = is_group_aes_specified(mapping), step.increase = step.increase, p.adjust.method = p.adjust.method, significance = fortify_signif_symbols_encoding(significance), ... ) ) } get_friedman_test_label_template <- function(label){ switch( label, as_italic = "{method}, italic(p) = {p.format}", as_detailed = "{method}, X2({df}) = {statistic}, p = {p.format}, n = {n}", as_detailed_italic = "{method}, italic(chi)^2 ({df}) = {statistic}, italic(p) = {p.format}, italic(n) = {n}", as_detailed_expression = "{method}, italic(chi)^2({df}) = {statistic}, italic(p) = {p.format}, italic(n) = {n}", label ) } ggpubr/R/facet.R0000644000176200001440000001342214342705172013155 0ustar liggesusers#' @include utilities.R NULL #'Facet a ggplot into Multiple Panels #'@description Create multi-panel plots of a data set grouped by one or two #' grouping variables. Wrapper around \code{\link[ggplot2]{facet_wrap}} #'@param p a ggplot #'@param facet.by character vector, of length 1 or 2, specifying grouping #' variables for faceting the plot into multiple panels. Should be in the data. #'@param nrow,ncol Number of rows and columns in the panel. Used only when the #' data is faceted by one grouping variable. #'@param scales should axis scales of panels be fixed ("fixed", the default), #' free ("free"), or free in one dimension ("free_x", "free_y"). #'@param short.panel.labs logical value. Default is TRUE. If TRUE, create short #' labels for panels by omitting variable names; in other words panels will be #' labelled only by variable grouping levels. #'@param labeller Character vector. An alternative to the argument #' \code{short.panel.labs}. Possible values are one of "label_both" (panel #' labelled by both grouping variable names and levels) and "label_value" #' (panel labelled with only grouping levels). #'@param panel.labs a list of one or two character vectors to modify facet panel #' labels. For example, panel.labs = list(sex = c("Male", "Female")) specifies #' the labels for the "sex" variable. For two grouping variables, you can use #' for example panel.labs = list(sex = c("Male", "Female"), rx = c("Obs", #' "Lev", "Lev2") ). #'@param panel.labs.background a list to customize the background of panel #' labels. Should contain the combination of the following elements: \itemize{ #' \item \code{color, linetype, size}: background line color, type and size #' \item \code{fill}: background fill color. } For example, #' panel.labs.background = list(color = "blue", fill = "pink", linetype = #' "dashed", size = 0.5). #'@param panel.labs.font a list of aestheics indicating the size (e.g.: 14), the #' face/style (e.g.: "plain", "bold", "italic", "bold.italic") and the color #' (e.g.: "red") and the orientation angle (e.g.: 45) of panel labels. #'@param panel.labs.font.x,panel.labs.font.y same as panel.labs.font but for #' only x and y direction, respectively. #'@param strip.position (used only in \code{facet_wrap()}). By default, the #' labels are displayed on the top of the plot. Using \code{strip.position} it #' is possible to place the labels on either of the four sides by setting #' \code{strip.position = c("top", "bottom", "left", "right")} #'@param ... not used #' @examples #' p <- ggboxplot(ToothGrowth, x = "dose", y = "len", #' color = "supp") #' print(p) #' #' facet(p, facet.by = "supp") #' #' # Customize #' facet(p + theme_bw(), facet.by = "supp", #' short.panel.labs = FALSE, # Allow long labels in panels #' panel.labs.background = list(fill = "steelblue", color = "steelblue") #' ) #'@name facet #'@rdname facet #'@export facet <- function(p, facet.by, nrow = NULL, ncol = NULL, scales = "fixed", short.panel.labs = TRUE, labeller = "label_value", panel.labs = NULL, panel.labs.background = list(color = NULL, fill = NULL), panel.labs.font = list(face = NULL, color = NULL, size = NULL, angle = NULL), panel.labs.font.x = panel.labs.font, panel.labs.font.y = panel.labs.font, strip.position = "top", ... ) { if(length(facet.by) > 2) stop("facet.by should be of length 1 or 2.") if(!missing(labeller)){ if(labeller == "label_value") short.panel.labs = TRUE else if(labeller == "label_both") short.panel.labs = FALSE else stop("Don't support the following labeller: ", labeller, call. = FALSE) } panel.labs.background <- .compact(panel.labs.background) panel.labs.font.x <- .compact(panel.labs.font.x) panel.labs.font.y <- .compact(panel.labs.font.y) .labeller <- "label_value" if(!is.null(panel.labs)){ .labeller <- .create_labeller(p$data, panel.labs) } else if(!short.panel.labs) { .labeller <- label_both } if(length(facet.by) == 1){ facet.formula <- paste0("~", glue::backtick(facet.by)) %>% stats::as.formula() p <- p + facet_wrap(facet.formula, nrow = nrow, ncol = ncol, scales = scales, labeller = .labeller, strip.position = strip.position) } else if(length(facet.by) == 2){ facet.formula <- paste(glue::backtick(facet.by), collapse = " ~ ") %>% stats::as.formula() p <- p + facet_grid(facet.formula, scales = scales, labeller = .labeller) } if(!.is_empty(panel.labs.background)) p <- p + theme(strip.background = do.call(element_rect, panel.labs.background)) if(!.is_empty(panel.labs.font.x)) p <- p + theme(strip.text.x = do.call(element_text, panel.labs.font.x)) if(!.is_empty(panel.labs.font.y)) p <- p + theme(strip.text.y = do.call(element_text, panel.labs.font.y)) p } # Create labeller to rename panel labels .create_labeller <- function(data, panel.labs = NULL) { if(is.null(panel.labs)) return(NULL) if(!is.null(panel.labs) & !.is_list(panel.labs)) stop("Argument panel.labs should be a list. Read the documentation.") if(is.null(names(panel.labs))) stop("panel.labs should be a named list. ", "Ex: panel.labs = list(sex = c('Male', 'Female') )") variables <- names(panel.labs) . <- NULL .labels <- list() for(variable in variables){ current.levels <- .levels(data[[variable]]) provided.levels <- panel.labs[[variable]] if(length(current.levels) != length(provided.levels)){ stop("The number of ", variable, " levels in panel.labs ", "and in the data are different.") } names(provided.levels) <- current.levels .labels[[variable]] <- provided.levels } if(!.is_empty(.labels)) do.call(ggplot2::labeller, .labels) else return(NULL) } ggpubr/R/geom_exec.R0000644000176200001440000000607114340626116014026 0ustar liggesusers#' Execute ggplot2 functions #' @description A helper function used by ggpubr functions to execute any geom_* #' functions in ggplot2. Useful only when you want to call a geom_* function #' without carrying about the arguments to put in aes(). Basic users of ggpubr #' don't need this function. #' @param geomfunc a ggplot2 function (e.g.: geom_point) #' @param data a data frame to be used for mapping #' @param position Position adjustment, either as a string, or the result of a #' call to a position adjustment function. #' @param ... arguments accepted by the function #' @return return a plot if geomfunc!=Null or a list(option, mapping) if #' geomfunc = NULL. #' @examples #' \dontrun{ #' ggplot() + geom_exec(geom_point, data = mtcars, #' x = "mpg", y = "wt", size = "cyl", color = "cyl") #' } #' @export geom_exec <- function (geomfunc = NULL, data = NULL, position = NULL, ...) { params <- list(...) mapping <- list() # option to pass to mapping aes() option <- list() # option to the geom_*() allowed_options <- c( # general "x", "y", "color", "colour", "linetype", "fill", "size", "shape", "width", "alpha", "na.rm", "lwd", "pch", "cex", "position", "stat", "geom", "show.legend", "inherit.aes", "fun.args", "fontface", # point "stroke", # boxplot "outlier.colour", "outlier.shape", "outlier.size", "outlier.stroke", "notch", "notchwidth", "varwidth", # dot plot "binwidth", "binaxis", "method", "binpositions", "stackdir", "stackratio", "dotsize", # Violin "trim", "draw_quantiles", "scale", # error "ymin", "ymax", "xmin", "xmax", # text "label", "hjust", "vjust", "fontface", "angle", "family", "parse", # text.repel "segment.size", "force", "max.overlaps", "seed", # smooth "se", "level", "fullrange", "conf.int.level", # straightline "xintercept", "yintercept", # histograms "bins", "weight", # rug "sides", # segment "arrow", "xend", "yend", # stat_summary, "fun.data", "fun.y", "fun.ymin", "fun.ymax", # bracket "y.position", "tip.length", "label.size", "step.increase", "bracket.nudge.y", "bracket.shorten", "coord.flip" ) columns <- colnames(data) for (key in names(params)) { value <- params[[key]] if (is.null(value)) { } else if (unlist(value)[1] %in% columns & key %in% allowed_options) { mapping[[key]] <- value } else if (key %in% allowed_options) { option[[key]] <- value } else if (key =="group") { mapping[[key]] <- value # for line plot } else if(key == "step.group.by"){ # for geom_bracket, value are variable name. # but this parameter is an option not an aes option[[key]] <- value } # else warnings("Don't know '", key, "'") } if (!is.null(position)) option[["position"]] <- position option[["data"]] <- data if(is.null(geomfunc)){ res <- list(option = option, mapping = mapping) } else{ option[["mapping"]] <- create_aes(mapping) res <- do.call(geomfunc, option) } res } ggpubr/R/stat_central_tendency.R0000644000176200001440000000716114332553655016460 0ustar liggesusers#' @include utilities.R NULL #' Add Central Tendency Measures to a GGPLot #' #' @description Add central tendency measures (mean, median, mode) to density #' and histogram plots created using ggplots. #' #' Note that, normally, the mode is used for categorical data where we wish to #' know which is the most common category. Therefore, we can have have two or #' more values that share the highest frequency. This might be problematic for #' continuous variable. #' #' For continuous variable, we can consider using mean or median as the #' measures of the central tendency. #' @inheritParams ggplot2::layer #' @param ... other arguments to pass to \code{\link[ggplot2:geom_path]{geom_line}}. #' @param na.rm If FALSE (the default), removes missing values with a warning. #' If TRUE silently removes missing values. #' @param type the type of central tendency measure to be used. Possible values #' include: \code{"mean", "median", "mode"}. #' @seealso \code{\link{ggdensity}} #' @examples #' # Simple density plot #' data("mtcars") #' ggdensity(mtcars, x = "mpg", fill = "red") + #' scale_x_continuous(limits = c(-1, 50)) + #' stat_central_tendency(type = "mean", linetype = "dashed") #' #' # Color by groups #' data(iris) #' ggdensity(iris, "Sepal.Length", color = "Species") + #' stat_central_tendency(aes(color = Species), type = "median", linetype = 2) #' #' # Use geom = "point" for central tendency #' data(iris) #' ggdensity(iris, "Sepal.Length", color = "Species") + #' stat_central_tendency( #' aes(color = Species), type = "median", #' geom = "point", size = 4 #' ) #' #' # Facet #' ggdensity(iris, "Sepal.Length", facet.by = "Species") + #' stat_central_tendency(type = "mean", color = "red", linetype = 2) + #' stat_central_tendency(type = "median", color = "blue", linetype = 2) #' #' @export stat_central_tendency <- function(mapping = NULL, data = NULL, geom = c("line", "point"), position = "identity", na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, type = c("mean", "median", "mode"), ...) { type <- match.arg(type) geom <- match.arg(geom) if(is.null(mapping)){ mapping <- ggplot2::aes(y = NULL) }else{ mapping["y"] <- list(NULL) } layer( stat = StatCentralTendency, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list(na.rm = na.rm, type = type, geom = geom, ...) ) } StatCentralTendency <- ggproto("StatCentralTendency", Stat, required_aes = c("x"), compute_group = function(data, scales, type, geom) { center.func <- switch (type, mean = mean, median = stats::median, mode = .get_mode ) .center <- center.func(data$x, na.rm = TRUE) n <- length(.center) if(geom == "line"){ results <- data.frame(x = rep(.center, each = 2),y = c(-Inf, Inf)) if(n >= 2) results$group <- rep(1:n, each = 2) } else if(geom == "point") { results <- data.frame(x = .center, y = -Inf) } results } ) # from rstatix .get_mode <- function (x, na.rm = TRUE) { if(na.rm) x <- stats::na.omit(x) .x <- factor(x) .table <- table(.x) .max <- max(.table) if (all(.table == .max)) { .mode <- NA } else { .mode <- names(.table)[.table == .max] } if (is.numeric(x)) { .mode <- as.numeric(.mode) } .mode } ggpubr/R/get_coord.R0000644000176200001440000000552714332576562014057 0ustar liggesusers#' Checks and Returns Data Coordinates from Multiple Input Options #' #' @description Checks and returns selected coordinates from multiple input #' options, which can be either data (x-y) coordinates or npc (normalized #' parent coordinates). #' #' Helper function internally used in \code{ggpubr} function to guess the type #' of coordinates specified by the user. For example, in the function #' \code{stat_cor()}, users can specify either the option \code{label.x} (data #' coordinates) or \code{label.x.npc} (npc coordinates); those coordinates are #' passed to \code{get_coord()}, which will make some checking and then return #' a unique coordinates for the label position. #' @inheritParams as_npc #' @param data.ranges a numeric vector of length 2 containing the data ranges #' (minimum and the maximum). Should be specified only when \code{coord = #' NULL} and \code{npc} is specified. Used to convert \code{npc} to data #' coordinates. Considered only when the argument \code{npc} is specified. #' @param coord data coordinates (i.e., either x or y coordinates). #' @param npc numeric (in [0-1]) or character vector of coordinates. If #' character, should be one of c('right', 'left', 'bottom', 'top', 'center', #' 'centre', 'middle'). Note that, the \code{data.ranges}, \code{step} and #' \code{margin.npc}, arguments are considered only when \code{npc} is #' specified. The option \code{npc} is ignored when the argument \code{coord} is specified. #' @return a numeric vector representing data coordinates. #' @seealso \code{\link{as_npc}}, \code{\link{npc_to_data_coord}}. #' @examples #' # If npc is specified, it is converted into data coordinates #' get_coord(data.ranges = c(2, 20), npc = "left") #' get_coord(data.ranges = c(2, 20), npc = 0.1) #' #' # When coord is specified, no transformation is performed #' # because this is assumed to be a data coordinate #' get_coord(coord = 5) #' #' # For grouped plots #' res_top <- get_coord( #' data.ranges = c(4.2, 36.4), group = c(1, 2, 3), #' npc = "top", step = -0.1, margin.npc = 0 #' ) #' res_top #' #' @rdname get_coord #' @export get_coord <- function(group = 1L, data.ranges = NULL, coord = NULL, npc = "left", step = 0.1, margin.npc = 0.05){ if(!is.null(coord)){ if(!is.numeric(group)){ stop("get_coord: 'group' should be numeric. ", "Current class is: ", class(group)) } # If coords are too short, they are recycled. coord <- ifelse(length(coord) >= group, coord[group], coord[1]) return(coord) } else if(!is.null(npc)){ if(is.null(data.ranges)){ stop("Specify the option data.ranges", call. = FALSE) } npc <- ifelse(length(npc) >= group, npc[group], npc[1]) coord <- as_npc( npc, group = group, step = step, margin.npc = margin.npc ) %>% npc_to_data_coord(data.ranges) } coord } ggpubr/R/ggtext.R0000644000176200001440000002256714342651060013403 0ustar liggesusers#' @include utilities.R ggpar.R stat_chull.R stat_conf_ellipse.R NULL #' Text #' @description Add text to a plot. #' @inheritParams ggscatter #' @param data a data frame #' @param x,y x and y variables for drawing. #' @param label the name of the column containing point labels. Can be also a #' character vector with length = nrow(data). #' @param color text font color. #' @param size text font size. #' @param face text font style. Allowed values are one of c("plain", "bold", #' "italic", "bold.italic"). #' @param parse If \code{TRUE}, the labels will be parsed into expressions and #' displayed as described in \code{?plotmath}. #' @param family character vector specifying font family. #' @param show.legend logical. Should text be included in the legends? NA, the #' default, includes if any aesthetics are mapped. FALSE never includes, and #' TRUE always includes. #' @param label.select can be of two formats: \itemize{ \item a character vector #' specifying some labels to show. \item a list containing one or the #' combination of the following components: \itemize{ \item \code{top.up} and #' \code{top.down}: to display the labels of the top up/down points. For #' example, \code{label.select = list(top.up = 10, top.down = 4)}. \item #' \code{criteria}: to filter, for example, by x and y variabes values, use #' this: \code{label.select = list(criteria = "`y` > 2 & `y` < 5 & `x` \%in\% #' c('A', 'B')")}. } } #' @param repel a logical value, whether to use ggrepel to avoid overplotting #' text labels or not. #' @param label.rectangle logical value. If TRUE, add rectangle underneath the #' text, making it easier to read. #' @param grouping.vars grouping variables to sort the data by, when the user #' wants to display the top n up/down labels. #' @param position Position adjustment, either as a string, or the result of a #' call to a position adjustment function. #' @param ggp a ggplot. If not NULL, points are added to an existing plot. #' @param ... other arguments to be passed to \code{\link{ggpar}}. #' @details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, #' xlab, ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: #' palette = "Dark2" or palette = c("gray", "blue", "red") \item legend title, #' labels and position: legend = "right" } #' @seealso \code{\link{ggpar}} #' @examples #' # Load data #' data("mtcars") #' df <- mtcars #' df$cyl <- as.factor(df$cyl) #' df$name <- rownames(df) #' head(df[, c("wt", "mpg", "cyl")], 3) #' #' # Textual annotation #' # +++++++++++++++++ #' ggtext(df, x = "wt", y = "mpg", #' color = "cyl", palette = c("#00AFBB", "#E7B800", "#FC4E07"), #' label = "name", repel = TRUE) #' #' # Add rectangle around label #' ggtext(df, x = "wt", y = "mpg", #' color = "cyl", palette = c("#00AFBB", "#E7B800", "#FC4E07"), #' label = "name", repel = TRUE, label.rectangle = TRUE) #' #' #' @export ggtext <- function(data, x = NULL, y = NULL, label = NULL, color = "black", palette = NULL, size = 11, face = "plain", family = "", show.legend = NA, label.select = NULL, repel = FALSE, label.rectangle = FALSE, parse = FALSE, grouping.vars = NULL, position = "identity", ggp = NULL, ggtheme = theme_pubr(), ...) { . <- NULL .dots <- list(...) data <- as.data.frame(data) if(length(label) >1){ if(length(label) != nrow(data)) stop("The argument label should be a column name or a vector of length = nrow(data). ", "It seems that length(label) != nrow(data)") else data$label.xx <- label label <- "label.xx" } if(is.null(ggp)) p <- ggplot(data, create_aes(list(x = x, y = y))) else p <- ggp # Add textual annotation # ++++++ alpha <- 1 if(!is.null(list(...)$alpha)) alpha <- list(...)$alpha if(is.null(label)) return(p) lab_data <- data # Special case for density plot and histogram # y is calculated as ..count.. or ..density.. # we should estimate label y from ggplot2 output .is_density_plot <- y[1] %in% c("..count..", "..density..") if(.is_density_plot){ lab_data <- .hist_label_data(p, grouping.vars = list(...)$facet.by, x = x) y <- "lab.y" # hist.data <- ggplot_build(p)$data[[1]][, c("x", "y", "count", "density")] # hist.x <- hist.data$x # hist.y <- hist.data$y # break.x <- c(0, hist.x) %>% unique() # label.break <- 1:(length(break.x)-1) # lab.y <- .select_vec(data, x) %>% # cut(breaks = break.x, labels = label.break) %>% # hist.y[.] # lab_data$lab.y <- lab.y # y <- "lab.y" # lab_data <- lab_data %>% dplyr::filter(!is.na(lab.y)) } # Select some labels to show if(!is.null(label.select)){ lab_data <- .get_label_data (lab_data, x, y, label = label, label.select = label.select, grouping.vars = grouping.vars) } if(repel){ max.overlaps = getOption("ggrepel.max.overlaps", default = Inf) ggfunc <- ggrepel::geom_text_repel if(label.rectangle) ggfunc <- ggrepel::geom_label_repel p <- p + geom_exec(ggfunc, data = lab_data, x = x, y = y, label = label, fontface = face, family = family, show.legend = show.legend, size = size/3, color = color, alpha = alpha, parse = parse, box.padding = unit(0.35, "lines"), point.padding = unit(0.3, "lines"), force = 1, segment.size = 0.2, seed = 123, max.overlaps = max.overlaps ) } else{ ggfunc <- geom_text vjust <- -0.7 hjust <- NULL if(label.rectangle) { ggfunc <- geom_label vjust <- -0.4 } vjust <- ifelse(is.null(.dots$vjust), vjust, .dots$vjust) if(!is.null(.dots$hjust)) hjust <- .dots$hjust p <- p + geom_exec(ggfunc, data = lab_data, x = x, y = y, color = color, label = label, fontface = face, family = family, show.legend = show.legend, size = size/3, color = color, parse = parse, vjust = vjust, hjust = hjust, alpha = alpha, position = position) } #p <- ggpar(p, palette = palette, ggtheme = ggtheme, ...) if(family != "") p <- p + theme(text = element_text(family = family)) p } # data: data frame # x, y: x and y variables # label: label columns # label.select: select some labels. Can be a character vector, or a list # with the following components (top.up, top.down) # grouping.vars grouping variables .get_label_data <- function(data, x, y, label = NULL, label.select = NULL, grouping.vars = NULL) { if(.is_list(label.select)){ expected.components = c("top.up", "top.down", "criteria") if(!any(expected.components %in% names(label.select))) stop("If label.select is a list, it should contain one or the combination ", "of the following element: ", .collapse(expected.components, sep = ", ")) } data <- as.data.frame(data) if(is.null(label)) lab_data <- NULL else if(is.null(label.select)) lab_data <- data else if(.is_list(label.select)){ lab_data <- data top_up <- top_down <- . <- NULL if(!is.null(label.select$top.up)) top_up <- .top_up(data, x, y, n = label.select$top.up, grouping.vars = grouping.vars) if(!is.null(label.select$top.down)) top_down <- .top_down(data, x, y, n = label.select$top.down, grouping.vars = grouping.vars) if(!is.null(top_up) | !is.null(top_down)) lab_data <- rbind(top_up, top_down) if(!is.null(label.select$criteria)){ criteria <- gsub("`y`", y, label.select$criteria) %>% gsub("`x`", x, .) lab_data <- dplyr::filter(lab_data, !!rlang::parse_expr(criteria)) } } else lab_data <- subset(data, data[[label]] %in% label.select, drop = FALSE) return(lab_data) } # Get histogram/density label y coord from ggplot output # grouping.vars : facet variables # x: x variable name .hist_label_data <- function(p, grouping.vars = NULL, x = NULL){ . <- NULL #x <- .mapping(p) %>%.$x hist.data <- ggplot_build(p)$data[[1]] data <- p$data if(is.null(grouping.vars)){ return(.hist_label_y(hist.data, data, x )) } data <- p$data %>% df_nest_by(vars = grouping.vars) hist.data <- hist.data %>% df_nest_by(vars = "PANEL") %>% .$data data <- data %>% mutate(hist.data = hist.data) lab.data <- purrr::map2(data$hist.data, data$data, .hist_label_y, x) data <- data %>% mutate(lab.data = lab.data ) %>% df_select(vars = c( "lab.data", grouping.vars)) %>% tidyr::unnest() data } # Get histogram/density label y coord from ggplot output # hist.data: histogram data. ggplot_build(p)$data[[1]] # data: data frame # x: x variable name .hist_label_y <- function(hist.data, data, x ){ . <- NULL hist.x <- hist.data$x hist.y <- hist.data$y break.x <- c(0, hist.x) %>% unique() label.break <- 1:(length(break.x)-1) lab.y <- .select_vec(data, x) %>% cut(breaks = break.x, labels = label.break) %>% hist.y[.] data$lab.y <- lab.y data <- data %>% dplyr::filter(!is.na(lab.y)) data } ggpubr/R/ggparagraph.R0000644000176200001440000000547614337533653014377 0ustar liggesusers#' @include utilities.R NULL #'Draw a Paragraph of Text #'@description Draw a paragraph o text. Splits a long text into multiple lines #' (by inserting line breaks) so that the output will fit within the current #' viewport. #'@param text the text to plot. #'@param color font color, example: color = "black" #'@param size font size, example: size = 12 #'@param face font face. Allowed values are one of "plain", "italic", "bold", #' "bold.italic". #' @param family font family #' @param lineheight Line height, example: lineheight = 2. #'@author Alboukadel Kassambara #' @examples #' # Density plot #'density.p <- ggdensity(iris, x = "Sepal.Length", #' fill = "Species", palette = "jco") #' #'# Text plot #'text <- paste("iris data set gives the measurements in cm", #' "of the variables sepal length and width", #' "and petal length and width, respectively,", #' "for 50 flowers from each of 3 species of iris.", #' "The species are Iris setosa, versicolor, and virginica.", sep = " ") #'text.p <- ggparagraph(text, face = "italic", size = 12) #' #'# Arrange the plots on the same page #'ggarrange(density.p, text.p, #' ncol = 1, nrow = 2, #' heights = c(1, 0.3)) #' #'@export ggparagraph <- function(text, color = NULL, size = NULL, face = NULL, family = NULL, lineheight = NULL) { style <- grid::gpar(col = color, fontsize = size, fontface = face, fontfamily = family, lineheight = lineheight) p <- grid::grob(text = text, cl = "splitText", gp = style) p <- as_ggplot(p) return(p) } # Helper functions # Extracted from RGraphics package # ::::::::::::::::::::::::::::::::::::::::::: splitString <- function(text) { strings <- strsplit(text, " ")[[1]] if (length(strings) < 2) return(text) newstring <- strings[1] linewidth <- grid::stringWidth(newstring) gapwidth <- grid::stringWidth(" ") availwidth <- grid::convertWidth(unit(1, "npc"), "in", valueOnly=TRUE) for (i in 2:length(strings)) { width <- grid::stringWidth(strings[i]) if (grid::convertWidth(linewidth + gapwidth + width, "in", valueOnly=TRUE) < availwidth) { sep <- " " linewidth <- linewidth + gapwidth + width } else { sep <- "\n" linewidth <- width } newstring <- paste(newstring, strings[i], sep=sep) } newstring } #' @method drawDetails splitText #' @rdname ggparagraph #' @param x a grid grob #' @param recording a logical value indicating whether a grob is being added to #' the display list or redrawn from the display list. #' @export drawDetails.splitText <- function(x, recording) { grid::grid.text(splitString(x$text), x=0, y=1, just=c("left", "top")) } ggpubr/R/stat_anova_test.R0000644000176200001440000005751314333301370015272 0ustar liggesusers#' @include utilities.R utils_stat_test_label.R NULL #'Add Anova Test P-values to a GGPlot #'@description Adds automatically one-way and two-way ANOVA test p-values to a #' ggplot, such as box blots, dot plots and stripcharts. #'@inheritParams ggplot2::layer #'@inheritParams stat_pvalue_manual #'@param method ANOVA test methods. Possible values are one of #' \code{c("one_way", "one_way_repeated", "two_way", "two_way_repeated", #' "two_way_mixed")}. #'@param wid (factor) column name containing individuals/subjects identifier. #' Should be unique per individual. Required only for repeated measure tests #' (\code{"one_way_repeated", "two_way_repeated", "friedman_test", etc}). #'@param group.by (optional) character vector specifying the grouping variable; #' it should be used only for grouped plots. Possible values are : \itemize{ #' \item \code{"x.var"}: Group by the x-axis variable and perform the test #' between legend groups. In other words, the p-value is compute between legend #' groups at each x position \item \code{"legend.var"}: Group by the legend #' variable and perform the test between x-axis groups. In other words, the #' test is performed between the x-groups for each legend level. } #'@param type the type of sums of squares for ANOVA. Allowed values are either #' 1, 2 or 3. \code{type = 2} is the default because this will yield identical #' ANOVA results as type = 1 when data are balanced but type = 2 will #' additionally yield various assumption tests where appropriate. When the data #' are unbalanced the \code{type = 3} is used by popular commercial softwares #' including SPSS. #'@param effect.size the effect size to compute and to show in the ANOVA #' results. Allowed values can be either "ges" (generalized eta squared) or #' "pes" (partial eta squared) or both. Default is "ges". #'@param error (optional) for a linear model, an lm model object from which the #' overall error sum of squares and degrees of freedom are to be calculated. #' Read more in \code{\link[car]{Anova}()} documentation. #'@param correction character. Used only in repeated measures ANOVA test to #' specify which correction of the degrees of freedom should be reported for #' the within-subject factors. Possible values are: \itemize{ \item{"GG"}: #' applies Greenhouse-Geisser correction to all within-subjects factors even if #' the assumption of sphericity is met (i.e., Mauchly's test is not #' significant, p > 0.05). \item{"HF"}: applies Hyunh-Feldt correction to all #' within-subjects factors even if the assumption of sphericity is met, #' \item{"none"}: returns the ANOVA table without any correction and #' \item{"auto"}: apply automatically GG correction to only within-subjects #' factors violating the sphericity assumption (i.e., Mauchly's test p-value is #' significant, p <= 0.05). } #'@param p.adjust.method method for adjusting p values (see #' \code{\link[stats]{p.adjust}}). Has impact only in a situation, where #' multiple pairwise tests are performed; or when there are multiple grouping #' variables. Allowed values include "holm", "hochberg", "hommel", #' "bonferroni", "BH", "BY", "fdr", "none". If you don't want to adjust the p #' value (not recommended), use p.adjust.method = "none". #'@param significance a list of arguments specifying the signifcance cutpoints #' and symbols. For example, \code{significance <- list(cutpoints = c(0, #' 0.0001, 0.001, 0.01, 0.05, Inf), symbols = c("****", "***", "**", "*", #' "ns"))}. #' #' In other words, we use the following convention for symbols indicating #' statistical significance: \itemize{ \item \code{ns}: p > 0.05 \item #' \code{*}: p <= 0.05 \item \code{**}: p <= 0.01 \item \code{***}: p <= 0.001 #' \item \code{****}: p <= 0.0001 } #'@param label character string specifying label. Can be: \itemize{ \item the #' column containing the label (e.g.: \code{label = "p"} or \code{label = #' "p.adj"}), where \code{p} is the p-value. Other possible values are #' \code{"p.signif", "p.adj.signif", "p.format", "p.adj.format"}. \item an #' expression that can be formatted by the \code{\link[glue]{glue}()} package. #' For example, when specifying \code{label = "Anova, p = \{p\}"}, the #' expression \{p\} will be replaced by its value. \item a combination of #' plotmath expressions and glue expressions. You may want some of the #' statistical parameter in italic; for example:\code{label = "Anova, italic(p) #' = {p}"}. \item a constant: \code{label = "as_italic"}: display statistical #' parameters in italic; \code{label = "as_detailed"}: detailed plain text; #' \code{label = "as_detailed_expression"} or \code{label = #' "as_detailed_italic"}: detailed plotmath expression. Statistical parameters #' will be displayed in italic.}. #'@param label.x.npc,label.y.npc can be \code{numeric} or \code{character} #' vector of the same length as the number of groups and/or panels. If too #' short they will be recycled. \itemize{ \item If \code{numeric}, value should #' be between 0 and 1. Coordinates to be used for positioning the label, #' expressed in "normalized parent coordinates". \item If \code{character}, #' allowed values include: i) one of c('right', 'left', 'center', 'centre', #' 'middle') for x-axis; ii) and one of c( 'bottom', 'top', 'center', 'centre', #' 'middle') for y-axis.} #'@param parse If TRUE, the labels will be parsed into expressions and displayed #' as described in \code{?plotmath}. #'@param label.x,label.y \code{numeric} Coordinates (in data units) to be used #' for absolute positioning of the label. If too short they will be recycled. #'@param step.increase numeric value in with the increase in fraction of total #' height for every additional comparison to minimize overlap. The step value #' can be negative to reverse the order of groups. #'@param ... other arguments to pass to #' \code{\link[ggplot2:geom_text]{geom_text}}, such as:\itemize{ \item #' \code{hjust}: horizontal justification of the text. Move the text left or #' right and \item \code{vjust}: vertical justification of the text. Move the #' text up or down. } #'@param na.rm If FALSE (the default), removes missing values with a warning. If #' TRUE silently removes missing values. #' #'@section Computed variables: \itemize{ \item{DFn}: Degrees of Freedom in the #' numerator (i.e. DF effect). \item{DFd}: Degrees of Freedom in the #' denominator (i.e., DF error). \item{ges}: Generalized Eta-Squared measure of #' effect size. Computed only when the option \code{effect.size = "ges"}. #' \item{pes}: Partial Eta-Squared measure of effect size. Computed only when #' the option \code{effect.size = "pes"}. \item{F}: F-value. \item{p}: p-value. #' \item{p.adj}: Adjusted p-values. \item{p.signif}: P-value significance. #' \item{p.adj.signif}: Adjusted p-value significance. \item{p.format}: #' Formated p-value. \item{p.adj.format}: Formated adjusted p-value. \item{n}: #' number of samples. } #' #' @examples #' # Data preparation #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Transform `dose` into factor variable #' df <- ToothGrowth #' df$dose <- as.factor(df$dose) #' # Add individuals id #' df$id <- rep(1:10, 6) #' # Add a random grouping variable #' set.seed(123) #' df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) #' df$len <- ifelse(df$group == "grp2", df$len+2, df$len) #' df$len <- ifelse(df$group == "grp3", df$len+7, df$len) #' head(df, 3) #' #' #' # Basic boxplot #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Create a basic boxplot #' # Add 5% and 10% space to the plot bottom and the top, respectively #' bxp <- ggboxplot(df, x = "dose", y = "len") + #' scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) #' #' # Add the p-value to the boxplot #' bxp + stat_anova_test() #' #'\dontrun{ #' # Change the label position #' # Using coordinates in data units #' bxp + stat_anova_test(label.x = "1", label.y = 10, hjust = 0) #' } #' #' # Format the p-value differently #' custom_p_format <- function(p) { #' rstatix::p_format(p, accuracy = 0.0001, digits = 3, leading.zero = FALSE) #' } #' bxp + stat_anova_test( #' label = "Anova, italic(p) = {custom_p_format(p)}{p.signif}" #' ) #' #' # Show a detailed label in italic #' bxp + stat_anova_test(label = "as_detailed_italic") #' #' #' # Faceted plots #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Create a ggplot facet #' bxp <- ggboxplot(df, x = "dose", y = "len", facet.by = "supp") + #' scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) #' # Add p-values #' bxp + stat_anova_test() #' #' #' # Grouped plots #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' bxp2 <- ggboxplot(df, x = "group", y = "len", color = "dose", palette = "npg") #' #' # For each x-position, computes tests between legend groups #' bxp2 + stat_anova_test(aes(group = dose), label = "p = {p.format}{p.signif}") #' #' # For each legend group, computes tests between x variable groups #' bxp2 + stat_anova_test(aes(group = dose, color = dose), group.by = "legend.var") #' #' #'\dontrun{ #' # Two-way ANOVA: Independent measures #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Visualization: box plots with p-values #' # Two-way interaction p-values between x and legend (group) variables #' bxp3 <- ggboxplot( #' df, x = "supp", y = "len", #' color = "dose", palette = "jco" #' ) #' bxp3 + stat_anova_test(aes(group = dose), method = "two_way") #' #' # One-way repeatead measures ANOVA #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' df$id <- as.factor(c(rep(1:10, 3), rep(11:20, 3))) #' ggboxplot(df, x = "dose", y = "len") + #' stat_anova_test(method = "one_way_repeated", wid = "id") #' #' # Two-way repeatead measures ANOVA #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' df$id <- as.factor(rep(1:10, 6)) #' ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") + #' stat_anova_test(aes(group = supp), method = "two_way_repeated", wid = "id") #' #' # Grouped one-way repeated measures ANOVA #' ggboxplot(df, x = "dose", y = "len", color = "supp", palette = "jco") + #' stat_anova_test(aes(group = supp, color = supp), #' method = "one_way_repeated", wid = "id", group.by = "legend.var") #' } #'@export stat_anova_test <- function(mapping = NULL, data = NULL, method = c("one_way", "one_way_repeated", "two_way", "two_way_repeated", "two_way_mixed"), wid = NULL, group.by = NULL, type = NULL, effect.size = "ges", error = NULL, correction = c("auto", "GG", "HF", "none"), label = "{method}, p = {p.format}", label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, step.increase = 0.1, p.adjust.method = "holm", significance = list(), geom = "text", position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, parse = FALSE, ...) { label <- get_anova_test_label_template(label) if(effect.size == "pes"){ label <- gsub(pattern = "ges", replacement = "pes", x = label, fixed = TRUE) label <- gsub(pattern = "eta2[g]", replacement = "eta2[p]", x = label, fixed = TRUE) } if(missing(parse) & is_plotmath_expression(label)){ parse <- TRUE } correction <- match.arg(correction) method <- match.arg(method) if(!is.null(wid)){ if(!is.null(mapping)) mapping$wid <- as.name(wid) else mapping <- create_aes(list(wid = wid)) } layer( stat = StatCompareMultipleMeans, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list( method = method, method.args = list(type = type, effect.size = effect.size, error = error), group.by = group.by, correction = correction, na.rm = na.rm, stat.label = label, label.x.npc = label.x.npc , label.y.npc = label.y.npc, label.x = label.x, label.y = label.y, parse = parse, is.group.specified = is_group_aes_specified(mapping), step.increase = step.increase, p.adjust.method = p.adjust.method, significance = fortify_signif_symbols_encoding(significance), ... ) ) } StatCompareMultipleMeans <- ggproto("StatCompareMultipleMeans", Stat, required_aes = c("x", "y"), default_aes = aes(wid = NULL), setup_params = function(data, params){ # Initialize parameters methods_for_repeated_measures <- c( "one_way_repeated", "two_way_repeated", "two_way_mixed", "friedman_test" ) if(params$method %in% methods_for_repeated_measures){ if(is.null(data$wid)){ stop( "The argument `wid` (sample id) is required for repeated measures tests.\n", "Specify it using wid = 'id_col_name', where id_col_name is the column containing ids.", call. = FALSE ) } } return(params) }, compute_panel = function(data, scales, method, method.args, group.by, correction, p.adjust.method, stat.label, label.x.npc, label.y.npc, label.x, label.y, significance, is.group.specified, step.increase){ p <- p.adj <- x <- NULL if(method %in% c("one_way_repeated", "friedman_test")){ # One-way repeated measures ANOVA if(!is.group.specified) data$group <- data$x } df <- data is.grouped.plots <- contains_multiple_grouping_vars(df) # Statistical test parameters # test_args <- get_test_args(data, between, within) test_args <- get_test_args(data, method = method, group.by = group.by) wid <- test_args$wid between <- test_args$between within <- test_args$within group <- test_args$group nb_vars <- unique(c(between, within)) %>% length() is_two_way <- nb_vars >= 2 # label group id. Used to shift coordinates to avoid overlaps. x.group <- y.group <- 1 # Run statistical tests df <- df %>% rstatix::convert_as_factor(vars = c(between, within)) if(!is.null(group)){ df <- df %>% rstatix::df_group_by(vars = group) } anova_methods <- c("one_way", "one_way_repeated", "two_way", "two_way_repeated", "two_way_mixed") if(method %in% anova_methods){ method.args <- method.args %>% .add_item(data = df, dv = "y", between = between, within = within, wid = wid) stat.test <- do.call(rstatix::anova_test, method.args) %>% rstatix::get_anova_table(correction = correction) method.name <- "Anova" } else if(method == "kruskal_test"){ .formula <- paste0("y ~", between) %>% as.formula() method.name <- "Kruskal-Wallis" stat.test <- rstatix::kruskal_test(df, .formula) stat.test$statistic <- round(stat.test$statistic, 2) } else if(method == "welch_anova_test"){ .formula <- paste0("y ~", between) %>% as.formula() method.name <- "Welch Anova" stat.test <- rstatix::welch_anova_test(df, .formula) stat.test$statistic <- round(stat.test$statistic, 2) } else if(method == "friedman_test"){ if(is.null(within)) stop("The argument 'within' is required.") if(is.null(wid)) stop("The argument 'wid' is required.") .formula <- paste0("y ~", within, " | ", wid) %>% as.formula() method.name <- "Friedman test" stat.test <- rstatix::friedman_test(df, .formula) stat.test$statistic <- round(stat.test$statistic, 2) } else stop("Don't support the method: ", method, call. = FALSE) # Prepare the output for visualization if(is_two_way){ stat.test <- get_interaction_row(stat.test) } # Grouped tests else if(!is.null(group)){ # When data is grouped by x variable and # stat test computed between legend groups at each x position # labels group ids are x if(group == "x"){ x.group <- stat.test$x if(is.null(label.x) & length(label.x.npc) == 1) label.x <- stat.test$x } # When data is grouped by legend variable and # stat test is computed between x variable groups # labels are stacked on y-axis. labels group ids are group (legend var) else if(group == "group"){ if("colour" %in% colnames(df)) stat.test$colour <- .levels(df$colour) y.group <- stat.test$group } } sy <- significance stat.test <- stat.test %>% rstatix::adjust_pvalue(method = p.adjust.method) %>% rstatix::add_significance(p.col = "p", cutpoints = sy$cutpoints, symbols = sy$symbols) %>% rstatix::add_significance(p.col = "p.adj", cutpoints = sy$cutpoints, symbols = sy$symbols) %>% rstatix::p_format(p, p.adj, new.col = TRUE, accuracy = 1e-4) %>% add_stat_n() %>% keep_only_tbl_df_classes() %>% mutate(method = method.name) %>% add_stat_label(label = stat.label) stat.test$x <- get_coord( data.ranges = scales$x$dimension(), coord = label.x, npc = label.x.npc, margin.npc = 0, group = x.group ) stat.test$y <- get_coord( data.ranges = scales$y$dimension(), coord = label.y, npc = label.y.npc, margin.npc = 0, group = y.group, step = -step.increase ) # set label horizontal and vertical justification stat.test <- set_label_hvjust(stat.test, data = df, group) stat.test } ) # Returns arguments for the tests # data: layer data get_test_args <- function(data, method = "one_way", group.by = NULL){ # Sample within id (considered for repeated measures) wid <- between <- within <- group <- NULL if("wid" %in% colnames(data)) wid <- "wid" # Grouped or not grouped plots is_grouped_plots <- data %>% contains_multiple_grouping_vars() if(method %in% c("one_way", "kruskal_test", "welch_anova_test")){ between <- "x" if(is_grouped_plots){ if(is.null(group.by)) group.by = "x.var" # Group by x axis variable and compute test between legend variable groups if(group.by == "x.var") { group <- "x" between <-"group" } # Group by legend variable and compute test between x axis groups else if (group.by == "legend.var") { group <- "group" between <- "x" } } } else if(method %in% c("one_way_repeated", "friedman_test")){ within <- "x" if(is_grouped_plots){ if(is.null(group.by)) group.by = "x.var" # Group by x axis variable and compute test between legend variable groups if(group.by == "x.var") { group <- "x" within <-"group" } # Group by legend variable and compute test between x axis groups else if (group.by == "legend.var") { group <- "group" within <- "x" } } } else if(method == "two_way"){ between <- c("x", "group") } else if(method == "two_way_repeated"){ within <- c("x", "group") } else if(method == "two_way_mixed"){ # Auto-detect between- and within-subjects variables # ID should be unique for one of the grouping variable # It's unique for the within-ss variable when data is in a wide format wid.freq.group <- data %>% dplyr::group_by(.data$group) %>% dplyr::count(.data$wid) %>% dplyr::pull(.data$n) %>% unique() wid.freq.x <- data %>% dplyr::group_by(.data$x) %>% dplyr::count(.data$wid) %>% dplyr::pull(.data$n) %>% unique() if(!(all(wid.freq.group == 1) | all(wid.freq.x == 1))){ stop("This is not a mixed design. Check your data.", call. = FALSE) } if(all(wid.freq.group == 1)){ within <- "group" between <- "x" } else if(all(wid.freq.x == 1)){ within <- "x" between <- "group" } } # end two-way-mixed list(dv = "y", between = between, within = within, wid = wid, group = group) } # Take the last row of the ANOVA table # Corresponds to the interaction in the two-way model. # In one-way: there is only one row get_interaction_row <- function(stat.test){ utils::tail(stat.test, 1) } get_anova_test_label_template <- function(label){ switch( label, as_italic = "{method}, italic(p) = {p.format}", as_detailed = "{method}, F({DFn}, {DFd}) = {F}, eta2[g] = {ges}, p = {p.format}, n = {n}", as_detailed_italic = "{method}, italic(F)({DFn}, {DFd}) = {F}, eta2[g] = {ges}, italic(p) = {p.format}, italic(n) = {n}", as_detailed_expression = "{method}, italic(F)({DFn}, {DFd}) = {F}, eta2[g] = {ges}, italic(p) = {p.format}, italic(n) = {n}", label ) } # set label horizontal and vertical justification # group: grouping variable; either "x" or "group" set_label_hvjust <- function(stat.test, data, group){ # Adapt hjust and x position for grouped plots hjust <- 0.2 vjust <- 0 if(!is.null(group)){ if(group == "x"){ # Center label at each x position hjust <- 0.5 } else if(group == "group"){ n <- length(stat.test$group) dodge <- 0.8 if(all(stat.test$x == 1)){ # Move labels to the left stat.test$x <- round(((dodge - dodge*n) / (2*n)) + stat.test$x, 2) } } } # Two-way anova: move label to the left else if("Effect" %in% colnames(stat.test)){ if(all(stat.test$Effect == "x:group") & all(stat.test$x == 1)){ n <- length(unique(data$group)) dodge <- 0.8 stat.test$x <- round(((dodge - dodge*n) / (2*n)) + stat.test$x, 2) } } stat.test <- stat.test %>% tibble::add_column(hjust = hjust, vjust = vjust) stat.test } ggpubr/R/create_aes.R0000644000176200001440000000547614334106575014203 0ustar liggesusers#' @include utilities.R NULL #' Create Aes Mapping from a List #' #' @description Create aes mapping to make programming easy with ggplot2. #' @param .list a list of aesthetic arguments; for example .list = list(x = "dose", y = "len", color = "dose"). #' @param parse logical. If TRUE, parse the input as an expression. #' #' @examples #' # Simple aes creation #' create_aes(list(x = "Sepal.Length", y = "Petal.Length" )) #' #' # Parse an expression #' x <- "log2(Sepal.Length)" #' y <- "log2(Petal.Length)" #' create_aes(list(x = x, y = y ), parse = TRUE) #' #' # Create a ggplot #' mapping <- create_aes(list(x = x, y = y ), parse = TRUE) #' ggplot(iris, mapping) + #' geom_point() #' #' @export create_aes <- function(.list, parse = TRUE){ if(missing(parse)){ parse <- base::getOption("ggpubr.parse_aes", default = TRUE) } if(parse){ return(create_aes.parse(.list)) } else{ return(create_aes.name(.list)) } } # Ref: https://rpubs.com/hadley/97970 # Parse as name. If x_var is "a + b", as.name() will turn it into a variable called `a + b`. create_aes.name <- function(.list){ .list <- .list %>% purrr::map(function(x) to_name(x)) do.call(ggplot2::aes, .list) } # Parse an expression. If x_var is "a + b", parse() will turn it into the function call a + b create_aes.parse <- function(.list){ .list <- .list %>% purrr:: map(function(x) parse_expression(x)) do.call(ggplot2::aes, .list) } parse_expression <- function(x){ if(is_parsable_aes(x)){ # if contains space, just add backsticks using as.name() if(contains_space(x)){ if(!is_math_string(x)) return(as.name(x)) } x <- parse(text = x)[[1]] } x } to_name <- function(x){ if(is_parsable_aes(x)){ x <- as.name(x) } x } # Check if parsable aesthetic is_parsable_aes <- function(x){ is.character(x) & (!is_numeric_char(x)) & (length(x) == 1) } # Check if x is a numeric string "1", "2" # return TRUE for "1", "2", etc is_numeric_char <- function(x){ if(is.character(x)) res <- grepl("^[[:digit:]]+$", x) else res <- FALSE res } # Fortify variable name---------------------------- fortify_variable_name <- function(x){ if(contains_space(x)){ if(!is_math_string(x)){ } } } # Check if string contains space contains_space <- function(x){ grepl("\\s", x) } extract_text_inside_parenthesis <- function(x){ regmatches(x, gregexpr("(?<=\\().*?(?=\\))", x, perl=TRUE))[[1]] } # Check if text contains mathematical operators is_math_string <- function(x){ # operators <- unlist(lapply( c("Arith","Compare","Math"), methods::getGroupMembers )) operators <- c("+", "-", "*", "^", "%%", "%/%", "/", "==", ">", "<", "!=", "<=", ">=") contains_math_operators <- unlist(lapply(operators, grepl, x, fixed = TRUE)) contains_parentheses <- grepl(pattern = "\\(.*\\)", x) any(c(contains_math_operators, contains_parentheses)) } ggpubr/R/utils_stat_test_label.R0000644000176200001440000001346614332576562016504 0ustar liggesusers# check symnum.args -------------------------------- fortify_signif_symbols_encoding <- function(symnum.args = list()){ if(.is_empty(symnum.args)){ symnum.args <- list( cutpoints = c(0, 1e-04, 0.001, 0.01, 0.05, Inf), symbols = c("****", "***", "**", "*", "ns") ) } else { symnum.args.isok <- (length(symnum.args$symbols) == length(symnum.args$cutpoints)-1) if(!symnum.args.isok) stop( "Incorrect format detected in 'symnum.args'. ", "Check the documentation. ", "length(symbols) should be length(cutpoints)-1", call. = FALSE ) } symnum.args } # Check user specified label ----------------------------- # Check if is glue package expression is_glue_expression <- function(label){ grepl("\\{|\\}", label, perl = TRUE) } # Check if label is a plotmath expression contains_plotmath_symbols <- function(label){ grepl("==|italic\\s?\\(|bold\\s?\\(|bolditalic\\s?\\(", label) } starts_with_list <- function(label){ grepl("^list\\s?\\(", label) } is_plotmath_expression <- function(label){ starts_with_list(label) | contains_plotmath_symbols(label) } # Fortify label -------------------- # if label is plotmath expression, then # fortify it in case users miss something contains_p_signif <- function(label){ any(grepl("p*\\.signif", label)) } contains_twoequal_signs <- function(label){ any(grepl("==", label)) } replace_simple_by_double_equals <- function(label){ if(!contains_twoequal_signs(label)){ label <- gsub("=", "==", label) } label } escape_psignif_asteriks <- function(label){ # Escaping asteriks (special plotmath symbols) in p.signif or p.adj.signif by adding quote label <- gsub(pattern = "\\}\\{(p.*.signif)\\}", replacement = "}*`{\\1}`", x = label) # p signif preceded with space label <- gsub(pattern = "~\\{(p.*.signif)\\}", replacement = "~`{\\1}`", x = label) label <- gsub(pattern = "=+?\\s+?\\{(p.*.signif)}", replacement = "== `{\\1}`", x = label) label } # Get statistical test label to be displayed ------------------- # stat.test: statistical test output # description: the description of the stat test, for example: "Anova" # label: can be p, p.signif, p.adj or glue expression add_stat_label <- function (stat.test, label = NULL){ is_plotmath <- FALSE if(is.null(label)){ stat.test$label <- add_p(stat.test$p.format) } else{ is_plotmath <- is_plotmath_expression(label) if(is_plotmath){ label <- fortify_plotmath(label) } if(is_glue_expression(label)){ stat.test <- stat.test %>% mutate(label = glue(label)) } else { if(!(label %in% colnames(stat.test))){ stop( "Can't find the value of the argument label ('", label, "') in the computed ", "statistical test table.", call. = FALSE ) } stat.test$label <- as.character(stat.test[[label]]) } } label <- gsub(pattern = "=+(\\s+)?<", replacement = "<\\1", stat.test$label ) if(is_plotmath){ label <- replace_simple_by_double_equals(label) label <- gsub(pattern = "\\s", replacement = "~", label) label <- gsub(pattern = "~==~", replacement = "~`=`~", label ) label <- gsub(pattern = "~<~", replacement = "~`<`~", label ) # Make sure that decimal values will be displayed asis in character when parsed by ggplot # Add quote around numeric values label <- gsub("([0-9.-]+)", "'\\1'", label) # Escape minus in text label <- gsub("Kruskal'-'Wallis", "'Kruskal-Wallis'", label) } stat.test$label <- label stat.test } fortify_plotmath <- function(label){ label <- gsub(pattern = "~", replacement = " ", x = label, fixed = TRUE) if(!starts_with_list(label)) label <- paste0("list(", label, ")") if(contains_p_signif(label)){ # Escape p signif stars label <- gsub(pattern = "\\}\\{p.signif\\}", replacement = "}*`{p.signif}`", x = label) label <- gsub(pattern = "\\}\\{p.adj.signif\\}", replacement = "}*`{p.adj.signif}`", x = label) # Escape p signif stars preceded by space label <- gsub(pattern = "\\s\\{p.signif\\}", replacement = " `{p.signif}`", x = label) label <- gsub(pattern = "\\s\\{p.adj.signif\\}", replacement = " `{p.adj.signif}`", x = label) # Escape p signif stars preceded by equal signs label <- gsub(pattern = "=(\\s+)?\\{p.signif}", replacement = "=\\1`{p.signif}`", x = label) label <- gsub(pattern = "=(\\s+)?\\{p.adj.signif}", replacement = "=\\1`{p.adj.signif}`", x = label) } label <- gsub(pattern = "eta2[g]", replacement = "eta[g]^2", x = label, fixed = TRUE) label <- gsub(pattern = "eta2[p]", replacement = "eta[p]^2", x = label, fixed = TRUE) label } # Add p prefix # add_p(0.05) --> p = 0.05 # add_p("<0.05") --> p < 0.05 add_p <-function(label){ contain.inf.symbol <- grepl("<", label) label2 <- paste0("p", " = ", label) if(sum(contain.inf.symbol) > 0){ # no need to add = label2[contain.inf.symbol] <- paste0("p", label[contain.inf.symbol]) } # Add space before and after inf symbol label2 <- gsub(pattern = "<", replacement = " < ", label2) label2 } # Add statistical test number of samples add_stat_n <- function(stat.test){ stat.test$n <- rstatix::get_n(stat.test) stat.test } # gg layer data checking -------------------------- # Check whether there is multiple grouping variables # This is the case for grouped plots contains_multiple_grouping_vars <- function(data){ !all(data$x == data$group) } # Check if group variable is specified in aes is_group_aes_specified <- function(mapping){ answer <- FALSE if(is.null(mapping)) { answer <- FALSE } else if(!is.null(mapping$group)) { answer <- TRUE } answer } # Manipulating statistical test outputs ----------------- keep_only_tbl_df_classes <- function(x){ toremove <- setdiff(class(x), c("tbl_df", "tbl", "data.frame")) if(length(toremove) > 0){ class(x) <- setdiff(class(x), toremove) } x } ggpubr/R/stat_welch_anova_test.R0000644000176200001440000001122514332576562016462 0ustar liggesusers#' @include utilities.R utils_stat_test_label.R stat_anova_test.R NULL #'Add Welch One-Way ANOVA Test P-values to a GGPlot #'@description Add Welch one-way ANOVA test p-values to a ggplot, such as #' box blots, dot plots and stripcharts. #'@inheritParams ggplot2::layer #'@inheritParams stat_pvalue_manual #'@inheritParams stat_anova_test #' #'@section Computed variables: \itemize{ #' \item{statistic}: the value of the test statistic (F-value) #' \item{DFn}: Degrees of Freedom in the numerator (i.e. DF effect) #' \item{DFd}: Degrees of Freedom in the denominator (i.e., DF error) #' \item{p}: p-value. #' \item{p.adj}: Adjusted p-values. #' \item{p.signif}: P-value significance. #' \item{p.adj.signif}: Adjusted p-value significance. #' \item{p.format}: Formated p-value. #' \item{p.adj.format}: Formated adjusted p-value. #' \item{n}: number of samples. #' } #' #' @examples #' # Data preparation #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Transform `dose` into factor variable #' df <- ToothGrowth #' df$dose <- as.factor(df$dose) #' # Add a random grouping variable #' set.seed(123) #' df$group <- sample(factor(rep(c("grp1", "grp2", "grp3"), 20))) #' df$len <- ifelse(df$group == "grp2", df$len+2, df$len) #' df$len <- ifelse(df$group == "grp3", df$len+7, df$len) #' head(df, 3) #' #' #' # Basic boxplot #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Create a basic boxplot #' # Add 5% and 10% space to the plot bottom and the top, respectively #' bxp <- ggboxplot(df, x = "dose", y = "len") + #' scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) #' #' # Add the p-value to the boxplot #' bxp + stat_welch_anova_test() #' #' # Change the label position #' # Using coordinates in data units #' bxp + stat_welch_anova_test(label.x = "1", label.y = 10, hjust = 0) #' #' # Format the p-value differently #' custom_p_format <- function(p) { #' rstatix::p_format(p, accuracy = 0.0001, digits = 3, leading.zero = FALSE) #' } #' bxp + stat_welch_anova_test( #' label = "Welch Anova, italic(p) = {custom_p_format(p)}{p.signif}" #' ) #' #' # Show a detailed label in italic #' bxp + stat_welch_anova_test(label = "as_detailed_italic") #' #' #' # Faceted plots #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' # Create a ggplot facet #' bxp <- ggboxplot(df, x = "dose", y = "len", facet.by = "supp") + #' scale_y_continuous(expand = expansion(mult = c(0.05, 0.1))) #' # Add p-values #' bxp + stat_welch_anova_test() #' #' #' # Grouped plots #' #%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #' bxp2 <- ggboxplot(df, x = "group", y = "len", color = "dose", palette = "npg") #' #' # For each x-position, computes tests between legend groups #' bxp2 + stat_welch_anova_test(aes(group = dose), label = "p = {p.format}{p.signif}") #' #' # For each legend group, computes tests between x variable groups #' bxp2 + stat_welch_anova_test(aes(group = dose, color = dose), group.by = "legend.var") #' #' @export stat_welch_anova_test <- function(mapping = NULL, data = NULL, group.by = NULL, label = "{method}, p = {p.format}", label.x.npc = "left", label.y.npc = "top", label.x = NULL, label.y = NULL, step.increase = 0.1, p.adjust.method = "holm", significance = list(), geom = "text", position = "identity", na.rm = FALSE, show.legend = FALSE, inherit.aes = TRUE, parse = FALSE, ...) { label <- get_welch_anova_test_label_template(label) if(missing(parse) & is_plotmath_expression(label)){ parse <- TRUE } layer( stat = StatCompareMultipleMeans, data = data, mapping = mapping, geom = geom, position = position, show.legend = show.legend, inherit.aes = inherit.aes, params = list( method = "welch_anova_test", method.args = list(), group.by = group.by, correction = "none", na.rm = na.rm, stat.label = label, label.x.npc = label.x.npc , label.y.npc = label.y.npc, label.x = label.x, label.y = label.y, parse = parse, is.group.specified = is_group_aes_specified(mapping), step.increase = step.increase, p.adjust.method = p.adjust.method, significance = fortify_signif_symbols_encoding(significance), ... ) ) } get_welch_anova_test_label_template <- function(label){ switch( label, as_italic = "{method}, italic(p) = {p.format}", as_detailed = "{method}, F({DFn}, {DFd}) = {statistic}, p = {p.format}, n = {n}", as_detailed_italic = "{method}, italic(F)({DFn}, {DFd}) = {F}, italic(p) = {p.format}, italic(n) = {n}", as_detailed_expression = "{method}, italic(F)({DFn}, {DFd}) = {F}, italic(p) = {p.format}, italic(n) = {n}", label ) } ggpubr/R/font.R0000644000176200001440000000742514332553655013055 0ustar liggesusers#'Change the Appearance of Titles and Axis Labels #' #'@description Change the appearance of the main title, subtitle, caption, axis #' labels and text, as well as the legend title and texts. Wrapper around #' \code{\link[ggplot2:element]{element_text}()}. #' #'@param object character string specifying the plot components. Allowed values #' include: \itemize{ \item \code{"title"} for the main title \item #' \code{"subtitle"} for the plot subtitle \item \code{"caption"} for the plot #' caption \item \code{"legend.title"} for the legend title \item #' \code{"legend.text"} for the legend text \item \code{"x", "xlab", or "x.title"} #' for x axis label \item \code{"y", "ylab", or "y.title"} for y axis label \item #' \code{"xy", "xylab", "xy.title" or "axis.title"} for both x and y axis #' labels \item \code{"x.text"} for x axis texts (x axis tick labels) \item #' \code{"y.text"} for y axis texts (y axis tick labels) \item \code{"xy.text"} #' or \code{"axis.text"} for both x and y axis texts } #' #'@param size numeric value specifying the font size, (e.g.: \code{size = 12}). #'@param color character string specifying the font color, (e.g.: \code{color = #' "red"}). #'@param face the font face or style. Allowed values include one of #' \code{"plain", "bold", "italic", "bold.italic"}, (e.g.: \code{face = #' "bold.italic"}). #'@param family the font family. #'@param ... other arguments to pass to the function #' \code{\link[ggplot2:element]{element_text}()}. #' #'@examples #'# Load data #'data("ToothGrowth") #' #'# Basic plot #'p <- ggboxplot(ToothGrowth, x = "dose", y = "len", color = "dose", #' title = "Box Plot created with ggpubr", #' subtitle = "Length by dose", #' caption = "Source: ggpubr", #' xlab ="Dose (mg)", ylab = "Teeth length") #'p #' #'# Change the appearance of titles and labels #'p + #' font("title", size = 14, color = "red", face = "bold.italic")+ #' font("subtitle", size = 10, color = "orange")+ #' font("caption", size = 10, color = "orange")+ #' font("xlab", size = 12, color = "blue")+ #' font("ylab", size = 12, color = "#993333")+ #' font("xy.text", size = 12, color = "gray", face = "bold") #' #'# Change the appearance of legend title and texts #'p + #' font("legend.title", color = "blue", face = "bold")+ #' font("legend.text", color = "red") #' #'@export font <- function(object, size = NULL, color = NULL, face = NULL, family = NULL, ...){ elmt <- element_text(size = size, color = color, face = face, family = family, ...) switch(object, title = theme(plot.title = elmt), subtitle = theme(plot.subtitle = elmt), caption = theme(plot.caption = elmt), x = theme(axis.title.x = elmt), xlab = theme(axis.title.x = elmt), x.title = theme(axis.title.x = elmt), y = theme(axis.title.y = elmt), ylab = theme(axis.title.y = elmt), y.title = theme(axis.title.y = elmt), xy = theme(axis.title.x = elmt, axis.title.y = elmt), xylab = theme(axis.title.x = elmt, axis.title.y = elmt), xy.title = theme(axis.title.x = elmt, axis.title.y = elmt), axis.title = theme(axis.title.x = elmt, axis.title.y = elmt), legendtitle = theme(legend.title = elmt), legend.title = theme(legend.title = elmt), legendtext = theme(legend.text = elmt), legend.text = theme(legend.text = elmt), # Axis tick labels x.text = theme(axis.text.x = elmt), y.text = theme(axis.text.y = elmt), xy.text = theme(axis.text.x = elmt, axis.text.y = elmt), yxtext = theme(axis.text.x = elmt, axis.text.y = elmt), axis.text = theme(axis.text.x = elmt, axis.text.y = elmt), stop("Don't support ", object) ) } ggpubr/R/ggpubr_options.R0000644000176200001440000000040514343207174015131 0ustar liggesusers#' Global Options for GGPubr #' @description Displays allowed global options in ggpubr. #' @examples #' #' ggpubr_options() #' #' @export ggpubr_options <- function(){ list( ggpubr.parse_aes = TRUE, ggpubr.null_device = cowplot::pdf_null_device ) } ggpubr/R/get_palette.R0000644000176200001440000000631614332553655014402 0ustar liggesusers#'Generate Color Palettes #' #'@description Generate a palette of k colors from ggsci palettes, RColorbrewer #' palettes and custom color palettes. Useful to extend RColorBrewer and ggsci to support more colors. #'@param palette Color palette. Allowed values include: \itemize{ \item #' \strong{Grey color palettes}: "grey" or "gray"; \item \strong{RColorBrewer #' palettes}, see \code{\link[RColorBrewer:ColorBrewer]{brewer.pal}} and details section. #' Examples of palette names include: "RdBu", "Blues", "Dark2", "Set2", ...; #' \item \strong{Custom color palettes}. For example, palette = c("#00AFBB", #' "#E7B800", "#FC4E07"); \item \strong{ggsci scientific journal palettes}, #' e.g.: "npg", "aaas", "lancet", "jco", "ucscgb", "uchicago", "simpsons" and #' "rickandmorty". } #'@param k the number of colors to generate. #'@details #'\strong{RColorBrewer palettes}: To display all available color #' palettes, type this in R:RColorBrewer::display.brewer.all(). Color palette #' names include: #' #' \itemize{ \item \strong{Sequential palettes}, suited to ordered data that #' progress from low to high. Palette names include: Blues BuGn BuPu GnBu #' Greens Greys Oranges OrRd PuBu PuBuGn PuRd Purples RdPu Reds YlGn YlGnBu #' YlOrBr YlOrRd. \item \strong{Diverging palettes}:Gradient colors. Names #' include: BrBG PiYG PRGn PuOr RdBu RdGy RdYlBu RdYlGn Spectral. \item #' \strong{Qualitative palettes}: Best suited to representing nominal or #' categorical data. Names include: Accent, Dark2, Paired, Pastel1, Pastel2, #' Set1, Set2, Set3. #' } #' #'@return Returns a vector of color palettes. #' #'@examples #'data("iris") #' iris$Species2 <- factor(rep(c(1:10), each = 15)) #' #'# Generate a gradient of 10 colors #'ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", #' color = "Species2", #' palette = get_palette(c("#00AFBB", "#E7B800", "#FC4E07"), 10)) #' #'# Scatter plot with default color palette #'ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", #' color = "Species") #' #'# RColorBrewer color palettes #'ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", #' color = "Species", palette = get_palette("Dark2", 3)) #' #' # ggsci color palettes #'ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", #' color = "Species", palette = get_palette("npg", 3)) #' #' # Custom color palette #'ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", #' color = "Species", #' palette = c("#00AFBB", "#E7B800", "#FC4E07")) #' #' # Or use this #'ggscatter(iris, x = "Sepal.Length", y = "Petal.Length", #' color = "Species", #' palette = get_palette(c("#00AFBB", "#FC4E07"), 3)) #' #' #' #' #' #'@export get_palette <- function(palette = "default", k) { # Check if RColorBrewer, ggsci, hue or grey/gray color palettes if(.is_col_palette(palette)){ if(palette %in% .brewerpal()) .get_brewer_pal(palette, k) else if(palette %in% .ggscipal()) .get_ggsci_pal(palette, k) else if(palette %in% c("default", "hue")){ hues <- seq(15, 375, length = k + 1) grDevices::hcl(h = hues, l = 65, c = 100, alpha = 1)[1:k] } # Grey color palette else if(palette %in% c("grey", "gray")){ grDevices::grey.colors(k, start = 0.2, end = 0.8) } } else grDevices::colorRampPalette(palette)(k) } ggpubr/R/ggdonutchart.R0000644000176200001440000001160114345714554014570 0ustar liggesusers#'@include utilities.R ggpar.R ggpie.R NULL #'Donut chart #'@description Create a donut chart. #'@inheritParams ggboxplot #'@inheritParams ggplot2::geom_errorbar #'@param x variable containing values for drawing. #'@param label variable specifying the label of each slice. #'@param lab.pos character specifying the position for labels. Allowed values #' are "out" (for outside) or "in" (for inside). #'@param lab.adjust numeric value, used to adjust label position when lab.pos = #' "in". Increase or decrease this value to see the effect. #'@param lab.font a vector of length 3 indicating respectively the size (e.g.: #' 14), the style (e.g.: "plain", "bold", "italic", "bold.italic") and the #' color (e.g.: "red") of label font. For example \emph{lab.font= c(4, "bold", #' "red")}. #'@param font.family character vector specifying font family. #'@param color,fill outline and fill colors. #'@param ... other arguments to be passed to be passed to ggpar(). #'@details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, #' ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette #' = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels #' and position: legend = "right" \item plot orientation : orientation = #' c("vertical", "horizontal", "reverse") } #'@seealso \code{\link{ggpar}}, \code{\link{ggpie}} #' @examples #' #' # Data: Create some data #' # +++++++++++++++++++++++++++++++ #' #' df <- data.frame( #' group = c("Male", "Female", "Child"), #' value = c(25, 25, 50)) #' #' head(df) #' #' #' # Basic pie charts #' # ++++++++++++++++++++++++++++++++ #' #' ggdonutchart(df, "value", label = "group") #' #' #' # Change color #' # ++++++++++++++++++++++++++++++++ #' #' # Change fill color by group #' # set line color to white #' # Use custom color palette #' ggdonutchart(df, "value", label = "group", #' fill = "group", color = "white", #' palette = c("#00AFBB", "#E7B800", "#FC4E07") ) #' #' #' # Change label #' # ++++++++++++++++++++++++++++++++ #' #' # Show group names and value as labels #' labs <- paste0(df$group, " (", df$value, "%)") #' ggdonutchart(df, "value", label = labs, #' fill = "group", color = "white", #' palette = c("#00AFBB", "#E7B800", "#FC4E07")) #' #' # Change the position and font color of labels #' ggdonutchart(df, "value", label = labs, #' lab.pos = "in", lab.font = "white", #' fill = "group", color = "white", #' palette = c("#00AFBB", "#E7B800", "#FC4E07")) #' #' #' #'@export ggdonutchart <- function( data, x, label = x, lab.pos = c("out", "in"), lab.adjust = 0, lab.font = c(4, "plain", "black"), font.family = "", color = "black", fill = "white", palette = NULL, size = NULL, ggtheme = theme_pubr(), ... ) { lab.pos <- match.arg(lab.pos) lab.font <- .parse_font(lab.font) %>% .check_pie_labfont() # We should order the data in desc order. Because, # in stacked bar plot the order of factor levels are reversed # Very important to have the label in the right place group.vars <- intersect(c(fill, color), names(data)) if(length(group.vars) != 0){ group.val <- dplyr::pull(data, group.vars[1]) data <- data %>% dplyr::arrange(dplyr::desc(group.val)) } # Label y coordinates when placed inside slices .x <- dplyr::pull(data, x) data <- data %>% dplyr::mutate( .lab.ypos. = cumsum(.x) -0.5*.x -lab.adjust ) if(length(label) > 1 & length(label) != nrow(data)) stop("label should be of the same length as data") else if(length(label) > 1){ # 1. Add label column data <- data %>% dplyr::mutate(.label. = label) label <- ".label." } p <- ggplot(data, create_aes(list(x = 2, y = x))) + geom_exec( geom_bar, data, stat = "identity", fill = fill, color = color, size = size ) p <- ggpar( p, palette = palette, ggtheme = ggtheme, font.family = font.family, ... ) + coord_polar( theta = "y", start = 0, clip = "off" ) + ggtheme + .remove_axis() # Annotate pie slice #::::::::::::::::::::::::::::::::::: if(!is.null(label)){ # Label each slice at the middle of the slice if(lab.pos == "out"){ p <- p + scale_y_continuous( breaks = cumsum(.x) - .x/2, labels = dplyr::pull(data, label) ) + ggplot2::theme(axis.text.x = element_text( face = lab.font$face, color = lab.font$color, size = 2.5*lab.font$size, family = font.family )) } # Compute the cumulative sum as label ypos if(lab.pos == "in"){ p <- p + geom_text( create_aes(list(y = ".lab.ypos.", label = label)), size = lab.font$size, fontface = lab.font$face, colour = lab.font$color, family = font.family )+ clean_theme() } } p + xlim(0.5, 2.5) } ggpubr/R/grids.R0000644000176200001440000000227414332553655013214 0ustar liggesusers#'Add Grids to a ggplot #' #'@description Add grids to ggplot. #'@param axis axis for which grid should be added. Allowed values include \code{c("xy", "x", "y")}. #'@param color grid line color. #'@param size numeric value specifying grid line size. #'@param linetype line type. An integer (0:8), a name (blank, solid, dashed, #' dotted, dotdash, longdash, twodash). Sess \code{\link{show_line_types}}. #' #' #'@examples #'# Load data #'data("ToothGrowth") #' #'# Basic plot #'p <- ggboxplot(ToothGrowth, x = "dose", y = "len") #'p #' #'# Add border #' p + grids(linetype = "dashed") #'@export grids <- function(axis = c("xy", "x", "y"), color = "grey92", size = NULL, linetype = NULL) { axis <- match.arg(axis) grid.major <- element_line(color = color, size = size, linetype = linetype) grid.minor <- element_line(color = color, size = 0.25, linetype = linetype) switch(axis, xy = theme(panel.grid.major = grid.major, panel.grid.minor = grid.minor), x = theme(panel.grid.major.x = grid.major, panel.grid.minor.x = grid.minor), y = theme(panel.grid.major.y = grid.major, panel.grid.minor.y = grid.minor) ) } ggpubr/R/ggviolin.R0000644000176200001440000001500114342647721013711 0ustar liggesusers#' @include utilities.R ggpar.R NULL #'Violin plot #'@description Create a violin plot with error bars. Violin plots are similar to #'box plots, except that they also show the kernel probability density of the #'data at different values. #'@inheritParams ggboxplot #'@param width violin width. #'@param alpha color transparency. Values should be between 0 and 1. #'@inheritParams ggplot2::geom_violin #' @param ... other arguments to be passed to #' \code{\link[ggplot2]{geom_violin}}, \code{\link{ggpar}} and #' \code{\link{facet}}. #'@details The plot can be easily customized using the function ggpar(). Read #' ?ggpar for changing: \itemize{ \item main title and axis labels: main, xlab, #' ylab \item axis limits: xlim, ylim (e.g.: ylim = c(0, 30)) \item axis #' scales: xscale, yscale (e.g.: yscale = "log2") \item color palettes: palette #' = "Dark2" or palette = c("gray", "blue", "red") \item legend title, labels #' and position: legend = "right" \item plot orientation : orientation = #' c("vertical", "horizontal", "reverse") } #'@seealso \code{\link{ggpar}} #' @examples #' # Load data #' data("ToothGrowth") #' df <- ToothGrowth #' #' # Basic plot #' # +++++++++++++++++++++++++++ #'ggviolin(df, x = "dose", y = "len") #' # Change the plot orientation: horizontal #'ggviolin(df, "dose", "len", orientation = "horiz") #' #' # Add summary statistics #' # ++++++++++++++++++++++++++ #' # Draw quantiles #' ggviolin(df, "dose", "len", add = "none", #' draw_quantiles = 0.5) #' #' # Add box plot #' ggviolin(df, x = "dose", y = "len", #' add = "boxplot") #' #'ggviolin(df, x = "dose", y = "len", #' add = "dotplot") #' #' # Add jitter points and #' # change point shape by groups ("dose") #'ggviolin(df, x = "dose", y = "len", #' add = "jitter", shape = "dose") #' #' #' # Add mean_sd + jittered points #' ggviolin(df, x = "dose", y = "len", #' add = c("jitter", "mean_sd")) #' #' # Change error.plot to "crossbar" #' ggviolin(df, x = "dose", y = "len", #' add = "mean_sd", error.plot = "crossbar") #' #' #' # Change colors #' # +++++++++++++++++++++++++++ #' # Change outline and fill colors #' ggviolin(df, "dose", "len", #' color = "black", fill = "gray") #' #' # Change outline colors by groups: dose #' # Use custom color palette and add boxplot #' ggviolin(df, "dose", "len", color = "dose", #' palette = c("#00AFBB", "#E7B800", "#FC4E07"), #' add = "boxplot") #' #' # Change fill color by groups: dose #' # add boxplot with white fill color #' ggviolin(df, "dose", "len", fill = "dose", #' palette = c("#00AFBB", "#E7B800", "#FC4E07"), #' add = "boxplot", add.params = list(fill = "white")) #' #' #' # Plot with multiple groups #' # +++++++++++++++++++++ #' # fill or color box plot by a second group : "supp" #'ggviolin(df, "dose", "len", color = "supp", #' palette = c("#00AFBB", "#E7B800"), add = "boxplot") #' #'@export ggviolin <- function(data, x, y, combine = FALSE, merge = FALSE, color = "black", fill = "white", palette = NULL, alpha = 1, title = NULL, xlab = NULL, ylab = NULL, facet.by = NULL, panel.labs = NULL, short.panel.labs = TRUE, linetype = "solid", trim = FALSE, size = NULL, width = 1, draw_quantiles = NULL, select = NULL, remove = NULL, order = NULL, add = "mean_se", add.params = list(), error.plot = "pointrange", label = NULL, font.label = list(size = 11, color = "black"), label.select = NULL, repel = FALSE, label.rectangle = FALSE, position = position_dodge(0.8), ggtheme = theme_pubr(), ...) { # Default options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .opts <- list( combine = combine, merge = merge, color = color, fill = fill, palette = palette, alpha = alpha, title = title, xlab = xlab, ylab = ylab, facet.by = facet.by, panel.labs = panel.labs, short.panel.labs = short.panel.labs, linetype = linetype, trim = trim, size = size, width = width, draw_quantiles = draw_quantiles, select = select , remove = remove, order = order, add = add, add.params = add.params, error.plot = error.plot, label = label, font.label = font.label, label.select = label.select, repel = repel, label.rectangle = label.rectangle, position = position, ggtheme = ggtheme, ...) if(!missing(data)) .opts$data <- data if(!missing(x)) .opts$x <- x if(!missing(y)) .opts$y <- y # User options #::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: .user.opts <- as.list(match.call(expand.dots = TRUE)) .user.opts[[1]] <- NULL # Remove the function name # keep only user arguments for(opt.name in names(.opts)){ if(is.null(.user.opts[[opt.name]])) .opts[[opt.name]] <- NULL } .opts$fun <- ggviolin_core if(missing(ggtheme) & (!is.null(facet.by) | combine)) .opts$ggtheme <- theme_pubr(border = TRUE) if(missing(ggtheme) & !is.null(facet.by)) .opts$ggtheme <- theme_pubr(border = TRUE) p <- do.call(.plotter, .opts) if(.is_list(p) & length(p) == 1) p <- p[[1]] return(p) } ggviolin_core <- function(data, x, y, color = "black", fill = "white", palette = NULL, alpha = 1, title = NULL, xlab = NULL, ylab = NULL, linetype = "solid", trim = FALSE, size = NULL, width = 1, draw_quantiles = NULL, add = "mean_se", add.params = list(), error.plot = "pointrange", ggtheme = theme_pubr(), position = position_dodge(0.8), ...) { if(!is.factor(data[[x]])) data[[x]] <- as.factor(data[[x]]) pms <- .violin_params(...) p <- ggplot(data, create_aes(list(x = x, y = y))) + geom_exec(geom_violin, data = data, color = color, fill = fill, linetype = linetype, trim = trim, size = size, width = width, alpha = alpha, position = position, draw_quantiles = draw_quantiles, stat = pms$stat, scale = pms$scale) # Add #+++++++++++++++++++ if(is.null(add.params$group)){ if(fill %in% names(data)) add.params$group <- fill } add.params <- .check_add.params(add, add.params, error.plot, data, color, fill, ...) %>% .add_item(p = p, add = add, error.plot = error.plot, position = position) p <- do.call(ggadd, add.params) %>% ggpar(palette = palette, ggtheme = ggtheme, title = title, xlab = xlab, ylab = ylab,...) p } ggpubr/NEWS.md0000644000176200001440000010424214367517046012656 0ustar liggesusers# ggpubr 0.6.0 ## New features - New function `ggadjust_pvalue()` added to adjust p-values produced by `geom_pwc()` on a ggplot (#522). - New data added: `gene_expression` - Global options: New available package options: `ggpubr.null_device`, which value should be a function that creates an appropriate null device. These include: `cowplot::pdf_null_device`, `cowplot::png_null_device`, `cowplot::cairo_null_device` and `cowplot::agg_null_device`. Default is `cowplot::pdf_null_device`. This is used in function like `as_ggplot()`, which needs to open a graphics device to render ggplot objects into grid graphics objects. This function is used to open null device for avoiding the display of unnecessary blank page when calling `ggarrange()` or `as_ggplot()` (#306 and #158). The default option can be changed using, for example, `options(ggpubr.null_device = cowplot::png_null_device)`. ## Major changes - `gadd()`: Restoring back random state after setting seed when adding jittered points. To do so, the seed number is just passed to `position_jitter()` and `position_jitterdodge()`, which preserve the initial random state ( #177 and #349) . - `ggpubr` requires now a version of `ggrepel >= 0.9.2.9999`, which restores now the initial random state after set.seed(). see https://github.com/slowkow/ggrepel/issues/228 - `ggpubr` requires now a version of `cowplot >= 1.1.1` ## Minor changes - `ggtexttable()`: doc updated with another example; text justification for individual cells/rows/columns (#335). - `ggpie()`: setting the default of `clip = "off"` in `coord_polar()` so that `ggpie()` does not crop labels (#429) - `as_ggplot()`: using null_device to avoid blank page #306 and #158 - `ggarrange()`: using null_device to avoid blank page #306 and #158 - Indexing variable in a data frame: using df[[x]] instead of df[, x] to make sure that the result is a vector even if the `df` is a tibble. - `ggexport()`: support added for graphics device svg (#469) - `ggpie()` and `ggdonutchart()` now fully reacts to the option `lab.font` (#502) - Replacing deprecated `gather_()` in both internal (`.check_data()`) and exported functions (`compare_means()`) (#513) - `stat_compare_means()`: The dot-dot notation (`..p.signif..`) was deprecated in ggplot2 3.4.0; `after_stat(p.signif)` should be used; updated so that `..p.signif..` is automatically converted into `after_stat()` format without warning for bacward compatibility. - Enable faceting by column names with spaces (#391) - Licence changed to GPL (>= 2) (#482) - `desc_statby()` doc updated to clarify the difference between SD (standard deviation) and SE (standard error) (#492) - The message `geom_smooth() using formula 'y ~ x'` is now turned off in `ggscatter()`(#488) ## Bug fixes - `ggtext()`: fix warning "`filter_()` was deprecated in dplyr 0.7.0". - `ggqqplot()`: the argument `conf.int` is taken into account now when specified (#524). - `ggqqplot()`: Fixing the warning: "The following aesthetics were dropped during statistical transformation: sample" (#523) - Requiring `rstatix v >=0.7.1.999` for preserving factor class in `emmeans_test()` (#386) - `ggmaplot()`: Suppressing ggmaplot warning: *Unlabeled data points (too many overlaps). Consider increasing max.overlaps* (#520) - `compare_means()`: works now when the grouping variable levels contain the key words group2 or group1 (#450) - `ggparagraph()` : fixing bug about minimum paragraph length (#408) - `ggexport()`: the verbose argument is now considered when specifyed by user (#474) # ggpubr 0.5.0 ## New features - New functions `stat_anova_test()`, `stat_kruskal_test()`, `stat_welch_anova_test()`, `stat_friedman_test()` and `geom_pwc()` added. These are flexible functions to add p-values onto ggplot with more options. The function `geom_pwc()` is for adding pairwise comparisons p-values to a ggplot; supportted statistical methods include "wilcox_test", "t_test", "sign_test", "dunn_test", "emmeans_test", "tukey_hsd" and "games_howell_test". - New functions to convert character vector coordinates into NPC (normalized parent coordinates) and data coordinates: `as_npc()`, `npc_to_data_coordinates()` and `get_coord()`. - Global options: - New function `ggpubr_options()` to display allowed global options in ggpubr - New available package options: `ggpubr.parse_aes`. logical indicating whether to parse or not the aesthetics variables names. Default is `TRUE`. For example, if you want ggpubr to handle non-standard column names, like A-A, without parsing, then set this option to FALSE using `options(ggpubr.parse_aes = FALSE)`. ## Minor changes - Minimum rstatix version needed is set to 0.7.1 - Minimum ggplot2 version needed is set to 3.4.0 - `stat_conf_ellipse`: ensure stat returns a data.frame for compatibility with ggplot2 v>=3.4.0 - `stat_compare_means()`: - Unit tests added - Updated to use `after_stat(p.signif)` as the dot-dot notation (`..p.signif..`) was deprecated in ggplot2 3.4.0 (#509). - `ggdensity()` and `gghistogram()`: dot-dot notation (`..density..`, `..count..`) replaced by `after_stat(density)` and `after_stat(count)`, respectively for compatibility with ggplot2 3.4.0. - `create_aes()`: - Default is now to parse its input, which can be an expression (#348). If you want ggpubr to handle non-standard column names (#229), like A-A, without parsing, then set this option to FALSE using `options(ggpubr.parse_aes = FALSE)`. - Supports space in column names like "Dimension 1" - Unittest added - Arguments (`digits` and `table.font.size`) added to `ggsummarystats()` for changing the summary table decimal place and text size (#341). - In `stat_pvalue_manual()` the argument `hide.ns` can be either a logical value (TRUE or FALSE) or a character value ("p" or "p.adj" for filtering out non significant by p-value or adjusted p-values). - Now, the x-axis tick label names correctly align with the corresponding ticks when the rotation angle of the texts is set to 90. This is automatically achieved by setting internally `vjust = 0.5` (#301). - `Capital NS.` is no longer displayed by `stat_compare_means()` (#171) - Unit tests added for`ggshistogram()` to make sure that it works when: - using `after_stat()`, - using after_stat() with trailing space inside parentheses. - Unit tests added for`ggscatter()` to make sure that: - it works when there is spaces in variable names - it can handle non-standard column names when `ggpubr.parse_aes` global option is set to FALSE (#229) # ggpubr 0.4.0 ## New features - New functions added to customize `ggtexttable()` (#125, #129 and #283): - `tab_cell_crossout()`: cross out a table cell. - `tab_ncol(), tab_nrow()`: returns, respectively, the number of columns and rows in a ggtexttable. - `tab_add_hline()`: Creates horizontal lines or separators at the top or the bottom side of a given specified row. - `tab_add_vline()`: Creates vertical lines or separators at the right or the left side of a given specified column. - `tab_add_border(), tbody_add_border(), thead_add_border()`: Add borders to table; tbody is for table body and thead is for table head. - `tab_add_title()` and `tab_add_footnote()` to add titles and footnotes (#243). - ggpubr functions updated to handle non-standard column names, for example ("A-A") (#229). - New function `create_aes()` added to create aes mapping from a list. Makes programming easy with ggplot2 (#229). - New argument `coord.flip` added to support adding p-values onto horizontal ggplots (#179). When adding the p-values to a horizontal ggplot (generated using `coord_flip()`), you need to specify the option `coord.flip = TRUE`. - New errorbar functions - `median_hilow_()` and `median_q1q3()` - added ([@davidlorenz, #209](https://github.com/kassambara/ggpubr/issues/209)): - `median_hilow_()`: computes the sample median and a selected pair of outer quantiles having equal tail areas. This function is a reformatted version of `Hmisc::smedian.hilow()`. The confidence limits are computed as follow: `lower.limits = (1-ci)/2` percentiles; `upper.limits = (1+ci)/2` percentiles. By default (`ci = 0.95`), the 2.5th and the 97.5th percentiles are used as the lower and the upper confidence limits, respectively. If you want to use the 25th and the 75th percentiles as the confidence limits, then specify `ci = 0.5` or use the function `median_q1q3()`. - `median_q1q3()`: computes the sample median and, the 25th and 75th percentiles. Wrapper around the function median_hilow_() using ci = 0.5. - New function `get_breaks()` added to easily create breaks for numeric axes. Can be used to increase the number of x and y ticks by specifying the option `n`. It's also possible to control axis breaks by specifying a step between ticks. For example, if by = 5, a tick mark is shown on every 5 ([@Chitanda-Satou, #258](https://github.com/kassambara/ggpubr/issues/258)). ## Major changes - The following enhancement has been added to `ggscatterhist()` ([@juliechevalier, #176](https://github.com/kassambara/ggpubr/issues/176)): - the output of `ggscatterhist()` is now a list of ggplots, containing the main scatter plot (`sp`) and the marginal plots (`xplot` and `yplot`), which can be customized by the end user using the standard ggplot verbs - An S3 printing method is now available for an object of class ggscatterhist. The printing method displays the arranged final figure. ## Minor changes - Now, when creating a box plot with error bars, color and fill argiments are taken into account in the errorbar function (#105). - New argument `alternative` supported in `stat_cor()` (#276). - New argument `position` in `ggline()` to make position "dodged" (#52). - New argument `outlier.shape` in ggboxplot(). Default is 19. To hide outlier, specify outlier.shape = NA. When jitter is added, then outliers will be automatically hidden. - Sorting can be now disabled in `ggdotchart()` using the option `sorting = "none"` (#115, #223). - New argument `weight` added in `gghistogram()` for creating a weighted histogram (#215) - Now `ggscaterhist()` takes into account the argument `position` in `margin.params` when marginal plot is a histogram (#286). - `ggbarplot()` enhanced to better handle the creation of dodged bar plots combined with jitter points ([@aherholt, #176](https://github.com/kassambara/ggpubr/issues/282)) - New argument `bracket.shorten` added in `stat_pvalue_manual()` and `geom_bracket()`. a small numeric value in [0-1] for shortening the with of bracket (#285). - New argument `bracket.nudge.y` added in `stat_pvalue_manual()` and `geom_bracket()`. Vertical adjustment to nudge brackets by. Useful to move up or move down the bracket. If positive value, brackets will be moved up; if negative value, brackets are moved down ([#281](https://github.com/kassambara/ggpubr/issues/281)). - New argument `numeric.x.axis` added in `ggerrorplot()`; logical value, If TRUE, x axis will be treated as numeric. Default is FALSE ([#280](https://github.com/kassambara/ggpubr/issues/280)). - The option `width` is now considered in `ggadd()` for plotting error bars ([#278](https://github.com/kassambara/ggpubr/issues/278)). - New argument `linetype` in `ggpaired()`. - `geom_exec()` used in `ggpaired()` to add lines between paired points. - `ggmaplot()` now supports two input formats (#198): 1. baseMean | log2FoldChange|padj: Here, we'll use log2(baseMean) as the x-axis variable 2. baseMeanLog2 | log2FoldChange|padj: here, baseMeanLog2 is assumed to be the mean of logged values; so we'll use it as x-axis variable without any transformation. - new arguments added in `ggmaplot()`: - `alpha` for controlling point transparency/density ([@apcamargo, #152](https://github.com/kassambara/ggpubr/issues/152)). - `label.select` to select specific genes to show on the plot ([@apastore, #70](https://github.com/kassambara/ggpubr/issues/70)) - In `ggadd()` the `fill` argument is considered for jitter points only when the point shape is in 21:25 ([@atakanekiz, #148](https://github.com/kassambara/ggpubr/issues/148)). - New argument `parse` added in `ggscatter()` and in `ggtext()`. If TRUE, the labels will be parsed into expressions and displayed as described in ?plotmath (#250). - New argument `stroke` supported in `ggscatter()` and in `ggline()`. Used only for shapes 21-24 to control the thickness of points border ([@bioguy2018, #258](https://github.com/kassambara/ggpubr/issues/236)). - the `stat_cor()` function code has been simplified. New arguments `p.accuracy` and `r.accuracy` added; a real value specifying the number of decimal places of precision for the p-value and the correlation coefficient, respectively. Default is NULL. Use (e.g.) 0.01 to show 2 decimal places of precision ([@garthtarr, #186](https://github.com/kassambara/ggpubr/issues/186), [@raedevan6, #114](https://github.com/kassambara/ggpubr/issues/114), [#270](https://github.com/kassambara/ggpubr/issues/270)). ## Bug fixes - `annotate_figure()` manual updated to show how to use of superscript/subscript in the axis labels (#165). - `ggtextable()` now supports further customization when theme is specified (#283). - the argument `font.family` is now correctly handled by `ggscatter()` (#149) - `ggpar()` arguments are correctly applied using `ggpie()` (#277). - `ggscatter()`: When `conf.int = FALSE`, fill color is set to "lightgray" for the regression line confidence band ([@zhan6073, #111](https://github.com/kassambara/ggpubr/issues/111)). - Now, `gghistogram()` supports the paramter `yticks.by` ([@Chitanda-Satou, #258](https://github.com/kassambara/ggpubr/issues/258)). # ggpubr 0.3.0 ## New features - New functions: - `ggsummarystats()` to create a GGPLOT with summary stats table under the plot ( [#251](https://github.com/kassambara/ggpubr/pull/251)). - `clean_table_theme()` to clean the the theme of a table, such as those created by `ggsummarytable()` - `ggbarplot()` now supports stacked barplots with error bars ([#245](https://github.com/kassambara/ggpubr/pull/245)). ## Minor changes - New arguments: - `vjsut` in `stat_compare_means()` to move the text up or down relative to the bracket. - `type` in `geom_bracket()` to specify label type. Can be "text" or "expression" (for parsing plotmath expression); [#253](https://github.com/kassambara/ggpubr/issues/253). - `labeller` to the function `facet()` - `position` in `get_legend()` to specify legend position - `legend.grob` in `ggarrange()` to specify a common legend you want to add onto the combined plot. - Maintenance adaptation to dplyr new version by removing deprecated functions, such as group_by_, select_, arrange_, etc ## Bug fixes - Now, Barplots are correctly labelled when custom labels are specified by users ([@sekharcu, #234](https://github.com/kassambara/ggpubr/issues/234)) # ggpubr 0.2.5 ## Minor changes - New arguments `cor.coef.name` in the function `stat_cor()`. Can be one of "R" (pearson coef), "rho" (spearman coef) and "tau" (kendall coef). Uppercase and lowercase are allowed ([@andhamel, #216](https://github.com/kassambara/ggpubr/issues/228)). - New arguments `digits, r.digits, p.digits` in the function `stat_cor()`. Integer indicating the number of decimal places (round) or significant digits (signif) to be used for the correlation coefficient and the p-value ([@raedevan6, #216](https://github.com/kassambara/ggpubr/issues/114)). - `compare_means()` adapted to tidyr v>= 1.0.0 by specifying cols in the unnest() function ([@Youguang, #216](https://github.com/kassambara/ggpubr/issues/216)). # ggpubr 0.2.4 ## Minor change - unnest adapted to tidyr 1.0.0 - `stat_pvalue_manual()` can now handle an rstatix test result containing only one group column. # ggpubr 0.2.3 ## New features - New function `stat_central_tendency()` to add central tendency measures (mean, median, mode) to density and histogram plots - New function `stat_overlay_normal_density()` to overlay normal density plot (with the same mean and SD) to the density distribution of 'x'. ## Minor changes - The option `exact = FALSE` is no longer used when computing correlation in `stat_cor()` ([@tiagochst, #205](https://github.com/kassambara/ggpubr/issues/205)) ## Bug fixes - `ggpie()` keeps now the default order of labels ([@WortJohn, #203](https://github.com/kassambara/ggpubr/pull/203)) # ggpubr 0.2.2 ## New fatures - New function `geom_bracket()` for adding brackets with label annotation to a ggplot. Helpers for adding p-value or significance levels to a plot. ## Minor changes - `compare_means()` has been adapted to tidyr v1.0.0 ([@jennybc, #196](https://github.com/kassambara/ggpubr/pull/196)) - `geom_exec()` now handles `geom_bracket()` arguments - New arguments `vjust`, `hide.ns`, `step.increase`, `step.group.by`, `color` and `linetype` added in `stat_pvalue_manual()` - `stat_pvalue_manual()` can now guess automatically the significance label column. - New argument `show.legend` added to `ggadd()` and `add_summary()` functions. ## Bug fixes - Bug fixes in `gghistogram()`. Works now when the x variable is R keyword, such as var, mean, etc. ([#192](https://github.com/kassambara/ggpubr/issues/192)) - In `ggline()`, error bars now react automatically to grouping by line type ([#191](https://github.com/kassambara/ggpubr/issues/191)) # ggpubr 0.2.1 ## Minor changes - New arguments `step.increase` added in `stat_compare_means()` to avoid overlap between brackets. - In `stat_pvalue_manual()` x axis variable is no longer automatically converted into factor. If your x variable is a factor, make sure that it is converted into factor. - `stat_pvalue_manual()` can automatically handle the output of rstatix tests - `ggbarplot()` and `ggviolin()` now automatically create error bars by groups when users forget the option `add.params = list(group = )` ([#183](https://github.com/kassambara/ggpubr/issues/183)). - Now, `ggarrange()` works when either `ncol = 1` or `nrow = 1` ([@GegznaV, #141](https://github.com/kassambara/ggpubr/issues/144). - When method = "wilcox.test", the function `compare_means()` set automatically the option `exact = FALSE`. This is no longer the case ([@stemicha, #141](https://github.com/kassambara/ggpubr/issues/141). - `stat_pvalue_manual()` now supports dodged grouped plots ([@emcnerny, #104](https://github.com/kassambara/ggpubr/issues/104)). - the argument `position` is now handled by `ggdotplot()` ([@Adam-JJJJJ, #178](https://github.com/kassambara/ggpubr/issues/178)) ## Bug fixes - Adding points works now for barplots grouped by fill color ([@elenichri](https://github.com/kassambara/ggpubr/issues/173)) - `label.sep` argument works now in `ggscatter()` and `stat_cor()` ([@sbbmu, #150](https://github.com/kassambara/ggpubr/issues/150)) - Fix in `ggscatter()` to avoid freezing when the `add` argument is incorrect ([@atakanekiz, #135](https://github.com/kassambara/ggpubr/issues/180)). # ggpubr 0.2 ## Bug fixes - P-value for multiple comparisons by group (stat_compare_means()) are now correctly displayed ([@elisheva100, #135](https://github.com/kassambara/ggpubr/issues/135)). # ggpubr 0.1.9 ## Minor changes - ggsci palettes have been updated to add new palettes: nejm, jama, ucscgb, d3, locuszoom, igv, startrek, tron, futurama, simpsons ([@cbrueffer, #118](https://github.com/kassambara/ggpubr/pull/127) ## Bug fixes - The option `ref.group` was only considered when the grouping variable contains more than two levels. In that case, each level is compared against the specified reference group. Now, `ref.group` option is also considereded in two samples mean comparisons ([@OwenDonohoe, #118](https://github.com/kassambara/ggpubr/issues/118)) - Now, `ggqqplot()` reacts to the argument `conf.int.level` ([@vsluydts, #123](https://github.com/kassambara/ggpubr/issues/123) - Added error bar color is now inherited from the main plot ([@JesseRop, #109](https://github.com/kassambara/ggpubr/issues/109) # ggpubr 0.1.8 ## New features - New arguments `bxp.errorbar` added to `ggboxplot()` for adding error bars at the top of the box plots ([@j3ypi, #105](https://github.com/kassambara/ggpubr/issues/105). - New function `stat_pvalue_manual()` for adding p-values generated elswhere ([@achamess, #81](https://github.com/kassambara/ggpubr/issues/81), [@grst, #65](https://github.com/kassambara/ggpubr/issues/65)). ## Minor changes - `alpha`option added to `ggviolin()` [@mtmatter, #77](https://github.com/kassambara/ggpubr/pull/77) - New argument `bracket.size` added to `stat_compare_means()` [@mtmatter, #43](https://github.com/kassambara/ggpubr/issues/43) - Now, the function `stat_cor()` supports R^2 as an option [@philament, #32](https://github.com/kassambara/ggpubr/issues/32) - New argument `position` added in `gghistogram()`. Allowed values include "identity", "stack", "dodge". - New argument `ci` added in `ggerrorplot()` [@abrar-alshaer, #94](https://github.com/kassambara/ggpubr/issues/94) ## Bug fixes - Now, `ggscatter()` can remove the letter 'a' from the legend, when the argument `show.legend.text = FALSE` specified [@atsyplenkov, #106](https://github.com/kassambara/ggpubr/issues/106). - Now, adding a `size` option to ggscatter `add.params` is supported [@retrogenomics, #94](https://github.com/kassambara/ggpubr/issues/53). # ggpubr 0.1.7 ## New features - New function `ggdonutchart()` added. ## Minor changes - Significance levels can be now customized and passed to `stat_compare_means()` ([@jaison75, #45](https://github.com/kassambara/ggpubr/issues/30)). - Editing pdf size is now supported in `ggexport()` ([@JauntyJJS, #45](https://github.com/kassambara/ggpubr/issues/63)). ## Bug fixes - In `ggscatterhist()` the x variable was plotted two times, on both the plot x & y margins, instead of having, as expected, a) the x variable on the main plot x margin and 2) the y variable on the main plot y margin. This has been now fixed. - In previous version, `ggdotchart()` sorted automatically within groups when the `color` argument is specified, even when groups = NULL. This default behaviour has been now removed. Sorting withi groups is performed only when the argument `group` is specified ([@sfeds, #90](https://github.com/kassambara/ggpubr/issues/90)). - Now, `yticks.by` and `xticks.by` work with NAs ([@j3ypi, #89](https://github.com/kassambara/ggpubr/issues/89)). # ggpubr 0.1.6 ## New features - New function `ggballoonplot()` added to visualize a contingency table. - `ggdotchart()` can be now used to plot multiple groups with `position = position_dodge()` ([@ManuelSpinola, #45](https://github.com/kassambara/ggpubr/issues/45)). - New function `ggscatterhist()` to create a scatter plot with marginal histograms, density plots and box plots. - New theme `theme_pubclean()`: a clean theme without axis lines, to direct more attention to the data. - New arguments in `ggarrange()` to customize plot labels ([@G-Thomson, #41](https://github.com/kassambara/ggpubr/issues/38)): - font.label - label.x and label.y - hjust and vjust - New argument `method.args` added to `stat_compare_means()`. A list of additional arguments used for the test method. For example one might use method.args = list(alternative = "greater") for wilcoxon test ([@Nicktz, #41](https://github.com/kassambara/ggpubr/issues/41)). - New argument `symnum.args` added to `stat_compare_means()`. A list of arguments to pass to the function symnum for symbolic number coding of p-values. For example, `symnum.args <- list(cutpoints = c(0, 0.0001, 0.001, 0.01, 0.05, 1), symbols = c("****", "***", "**", "*", "ns"))` - New functions `table_cell_font()` and `table_cell_bg()` to easily access and change the text font and the background of `ggtexttable()` cells ([@ProbleMaker, #29](https://github.com/kassambara/ggpubr/issues/29)). - New argument `numeric.x.axis` in `ggline()`. logical. If TRUE, x axis will be treated as numeric. Default is FALSE. ([@mdphan, #35](https://github.com/kassambara/ggpubr/issues/35)) - New argument `lab.nb.digits` in `ggbarplot()`. Integer indicating the number of decimal places (round) to be used ([#28](https://github.com/kassambara/ggpubr/issues/28)). Example: lab.nb.digits = 2. - New argument `tip.length` in `stat_compare_means()`. Numeric vector with the fraction of total height that the bar goes down to indicate the precise column. Default is 0.03. Can be of same length as the number of comparisons to adjust specifically the tip lenth of each comparison. For example tip.length = c(0.01, 0.03). ## Minor changes - Now `get_legend()` returns NULL when the plot doesn't have legend. ## Bug fixes - Now data argument are supported in `stat_compare_means()` when the option comparisons are specified ([@emcnerny, #48](https://github.com/kassambara/ggpubr/issues/48)) - Now `compare_means()` returns the same p-values as `stat_compare_means()` ([@wydty, #15](https://github.com/kassambara/ggpubr/issues/34)). - `stat_compare_means()` now reacts to label = "p.format" when comparisons specified ([#28](https://github.com/kassambara/ggpubr/issues/28)). - Now, the p.values are displayed correctly when ref.group is not the first group ([@sehufnkjesktgna, #15](https://github.com/kassambara/ggpubr/issues/27)). # ggpubr 0.1.5 ## Minor changes - In `ggpar()`, now `legend.title` can be either a character vector, e.g.: legend.title = "Species" or a list, `legend.title = list(color = "Species", linetype = "Species", shape = "Species")`. - New argument `ellipse.border.remove` in `ggscatter()` to remove ellipse border lines. ```r ggscatter(mtcars, x = "mpg", y = "wt", color = "cyl", ellipse = TRUE, mean.point = TRUE, ellipse.border.remove = TRUE) ``` - In `ggscatter`(), the argument `mean.point` now reacts to fill color. - Support for text justification added in `ggtexttable()` ([@cj-wilson, #15](https://github.com/kassambara/ggpubr/issues/18)) - The function `ggpie()` can now display japanese texts. New argument `font.family` in `ggpie`() and in `ggpar()` ([@tomochan001, #15](https://github.com/kassambara/ggpubr/issues/15)). - Using time on x axis works know with `ggline()` and `ggbarplot()` ([@jcpsantiago, #15](https://github.com/kassambara/ggpubr/issues/17)). ## Bug fixes - `stat_compare_means()` now reacts to `hide.ns` properly. - `drawDetails.splitText()` exported so that the function `ggparagraph()` works properly. - Now, ggpubr functions accept expression for label text - In `ggbarplot()`, now labels correspond to the true size of bars ([@tdelhomme, #15](https://github.com/kassambara/ggpubr/issues/15)). - `stat_compare_means()` now keep the default order of factor levels ([@RoKant, #12](https://github.com/kassambara/ggpubr/issues/12)). # ggpubr 0.1.4 ## New features - New helper functions: - `gradient_color()` and `gradient_color()`: change gradient color and fill palettes. - `clean_theme()`: remove axis lines, ticks, texts and titles. - `get_legend()`: to extract the legend labels from a ggplot object. - `as_ggplot()`: Transform the output of `gridExtra::arrangeGrob()` and `gridExtra::grid.arrange()` to a an object of class ggplot. - `ggtexttable()`: to draw a textual table. - `ggparagraph()`: to draw a paragraph of text. - fill_palette() and color_palette() to change the fill and color palette, respectively. - `annotate_figure()` to annotate (arranged) ggplots. - `text_grob()` to create easily a customized text graphical object. - `background_image()` to add a background image to a ggplot. - New theme function `theme_transparent()` to create a ggplot with transparent background. ## Minor changes - In `gghistogram()`, density curve and rug react to the fill color. - `ggarrange()`: - New argument `àlign` to specify whether graphs in the grid should be horizontally ("h") or vertically ("v") aligned. - New argument `legend` to remove or specify the legend position when arranging multiple plots. - New argument `common.legend` to create a common unique legend for multiple plots. # ggpubr 0.1.3 ## New features - New functions: - `ggarrange()` to arrange multiple ggplots on the same page. - `ggexport()` to export one or multiple ggplots to a file (pdf, eps, png, jpeg). - `ggpaired()` to plot paired data. - `compare_means()` to compare the means of two or multiple groups. Returns a data frame. - `stat_compare_means()` to add p-values and significance levels to plots. - `stat_cor()` to add correlation coefficients with p-values to a scatter plot. - `stat_stars()` to add stars to a scatter plot. - Now, the argument `y` can be a character vector of multiple variables to plot at once. This might be useful in genomic fields to plot the gene expression levels of multiple genes at once. see `ggboxplot()`, `ggdotplot()`, `ggstripchart()`, `ggviolin()`, `ggbarplot()` and `ggline`. - The argument `x` can be a vector of multiple variables in `gghistogram()`, `ggdensity()`, `ggecdf()` and `ggqqplot()`. - New functions to edit ggplot graphical parameters: - `font()` to change the appearance of titles and labels. - `rotate_x_text()` and `rotate_y_text()` to rotate x and y axis texts. - `rotate()` to rotate a ggplot for creating horizontal plot. - `set_palette()` or `change_palette()` to change a ggplot color palette. - `border()` to add/change border lines around a ggplot. - `bgcolor()` to change ggplot panel background color. - `rremove()` to remove a specific component from a ggplot. - `grids()` to add grid lines. - `xscale()` and `yscale()` to change axis scale. - New helper functions: - `facet()` added to create multi-panel plots ([#5](https://github.com/kassambara/ggpubr/issues/5)). - `add_summary()` to add summary statistics. - `ggadd()` to add summary statistics or a geometry onto a ggplot. - New data set added: `gene_citation` - New arguments in `ggpar()`: `x.text.angle` and `y.text.angle` ## Major changes - New arguments in ggpubr functions, see `ggboxplot()`, `ggdotplot()`, `ggstripchart()`, `ggviolin()`, `ggbarplot()` and `ggline`: - `combine` added to combine multiple y variables on the same graph. - `merge` to merge multiple y variables in the same ploting area. - `select` to select which item to display. - `remove` to remove a specific item from a plot. - `order` to order plot items. - `label, font.label, label.select, repel, label.rectangle` to add and customize labels - `facet.by, panel.labs and short.panel.labs`: support for faceting and customization of plot panels - New argument `grouping.vars` in `ggtext()`. Grouping variables to sort the data by, when the user wants to display the top n up/down labels. - New arguments in `theme_pubr()`: - border, - margin, - legend, - x.text.angle ## Minor changes - Now, the argument `palette` Can be also a numeric vector of length(groups); in this case a basic color palette is created using the function `grDevices::palette()`. ## Bug fixes - Now, `ggpar()` reacts to palette when length(palette) = 1 and palette is a color name [#3](https://github.com/kassambara/ggpubr/issues/3). - `ggmaplot()` now handles situations, where there is only upregulated, or downlegulated gnes. # ggpubr 0.1.2 ## New features - New function `get_palette()` to generate a palette of k colors from ggsci palettes, RColorbrewer palettes and custom color palettes. Useful to extend RColorBrewer and ggsci to support more colors. ## Minor changes - Now the `ggpar()` function can handle a list of ggplots. - Now the default legend position is `right`. - New argument `show.legend.text` in the `ggscatter()` function. Use show.legend.text = FALSE to hide text in the legend. - New arguments `title, submain, subtitle, caption, font.submain, font.subtitle, font.caption` in the `ggpar()` function. - New argument `font.family` in `ggscatter()`. ## Bug fixed - The mean within group for `ggdensity` (`gghistogram`) are now shown if data have NA values [@chunkaowang, #1](https://github.com/kassambara/ggpubr/issues/1) # ggpubr 0.1.1 ## New features - New function `ggtext()` for textual annotation. - New argument star.plot in `ggscatter()`. A logical value. If TRUE, a star plot is generated. - New helper function `geom_exec()`. A helper function used by ggpubr functions to execute any geom_xx functions in ggplot2. Useful only when you want to call a geom_xx function without carrying about the arguments to put in `ggplot2::aes()`. - New arguments sort.val and top in `ggbarplot()`. - sort.val: a string specifying whether the value should be sorted. Allowed values are "none" (no sorting), "asc" (for ascending) or "desc" (for descending). - top: a numeric value specifying the number of top elements to be shown. - New function `theme_classic2()` added. Classic theme with axis lines. ## Minor changes - `ggboxplot()`, `ggviolin()`, `ggdotplot()`, `ggstripchart()`, `gghistogram()`, `ggdensity()`, `ggecdf()` and `ggqqplot()` can now handle one single numeric vector. ``` # Example ggboxplot(iris$Sepal.Length) ``` - Now, in `gghistogram()`, when add_density = TRUE, y scale remains = "..count..". - Now, default theme changed to theme_classic2() - Default point size and line size set to NULL # ggpubr 0.1.0 ## Plot one variable - X: Continuous - ggdensity(): Density plot - gghistogram(): Histogram plot - ggecdf(): Empirical cumulative density function - ggqqplot(): QQ plots ## Plot two variables - X & Y: Discrete X and Continuous Y - ggboxplot(): Box plot - ggviolin(): Violin plot - ggdotplot(): Dot plot - ggstripchart(): Stripchart (jitter) - ggbarplot(): Bar plot - ggline(): Line plot - ggerrorplot(): Error plot - ggpie(): Pie chart - ggdotchart(): Cleveland's dot plots ## Plot two continuous variables - ggscatter(): Scatter plot ## Graphical paramters - ggpar(): Change graphical parameters - show_line_type(): Line types available in R - show_point_shapes(): Point shapes available in R - theme_pubr(): Create a publication ready theme - labs_pubr(): Format only plot labels to a publication ready style ## Genomics - ggmaplot(): MA-plot from means and log fold changes ## Data - diff_express: Differential gene expression analysis results ## Other - desc_statby(): Descriptive statistics by groups - stat_chull(): Plot convex hull of a set of points - stat_conf_ellipse(): Plot confidence ellipses - stat_mean(): Draw group mean points ggpubr/MD50000644000176200001440000002712414371467262012072 0ustar liggesusers32c4c621755a28a5a69a4f415b9001eb *DESCRIPTION 2f42f08b736c0b3beba2bec37f722420 *NAMESPACE 973899d5c435a2bead373719b79d3820 *NEWS.md 125098a60f62c2550dfbd33beaa2edd8 *R/add_summary.R e57fdcb77fe4dbc9d71b325b47355cae *R/annotate_figure.R ba1b7e4e08c2d392a3f13ed55d30a353 *R/as_ggplot.R 725d96608ccbabfe8dc4a976106e77e7 *R/as_npc.R 26a7fe18609d3884b39105579279d47f *R/axis_scale.R c1932e81cf6ceadbadf77bdf1eca857f *R/background_image.R 9a9b8226b2cc87dcd94a2e59dc15bd29 *R/bgcolor.R 114cde034f4d99d743db0bfdf5905ed0 *R/border.R 10364a47e2d425f9f09a2fb7ddcc7ad2 *R/compare_means.R a1e91b78bc5db3eb007942de8c39380d *R/create_aes.R 4c2a11a8d347c27c8ec34e395cd18959 *R/desc_statby.R 275ec2e7c56ac0480750a2b44a91e7fe *R/diff_express.R d4a98d1b1805a1a4bcc2e16c94be070e *R/facet.R 407ce69412a97c5a250f7f63a617dfd3 *R/font.R b1679e720e5682f64dd2033a77742dc2 *R/gene_citation.R 014228efba41e00b16fdf6de65c7c634 *R/gene_expression.R 10036c9caf3f6b0c0d715f99bfde94df *R/geom_bracket.R 8f65e43017073ebba38bf5b48671c690 *R/geom_exec.R 0b790668d48bee8b04f848fb8c4ca01b *R/geom_pwc.R e3c3e70812f28ac125a37c81e10f02f5 *R/get_breaks.R 3b546165ee0bf6cdd2cf9ab2951ebece *R/get_coord.R eb1387a58a404ac7b4d1182f07fb03ba *R/get_legend.R ec032bd6450f01654a46bb9fd14dd2b0 *R/get_palette.R 2c11e34739c88370d0acc549cd927417 *R/ggadd.R fa56117dc921a78f4b296ce9d1cbd33c *R/ggadjust_pvalue.R f73ed0fa0698b1ce4fdace252e13437c *R/ggarrange.R 183aaab4cb220e1742fb89fa3eace8e4 *R/ggballoonplot.R 89bcfa770cead0957b262218647ddd55 *R/ggbarplot.R 590027baf321f20bd3aed3afd7def07f *R/ggboxplot.R b7f0ad09179ddcf10258644f3bdaaa74 *R/ggdensity.R bb5d7d7b35ef7bcdcecdc767f9757d82 *R/ggdonutchart.R 540a8effc6ce5d8e7a0a7ceb3a4786c4 *R/ggdotchart.R e94f95d66b1661d36ee9c27ce65bc6f9 *R/ggdotplot.R 4eff1601481fc67086ab0fd48b6d9381 *R/ggecdf.R b7c1c3d539bbf119519791d7e5fd2afd *R/ggerrorplot.R aefaa964f9527a54a29dd3b921736f14 *R/ggexport.R 7a347baf3dedbc9cba7f509248cd1d59 *R/gghistogram.R da55365b5a8430ad831637e94197d219 *R/ggline.R bf8d26a894a28a59c55bb0c6af8a638e *R/ggmaplot.R 6c51ad96729b9c2b925b2751bc540bd6 *R/ggpaired.R ea4720726eacc4bd50ecfd786981560e *R/ggpar.R c22834d90ead909ee04aedd13be844ae *R/ggparagraph.R 99824e5095c1091378e4404ee3766bae *R/ggpie.R 5a19be496575da788e86967f4ea4a772 *R/ggpubr-package.R f5c78594a97dfc8162b4e5660d92bff0 *R/ggpubr_args.R 848c9544fc099d421b3467f44fac1417 *R/ggpubr_options.R f202b54d59235e9cdbb1afd3d385fb39 *R/ggqqplot.R 51d6579079ded68d0acf34e62ba145a7 *R/ggscatter.R 6e44afb0608f997aa7e37c1a44dcc427 *R/ggscatterhist.R 200cc861045bf78b8937b7200e2c772a *R/ggstripchart.R 646add725a8b1e87b85b9da6b6036f9a *R/ggsummarystats.R c330cd0d00f39db822ef158b4966a1dd *R/ggtext.R 738339785f0b220e812e94eca0a5f5dc *R/ggtexttable.R 98b4938c953f478954ed7ea665d70f0d *R/ggviolin.R 8ee878cd07b7a62f32ad9e101d429888 *R/gradient_color.R ebb5f18b9dac96d34566abe36258f37f *R/grids.R e3ad78c6f3241d3ca295e9d70c5291b0 *R/npc_to_data_coord.R ff27c5be5da8b85d52eba404a0bf2686 *R/reexports.R b5e1e020823d44ee399904f993f59c3d *R/rotate.R 4ed6e9393f5878eb83ad918ca9259693 *R/rotate_axis_text.R 345b62b62f3606dfc9371a8ae78a06f1 *R/rremove.R 70d669b417100b87627e33a0bbe60986 *R/set_palette.R 2e971952af167291c1986fe4414c90dd *R/show_line_types.R 2a9f66cdb3087b37761c2b75ab62d3c0 *R/show_point_shapes.R 3a80f467b539f32fb03385b9157d6319 *R/stat_anova_test.R 1d425a406419e84f2c885ad8398d03b6 *R/stat_central_tendency.R 85dd822871eec1de68d71519b2e7e7de *R/stat_chull.R 6cae72e1bbf064bfb85dead4cd8b9ff9 *R/stat_compare_means.R 998e34e5a65501985df96d5bb57be3b5 *R/stat_conf_ellipse.R e4e47afc5d7ce4edde3310b9323c785b *R/stat_cor.R 5ddcc809440850437aec52be056e6246 *R/stat_friedman_test.R 65e599111e52a3b9905d8e2488aef656 *R/stat_kruskal_test.R 8381fe01c14f1860726af5af0c5c39c0 *R/stat_mean.R 8808d0a9f75867b21eca62a06a4e91c9 *R/stat_overlay_normal_density.R 9b860f87472e35d9912debcc4aa8993d *R/stat_pvalue_manual.R ef2ba521894cc55eb64943a062e1c4ac *R/stat_regline_equation.R 3488a4ab96bc8c8694d35edfc3f63f3b *R/stat_stars.R e8f309a16a16cbac5e07f60f96dc5a89 *R/stat_welch_anova_test.R 1ce96e10f61c3b44330f9dcf57c05653 *R/text_grob.R 8098b5e4e0ce34a138c0ff544524f882 *R/theme_pubr.R 675f281c880755a59765703dea24a112 *R/theme_transparent.R 7c3f8044dae674dc40da9e3e8f07c295 *R/utilities.R 8f78488045642b8fc301936d2b836ca9 *R/utilities_base.R 7d8842da561afbcc063beafe5ab75069 *R/utilities_color.R ee5da2d9755af4c6efd30d7a6af7c0bd *R/utilities_label.R 2a34263b798c2374bf077c828e9f4fae *R/utils-aes.R 4fd516686d32f5265ec9fb8d853e5700 *R/utils-geom-signif.R 65cef5e0674056f6fc07dd2b3ca85c13 *R/utils-pipe.R 68972e2b1bff9fcb7967c7dedf6ef028 *R/utils-tidyr.R aa73013d40ed9f8b052e809d89a74e6d *R/utils_stat_test_label.R 9ac3708387cbf6713e6312a57b384697 *README.md 54735e15f7e196d7bb48504609e34b72 *data/diff_express.rda dfc984ddde23ce99f7f91dd4738c818a *data/gene_citation.rda 47cc2b2ead6da9ff1268132ede9c49fd *data/gene_expression.rda f74ed0de009c0309006735d08f20292a *inst/demo-data/housetasks.txt 61ce47096380514bb9d73f2c60ac3dba *inst/images/background-image.png 95da12bc8a4c26706b589790ca44bdda *man/add_summary.Rd 11b255f7313c5f48bca95840c0c3400d *man/annotate_figure.Rd f8b90d4037a68b41a9179c9add0c00b6 *man/as_ggplot.Rd eb92d0da701c049625b4137d60b0a4b5 *man/as_npc.Rd 7f895ad43977a773de629189d10ef890 *man/axis_scale.Rd 4d7bd77a4fca0c1c1f70a85bfe9e76b6 *man/background_image.Rd 044b15d855b96975f04752a6b4e11dd4 *man/bgcolor.Rd 175ed36d928d3f1bb6f4cb233d6a5ac3 *man/border.Rd 87b931b05e4d94945e2829d4e3e26f1b *man/compare_means.Rd 360418355eef29c024e54aecfcda29ab *man/create_aes.Rd 9cb2fe8078b334622dff28ed89de91cd *man/desc_statby.Rd e2602aa9dda2ff3f98d6d9698f0152db *man/diff_express.Rd 5d5886a1ad649f7999a201be7cb5d836 *man/facet.Rd 5f6008ca9934c2097d4b71dcd76ae1a9 *man/font.Rd c2a7bdea8e84ab8b18ece0be21f36f90 *man/gene_citation.Rd 83dea6bc46f9626a5cb1df5d7046c9f5 *man/gene_expression.Rd 3c307087881c1991faf78941b59af59d *man/geom_bracket.Rd 196319aa72acce32fe21e62dfb859341 *man/geom_exec.Rd 96bdd7d294d693e6301da6cebb65f3be *man/geom_pwc.Rd 45d9dad30606ab08aa50b974db90a6dd *man/geom_signif.Rd 4e0fe729227ae8e84328acbbc9a9298c *man/get_breaks.Rd 408b5b36f0fadff9984ac02077060ffd *man/get_coord.Rd 80780b64aab25f62f199efa7d8568be6 *man/get_legend.Rd 7a1204f9e01a4eeeb1f02f1c3610c172 *man/get_palette.Rd 03b9cdd3efbca631cb999033e0e3f27c *man/ggadd.Rd 73e013c29918ff01f2212da0c4098f56 *man/ggadjust_pvalue.Rd b58b1b33df5f3526a936f27aa98282f4 *man/ggarrange.Rd 360e85605af5766b0e4837129d04df8d *man/ggballoonplot.Rd b65e791b8b4eff3a22e55d6d1fb5c21c *man/ggbarplot.Rd 4b005c01f1d43adae8a1adf9a0c88cfd *man/ggboxplot.Rd 33945e48940a62e9707b936c82522b88 *man/ggdensity.Rd 4e0680c56b94cc4b3b19ad28ef9151cd *man/ggdonutchart.Rd d4cbe3192c93028ab6cc0750f2218d30 *man/ggdotchart.Rd 94105cd10322d5a9c96795e47e9e086e *man/ggdotplot.Rd 3c5d568b6edeed60b3747012ae3a534f *man/ggecdf.Rd c53c1542b77d7da740021b5d63150a10 *man/ggerrorplot.Rd 9cf2f66bf5838f600a1914379831380f *man/ggexport.Rd 13d9ff924362cb2f00edb4a40597700d *man/gghistogram.Rd 242a78edd07f877b6f12fc53e3ed3f43 *man/ggline.Rd bd92ec9fec29051e57e90f94d20d0dd8 *man/ggmaplot.Rd ecb02b1bdc8b5aee5de891092d2a1d24 *man/ggpaired.Rd ac33bba83a255d2f0a6b6ad5b25ccf5e *man/ggpar.Rd 9a333f1acfce9588fd66cd3b2db58999 *man/ggparagraph.Rd 550994b6b2c10b1d04a701dcc43fffb6 *man/ggpie.Rd 9041a497cfe02a9d29b9d497adef7894 *man/ggpubr-package.Rd 1caf5e9ade2da3d7880162b959405d48 *man/ggpubr_args.Rd 9a1ec298ac03913c0c945a1db18dd550 *man/ggpubr_options.Rd 75a4ff01456e48e7dd30212d3667a269 *man/ggqqplot.Rd 0367e9179826572ab2a9d08b41f29de3 *man/ggscatter.Rd 437d44c81af0f2d008db7db11b39acba *man/ggscatterhist.Rd c52217ac07abda90158ef77d730b8f28 *man/ggstripchart.Rd e19da2096e436f101837df6b7e191993 *man/ggsummarystats.Rd 3186129357a0f4ed9cb459b4209829e3 *man/ggtext.Rd b711bc3f7a5659e8fffdd960f278fd2c *man/ggtexttable.Rd 6d8b10ebfe3a2809d8eee1ea02b87927 *man/ggviolin.Rd 97a222ce3d3c6c7edb2e1dc59797242d *man/gradient_color.Rd d1754328d307fa955a3f580d843dad74 *man/grids.Rd b16afc70e0ba8094ec72876e3414a000 *man/npc_to_data_coord.Rd 4894ca10756199e25f914bfd34f517b0 *man/pipe.Rd 4323901e20ae0bbe7322d9f3c2097691 *man/reexports.Rd a7b102bc3bf73c40fd37e08fc1447be4 *man/rotate.Rd 6e3ee3838d370c79c5601e654ec57603 *man/rotate_axis_text.Rd 4da4a32f19c8b50ff752a8a94af4210f *man/rremove.Rd e6f941c6058527f25f98352fc18168c9 *man/set_palette.Rd 7fe1ee9654a94ce521e56ac65cf0af3c *man/show_line_types.Rd cf1a0effa04a6dd023e052dc0a9c62f7 *man/show_point_shapes.Rd 37c23ba43b0bc8c3f117a2c3dc05b1bc *man/stat_anova_test.Rd 21b771b74d80a111cef0bdf550689778 *man/stat_central_tendency.Rd 35097cd07b12de2e1cc749fcd673a914 *man/stat_chull.Rd 51d82e99ff42e7f84fd230137d3ee29d *man/stat_compare_means.Rd 4bc1fad663008998b419b314a49c5caf *man/stat_conf_ellipse.Rd 3d4995277b7d0dde03ffd2972b3f2466 *man/stat_cor.Rd ec8f127dbf227a8099e56ba6501230d8 *man/stat_friedman_test.Rd 519b2002f15706a44fff51cf9fe0ae1d *man/stat_kruskal_test.Rd a732b1edb4aa13597e1a2668ff37ef14 *man/stat_mean.Rd 5e800beadd31b8b401bca36d1018e4d6 *man/stat_overlay_normal_density.Rd facc39a60e1e4f0196ccc61e5f6cf7ef *man/stat_pvalue_manual.Rd 1c6a2b39bb0b1ef082ec9d050ac4fe6a *man/stat_regline_equation.Rd 5b9269e5ca77e0e1663713e422dea160 *man/stat_stars.Rd ea917c9ea321e96f2b4038f39e9c7c1a *man/stat_welch_anova_test.Rd 133484c41b74ca68cb74bd76006f33bb *man/text_grob.Rd 33ddf065abc6913970cc6ec1a3f836b7 *man/theme_pubr.Rd dd7941a6f7541c9999701585a3dd4280 *man/theme_transparent.Rd 20c8d0d8028273b16ecca662babe449b *tests/testthat.R 789a6dd41b32e532db58eacaef787a1f *tests/testthat/test-add_stat_label.R db55119e08ff3a3e856bc972717cd000 *tests/testthat/test-as_npc.R 60850481b80673a7361cef6294573a36 *tests/testthat/test-check_data.R e2bae42c6e6709010008fee84ced2717 *tests/testthat/test-compare_means.R 857bca413d3676cd0df97cae160a860c *tests/testthat/test-create_aes.R 64c9506bd39bee98bbda54283d26d7b9 *tests/testthat/test-facet.R b3fdc5cf7d191d0f65bc4ef430c8ba6c *tests/testthat/test-geom_pwc.R 2f1afa333f4593d368ca548e83f4e08b *tests/testthat/test-get_coord.R d16319d063e5a6a138445201ef6c40a0 *tests/testthat/test-ggadjust_pvalue.R d0519f37a341d8214f98c44eac872cbb *tests/testthat/test-ggboxplot.R 737febf28bc054afba476aef2a6178ba *tests/testthat/test-gghistogram.R ad4ea769969d107cecc3dfd6819d85c1 *tests/testthat/test-ggscatter.R 5cd0b9ca3453dd7857ee1c2298c37585 *tests/testthat/test-ggstripchart.R 030872c5571fb9e2501517496e1a9319 *tests/testthat/test-ggtext.R dbfaee47adce8bdeddb3f7b04544a2c2 *tests/testthat/test-stat_anova_test.R 368e3e430736d100d8af08355956dec5 *tests/testthat/test-stat_compare_means.R e51d5cf8db523792ef0da8f8e92be249 *tests/testthat/test-stat_friedman_test.R 06ee1fa27aeec993a213031674582124 *tests/testthat/test-stat_kruskal_test.R 606321f1f48c8aa68b0452c826900e9d *tests/testthat/test-stat_welch_anova_test.R 57acbe714f158a1953b43ab18ab7654c *tests/testthat/test-utils-tidyr.R 37422d1a3da76ceab755a1a96123c006 *tools/README-cleveland-dot-plots-1.png 47d00720c0330a9193c65d66b050355b *tools/README-deviation-graphs-1.png a0fce0dce6ec66d77356ef156712ab27 *tools/README-deviation-graphs-horizontal-1.png a21df7fa5de5d6536bdd057ef980bef5 *tools/README-ggpubr-1.png 2007231376812daad61e76a584992407 *tools/README-ggpubr-2.png 1e62801ec6ea8704794316bbcf16472b *tools/README-ggpubr-box-plot-dot-plots-strip-charts-1.png 9ab794be0051c428926d21eb75d86d91 *tools/README-ggpubr-box-plot-dot-plots-strip-charts-2.png caca637c3e963f897b05f2a24f285e0a *tools/README-ggpubr-box-plot-dot-plots-strip-charts-3.png 95fc75cd9d9eb541d3e386faab82d4ae *tools/README-lollipop-chart-1.png 4e456b85d7fbce79ed4aacd77ec4503e *tools/README-lollipop-chart-deviation-1.png bf8176e56efb084b09650066516203af *tools/README-lollipop-chart-rotate-1.png 17a82f82373023e60df7559760a006e7 *tools/README-ordered-bar-plots-1.png d420e00067630180cac6dc022779ed4d *tools/README-ordered-bar-plots-by-groups-1.png ggpubr/inst/0000755000176200001440000000000014332567004012521 5ustar liggesusersggpubr/inst/demo-data/0000755000176200001440000000000014366561572014367 5ustar liggesusersggpubr/inst/demo-data/housetasks.txt0000644000176200001440000000050514332553656017316 0ustar liggesusers"" "Wife" "Alternating" "Husband" "Jointly" "Laundry" 156 14 2 4 "Main_meal" 124 20 5 4 "Dinner" 77 11 7 13 "Breakfeast" 82 36 15 7 "Tidying" 53 11 1 57 "Dishes" 32 24 4 53 "Shopping" 33 23 9 55 "Official" 12 46 23 15 "Driving" 10 51 75 3 "Finances" 13 13 21 66 "Insurance" 8 1 53 77 "Repairs" 0 3 160 2 "Holidays" 0 1 6 153 ggpubr/inst/images/0000755000176200001440000000000014366561572014001 5ustar liggesusersggpubr/inst/images/background-image.png0000644000176200001440000061572614332553656017724 0ustar liggesusersPNG  IHDR5;<sRGB@IDATx$gtiC!Bx#@x3Ioʮս]fZcܙۦgB& !@$%+3A>■v7N\n%'?GZ~?QumG)6#Rwm۽E)q:I-ۺN^zJmDϰ Tί7(3/O/+TmuM!U]̳;TPHS 7gf*#?S?]Ԃ 57=j|B#cݮ$g]難ZX wKUvBAxnZ#O^Mk;~IZG ،:^Ե嚛v|'`X49~|_^*;Q;459{UڼezG+MLL+8"DCoTOqm*,,VYisVS/UlcT~VoZ6ʭW\ξJO^ݛuJQUZ~p_}ت ];wF%{hl­;i/z_y_@׬8ϩ߷KVw-֎Bw^>?FFFtum`:qpou/yx[٣+ KuS] yx~֔ǥ5*T/;6gfW?l҃[*ZBn(یTZZ\[#^UK=LZ3~z7 5ʭtgZ^k UyF6V:?vQƟv|OUOǠwhK1 ?bRe_}[tBm:ٽt{TqS9]]U-K/?Qg*ܰR#=)Qr`ⓢtcz,Y0UUޒ-޾FQ]]x`^rYaOI6mZ~7*޾Em *?uF=*]9R\b)-kp{p9ՊU?7n*>%FWÛO-VJ^Ns*Q`ynSYi kvVOڵ^Q%ڰ{n\* Gk`t6T -+YwԇS|BR`8K4Z\_+&9Z>xBc@VhhxHkmGW416lSW[/A% U_Tuq]d+9#Yg?(=/K9 tVOokiݮ =\8@|C49:ɽkǻ}-|\n]QXT gLk]wwq_+行a[Ϊ'YXswZQqQ[?rV*ڀUPMi6Я9eE:5?C)[ViM3nu+[BĤV=Ֆ8L,IWhhwQ Ϟpl&YW/^SGS y VKsVp~Reu=OPLEu[7?}ra gt]P29`^U; S-/P-p ASnЛa=2pbQX@]>o[$ ]9~Jy){uy6&vE}vv=Cy5A;ihT_/ mD# $((O2_HBA98?pF473!w-H6<<%p6Ƈ̹xkl_3SR ANQr9A~'كۏ#57,N6 AY} ?&ͩ^y70@6y923i <3z8aS K@ϻgy>@|/'`/AĠB"y3 T3]|Al>r:İx0ПCqM9BB"| \qv2<8*;21΅{A+N`kge/H#2 \x^HC̼S}d(-sWhT,SvPƇ4 qNGhk~=\^ޜ C7*L}O>Qrf 2b9A%2禕zl^:dVݿz[7S֢, Jjw^qVf($[B*@|5 ڴi6S2;gkJM,qo+>6PgrTiZU%˔_08)+_o:[>Ѓz ߸w557nNpFu꫓Zzo)Q;dAe.Hs2¥yR2S0K[|]l];Ty2^q6gsZy(-k5ѻL~AZy=ϓ75Mp\spZ_h'ҩ\{*wQ:H˩+ttft3fSR8|JK+61R[ g 0GuڙjjƷ6Ueaت<(\vKMQjoR\ksLy $8VCg@'z^i 3e\kJ_n]ַ@|$kuZ]\LɢDSVVn\U r lA{?xKk5f&A},ܰ\qѺr2hmf+$,P_yH8Զ6±r`?h&H iݎ֝>\U^ee9I0}OÕBǹ>įŧ%wgxJPJUV?d*es=z~ﹶޣfe2 :iVws_P)>+SKHɖ$_W~8K ݩE Z\xҨj|Y;׵r{<=}(js?6h"ٗ3ӭȨp^<&СuVvGPPw׫h{Mݟ1&j|d CMWWQFi|_ +4lDɤdsg.*>5Ai: 1'\ONPc] Yq]uϴUAd%X귯Vj >`7/HozyUtY(B/'jՖMznJv>@d |e'OM̫h#Z1!-UsdVQ=J"fukZ_jޭ*?_ΫS+7mPR{L_™R¥((ji!r=r17gqR4?}޾~m<@4ºq||mz7鬒3M`ekZ o{Ý\P \sU =9;PRd&yQdu2{VÓgkdI6PJv2rRUq:⩋WZ U%Y˳WAj{Pna]zhfJYnP=Uh9e.ƆڵvMLe-ELb(nJA]wLroᲕ:wjilp^vv|=MQ_գJOVc<{6ȑ\~p*xPϵZ xD 1ҨxYQWN*X@~tK)S5 p/^WSB2( ^\!MtUE7sP8 ";gb!FP-R8U"U˨aG7ax ef-h?ȋ=(`` 1~8DV]/E=GWuS6èR< WϞɃK%[^`  .O}q7CJ4bLjgXLj$;$㔛X-m/9^琢(INݻKYJ(@8*sq_v'u\x~O~Kh[]vЋ#.gkMDJV0{_Q=Ő$E*T/xR~ w>}WӞ 60EEdlpc dORʕ1QUu۴,3lá7a њ?~<^zd ķK΀4$ ScK,z:9~m10M(CS5oK9@l߅ b!w&9Jtұ9dM;([uÚ9l?l/(5'].wV "`_c@VqJOj~V)/|wB8dA/ćs<,E 05a b=o8H"ccUq&ud}' (AD{t9TkF60Ȩ؄dC <څ?+2&8|H)5іl}LF&(?$JLәo'>GM'{ sԊlWXLf Ԗ[.G~:P Բ3,F?*"/\x݁=V 273F@LĬuړ+9S~YJu%ZOo#PFU41$8zovelLQ{횆!srlnE>1Yp M-G~XAiglNחj$c/]Nikb|H3|HIsCPI-H?gOurqlhrrϨiFR[ n7$gR,\}o(o^2qztTWN]Ү9: Oۿ~GZVq{IdNSr45=AɒNiϧoSjɁd!pb#-Vo+&yVgUDA\S:[d R&_Pj>(ą~y~kV@zr8hR8Vub%3ӳMxԓAiFut"!YfAjx:(+p%۶ 春T;2dʻ9oCrax\ޤ v20׻ "+PS6sR@bpaԏ)c╒SӀ|]SFG))0LȧmGvY_4VȷPZ׷Aݟ];,; 7CmM]Coz\Dãc8^Y Z z@r$i6 ]S,<(Eß9ߵ8O?p}=hdmMt2 m*Y} <=`[;q&D)ʩJٿF]]oʀN-/YGO+:6Oo[G)\ 6? ΏߖnghМkb:,pw[ ǚHD:ScD- ťF&RB|-N1 ݩ훚 )D疟ovUp.ZzYc4oPTZ$m|KuQ#ŐV TTPÙ8LMAaҬy8>0ZȘvDamKxA(cSR!AZ1AQ.://2z}-C[**ZXdv|s  D%C[1`C23ZZB֎qSΐM3GF)UKD@S JWmw2 *jksӔ G.|.];MOqd%S\EQƴȢ jPNDt*O k(Iy  5>8mC=p$ilFY"K_V'D1<dpayǷ*@}Us:\PVn.& @M2r)sH *zBe$5tBɽzBJFG!mZn>̋nK}^޾G'){ɦvȂa,1%5ҰT =$mZ;q'0 g OA \8C;Y4Ɍe!N\3M|oչ {q-CYAҙ䦲T? -[ORIn`AY"'W8o!11M6iWΓL\^Bȶ54Pd*4փ;D$eZ|?)JJFеqȱ7uX塿?kd.2ez;p Ar,BPl}IR027~-X zؾ䍰zQvnRE6 -&ay rP`"4~ˆ^ ӓkslCbiThAQN_,ҵhvDd –3p옒v8p/ uv5-Z!gUKGa6ryt>Q0δN'Z0iu3zщHh;DGÁpƵ~k1 ݴQ\Fn#m1tiʐ(tѪ8u`=αҳ`7Zx[eٺ8t/{{kTaHQww4݌E6b]{/~'xGEY[vNB kqjlfGA9IQ -$8VvlDTLbub6 )-s9bʹ lAWuѪZiČʏ&y^ɡ 9z d_Q<;x3c?ùs6yCuN'g$fi%V|NDCiU•TLF|I^{gg]C޸LJC,dƁxMl@ʳF@/=TB#:@'ˤ| *d 954`I0z r騄0TZ; T-.TPN)S<0«'!HGnc5+k4HȐEȨ&jȪ&9@?GGt<5\N@ F ^ÞA偱I!l˩ߌ._Dh!;.[`vK bi,R\n:ONY\ZwU0;S5mΙ`kY$`O=yRVnYkiMhE@ss&xs&[ hx K9EŃAb&Nj2xݽjCMyMHJE,X$Xǒ* ]85yr|:6)2yzy=y/C>9G-r{:Q$g.ƹZV5Ɓ rv" gCbr pz0̚4kɊ5:Ë`DrL1͋am&wrF:w`WȇPΓ C6O3B[bZ -ngoݬSU"#vR)99c|3 yӎ wuooW-6hnp+8agp7w9`e$K֭u1Ҷ/)'PBVE4 p6k"DI,^voyDSӼ_]E&)Do㯚뙆粩=@ N1; لns 2HQ,j.\翦3V09Z^>LmSEd %C"KiYk!dG&Ah0 EK"1}d,*^ Vu8] ́h7ZՎVPěg;kЗ4xߏ~AwcK󠌘3L>0mW[ͯP !r(!psA& ( MC\sRf5&#,}$CmyϿg"Hn*@!P 6PlS"$<ajx)kByj :9i>(?dV,Ó`3V@| \v.+ǔNsisu\1NV.AK0ptr(Ղub|3s=]tZ>1Ƀ vtݝy}@!Bl]>tlgC7W;[ܝd%V%?|;NctVF0dtogr[KHg g֠9t&q2)h}::C$h+ Y |(:s5@oHc~Ϧb NY2j%L/+hwJL^N|sg( h>pWvC ܉ ;srJg;Ɩq*ӊDK!-EcD.DOEFLpoO.[/Q:g"nbiדyQd0iY UK k$By 8qb |U313xG/Ĺ JU^pF`3q1L~vtYۿ~munC!tdQߪRdߧ՜@8frW7->jbF|UpBT@G 36tn^=xhӨs A4TB ՘&TL)=yn6JNwZAi 2mI ٌc ㈤n2ixt==. ^{$=]:Q2%i˃JLNU5r_ϴC>U2Je/PO0?$:') T[ZLDLtJD)Ѥx'EL"DZ\#_l.& Vr~_eKչqs;{L0e&ԁi6>hpMCplK _EkSbn!ma=?3 /޵U 3dkݹdj&^\XRV:e~\@Dvd@پMC MPYDLJOGl넉~ &LRYWu/K`f' W#͇ 2z"v3IFQӹ0ʡBL[`JjL3F{nRZLuQ'<Dm J9hcŌg;QS6RlO9˅'g*F_Ȉuq?o/0۠h&->)6 J y s>ep&9ÙQ~1 &-\m![633p<*Xxvd6ۄ\\cQ1i?ʒzt>- lӬpP6b qhe#5#ld$ }lfsQ6ܭdSlN!k(hbbǡ$^5A3{y9{08TvQA]Z_4jfQTՄMhkA!Pު"1l}=I̔!]W^G}1Vxl/ mdjZFO9d݌@3G´P]Giےp0(JY͍7~UǣҒ̸ddOžZu5 0}Ő Ҧ'n36þauug l sa6ri;4VPHt` dTw?A BhO 6E.tYn_2k=@QwqL^a`fpZb*k |P/_ #y+hf g';zOɰECD޴ #@." gG`0K#G[ٻ:5M]'0;k3N98ǴS/lhݲbGnyIG!0%g!J&Ŕo:ͷ,y c_@[ic.ﱝ硟νܠ_i5 )zzY4C~vq?ଜ%YZоAz@dcojnS0.ԟY^ 2λD l8" 9(]| H9{ETP2ylH`kh022QR+`EO%{!U{oXƤܰNĤ!79v ̭Giftd" d(C\֏6j5qSSh1ngR3±HabӞ,>i2qlh ≠7.^fiGP47OwxkokƏu7$'#O~Zd_ck#N /ji@fa?\Fh#M} EVә\(dJ3h yT^~mZE#+*TΒlKu)fhuDd3ݶ<(߾CKKB:޴jR|9 9=o֢7]Y sA:ӬSlzL)jRf}Ze~}LF9=VCǥLm$;ыОl:ppa1)3;aG|G!P8ttЦM6ZuՙZkn ATctsQ:g/nj"ɀq ' F ˖lcҵu## Z!EmFQ)YzZ^a\̷+)6X/b{zP nC\Tnu9Jv )$Ǹkvk<Sj;)#N?/b{֑mxgJFt%*[JL랽)_xi%ꋗL !qYOV;WEhUq*u{:-˜h^bٺ@6}74t`oo݄6ƒ1OQɟm>i/ '-=T.! ",fƉCiYȤe$:i2TTt' `} k{銄UWA a~t=`3 o93=7ȈkLIf3,JƦǓґts )Єt3"kf~oq$/`iM4YܚH`Nu`8KKJ( ḨyHnњ݃ .L]iuQ4(L40)9`gBhKGY;8V]%&ZAj=%b=›H}Ha]tJ{E` G Bԍ#(;̒ãx T' H|kuS-3#7/qK(=*k|р!ߕ@IDAT.VlP5&!V|O,Fkɿ[^@v'-1Yc6͐wkd (̍h=8}/y]FGDHvýIT llB2AzN7_ѫoCrx2`2Zoz3.}O_jѺּͭ LZzY5 eJ$$^YeAIPd]Z'm+.=C1Li),gzR8'Zn=RK!9{`PB{vi=t̚AP;Zk#cBD O=Ѫ/ P+uE 2`͵dmcX]ᅪ aLgXxn;[ Mf@u17F8ݬ# fFXD.{65x-nciIO8Îϙ(KDC2yxy(t@Y"5=Y cNUifw/;; JAנ@0ul 72[iK]E%9ߋ!2ҶClsz\%i$r3q~?޴v+<% r UcF͂^fgW;D+1ќ0y 1A7g-Rnt__ R#c<\f%Z׋f=CvkEaF (N>XYTeAt^)fY ;I4$1 Ȉ6*h@YJ'uJu{Z(щȔ+oAM03l׀Ӭ66^Eh ï he^|F˭3Kv1yTоkV||6U8vW h3/'1?Ss? EVϹCR%M,MgZ{uD>{efN!\;ц.2ejK>3sju/˾*姠 `Hnϻ?cݿ@HI?_DdO wkcW d)4pҪ`Gw*kۯt?ELr浈 2qaf# 8!s0 L:y8A4F8:pDe,/o,L[Yc&`yfɜa[ða6d3skb^={1ĩOs.>L_#k@,c,2i6-1:9~3S;F7*aaG45Q0qb)yHktzM:@Ǯ{ahXszFOfެFcF]qhB؅vxE0, "<])s5P;bڛa$9jﳂ%#gb5t{^ZnmVG 0j\b! zJ{#26aF~thW5aqn:R&iQpoEYxd7] g. r3Oix0O1o[]Ö,\Hh6wz.2alB–ỉtY3kiV){#~LNbUNc}8ETXyl7 ~_}`h֘饛PQ| 7? G|}PO;wCP&^D2x&}F:M{DUDd⋖xfţlD4K}C rNeƋ_3oPD $l12f4B_^%nD8#|-O>CXEss_=ctw Nܹ5=`]#6U8[,|"u3n~ rd.̆8p$!OkXF=y |͗~s ([@VLǥS7& ƭX+ܟRR#Oc$_J-Jpi֦5^mkz1'1#z$o:A|gOޣbbmyz Fdڡ qu յet._QB@sQz{FHCb֠S= }#3;^q6JYtZi[;{ P,-u1Cv4WA FmHʺwZukbزd`튛C0۔ށ~:% Np'j4t.8..,?6J/HAk ${ľ8c$dء^foKy|]]Z7?RFehhѠ '4 4p[)?v!4*TK62&rvC.`Ă8M6h As+R⛒E7dz{{g{> ?B‰ؘT* J0Y 4I+DkLMk2V\+@4O 0zR dѲ"~X {lلH,@] M|%]B"[N{5[mqRHN0mV q`)?Zՙ'`͘o~μYoa$unjff@ mtۅ*j@3?$"ALew4Ği#7}O0-YRF¨(L67͐9#qq:=PcB xȤ]j @d2MV4cFjjy>,f?@"qZ5tk4)zSqAsEL2НWxDd1$QXtK$' e $6g45Y3%$FZBf&{4XpCZ3Dn - D؈84,o,nicHZ qՖ[ְ$%zc^@i _j>Z2LY?}=!+tD^'&%ΖJЇ;7h3Ӂ膀%PT Ne2[rKkM^|ϬQ~b3$B$qGR{XyJ翻L>|:1 Lׁd.8^QlaE&*6?ux?g"4C3(D&'|,t}[(uwE!\tj-ӗX^Ԃȋ0mT%76n &E@$ UڍkiͩN"31L݃9c>pnӁnpȾ,eS17.umn>Y 6!f!L.?dއOeōތ'J hgn0S&esdڀX[7>ְ~ΨJ3= y̰ 3fg٦9΃?"`"{cK%Y\4.o.ʬ]pZ- -i~ 71̜ -I.ݔX R~Hlˌ9p*{,^Rs,!A&-Z⚘FL3MD1ctA4(XB0ސ}/?E,d.^x,27e 1Ee7d6ra~pR !6!l |ㄸ,s&[ Cj7 )V y󳕜jܖ*o1 .Kgq~@{Γ}Z?iR1$0UYWNe>?L%缟 03Ɏg2?5Ũ>L>=w0{Cx::Zc6j~pXL 6=c".v4%㾴S#1Lؔ5Ye1  s?M;FAXc8^DGB8ALy s/'@`Sl1q Q'®TPq૴yĎ)Y ΍$N"5kɶ&Xg1Um)M&Pyl e\q^2`E6n/anWԚ U;6TւbІ62qk`&@MAwem9M=3.S.c؎'%Y?wM9YhD& ܄B6(Ad )ӟ~DDTjg)/u'أ>4 ̟nZ3!\}A^Dq+c "A5eD#wUN#kRtElS% ԸHrذ=2Ӡ}"&oi6*9@a^0F3 6Xcs\'u]$q1[ۖu#-Ј( {0d˞'㛺iMV^JI2<֚uat·مPTs̘E,wPgG9H@ @Hl[mwggwOU[jkk3nٖeeȒ! r9縿Μ>=ypu݀;.$3 r_t Kj)8KQfȢC!DŽ"U#ؽdNaaC.M>_GqRԤW۵5ud8ʟʴX| }|ZeaA[4il gEZE8\Jֱ̚A>{6Y&? kPQ`Iث%3/0U5AcΙQ$`] bˌQ)٨gu&}ǔ \Σߐq.N xuupfAg$٥ٟȲBj_=X94ܚ)-wK(}kV%d` '^~?<Prj(8y x<~()@ 8[9at&Y;WӀ3E%INZHkmM;ҼUw7CVodwA<ߐ%"4VHb:2s1awzaB/H{&;n]meQqxy(ΏX͒ QP$BL, k~0j$seH("ؑ4CD'J:?=&wa%m"#SHO@)38wnV!#78t@H۟`L[K3u7", pZQ;2 E,1%J?+@2%\bG_\P5V"=oS LB s.(3,.7N!yi7*PJZMX,όȼ p%" ʹ򘨌㋱Wg0 '#0NBmA*l/?G)w^R9<T >AG @dT<R\gٺyI[K(aMPFp)[?o?OֈF@X=·g=H . þ pk& !ArryO%[33R8*nk[zƿǯQ!ķ0Y(<=4!mIzsΛF{ŶΑVSF HIn">*{@, RH3˻N2dwv;8 F*+·*)yz1񓇳 d k"i/ חS=c_a.ؐpE$Hd#UX'?~Y倳D[Ƅkݫ>;MJK0JUJ;0~4W%3]9Yu %?9l|82G.~LNLlTE0mYH+]nGeB ȽxDzUgv3%$Ђ`(Kyxlт sF3PWɤ\Dt3ʆ @tomP 5)G֭@۱Njn2 A tR&/t[ƛQwh|!*}"kQ1ޣdhY"}w_h=&9%L$^XŪQpfW~DWyse(P6-YtrbR+)OU}>-(Ĉ8nl$SXAD %pK(PmlߊQ*|V[8N*DuAeFDRJ%(lP<`[~I{`$@2J4cO0Kf!' MTƖ xϱ+MVOL6`%=AhC&ʗs& Kǿd*L)ⅯhL+zG561xFW~p>TD%X*V[;CN\ik/NʮdJv CJpُ1Nq&ӌx˴NWB)?EC#TF@YUdB- 5:;p̺Ƃ$l0>}aStޮ8'/pP2z,N"`$w@a3略#$iRJ!S*J,T[Oԋb ?/_QSK⻯3"JPV=* 3+AƑ8m/(+x(iq DV7Ke""U"114Mp#%n'Xb&ɠS0}#˴ÂqdY{ ~ @u0%Q6I9`w. /} zpsD-8~ vkTOȔ &4.SFezgȨ4ö1بZ|7Hevʤ ~mޗ-H.kK&-L\8=R]ȟN#SfKIB[WOs/mGw1r5R}ivIݿz&0.u?k31I{?܂87.k5LЬ}QؽQZiE9|BJ=;ynƨ:z0ɭL1NTRd{pn 7t؇jzwR>?+e072(ݍi֏cQKx 4cOԲš$<'d@ S#Wq\Jvq;NjȉWepp'&T٠h@YhK"+IyYC}r06%Ztt(ɰh"۠uoHg_?oMG*Gn B^2 AD"{Mã"Vh]_y$Y;\CмPֲiX\'=ɐs5g[BųOQuo[3x e3P1*)iXg*2Ҝ-#V@n#325Aݑ;dh< 6 u bݔ'::cS)7wq4WV1DS~N,ɓ_2$r+و1"i甭a/#pSՆ='{=cslゲ ѮO171)dL=G5sP޾~I tu%I@Rz!^w[ A/AGnK~WoHw0 *Cw}xpQH7= ,RAQ3 :mjWuvh73¥/D%$L S2:IV=σD/Fp+EJvޟ^sL@ס.&At#$[a2:i U^3&C 2g@yAC}[!zcazY'*gDjf d?riGIjAF5>;a.AW,zyYӝBlF2ADnQ cV>%}~?Lg {$Hi%  ЧSBY%|(?6iM? :_k9P\aECiDaX ͪ3Qqy9%xÈξ( O|Y.=u\Z2b)8&<<.]I @\4Txy0xO3ܩVdt)|"ꎞ=OaF0Ϧ8Q"ʁ;ْz2ٯ>_nc I!Fd Ez'7RRW칈Q#~euҺJ N_S> \wﲧȳןBpz>}$d7_blDNDrL5BȦR7pDrtsÏbw1، n VI۽?*L+d ''ҙV"Q-2l s[wukC#C٩Ek=.stC 8 c[ZL7MhOٟb +fDq(Omh*hU9ܻjYTbjvsYmW,רl-x.>pp"a696`ֺG>*Eյ)UYz:њxJ/BUG\,Qk8 v|G`O*;(\in~wj[po}eLb T\~9n7/4;23Yc[%,6e/4Ӑz+~x@G'NMU /`8%/2(w'DR ]>ӊLedF1/5 s 4ZkI !سƙTԛWp@80 >~H3z[A)}a-$!MdŜi1 M 9H,mDJ=T0C!٨YL&]V39W)q(*/Yp-b&Fo_2eL4 y4~K&>țWHfP"G{L?Pݦ3x`\88rwm(Ռʾ4+8#!b:)2u| 22i|j{&ۑPٱ(DŽs.p#.0ZeL'G=g~ rL4|/Y=6`UG Ш>~'H"g<4>41S|-D0&We QB XEWсm5VӲJpDy2V{B5|8tA{ALu߅g:ĂЊJ%2OT,Ӱ{y; !bR~WO 'N` ofp*;Ȭl'֋ꭞa810ssاR=%\pj@7lCpo%l[`NS("UҪF +k {,R  ڣj鏷ԞCT*|RH$9ݔgNJN2AӐR sY sn bdo#!u;XcΎPj!ĚUS="HdLه„/^Q>\+xB^dB}w_J&#"R# lvu` !Njp@joAzKFl$ WokwaC篺ZBU;; ,iYm%L)obLOu1n#Ce(!Gmhx uM%K/Ϫ$kP@wwk8;2N\a> XS-2$H3^-x qjn`#> :vNhlLlGKb ~/;$ɛ^BJ##Z$Fzy^^$~nyx~&I mډ=&&]z׮}"A*K:Fbw욤f'P\k*k3h0\qKŽls UU*|ǞLw3mt& Ш[aO{A!M#NS&&`X$z`^ڊE8Ke,!ʥR #,+]TՅӍH) qIdDx* *.+l'En2Z{px*537!ʉMJ`\Sn4N#R27Q);'Fޮ/EqA]Ŕ3ޥ@FnusDf /)W¹1FVh՟]xX7a\V2U3%.s]Dk m@%X$ T>= Yk?譓6!Q\PVO( rX)wEYqEq '@Jʹ'<.J}4WY6-=ef0Jo[-]j?̻N* _Jjt .GkUض6wQBnQ_i1ƍLl,UY'bƥ$:0 ϏaSV6zYVme kjg TxLЛޛ.z;;@"Ae፦Z+f+&bxYv@WC0&t9 WS'1(B4`ҷ/pvuڕ{QvPzԟK5ZUE,eӺ/߱+OE(NǘG//uv Yo)hY/ŝ\4> w)j6o[xTz#`i7?@NA, b04<Yn^HA$@#m.*g0`՟#^']wpQ$*|LfIjƩPVԿWޣc/K6 ( D!>=,!=HW5YMwĖ4JnL6_x0;qx;KT|ȃBXtz2Q<%bZaJ%XZ9fGfbVG=b o-X!P;rӹ=4@=N;Rb6AI!gB2 _ [ O@PABt!.К{, Qo!=́/% Ս_%oT|%F) 8,<Y=L22ԉO#wƊ^SLx~m85"к!j@fV(ɻ(_o9٭S6>қw,ĆjWwܥyv@s.57[b:wQt/@5o^,>me1鷲u6cy :;H:hB,ߧh5_TϠ_\f;<3)){E{4CJ"xqW>jCnf3by.p(rRngM+#,ZKj m':!!W3a~]wD=Ѯ}E&QI[:c[[Dt/:{b&Ced= ڝNLm1 TČAƈU XebSxyNPwg"\mWz/,',G;\G)k˜ˬqrd-!ǀFPX_2EZJ+ BǧHg:͙4>~.06ٕy5Y+G63cxD ]N hMƟ%Pzv\yfp, ؈,ui88 a*1Kf%:a QGcrgģ72 .+3RFy"ip\am/DM ImogD0Z& "Sx ³XtKt4~!8%К,qŎh;rWKXS]繈6Ewb!ӄ-xSJina.x@ikpYJ2؅=dHV}{аk b[{ԣ"$)wFF j 7Rn32گ|2,{Y8A2FpxdC(qAfWbb~.;w鱇L{%s1L  0lJ?D[P_F +XcoE Va(KLW&gfrlQu1*PP ў:26S 0aIAHe(e-/L "Q:Y L2 Vq,f`X1pFn*)kz a)! Albnh0%hJR&e3\mڏ;YK/_TBw} !C\=,w0B'XJs 0K{~rD\ĬmEGET -B#޳ tvEEqowt1hs'Vh70V>9LaTV*z퐰,ɨpٞD^޽`"IUɂPد'8ʗ)5dj/6w5' K BUL>B>840FА8ogS4 > P-f??Dߋ (“x;[߫Wsx_dgz5x h h+1!Ỳ1Cψh`Vh6h3\dZ GYok  vF v#{C/7`7YNӿ&TUV`$Mpjnחp['/ LHb>!$bxv#wX6C@cb~W@V9Xҋ֠9pZxNXQ'>?fE]mtbFw?죘-ՂeoWV-NRya1`] mSTL-_* !?!V+kK؅&)MLN]CP=<<g4F5 t̸Ȃ\6h#%#_a D1m4#Hĭ;TS]-8>k^8e'V^W~{nL&pZBΈ0dIT֥OК : +}!S'FFͿ?`0 ՠU92!5ER`.'1UDUL/0{!p&XIJb]b\"A*WsmNMzblIPa5O{le8]_e8/JD}6 R̳_^ۥ$sy,] 'X\}cVHJ\QP~[P9(%oHS繬c>8s98#$d'U;0p?/1 ֽA'],/Oot]Fmrۆf9zx+.FdDgo7U9JLL+J GdmD{`E/nT"Y5 4 EE@%\W:diXX\a rm_@x ZO`7NŴE̢Xg!pV53UA6 .U;Ѕwf$`$JfLZVuuS!e$GÂaa m#Jdrq!#VMn%jxmR0F%* h/?<KB2Ok`Z]_ Vv0:j:FbWO@ONbLY.T̤#[ xa_ k?x<<OP0E+1;>\ɻzu'%{%FP0,"?G?$*Ψٷ90lM0\3#!M (ƓՉG5`.!,,a|p5@s :w/9ټg 1)`Z_ 569tcFvyBEpf6*9=E wxdsRa ~]ڼ.E@&xt$NUǤ .j7`}MT6,ZD^ơl'"񽘶d 3*{!4?_L:!%qɀK?s{2q$L@KqzhdhiaXhKn)pN͂3QCp=ܼږ7Q2&*! Y -©w?; _<\%ꎈ:ի/s@IDATRpֶ/1k.eX%.Vyp)@_d]j_SΝbJV?0G$ @(}Z/ objN۔}hFeq>cuq00pj [  CZw%P(&VTKAؼhӎiF*-c=B4 |eRcF2"+B*2&Kbsw|G9iTʞ8Ջ3J:{锖B҉EhD2{y{T-qNb $۲dx٣XY~1/=g 0"9dnܻd87c[Vϝa!\v2ja@RCظ>L~ (o;SN *d!0`߁:v)H,RFCvnRδPi9{ӎBKlbB2QzFĐB0CȃU6 m%t L`ʅ VpwW".Jd^UW& PwCE}WzC}K%~}5F.n|~5aAݭQxfoYXQ|t`H>-009p5DqDAIŶN^.1{ ڏA=wF~O7U}]';'P_#cKx+ ߜL%TC}/i _ )i( 2@y-UOBa8HMkfy 1!TF8䥕x V RNQvIaۓ>H6U=$+TvZzZ>"#T -Af0ۂYI>&zbLfgGoU?$=NR _&3!0{5& ;4OQ@q_RNUSa;US(Nkb.tM@H ,LR 0o?3-ҖG DG"Vu)S̆!Z'QZYTV[TE +O\AdTSUZƙ%%صEY-pbqe2zzx}';σ>B]H)2Ik)݄ZFd$YydbzXGYe-+p.3aGu T\;t<|bF\> Red^4Ed |' i<)hiޢ4pn ~߾4#| D1ba඙"HB&:H*bn:cv\)e'F1eoo&t7Փ1HN$4JFASL`H0! Ğ@eߛ:23`} + ^:0ǂ2X Aj :3X\r@+]߇ b{Zn, C´ߌL?$ eڹ=[}D*IUJ'z#e  SS%gLfUgS}_+K s~ Y0  bR~ƞ[,h!,!]h%Z5SNe٩ e_ù\vKLU!a"(b"oH(љsMx#men*}$SKH/`Xw<"")=*.WoMy|SAJ< Vʶ~hƜ᧌{5^1̔#fG$s #W֯_ޏsCI`g"X1F}KU"}{OągVU߁)> Y\E5e| ^$D8G"1AS7"QU0- :{II'-7.Q+`1i[=BQ" ^y96s7E]Y&H!!^(Wj*ި=99:"Ŧ)D(s5eZ,X[:kw1y<sOzk0+37jh3x ]Q?!Ƌcx({OzO,N`rӬB`@ D%*C+ţQ6yY5{ᦫwqYdl&3v{ʹ,&!e:p%8.38ʜ'U F~Y#ʿ.b@ϻ-TR껃߹w•s&@&`d*U~Kb2BE#,KIg2峬"^&b5Db&;;, v+ Z#U,$WwW)A"*@p]K(ƸTjYdw͟(<,-z$!:ŕ0jT6@Q!bVyG⪲dUT` M,‚?>RV SM/Ыa_j*ZXB(d1x}ǒ2{< "#V+I%gvĥEv X;XsF!Jj"?O*=355u5vivL! 8a+<:K$y 0,.@91Iç/}6=~PK_it:`Bw E1,A25 _oF-A3c$%ܤ}w[҄l( (OFtBy09EC t~ƹH w_);n.Ms`My %&H:FBE{'EU(ӺWMpAS0C@?Iu|x~J pr| S>Y@Lo W]P@}ȸ"oKJ&s-iFg^WB/񱬧]&P)dSC+t+\ґU# k`,.'LAkPq>W4VP3e_dz+> ;1x~^uؑ2u'L ~.|M% K6~-dUͿȹ\ہ2R92rE";E4lP32;NT0A͂yzh.R6ɹ,ÓĎ؀Fn']B,ՓohLNՆpޑwM倸r`|l#|( ϔJArt]mR99}I c=܁GV`o&F){; +V~Zʗr'!=U[ vYHe uKa(*_'u5|p3R\X/Edڛ9bEK頮xٖvjrn~yD hޭj.mT[0sEl(M^\ mY @U*gt%Ҷk/Q^RH/KlJ(꠿+\3eW\^Nr@ŲŖB)>PI4h̅6jgo~Wm+"y5^Sz4I$7L)zaz1KzjG! @Z"%z>+.4l,7'R #RlĖeC-1J4 e6b?n[|)ҧǃx[`ZYXJiJ#HwbIАHL+-'9zӿV+Rlz8.O$8ԚϤ $vZ3 z|$[weRasA84Z2r%#6@'?{]|@H/ux/2B[9_9IP& ʎH %>y3)kB{%6eEKCH_3rx~%xT)z HgpV=et.J p\@З8,8Rhu.K]w; Z:M0wf>Buj/4+&܂Ɂ\^au0R9w45^GGQ]tuSWjXځ-< FP`=ofo6XJ_Spq얩xIZ;-hٱT@ `EU݉ ީ')HXPK 18qO@"y"GwS^e3kԤ}g!)YCv*wں8/l80i'޼l⼘2b3[=%粗ȗEx_vuPUWa7nZh*f4 {d ʆfLŜUnjt>YY9EŽwŖ5 v̩Eh.OV?>Zv-"耑P1>L7'sx6@hFpoo9 I3vl!ٰٚKsǗukv䖷&+%/,XM K4;-8D\0S{ZѾK͡g`C a;dԾlsOp)ZYYM(ŖjIeRzY<;hK@  a<Sn8%'fHEV,/Jrl`@9 h my gC)Ŏs/Z ɬQ# p-* ?xgT[@[fh{~Fa&Za3V TY3);M1$R !p@ڙEczdTͯiT(]pyYFKm0ffT4kL6,oܬC=8  #a_@Yhl]0l!I!k3Xs´Iv[x`!O}ME5(NͰn5pgP,08`)1m+T\|jnPFFQW<rG/w;zUK%6Zi,[62iA@fǘҐ1><6MMxV_fHLL+T#}=$RZt*@{1G$lDA<*"@wlzZ{%L&@8>CJ/g!lXΡ,8~fp>PXٰ {Pi ]2K#b`݃}{;J_1b3ǿD.٫eD^3h9Ƙ Hx]A9 &r^^cfaM[ȸt\"loWh4g~oB\w'/YmAb;GVݍ 9@e3CJu=ߞp?Y#4?D!1<mws"{)YQzڏ9-`'wCU.QT`RӔ yE7uq= g/]|yvR :ʹ18N尴"+xC=q<*VzPMu;[ D1W7*UN#XǽPIkHvf.r]*4Ÿ1x J@oYZ'-TKuxq@^O{x:%{*(+]-$ QgUa`Ts^J V[T®.Ba 3wdCWC uq!;]:JxM62  Pcb ODm'*E؀6c =| !ȅjjMt&e27P1u"+AAC7'^Ao6,$ӟsP14yD L2g2kC|\?7~a>c)uqS >fÔLM+ԡmU;RS)u$%^43wN+jK; 7?Ս?>OŰv'[{z!O<pZģJSeݜӡ~KC# ScBJe,VgB0(pӰ1d&p/~Ko4r!$%1W }o)ECF;j('nyvZ-򩇕(~xI)7`$2E_??Q 0߯ jV.,l~" $d;M|&wc]!L ȍo,|ti2 ݫ*.*Ń{먦hW)(&8/_Rд34ÒV 켦.G;b'r]-1la*F@| A`$%T0V|ng WfTOO2*vsGxzM3,pN}XBO"c431WPe[X`'@t fv65 >¯nm]&>}#kX&$ĽzVd~3P@&ekxmK{Rgv?{ð'jt9`Ϙ'|XI&,)xw`qD`b{k0Pd2@;Cc?~4cD< Cp85Uo8԰nuQ;d{V ϓ s(?;|75oQuEpch>9sj6RiQUI7 Z,.zf;ybPbpA+,8|# (Z %Wۏ}8]dy6IOm .;*=]bM~C6%A\J:zJS;X3SxlG* s:W_^˿_?y☖Ӳ3 && L.(;mT +Go2j;%/r`߅_A0^%0R}@ȹS6ZA,ٸ sL?x/-k=gOA$󿑔D@իLx|##74~f'g)^3xW=t}K Zqn*,Qgn*nl 7b YόnFw pw;X{yj}ßoR/Wpė*,LJ f-xT i;dT rHƑ+Kd2,OU(&V@ۜ:Y~ ̯>q)׆z{ W2)g6BN)(qJNܝe,:K:!\7E3 O/9d|uHJL9g]>08@fL\@p9;w!~'t󩀘6ڗ×s_G8 Klxˤ`6h L%<4*%Ή<~w__uuKb&)a=S k,Ɖ@]N&\=/# &IdPRXaѱ<(L'lڋ=w.>=t@ݽ~K;Tnˮq2+O7zg^$e||k峅J +ZlQN.S&fer9 d;B=[ԅ|0d TTپL/+ލղVok7 !u==9k2*C'"~t;XxmFSsm]-DO'f!MYȼس2?Ë'X|S{a"595zE8EZl/a觻`3<P]{QxS՟߿f ԐԼŸ7=|, #>.횘zd@X4uLav簁 PYel?90!}[0bk(~G#*srPXOO~1RNwaP %nM{4_D@^zkO ;DžfZap[BKUFժltkSF,saԎ -\ܤ`K޽GV|f܊roAf,$|Z B# \Lm5{)Q, I 26!HA&&0N2a%Ro u4BB,u.By.iuq:m8\z{)3"w $KtkkAۛ1! Gmz:5mQyj.,s/ YHRfQqK53a", -u|!d;H[y *c>f.zA-dBjyq ӳzq"> B0Fxg4cCWZ:~3 n~L!T+$bZJYn`(}s~˗W$|8D[Lp ovs'gC > /A'd!X~ x&">u."GY9ʌi*gCcB"L? @ Uڕ1e LVӦʟE/4R~C~Y #j5㣓(_ͅ ? Gg5vgPjA3|rA$ L3y9&']:G{ΒFV= p/f^H{Aޢ*PwƟ _` .W$aͯn[)P m$ȯMooz{O0Hd\D ^e g]dޚfmr%bRԉ/PSݾ~KMa L壬 'FfĦS |//81Dh(\f~^p}ul%26Q_OjQ=刳jWW[,\J G$37!򭨹xFTt<8&MFdr{UT>juqzzJS1 5 8ʚL$l%$VL0 p61 Ծ2fݥDž;f %IHÃÉwƖ#+>#? +r-DxE%;-X&d $EUngI]7`VػX_v3PJ. #IhdiG)ڀ U? ! ;{<ʔ~y{=\2d@> NM]IC$ͫƮ ua457UD0i?S #CTxd1'wNySJV4HcXp)]geluAuao=i;Z]/*2Ec^UϵkE Gt} T~1uy,L: 6Y$XZ!=\r\taZMzg;Qvӕ'd`܆a29CոE/37%V*ښG0b.xJqWT@7s*P7:9nv&W.99݃{7_`\Oro=}azÿGǪ ‘`9dT𐖉={iY܁6cé2@4a*Qe7C!ʼR=;S%<2q"]TYg, jeq'X"xsw{Mmbi UB/$)U#A4@(.!< sVꚜ8xy9z6rʆ|k.w4  rh#jg}.; aaK=gcA!"ul\]Sɧ lKgh٪PZd zb 疆&0`$芬Vdy&XQ] gNH`}UR2h*AYzO&,Dމp-*e.G9ǵg0 B%r|_ZA{8ejnN٤ ȁ} w=NSٻ<@ܧCyY^C|}踥<8tȱj(X%p@zb}e]Qh} K$1&Pyik_Gk[f8m]ݴfC2L`J.)hHD&=üsq/5PJ9斖PP?sJGFU t$ w5p LDNN,P-*6+/V0y@\>NJO@8)m VhZxK,jGjPQKA+,XYgڔ.4ʼn *)q[\M:I[HJLnϲG;a& ANL6`xNfE:q.<.dLR"qN M!207Zh58 OsB* ˓۝)FXsʜ ڔ}|*N,2e,bD5#s#%(Rb/#x 0! T]gNX(tyNWߵLx|qfsz9$`2<*sWN$$1$s|.)Lkc7=q kp@&m꿊GNF+ $ zW+[G"ŁARf_ɤo0%vYuJfx-p57lb0 =MR]Gg+2l.t',nb3\\܊Md-Qka:{s<@IDAT <,`2 y@Jsa.iy`6+55=tTSVB#،ܧhIs_Y[7RK;dP -,^xK٤aVzyQgn񊢋᩼<$,!6Ńg-:=ԚgfǙ#ZU%A78Dȍ% _!c:n A/0+XZº7#,E_Zinal#|R}o"!]$d's8d OPU"Cޙ9sog)ZmLDsmm;'Cy0gxp,A"sUZfFQ&s?~*sqfT6Ԫ99Z8#;79QWXƒSSCy'YP:_V̳q'K4tCЩH0|͠{G2*բ=MT\_K; ?u)]~`g9&ܥD6RH$L9{Ń^Vj)KyuL|94!3Ҕ̺aeؓ@W Ge1@J?z3baCDbHH;qɬPƟ:` ERBw VM2b /ئ!Ym$%XC0s+c֙#NM\ ȳc(;K'2,yܷ! 5aCfY$,WHA|?8WN~Rig*P1H;D?Og@v&Zծs,)J' k$,<vi"8#MMoZ@%<7iY-&czھ8Ȣ8@ԆSƢȅk Aᇿ~A1scN [0nNnۻ:WA{ww.Em]2DG2$}+B1Z"bxDGk&nCc^<]/Pڃ|;MwNbaK42TEwL}?E-}a .hppI(ҋa N׏ G-ݧZ/b C 5?a>9װSXH=NU6h ^}/̇?az ìtARP8*x|  kk痔">~4~ߊ:$Ⓐ<9c^=]eObah7z젯v]r_NkM+pNe0%OZ hƳ)3o420z_B-HW]i]C{ GѰJRo࣫~{Njؕ1D0Pi!PNd9*pԇԊ ,mֵÏRpBƉ.h|g=cA&:DZ\]7{a6f8KY#@eZrZ|TB¢);U# Y1!R"$xjd،ʬ lH.\cc tk}`0NZ52J NV^Μ;?ڏ1ʀ9鎼@*}ȪTL 5W6OqӢ #"={HМ4]UsWG;ޓ~V xN],ŏXMwy|48ΛtEԃ^"&1f>xz gLAXiS O;l['3o $#ZrD4`Z$< "(ɣrwĜPJ@P ꠜk>1[{۲{o3s =XsL7;? *30%{'s U֦79:ھ8.@Ճ<[eRai9-#6@7b V̼,ƞZMg"CL2zM5B[Ev փ_uTҴ 7@DzhYfn/> [ovi2mSߗ2,M6%/{4#2EU*Uw(}d s5bv^~jy^Q &x4 ПXxCNjX7^NĢfVdT+ AndieÎ ͻ@p7w+o"^Kew(=kHʼn3l+hʪ_e% .xEiՁncq*9_~1 'bU 0\mm"YY.,H!Kwk&-4'P/-":Jm3wl4餺Q}9 SM<[TWK]BUCq[feF(Fj~şL+J2Jucn{mJz~+?2T! MwIb<% DJwmﰖw\Clxad\s +Kx|ܨe!TP E[`~ =9G*G.94@[s18,R 2NEjdVN>=WqjhY)KaC ggm;֋Є%1 Z/R/DaHᶄ܃V8 щN˸L<nIڐs-a)^d2;F֕d.4: < =_5%IXx"^ƅlc0Y Χ$ 4[Č;0y 0hWpnȔaJ;t!#ُ=f;5[)&Zt3iMO-R ΢&.Q %E4(q:Ct>sLR5ep)+a8Y(F<0t$4͙#QOS8T@N`%O<fIyeo*)й̇!Fb ౗,8WB1IBQ:+hA8j5Qj%/ ߃?5Ђ6=hXMb<@#c)@4t>Np:>934|꺟!W~-5GK;чE^'=UNZ ⃷@nUB4[co!҇LnakĬMN&A{oڡ9k6{)[3,Eِ)kw3R =Ic'd$9kԅ[ #{&90 i'M/6Cp BMYyo 90Q)CFè}ًЉ/GɶDse, D=G]ٶg8+y&(gcNhdTK +uߌ9NA\(j39(bf"}~|'kNj5p`eE{:#lz{Ô#)ك2Q-&C+7,&9>Npx/BZ>>^70@v3Ѝ7!"HbN 1=5li۳B;0QQeA> 僥8Cї]NH#cG^~Lef.Iw(;#9eYIc9sD1:W쩏^c!.(\]?8\vf"rOR˓/`8t'w<`1L!~yzuO |5̶56Xer@8"d saG&Ϗa)l.{PSZZU%||j,X-~4 LyhFcҌ^Һs_BO7]@ml >Ǧ P c'|_ǯpdVNGq^ $AVH;R[.3:|\ngSv<@\ vQb,Zz܂e e(!- 7-(֗f2mXD|s>}d(cu0=01ڸH4 LJn3 oO&mrS_eD' D$s+6i_QGjW褡ebp6sGFLd p6<,?Ѕ|.srdBf璻!Z9# RgGyb1/!z7sj4lrTrfup+X?iΡN0g+eW6NYva74 .{Gg?Ǐxw!qhajkT2Jbmxm;RaSqi{WdJX &q9cWȖMj%@1hɆax,c`Կ}Ȫ❷ pqvl#gS>ݧHo`5ɦ W B/0=_|ȁYIN1*tCˆ/d*X֍9J-IM w l  1.g^5q^|m?#I7$Ӭ6lRHzhྙILʛͷBͰ eAA,k'Ŏ043q]\c",Λ-%v_67i462~>x!ϤO.oL7lǡ"}xK;ɻ\bbH$&D uZ#$,Fd?`1p):X~]l6u"Dd` 8]8=vI4M6!0F.B'nYLsBDWGZBgsRvRJJ jxы@24@7-8@W6A5-bR 5}^ed>&%Pbgh$rx?>8 jdGf;(D#9ެ4QN[n0XK]>֞^w(%97WPco2hdq1A4̓,JEւZRP`9c17`\VE'&Uegs1Gu+H-㒒md-3jYȉ.aw`5ʥL utЅk{!{oo.-\\g w;H8INk7֙CPcܪ|G_'`W}@*l_Li$Ơ9#|}شLedRoj|YюRcLǦI9@voePNZ02 S\1XDA~l5FdCM"s7%mx90A8ښ.yWraJVJJtq`? m}} ?:faO3cж2,Rs-XIp!h>k \t ut!v2s?oy̰b;|2΍` 9"Mw\`\C r׺-KAMK nn݂:"ONJ DD?W 0)h.R[nfR^w<KKTOK 5ʔctƗx)ePƉ+gbWϭzL[қPw6Ik)K-/p׃UTyha2M8G22>ȍ_=p/6:tPm[Y|_Lj"Д܆ MџYkʋn|-W;WB߭Ño׻S4iaqFMS(cLzF}!'*| 4 eye?°ߟ5 tB`0ڡ ^cGƮ OZ/NG{ B4zUZ'R{k'NRx52cSmXȴnB4)Rs$ tuڡ<2-&C;K o?̛8aIB_Ȝݽ~2ĦY H<|ֺ]btx92lN{4d)`'Zg$?!چ.n=]v#"zyt] \oi{dd5_=[RTItM,}o {<sMn6UgC%߮2ӻUf3%._'$sߜ}BpL=N$":u֬VXψuraŒR2 :>, y[7qK c!"Vs*iZ9yKrO[MzoZh~F—5N&փ)P7@%oo:ELl՝+!c}-ލ4+Pd\Y_.Xس;_>\ m?,]>GY(knDh!U6eyJ mTxӾ&7H=5݃toNvq@03qi>ygr%c[0Z"89{Z'bo/Wj@ϣK㔒磦hc(PknTZݸ#^+Zy+P6#Ÿ1ے:4Q?xB ꕙ*6R .`&9dd㯃$wil4}ߣ/nð)q=!XRc(&ڬXC;-fЀ}16#GL'SM)0v:;18X: AT@*¹y#1ڢ/B(;Ϳ1G{ 8Yh-e͎ܲw;42RܛR2߇ç$ɮQjt QSn2/;BJW#>:)x8F wnp'z_njr&ҋ6&o! /LYsvSq$'П y75yŧ'9yrz滣ʬ:w ZSw)  ^?qD>KDnI w(;w ZcOZrCz *; `95w ɭX#ƩɃS+;0L!@DQG#=T˳P~ z5'PsBspwY"-KDYg1E >M`j.^! 0!w"#"*%45`tqL4EY !99R@}M0W1C {OI [5—VC(bPw嫯07Hq:9ʊ8n̋Xk{wqd h'xNbm\:ր/zI"aQ3qbKd4E͚&IJFLV'ZKY&`>MM[gڙ Cmt~JM8j^èE!zAƯ? #4:`C zeIɤc0c]¯Y{ TS0dz$i}q̅k 9q $ɯTZё ݬ _ܦ9486 9^ \*/F&Ÿ 6mFL$7;~eqx;>;>?`MYİ;eMdb%WMd4j6vk񹛟B %i!K=,@AgCޙ_5Օ7|#8ipQ49-hnr*c [~&k\#xrvNL*EEO2#=mS1!ݑ)` i4򾝹إ8Fj`_ȓt,su2>?JW'Rd/_o7+x'@S棅\.%9<;y޼Km p_\_]ǐ a"" \cT㱠wA훩y6R̀'&c fPffܭڠ9zit*ъ! H+7_c9}&ПƚǦum~nܥ^1oHq4MZ>Ggo.8ǔ!l(p_@l7FZ!}ä l%p@\:!.^%GZNE'?y('*rqm_?}mhC:r!;֎ҋe59$&)98:燼@SKb2NXvێdVIʸE>΢zp7,!sOBM(A"GA\h,s x|ϩBN:C|Mk_obDN)&%>3a/ cmB %0#ŤU&WV&Π0eafKLQ9~-S*7`vO'`]Az@G'WWY";ˠBD=dR? t#hyf'c@nW4'kW?09[7@F BEdn0Pjك ]Q͑t- ͵n.*{*KZ2l1 th NY9MQ(*)(xe2lÓ`51dkL~ q{$j,[J}0BTPxT6!P 5VN7aa_fX–_,a"mLHӋ7 ]@viNp6I1=9ƪXu D0)A`޾x -’Xoܞ~͖`#rC"q Y7@)"rLn'= yrNFtY>tf6;@~Nf_":!<8@Uݠopf&NOr <:\YdO@<@%0+6U8R&|EYW+uy Wj$ܐ:yZ[s7"E#6?!9=jN2L,"?7pYv]A;LSOW%`Xd s$Zϩ?wcܼV eZ#W%m2uHcN@$XB!]uq%s}V ({ۏPv `/]_D>Ck2FEB$sU`fD'#`b4-jua`ZouVj :TRxPj%cC-\r޹X"iz*:KXPi/g:VT9N}W֝49:LTfv%]O =< Wep#,\dKDCB9Mi10#Ⱦ;)ԱhFsf)* mN\À՗Q>Fy [Gl'о_d]TeٲX2_d^$ⓢ$w71[LZku7*$GPP½W;(9%{XdtWMlmFi˜8}4m*\-2=!FhĶ}h?5XZf_HڞC+K2VЬL%`"dev̶NK)%9)MڵqS2TJtBݤUo|xH1V!}'qv& ˙:kCj($(I[灭BcAy/^`5d9(i)(Y<-vZtgad퍨VcY%j#P* y89Z42=H $uV0$ҭeօ?I+yJzNNDNi>O()r]A6zpdlF/+|Y}B<[Es/>Ysן_>3줉{C33>ųgzx^=Xwh`5=CoK˶F X@O[%s`D]Q+T bsz6P¢f&,%$+[\/H9CJvm)@0̶sƍ@mcKEً1 T7#dbU8w7<:8TY-iuۅ;bu|7j5Jnoo'hg.FNwHVKU0t5P;Z!̾ x f79^}x^gҸ]6r{)5%;:ճXY+YJP_aj-/*: sxg0nR?ǡ0(,{:t N8ҩA6`Ȳ<r%<7,7@Di/(0XKsHB퉖Fؤp2P:fƒXw]1*MRqm=RDgV]!S᧱5NaV62“)hm<@8pPC#t .6^In:,>E@IDAT"=Zd;\1YKf5~f x18D ].U%~U76f6pSn$Zɲu: P0M]=;]].j7(zT φsYbELOODglx!ʄNUj Xg3I@ZQθH܁ %(Jf)lyyhG3&r~Dk]eCٚ[C`ׄt2xpd;סЭ3`Rb݉ ,~|ϚJId)N lqvT`e.JAu{ĖdAsih5Vݦsj,xngDT:%'ZR%Ҷ!J<ÿ|K-,D>NKTi/EjښLK gvoy@>7Rk7vqpzJ:ZVyHSHw0> <5'b Bo /TO\v@:e[0 Z:Ff!]-b6Ee$i9;;Pp=kzuY|y )s FWYoyݍڟSe@C۹ v|0pGWNtNOLSiݺyKP?F?p2V_EҶ>/ٱ4e lM?4{7ݙMNHhOyJ\M[K3jքՉԝ֬NW 6' ZrՉwPwv!z; ʉ+\K]]]QNS ( 5t NMLY-f>ȸDnK6z~=<$0B|iQ n@I^81VXbvXv' :!񤋎Q;deJbu0 5x!U־aٓrm>XR @!Bw[RlWB>jVɫcb. =k>ӫw.IYpR{4mG:;IIO>`x],T']  yjz"s39:VPL4Q{NW3rUҞ~ôd1_fAgzPbtf1!&#%#zy&);>CZwg|25+k^ 0GfNAJoob_)rwGnz]DvEw~)> 2 5zLGwPtߘ:tv"π,bANz}]nf+Yr;]9G6>XHxfoɋVZ1)Q#yA+-lP~Ut ]GYYiUރ~Ԓ.rv[;`6!FDݏq،r,`ahB"Qo1i,(}gEӝ Ԏz6.eR̮q&0q0c̅?OQ! La<&`jCA|S@mՠH ϳ9RE1ڞ:8a<l.!ݺg]K`\B#LtJrMH!{!u;(@r]uT¹Bh`җiIK=(o4uzJ-r5<4|h|Ow/y st/j(,ahj>O*5YnM?a5N@9^'Gwu΄/'ˁO?`dLS B-"w)pQJKc";U"V% "]apIzDeT6I>fh4BZEwV(KE n^ c.NNLRbYZC-yw Q/Z}-ݸ=B#{ȁ\˃q3yl|V(W 8焫O:O;e{59ocOET7Wy8C39@f3 vNUdK^tMbSS8\@26b~,9o_NI†{lx{DGKT8R]Wż>KWd~%5}})b!Z~?c"j}aR|޽06 iːW~.,N/-WHd-Vy$l&q%@,Mg^^ -ˢՄ߂?$) K2d&9L֒6` 7IȪuLC> +Vd&ȶ>A.0i:-n;ЁHy::?HH_o.%FfA>CvJTEˆK+f'A"6=󶕱֧xKx.ڏ%:`hۖ X#s$vqʃխyx.k@ՙݶ)ك.%9 1qV {` u2ʎϒgCC*抨w'>Oo,kTTD K 9`k&b!;o0[GIDh!)zE1/5&'Tţ¼5W>+r4,)=de3<:fcܻ\n_D24}1NKu  `a)[ jau ctc4/҉3P`gPFnɋdV2) Dlu&1=gYw602݄ PXD̉sM˱ߧ_φki,mݎ(mpN3 C@)^WoJ7EJj" E$%E>{'Lߡ2I=T -КEa{ cU@۴ 8s1DM=fn~o#yp7Y W`|㛐lhb\ {yViP I6?g %D=mpT$ONZ6$3=t.ڿ%EtbH"䃟CJ`btR,NV{xKa$sM΂"rJJ@!V]O us;0 ((ñAHHQlB2qx J;_,*c *6.+;qޏp`tvud2 @RZRqNdsħ2R %@ea#^" p sz'/>d[6y]lbQ0IS'st]VCV)rM֙6tY8YUjlBEnX5̢ > i_``#>1ٿ"m F򼽑,#Ȍ YgQ%cvb,0{YAc5 h8/`%&߼"{m4m s~I*9(DSB=pGN / U'(+@= Ës5vwg75N1ؠ  ƄXO@i1s&fO%u@tR-;Ef RNNrS&gb # 0$A41S@1c(HɯB6Izp&+:!=t Zv#z\y^銬2 <ϜSa-Z<ً&BXS'kq0{cu:g<$ 5ָE 'U)@w1M&") KۖC`PʀpijD{(e(e߇7g.ZC͟뵤l.jE6Sr9Esd/1m<[O@' d8RCJ[!+b%qj$@ł~=/g|F!FJ}nQR޾A&$E $΅ G Bҭ"?a(s?hy 8Mv.C\Dg~ p>O 0ݡKOz O!qLY'&LowK `2yi7yu`[J.h/]x%sn;"f*"$ fGD ĉ5_ACIf},L1^`#ȪzG [A4<l% ȤTSD!j|vIBlssvFO/3j}ڌQtp8je0-CwB4:`ycm:4Q{ZG-OYdߔFzKkɍ12\ eIj^ݚnU)@xQ5 ;7ho?Y!n(rg k22֋PTP lrL?fm#Fw7)/OB+#6X3"8*@$j@W7/woy0gԓIMB:2m _.`# ;,hxtv }>J ntFNpijYwuBCm;ZP|4)yg'(fiRs:s nDi'j.?+<e!%P@  DNE*ͬb֚5JP$AB,$5}v\ = {?9n|a;FMSLuIb-q6w?w?CfCRK} O@,z<9w `64%GĶD;9mWN*0H%0 t,tKa ﶩ1c!xEթٔ'͓arѵF.>eMS+"!aUu-Xޫ&A2ѮRD,w]d)r #Bg.Si|dc:_9/ Hk<2 qY /^#ƫ/vq Xx,Q7K_Of'y&/IŇXqAl2M8 #Ug] ۓAGWD{L19WcX]漸s'&F͡H.&8z2McB|kޏM$Tn_P80 z;^<Vɇ Vr HVxLt_=&)wb;x a 6aŷq="6&<}TAɄ堩`¤3(NuGs%3*i;Z)/Hf\"yhsٯ05S :qE;Rl Y h.-< cЄxcl NjX{0B{(1>Y񗟗]{b|\v =2PG+B9z։%Y\H3oɖR f%DV*<=D*^/}#22=݈(ر(3]Pʳ1jB[UKPzֳdPo*T+>ϧQ"S D)]?^Oӂy!H }}|ɭ2H})ę-_ cŪx:jϱ ; `5 T'3 A!e3wAՕEaFo[mNk!1b[?'a ‘.΢s$ yFH+^+˯"J?Ӷ͘XOE³в8{x:q `>` =^"jG@En6g[F6v2~ؒ83L|"[y,)}@ 8; <ކ,̎~.gTQ y*/Rj`.. ~/QjVF-DH. Y{-A_ٽq畠Z@ǾOHCW}1R'\ެ h\Ê0͏0чwx1nml?ƮYKG变I<\^}.A8K[KTUM 6[623Q"'̓DOr>WW)QVT;HnoӬTKͪD`TCTG66]bwd3he.pw@#3"5+= Kha}|=1tiўEd61V]"#>}DiKk)M4x(Ӝi  09߆6T1x#K>*\s9{>ixR&J6IvXt8' ck ЃuΔ B 'e-1]varWD x<`L |>`S|15 J،f`J6%0WNn)7VDu΅$.ڑQ"(`;P~hҠi@GgҭVs ](fLeZ0e%xF:=+G ȉik-z2 iU{d4YU.ׁu4Rt`iQ#=ދLj .:G{-45\ FDՉ8,KU)$QrAJbr&߁ifx'3/s^R,F]T{sYb#2?72.ֆzÔ n0 -86>8V6 T!;]eEs/p>aQ`F%}YzNn%"稱 D-qб8COEi#~oB-ӑ8і%dPeH* \p?ٛ75}WQr{63^^޾~t"hzjLϧuƁKLk!:B^:?g<2ہIA=6+Aֈjva/L=+%86 /`գ-dW;L/B͘6k<VYĉx.ڬ9]VCpK΍Y{RwDSJ^ԝRK{D1f\mT֕8?0\o{` ÔdkkxPZ:2}tNRƕ2H 3uDP)AaCLh bӸ3~o[ oIYk_^c i=*yZ#w1`E+,SY'O{Fp_Cg]eP;\qM@! wI=)?LQs fr/7sQJND1IVȅtRZՇYB+/Ycs:!@O>ϙjAȒL](U <`\tr#vYӌ+ْum^<%/i/+x9]G1ƚcKeDC ߁<L`Acs=h\b8ۂy1q[q j)T3U,$#S![N+(!gγ5G0K.\2 6II@*,ҎZcyooYy0f7f6jTho7|iȋO8ɯQA䂥ߙͿbՆA<{{1^f:h,-Y[6 wdQݚxA#1Y+dG%3&! b@sZ%3q$gUj?LAñZd;g3Rz}!'[w-VD>:&b-)G;P=+}V9^"2gidqWjf0Tʴ˲˹)+xh/Y$~n~z ;S"{3s:}8=#K}OvS,`aXMAmAtoE;TXWLMbvD)2ҁ"-?_⻬%Ք= t[ATLl;;yvE"Rrx:AvpO'8yڿW9_ Jb8*Xvj|ZYv*)߁! C:9{|qd J_C$Ggp)n:۷/P ʾq.Mʶ{XJ`2* t^嵂g'.+Shg~Y|O }%b;ek68w忕a>4FHG $V$f*6<^$ G' o/a7!9$'hh=(Gi_=ll~9i| NSq7r:A"h8ޟdeVܽ~ Ӷ/mr84\d21M6gdoe8- ^ݕ񼡲AQ}Q^adQ5G۲Ub6ʭ|8{BnZ HF3,t9OMz;p\: ǝ^? 6j`c_"-Լkh.cePs 2_Ms(-\ԖHWvۇװBuC嬢s>,7](sWg/AdШ`|Y\NHeJ1s\-.dXpa!7^.kx9ӌu;Q2@u2 Mw4%,ᅠe t1| /6(9w~xBRUZ~¬S7{3 !;I>G+e‘?Bd tp0 x+jLP5~8n"jTTÉNS.|"-Vo(]sKJS^\"f-PZŨC4DY`=o³dZrlIWw JQY?˝_W^f/K6 W _bJ&8G|{;YHqX/Y6_}J3HvV/3"} W;| 9 ӚySSVeﺓ3 IPjV{&M"J6q@gw !yTNxp!Hy2u2yFPw? Y-zHOdNUݼs;2ɜ}ޒ$bcұaKյ,HAܴ.q_1eʄqtiH ǯy0#Y(zx*REjr4= yt 98>^>Yٔ)v|i^ޙI#08`6 [n}(#a` Xo1no?}#aȩCׂ[em *S S[[/Z!-M.[fKF8 P&KIYʘPr5ȅzr` ̣v u/c"x% Ӥ ">0]u RՌE+*rGsL.!"ca*)ikgdr(Ё*Kg2A@ a@ t2 .^:&4Ҳ632_|BqMb5{|CO֪S{|f*crG'jo.㣒8{ل, M?biw6TEV>A2)|wj6Aj$AZg|O #5.L?<ޅu4l`!oٵU0\eyM&uegu3q&&eBli{<$q#wd[C?Z l3N>9KzXh̞WٔP7|A{F&`8^O@~HV&@cFwc3bf܋XVg-LX*Z~sA&s)A!DɡqXՐgU,$}~j6ݣI:y>?j\r tsTi%\PLA1IYj'o8F܌ʏ>:o؉ a"<XlBKp2_P6he@[E`/X&B zsK@9۞ C/pRvBcOiz7  sme"ޗr ImadW<)}b=[k[b(rP"C_JLyGom ''G#6

T!Vr^}QX1ݰG7lS=VY7`W5@xG%/O\5kCQvD _gO+dTs-30neR}W?8%B7pOW&$44ߡ ]vc6eai$'[kg43Y~kyMY*?ږCZoZ05+9gQߦN#ŶxmmuF1N}j/lD28ڽ'YomZ18OO5F8x<(eJ>-4M5h|5ٖ><K1^v#'^ʉm;4WOtUX.^b^tCM[;7n3&YGtr@Ir?"zɈu 2ǹi(GV"f"r%> S=SVYB@_\uBJ,yH9> ƴN[WMաp0;"eZ:H+\u6g'9 2hߒ@ꨶb8u1OT@mW 4ЪW[-B1N Mu(EwwI>se,E!Y6ewPf[NDqqcK}k%fn.n-x߀]|æ'jt`]{/~QStU8 $%VHO M[C4URb1̆U%;] ވj0~~Ô|s`P*\-g=J4TQi㳗8?c1k`ԲMiDbB|/ʎY7H)>ҝ4@IDATxs&(گ`![bKU}./*_ n"V0(sqq0]ٵ_rbSCVIo$}))EB7_~afs%A52G ֊qn1k;vof1zfcT2)}.sY4m{w󝝨Qj"CEhgp+U5M8 k#?{ݜ 5lL:vpN|)YjX;e:":obs] {j RS Y2Tзk*sx4.1f{a|s|?t\?dT4Up#Z$ -ܟKÁlgq˰a y.n7X k&ܒU~XӻhIcL\X2$"\mLT)WGdP(āRUS@[K77Wk&ŀ]M=LnG/UDe,b h.aU*ڝxnu#g4b~isH6S:/~}G1 U/Q9pyd5?N_>J"xCe~اPخ# cev`5xp#huH{<@vaAo_.fV( Eۙ@͙']u_h_[,>4 26f}n`c89< \pxܕq}$nV}}a'&. QQ6<}m :E+.Kt&pMn0rLO4^i7X] xG;^NM Wx:P<_8S9nr9?hZBHHpdR('m]*8wI^ͯ/x?9a>F ӗL A΅+ bZ@oVvX_3EuQ ظzMmYJ:&j,_ŸD{ ,dH.όlpqs\Li\YhRlN-AaMa1hxewlL]~ 7¸{j23*-gZ>#*1 2j[/3a)`MF-t_ςMd `0K@jy7,DSj緣 9-Hj-0 飲&iF\JT,l+S9OW_Y6K؆;L&n1q3%i͏X*{f7Y*&QjLY:W- ` b@@9+p߆]Qp.ÐV3eL/,:3wȳ_k}@K 14Gd֜%6= E4@!,>0h?j[Zd,%*Ǚktaǣ.f#Cg #~{Jv Rc &9@AaI7TU$Sc:^cCI>DF;muUNlLu6or[ ӨYH-sN.nQT.ev? ?5'prAg(,$Q9Q`-۴USv/VG簹ɷ։Jh4W04Fߘ}1||w#2j)'5`]ӷ* %Rʣx߆>Nj bM^%[<]GK&*Y- & ʡ X}Ff«)YF ?4m&^cY\4X ,l5y~Nāu=\(Mjainޓo""_0s{9FWxiezuɧ}kL"<{ `VKD~Opr7oFoQw7Gd\pAf>϶*VJMQmh$CVUuzyuuR(~JkaW|\Ub&66lͷx/.i3)߀D: 1vme{.p|O? /1fEoSd.u|?|oeb5xo7ϪYn#O9!`WA8^OP,hen*Cm> 6B#P!jVs[. uoC>5mb UR7~(#4J1Ő+#FkY >b< !-Si+x9"F(IqZ_~cW2]kw 9113=fG&˗ ~ln[E2PX܋D*|kI=6տ$LH9NCvܭc'~?}C"N 7۽&7G*߶Fp~澏Rp  ~<IԬ^d2Ah!$Zvj~x^6Ƈm“HZ?ZsL_e76]qZ=bή-Ī-LxH,>r>FnOT2Jm8N)ohЗj+\?& \\4KJdZh묉_D^D~jlHpN]z6shC돬xvf1㆘W޺eUaXtSwj#02 z?7tT*e3]YT@ɒ30kk i-\[cR([>>\vFွեXyLMEs4Pґ0)p$3-@ Tv7FI\&hR$8:DS}I^i ~7n0I z{{iN+UP>RZē*"6gW3-GK7 9/qzqo ǭ Y:Sh̶hFaJ֮*G>?8Gې%}CP +KP|C$+DeiM7 yVrĢM $eF =[9AJ8 >%9@тoqxD "t]|mjMWxd[(,X%;"4Ļ!v @i}~KKX Cƙ-1# !+izݚ;\2m0dGJ"{9ǿRep]_؍h!c*eX,hNUh[8qpTWKʽ.|ޛ ϐJ}Ӱ1}ANeCڿ&Z&ڥBB\ʵ٠Tk-ݬ Xdzϩ]{?<MZ8/ɰwI 3:oWXԨNڄiatFpC`SǠGڪK;BJ\EQuZZBJU"'6GH$~qڬf'(@אSɣq^oG+uK =-Ӷ:L*hl@Oo\>a\g}ABp`"v}HLgC*{v}HfYp#hyG\*jGDL* .:sG.yMOC<x _Jt1Sv)Nrv<ձD3 eprL=s苓@",y}`i.2(p2]^^ ۉP>0=p &hjS~e6wiI4sDwfzRjGޱCpQR,&ePi Nj**t֮h -ޕ.IxIjH9MA%r̶`F/pN Ұ(9^ Id,SJHĂ X[@@^ 3BL` Y|' Uh6:͂דe@ ž62OA*>w v*!z)7ղ}%Ouܻd #N;Jf*5Kmb":@^Ņw= i  k]"烀;;T1y V06W`%5a=1f,<ʶyYz`Z~9 o h2[BPXO=дs'$ ^~F#r Zp'  z,`X΄I?M\.H~yߊ6EPOOȌ ȤhoV+y7( ~| *-v9/ #φ: "{.Nբ;F}#D,#Dhty+h]L1 7#xT0sLvͽKWȠ4BϣF|E> Yes( qCyŋ 1+w$~pTZ.{3x"SXYq b*&ldZKh%S'Ң__2Nՙfftq(^A~i x= 0IPތns/SLX U,z-^H X% l JRb}ƥ:giLFaN}Iv&i[<$)%ؓ>\$FQa8ΠQٞ￞2!>KGӊ7Ls袵(-[ƩP788I,- F<ӘLSE5ɼ Ķ+,9K UR!c9-.ڰ{+ь8D:7oDL  A?_P8*&]74®D;`b3*aen KnjG8(&0ƕKZ6&68^vR]-Y]ܑot%!u r&qTœ≑tﺷ7oFsG{y/ZTЅ6~U$-TbCUYrWX_W-GK&3TeO\^"n3J7v|ds]e##iubVyx^`DZҤqo4C}zt es*a/>Qy3/p,} )%dM<&6d?U,KSLZʿ01FR/)o ̽||!H7G ?G)wCr/PHdپ{'1W##W6ژfTmf0qG?!7[R7<]v#O :'1-h2Y.oe:ݝW!> j"E}6hc_ƈ L'3KBC,U YZ8g]ʛ/ $-e6BS}_e%??hd&jp'yDfl잫ѥ$dEH^zMMTEyTih:9 H<y@V+e̳ s G:X](9p-e{`TPnr%)ބzP=7.,!pKDӱ];}̑k L;ްByYӊjw:[[C%%2Vn<XQarc{Sq>qKq9GM]}6GveYXKΗ͂ޭM_)ei^~Y rSBń:^f> ].Zo! .t{8 +ژWvL3l11<8D}&/w}l11TBo!yyPS71_`ѣNQz/0)FȶHDp/ZxpRvޞr@+ԜkQB:;m,. NH#f1|'oƟ`mt\H؂~Q ϿjӫL`o\ge^X2^ 'ݏu>A:?b4>Oυ;,g{wS9짤eܹ%Ns~TA(S P WpQ[";$!@qY uWX_F$R7yT~4f&kvqk w5]0B1xLڿf9sFH+o%J;a}8 <j9d>\#?{3 *;.t!x+Au P)ۥת}"O21fLYPGWNp]{Jϋeb I %V+ʁ D_1"M/26?(* .$㘮TZ7}wg1RHe5BiG֑/Ă^ *hT_^oW!. U| uN><֝M`ې{F"ϬHa*p]36tf%X{Z<1v2ԡmԸ#Y|uBW"tәYwGKXGF[PsŧR!ٸLEQ @ƕѬ47=M-LUv[C, $:Ʉn,ZQ?L Apڌ ᡈGi@Ry y3܋iXbX֫ mID#Y۫&?X"ם I%w{y'$5OIu/m"0@Wݬ<e^~):!:Z.;n</A=(ܗ9s2l[Wܹo9f56 &ˠp3zs7IWX }T4G6iUZLA c&#Qƹ7sN[j8ɈZÕw]1^WE1kϥT$C,Sc:ryd;d ~i=}, N\Sє<22#{ T^a 9 w؟_A= DK"\E`Źl!2`.y,l5>*cfkpF˖T~|JV ԓë- lGWZMŠ3+#.r Ds .!T{skV#{qx T)@Eg7>|-.㝯$1%NuZrYyی($ƁNFEڪlho&i!,"hlT:Qiy ԑJ0SO\=P"@d'$P֨W_ MMM㮮v/؉Go(,ⲳ֏ʖ+XYcq נٳ_1h`՘)?t-2Fbˮ{(qނ'#掖='y;:p}ˊ i&);:PZ,~ȃSNPk]:t40RxT%|)=wH'=I(A;1)Cp PisWÍO6cx`[B^᲍꽗y""\dX%?^ɻuYN:bDNZ{c.58wž !e=&MdGFq ),!5faRmf_385XzE f5#p|H94a7N<#|2 ->(9];S%-K2c l]* Q f^9P[PlGG5{l#G`WU"x~hX256^ *n),PGr9kC n,PAs?.6y[[բ Rkf -נTa.p}7E'^U6эw?Nywr%п̐XD4A+ߍ)jm4ܸ*%|󹄩Q=z&t錗gwPզ3K`4 Ɔxm$Ue & L AUוr^%/ܑ>B ոA&U;a)xi]bn{$Hu]H=2xxR7j/lRKۖ8V~p͢T6d |V%U!OX7L. bGaX*:Ɣk0&#|'QDfT=Tv.h \4ಎ̋4n'3r؀%}ҡw*8ۯv9#d܊(=w: 4%\W| J*nJ^-xh7lTE5#b"Ӄ4`xbtoS&P/*gnMrjޑew`/TAf[i,B1*#cpqs%NFQs^ra!w ^ 8DbK;@OE:<ƱqdZ7T{|/y>dGJ!ټSt3%`ev ݇.GpҎ> {:%ELa6b4NcSU^*qP ώG_4*2XI݈O'amDߜCb{" =Xu,0x@@)xMlGT m]rh/ALL䪎2ߝ6FU8i(+:=EE!@dW𕕆Ixܧ}Fӏ?ܥ )P\6۠3>5K#Kh~ؚMmi- CbsE(s`5XqG{a`8EK5;̚WD!2 41GoN-ǘBm,,D mE[Xh¦[EER7`2zȷx!Hg$6I {p.)濣TBC#ãu_\E%G>; ~|d{Cq0|>ʰ-g<\NW ]{--׏_#6.m@ Jxj'6=3 ~gEk:M-""7=dE}7;nLH3ey|`SnD &gwo#+^*bm̑QI8V \ny2 Q'8v$v qYw} b6q Jbv?[vl\7p mq . ŴN&0P¼%Obr矱!-2T^a-̰Dxގ\.dbp~?ogT\jUK͝ELT/nTu2Ƨ̞a[Mix _v5 XJ>}mm1 ucJ_ S)D0Iusٸw' ˳A]>3Qva̹u g>[{͍?]gK:;9!bCWf\o&`5qX*;:i˧>smM-7'{`CȨO6!)e_M}>km޳*w#a:qf& M2%KB p"chi0B!hz$.fiZMfqmʝǎ<^ <~|A roEjPEa"=h˦ kNgmWxgkywmT}7>%&܍$r,֥PWdzu&8y8aʍ[3\NIќְJ,(|5D\I܎Tڶ;L5yB8ȋVi(o^ a9KxOB$bp6jۗާ@)7olmV{n' SMnIJbwZ !7>IVP6iktl9èMKh7\s<f)Yd:HǥF3e|-8:KӼ$)(9' 1UVUWuUwMoK3ӕ TPT2* *9}gn-{>羯o?4#*9 &[m;2pu#4db+oxͷiq{8w=&ZXfmÂYVv4bCw  LNqmZdz25Bz;GZf)V~v,+d%Sv"˪IEJcDrTj[6j7שePrql{E5fRd Pxyk21XGh:oS,icQU=*㆜|C)dz_wqpе{*W4p16pѼjj?j`cs RR`!T&c}}=zSW%lٹx\c=L釡d7p͖[LN7o뜉O2FEXo M3#pp <;Ex}!(/ZO7ZnLw1ZBV 4Zv: `;< mEP:PeP;3Zɴ9SS`u֐F٧\-=BP&- _6q1 ,h\cuj*@n[͍<{>k+$z~^YÁ*w]j/?BW굸uRb=kXZ,^ < @]t4VFv1( a6ܐH:]픘aI᝱K2K8>gi#+ܞ(JcϏ >BcV[82 M}|XOћ!]逢Jˏmi]D<[@A+p :]!޳DcK-*p*^OHN5kCLKN!? "<TJWՒizx uY "rMԥ3h">akԝ;QC%iy?_{FIod5J"le7rW'jS0~ob˹06ѺfI%,e+3>|cJKf"Üf"2*AJ疝ȃLb `y%ߢe6/73'N Zj$sؗXeGG_ܲ1 0x!ڝ=Kh`؃%2%ϏY;tp 5o^Sf=Kث"d RɮIϳm[ac5+ `ɖf܎MJX.Ysԣtz4^Xa $=g >RwK{q#~Nkk!!SyyfH[!yu bYNyS [̶{ 0h/3,NblG Ps9aIv3)w2e'蜯ܼn:!ŧk#Ս J&7 i9\R/jKlC"$*؊CDu]7d5bkK n؟洞Z=Lf*|J Ʀ(uyMM"*_i-t{,t$(G70 a;;NmMZ}0x DE:V@c3w׎,[o;p]܅dY#s{9DX~SNaͥ5S_w5:BRuDE=M&L)) F$^pdbA侉i)iuvqs6-C=tzdlEyEߤx/էT|.vYeR J~t=Me}85?#MvcZ YNG`?jltb`+O0Ѫw(0ٕC!zM@>$^b#mbNO7okᛟL'M؄@`?EryδJ~RRMr GًDqVAPqXZmbD%22HHz5Zؖv j&./u{Q;xz!Wyi2[9"LRAP3gSSZB g;逕ߑ 'Jބ"o2pn~ n.؏هyj~\`^ѩwPvGW Fi|*4KL"j7K-ͬRw-eXsSa6|֛H-3=ah'W6Ŵ9o3oR”VdP+4bJFhs;z_gR֑4EZ25|R4gp6ypi$ЊX46g\x ye!lDB'C; _BwM >ā>H8s!T],-hsOM\FTt&q?aJm;ey,0J8TIyкOxI!xSV+w#}~SBѮ f) CW9LRxuY|V\t$Uv+[6<;n&nf+L}0˭@gԒ@:*>wL'˳`]yӋ+{YMyrh)=>M0|PtmA9 hJ` zm`PdE7Nͦ[Ltg :h}?]],7Cؤb%u ȶ5ׯ w_"9ࣣM֛?QhJ;tp[Yi9Oհ*,F' C+!=NPϞ/|x4Oʬj.(-S&XjݶEZ] Ibvnb|M^s@QuHvi͍adƹ_7I ڑy+ yN4J)}YT.a/9,ZIڄN@zi(|!cx ~n0Ϋ)}D >,,RnP1S'k\}C&s}`{9 C6qX'SrB&`~Qkt!UZbujEqSvC:'ی_XIȈh-ɰJo}E`yХMG-BWqA֣J @n&"]I:`^jL2c%ېy !j cxShxК BxZ4\t-pLi|?E_zГ8% PvT5ؗi}Fq=c" vyy|&fZ1ȱlR>0/]N=SA_hjÌf 6qdMZ|E16WJx:-jL% }=ȼ=&?q%̑IgG#.ۯfz8coiyi[ T >¤"kxސO$zWe aH.jL-ًr -7Ղb~S Ll9L.<(_1jg Li>rHƟQ=J,cmw^}hZ55.pهFcPPbF_jTl} [ 0nԲ!ȗصh|xd#p"Z/"vƙ^~)nv@^y<ݐI|aRduq:ۈ"!nP;[w3ߏ<_sd2ރpv.-?{f B@_Gm'Ohw!\ )`?x84dZ_psstC"2:)+# E[n1%2oPLN ;cQH3AZ+0vmŵ  35Ku_EpԀW]d:Ntncsvyl޵!g#Cغ$s|EaZj4kuڃ\z5%UЖqrOe-I"b­fك ÜyH6%Ss@м}(Nx Q| %(0Lt”f8I=p͒t-BBK3>xzY%YSwarZNY AŲ*P:K?P缧N0"aM,$kpSU=1IeoBh;6/4vsf9{R# 0S﬋M '[zณoQhzuS$ޘA|}^q؟ÓWo@vT8H̝܆ >f&˷Lxnع Yl:Ҳe8д0"'x:,:;_&3'X|?!-$jm阔[OXFچlj0ɘ&Mi~{Ʋ5yHT dSU3 (=f?$`J޽]{WoP~,n/'60op@ylB^~ImEig禫'l];?m$`]r㲸\G 9?8wdcC01 h<"Lq(`kbnYk3 ]X\ ݤ&%ܞ_x-7Asک&62 Lik2wqv5UI3Ƞ1>L}CIebp܄_]B$mi/"Ɂ &Pr[Zo}Gi>e>+u %[-Yv^f=լ)A幍RUQoyx+H+hi 7,$cɦ@Pg,7gH2v "ka0->fNtNȨT?Qy31,,`jv )"$۩ހK|3P/[948#L ?9ەBr=l?&]G>Oפ4@ ~{)%;ٕ;lX_[A9h"hW-&d3u\Tf d,z-<蜵5sTt/ˆW lۇ^ƸR֬l>ɗ߃ۯ(6Qz1;Ad _Zƥ2 cA/D D_!]dذ3\.]kjc=w%$(}6(4Ò)߸O }e38M %* `%[X 5iNcTܿMrqxYxz V /Z ~eVȻyLa'\P2*zCr9wMI?*+/]&5OCHH1OIC˘@ΈSWBI |8@&n>d<;QZfgEi3teKj07)n,\Ls})y\0 /,{݂$ʧޘ}M3 -j?{tUR>-)Ml~uy$Z#d1`s#rK9?s7 u5}SDS"DY>ҢqV:gpr@{eW>](+lʫBeS&BňDHʌp:V|tNMK %i;g_X (<.[9GV#}gm%=Qiv9$W%Ih"nT/B K?|0VneaZRUs0[\\&cK&ކ @bly0ݑ*Iѱ y|pU A{V3$+,S w%V `1Y2`bȰOjDD nO Nwh7Mf6(>C2:%S*QŸdN|zLgAp (g v?k]49HӽNƔDp@x8m8ۯoP %0,؁GJL |w3YeF$) (ͫC2J汌nN\ +@<5k=gKF݁ \nJz Լ>sZj Re?_z1'&غ,$zC~jp+ƜTT插p +|-RB'YNC PA6K6'KpqN?؂UQH)-W6]i{B?O1M0Z29+0.yAܖ d&baKspq77ꢱQK쵴3Len͠ 3C=."K'7d@AC=<~䨏L*X(xrԨ,|;XJܤ=fmeoԛ%O3n sd;r+e7%ZYZpqrha1NS:WuI XB!0s[Pf@TWLB 9QO753|v%5coesoG;j[6n;?q+wz%xV݄$/Qh ]pwkq:v|Ej^,ȄH{76s2AL@A}G_w"\ uL]׭a\I9E<#^d{C}{p62gzfԴ*۵@R,UAO`oƔ^Nv!(a1tIzg#:p8~?fL\[uŬUk3i!ç.K#i$K",ḿ}B 4ozL EySy TWYNJY7M@La|&&h5[kM^^k8n֬D 0sҫNA@TI%Q]dSzi~(E%*\@l Y^)u)ϚBZSI@px> -=FW#-Q֘z;d,2M.bZiYɰ8N x>$R7]0EG>$6.fݸv+lio?bܒ8eS.E$x?}k73>H65& (.Em]a] ^x5f&ԝށe #4 o[QH摾n$D"GyZNѹq`[cxdU{L >>Y/SSaPIswX厣;xylt |IU:p4zJ!m[fF $NN 0g,y޿66x*l6ȐDt E0:SAyVp6t Y_ODx 0"ߏ4~IP&a[Al9?vEwŕB`.}{r$!RF.*#;8>b\7:ˁTF3a>r L&8FP³ϔiנ FZc0f;4(HLr.| ?ѝZII{V\GǙ[mkw#V kXEf荙kp#0i}ڀR2 (žf!.n͇:_2gakUnj~&ᓿ*0*,`:n6 kM X7oaj?%p̼Uf1mzf {#[!v Ƥ:qy %dPOwH:A!XH@' MƔ{9zn0u* skFEfEzI#6jn16R)-4S!׶#6}nG2_bg~}ܫ6%2˶֥ɃHG~lֲG&X4 d)-ܐA0)3{{L |R.ח$2Z.&@ǤC6+x9B֙i۟ü_,Sõ6UtH}~>P1!El@Ǔ.%>݂<:Ĕda?qAs` 6I!,',]Zt3p>[QST5dT4ICuHLZ)x:DPd!P1;@yI XeM'ݗ,a ̀>kq \޴1-۔}Dk<̾US`lB)}@`ݼwS&oBܹ0 hS_~aop&Dij&MiVn&+ +7G޹ۦ2u&(6@]D{ Qu9٠{@+5!'Тvn(;,D0nb8{aVś0jRTdk7\OL ThGZbFѕ;ʭH+)=6lD㘜Eam޽"0e|ſa:mCĒם$.2QIf0E&,jm1oYQ׾6̤)ʿkP#<Ȼ|6q({d` :<JfUo"^ n^h!CKګC0,|_~B&Xd3&(() ZVNNd1U@ca}.+ č[^D t6 j߾5w5oRԙQpkyQC>s1ͺײq˵56noc.f|(S8˰,K,SPdEN/ H`L)s!M{w<)b;n8oaxK:qFt'75mhXwՔXiI;,"}I89sp1IGZF~s\ZOdž{8#it\L g'gvBy!9/ll [dwmjR'gstTbʡGH)C0-~aA,b3ޜYY}P+8\(v9{Tw15P'—=$rEUT[8T^`%+e!c@t] L b"-F"j1IěxE0tm f` UQTNY\@%fV%k3xFiRM)/2| W(OVi}u"OC6$COO:lpӑI&&?]%d2ESu$&Odz 7'iM[r(}b^{=|^,7csR6I鵑_9Q )lDJt#8 h.(ꛑVZf/ 7%tqJlwCNA 9A{8j}nxC9tU3>c,z "B.R&^[mص25+&ڽJ@IDAT^RIL'3LAs+ #I-?Peq2mT&!J.`771MF2H9Jǭ)7+qiXx}nSL^r 8, [y 3) C4x)@}Um|zĤI. NOCHRAo|^ˡ5ouFP|wBȈ[.u+;ŧIbyOb%y;6ihQInvsv8d'%z \ˏfxʑv,y DlE;[YFqhIvQk^Hnqm76C; ݑ`&?In J2\ ݆dMDx(0;9p;>`k3t ;v@00ѽ8a t csbIJFX )S3k=hJz@$ ň(1 \!B$bA*CzێS e UK/މ~?w2>cZ;~99S⍛@+lJJnd]?.t}yjiݐCj3H!>ӣ)xuxi6||n;-d(L7nâ 8;}iIvMB0<@у'+=.ڀ]\ (25#3RP U^R (L"?a8{y@낿)ݧIxhj 5&w^I Ud[![$!rݟl`h(3֐?'A2}QrZ}Wz+;_8ev9 ׺KBfW#<+X$_tbp-zaAL,]E3 L9䘈JP96[2~d#"{ԋyL^vI+SishFga 1f)mxEZġ@( nx7ȆX?ܵ9:PFHk_CVuμp9)=(z p$V \cOw?A^I`ٽe Nip@~*DHZ`&sh&X9;u!UCZ:CE(IAAg/rmu>BhavF</x'LU:zO%5Xבm[N'Yn`z姿,^}f1$޿us2Tey>Q4)qDD>0gGX`7Z6ՂuŅ(]Ddmbs!m~#e3\6s3\qRbK\"X 1'>H#~ȃ+7Ԥ"@J.maߔG&iכ`23k(dlcJ{c,4Oy)>(6i3ty6d2`(Ԯ }`hRR-#u*Kƍd>(WpN™{rͶcƤ%?̩O? 6ՋD'}3l C \ؔq`q;WpŮZI74K+xz'@R,rdr݌C+8jsP8z]-".lAIوx8i?'@xc cn%Xr=! %t4D! Xg}{LK}@`:(uJ ryKgRW鶞RGlj6k3 j|v7A5TV ilx % 3Ŵ@]1=Ev Ʀ DM>kUao9~Oph(oĝ,a8XDV y (sHHI j h.]| fւ[ ,z?;ie sK ‘QVM7:Dԩ!Ry]zQ~Θ6h&Ʊv,#œ6 VQ>cZ+w;+u+GTΠ X] R$U[Fb4HԮlkgV3͙&܁x9=fE=DT3={H;/Kƒ*3Xw2xe-{y٘E7Vqz3:5ȃQS1SZ8º,2 /M{4Jki'3!1SxC}^CA)]nbg y SYxE11j>&G4ƐV XbZ nuV`TTZ Oޘw D{5sd^1j&K\g--uާ6 ӇO g X[\ *nGCț$e5_:J7*>5E[4yp?<^َ1D5 Cܹi4:}PMM@ֲ]]afs"\a9$h6бQWgQ罙 ,a9&246Gtt̮լͬ"g}-nx?0o (Nһż-uF<i[PzHl/W_p."͚nׁVknCGoˇcHPסQ*([)m=d-=:R3hE*jkxi_<Wg,ATR1R9kq~^yRTbgyw"&9:OCA|D $B5`C0Yt@yo<1!cNm;M)RS$9xˆ) {펹5 K& B-dݫ=vZD.?DNjox 2GO\hq/gb?@R`Lh<56)Xа5xĉYimxC9w |>:i"_FU`_CK6ި?WВ,h} 4g'dMJ 2([/Udw\7OU@z͏!==)HL];y>|?WƥN#%ÑX pV>t'\Jv}Cn7/>'ǭ8^ ŕ0–rۚZ[xj-7t2`A\rMi !ߥ}g B_5SEeqǑ6jY?&G1K>zZC,Y:yWN뇸*svxL65*gHr'?=A,$" e>ûby*:p"OiTZc0W>!4Tfqɱ|^M8x;A0QYFst0=t[Oh 48O+53CڰdZCg۞ZTΞ}\1I7mj|0qrXDm7O0zJ!A_bOz-О3Q<,{7yPt\:q~PS4`{z[7#h_c׏gcZ^fI?{UyF`vCqOtT2c-m&:'e>UTmŚؗOEuSi/Z9O`RO7̿r6n$.~dQK8ljo6z䄢#qk.c.\ss04ThKc3h7Jɪv>Y|;enx**U6-+0kydlY9̒%/>=QGZO]<|@R~[ZꡱI:2^)) .]F+<~z)l? Ѿm]Ua ^GgGz2xkbMz+\ݟdڢT}D7GJ㛿\#}AgvR(5РZ8T/'s c] |2>FݎN&Ur4wadRJNj<e{3Y`s8Nr@:m[+hW6 ybVo[g~9ش;wY֬<߯d/ .2,Yr:{ U H=iE1~쥵KJ=tz^emKPФJ;і(#Hp)4Յ!*>&8)Ms^Cסغ7Df7DOf[PBolơ#PUZCqfAGޙ}R屸"@.L[zʋlj==NJO>n-/h' 3ĦBC;A~%LM `~/y60kfU)%Wsk 9,_ԬM~lZXom1 yiƨ3h%96FJl:Jcr394mP$dbRz3*Ko>ŗ%jZeNd@w2>TV5 ډTr3T/Gz'.s>d^a? MDoLa+צYk",pZsH۝y[!zG&gP\:sƼO=[8 j]'Aԭas "?:a޾tרE&cWq#PPޖ ^}!V%Ӛ~o{ ybNPV#Lv9i:K>G]<J*gfh 9n-o/sn_'Ys.k:4ʮ]G@uH<-zm'_.BQ4 _CP;Th/phͶ=ϳd3G/wmnXiȫb*{G\c.+hM["LeG?; Kn=TRYq@sV!,`up8=pWq"Mc(0v=vJ5!V܃.|s Vm-(wO2U<3DY~E<\6; jKKyP, -c#ް7%˸]G؀apQ@ 0L{~|@x89yw@!09Y*=~_qgͷYwYij1l}OZFWc7+f+N\qKEB'Ut <:M\`')\!IrUM?.IEgt k-n2bq=PގI'sLVDsp2}UiavTϼRk 1cHJ]lpEFhnÿW$>D>P=} 'YPdڛ] SfSݢ#='P $RTM'1\e-A\7h !DDD5XGLYD5& r*yg`a|pch҉_B}'OAf 0ߢ}K1gDZK^Hg؍|ztvUk$N>Dh9u8k93$e+_lǛ{)fہp0¸]!ܢ-@PskW t C {?fط}xb]m3Ƈ@uvAM8s&C1?SpQېԼ67(Ex:|^)E쌧-Q M4LӚքAb<{DXG0m.XdP05SC\-^Axev#Ky2>0ȥ!=,*M{<,ʿ*+@Stq HXb(d$ĎbF ԊˌS;-RPK' i#̓'}h6>U̼xu`0 :ʐInیO#(>B32f_o>\4 I^ej˖Gc^;E~k˟! qpa,h.4r: X,N} ǠlwYvys9 $D!r"Uhm5a xnnwWW$  B P( /^@ysg}:poَwۺ]cԅM$a͛:(ոIQ q['&%qQ4S39-М7Gg8N0?Ln'QQzӰ/{ۅ-8;peрse::>p3CÅ߅uP:(٠wZ&mI]-tEnbͶ ; m ?hD#$rHe fdAm|/ShBJ jkaoCW%|o>$*M&(uϊKVDܽcd}Y^[ />%GdM1Y{#G'ѣ5J9vWG]]iڻ9[.dai /3+1/–_MA vB=*hϪNϹ3\&Ъ8<Jgkُ;wC/5FF`˩_'ޫ'^DiY*<HۜQ9 E4t4Lm`)-&`aIqRJii$1$PD9514=Ƈܯ+t[֓vH.4<^-[sk>DYl%}G5 lޤL%J m1j0ɹGiV9+ xgVf~[4P$ 9 /ew!YL4b49Z5dǤy4hv5Ǿ=dcg6ةh-"ݫt[aހ YhH ҩqfE70Tvh;aH*=+mg])V Njߧ\Gg ,B*&=&'(ly: :;#G)rBGY ]~OD"p{E=_3&IqIv;"UW?d #|ߴ !XgXin)ECj:@ooM;4@ .42]wa :QNӄQVݥի NFn7f`^QX> ؼ #d]_%J Q^R,?{#4.Ì"*#*΃ )>æwޒ56vaG1>9fװvQդ>~ ]Z_2S$!i?XKI6bB|5ęFR9LP33Zk[;^iE}<=妣 (0Pnaq-̵F)WOx0ZuQyB\񢭦TV_Sdw@A&zp"N¸u42C3e#k%21NixBiEHpw额 -BAjW1~RvZ:51dsݓ&86 rӕ?djk DSδZNutW$uf18e^`] oENZ`]W-6C*[1mg]i$/W ]Bf:ʊ̪,+{aw<^o,'w1sMJA|!5xQןoa i L %<ڛ~^Hi;C'D]4[ k(!F(<pVրd}x&\FobT!Ug g@+.eEwҝbyOvt akzt9=]of5f595=;̃{r% }v28ޛK>BIx vl%{k.fcǬA'7,<2A1f hԤaNT?\|l|ƶEԾxmnA9O81^IIY_]Jm(⠈0:bϗ JӮF;˅!::>9Es`v`@Nf";nx/u+><= Hv+gQ5yf^!nT.wh@^D g_靰_EXj_mpNQ9Gf^~4xziIԢS-nsKLwn#HcE[w<@`xsVɃcVHE]`ހu9kџ}| p!SqΎsf Frڔ6$ I靻t*?6Kz5!Hb=MAj[nZK\.2.;c{'|1>|ezAVNI!8-u y!Ϭ1]]l#ujK@ SHV/ܾo\<\4T9vd|O`U\b 7RY@2.>xR޽Oj8N0#p0 dU+li(h/Cazt7(ho`zÔXvJ9fY&fpɂ(4R*Jt^|ìˑw]YW;K ޓ~YGpEhډ'@zȧ> i `ZоOmR66s?7B@ 8k}`^#W7;孄esƋǕO'N/XYHG[+p͡=)@OT7TJA8teQb̑ Цk. E<(aK/\A b^Kin,.SM徏?#rYn ,'8kS +J!|!薈5Ih7%֛u-+LmB/zk"ٰ*Cm HNʫ̇ų^#LƮ^4:eI_!;혴|I f k_,GPuYƩ?B2K^1qfxCS&t (JQԒz:i1f$HJjy.Z޴W k0iGVok%f=IEMVed2GF8Xd:0\9 >:F.u=NE+HHS`eCdFC0ZQw/Q/I1mC o-ԐIŋef'̂Ջh~oE2Qf$1)@9F⢟LJѦᦶ)(gR&PFFHs3ltSM̙86aN':{8Fߞ6"A'k",_J'>H$w8,H!: +Zn =ޒ$[)*Pu=i-[;GE^BIOIaZ䇲pJוmi^39 _O _4:n@;07͎OsҾyLMBXb`HV,2# t,Ch2%ц!,h3A^ⵔiC~![p~+z2\?B!Ւ0!{Eiy(3l9^m TƛoD+kʜyH BBY >}҃w/eųu0M(ox -nBc?;ًׯS r*}pIl1`e[6 BjJ]$WlQЙL*6nuݻ|47!Rh-~+UAoAT:PЎ E$%?\f^^i .& CU֐^oOei7Z(ԙ _]Z呏30alkqiGo +mv [|` #l&_k͢+f`6M\ os(@]. r,JW TvePYX9dz:ZU3sAdb8zPr(,xk;l,$߃8˲{P*XXDJH}Ɓ}ZDق a|-sr#1!ZUd|D BVH|z?:0(OoHc I1ˋ^Dc"zQ}*y%^G}$<8iJ_Y)3-ў /sp(Zj>g\_O^d65[fQUZ y)}HEJ>62ɘNYVpκ%x}>"t#.s(°'11OD{OCZm&&T郎#I`1&%/ji_j}+q>B/vڍlӴRfۺ l} /`Lk`7l5oLU*&%d/<ge ţ`&Wٯ)+(fߦ(jOh7i&>lRL ĥH׫Ղ;h?X<}%uh&|3C6FsS>sTvmv~ݡRq Ï@je2yUFF[MRnjAOaWY^?Xޗ{I]#^dg4}晖|L( 9$A痘 M<#t'ZWKN,bscmm6yi{}:v—% Od+2tX;vX !;ZH6U3!!n 6V{ >w_ :Km>/)pm;,Y 1F<pD>gyJu'=TJr(Hy :WN^06~! (;!t!~a9grcEARYPgwv><}|ܴіWL|/w`n!1v"@IDAT#呸XI#gJT~ꈽgRa(ji(|mY9d'2}A~ֿj— {/9:Sy ;o# H,sen4 nHܹ}^>y 6Fs@tYu3c酗/f{! `R9BݦLmEN7IԅM8a[o6<2hlJ%cG`Bw!vb֓^774eFOyHv56 :cv"cfw ,DN¤6_-@@mkKK/!]iu ב &xI R6VL\+y1.=(Ac!kX~M;3Xx ƶ#]%3 ,f 6VH0Y[@Y $ !,?D߲:1:2;==fۡ8d 9"*9(0gxRv)q cR0tqa^ ՛WـΘaHC.;A`קh'1q U`zzL,v=,)ljGJ M&dzX h@W1.lB"ԕnEt65 a>ˈ˜wIJI#y}d4#H&j p4WQ`bVunXWŐ}ٚb.aA=@'2 P7ߗ`8ύpj`dx Y[,q={ "yyy'H?7q+lфh\Ue-Dk 3*π7L N=g1ЏC#4dȂ޻Vlhf)iz3oz'&)]Gn.eHѶ  cC޲BEEBŦ⏫k9FPI.O,` 5Ljd+jLDEHӜkv9v⍊ҵ~qb|lݨٹ]ճ[B zR}k%*ڼ~Y9.4- m\m5k\]F> *'9=죃㈠M;= Нdh׶Ay'Mb9W&{]+8Io?]0=dܝ-ݖCo0}JrŐe.+v'z4 `ߔi, θL\ Gᄈ[&$Awb$! ?L^Ĉl<E[(1VaR41?C: > 6%x.9DRtXտc,- 叐(Gmx~eAW(ZwDdo^})xB\#y&Tr]qZz"{` RR-%&0/IB7ͪm. }^vٽѪ6yh z+KdtYk"#f\j%nqUϡH0) 0u.dHOXi ~щpP0:lW|E4p9l{L=7|tXQ#/&u7+gɨ{H'E?$)=8E#~MP ,o fo2X󰘜k^V|nCn9M% ͐jq<~;ZwP2)ibLb~L%&{`%ARҌ΢!<`Ẉۘ*/S >`}'4<#bl$]-2PFS.V'G!vѥZfiKPSi[߼.xhtXxD sIq#ruc/Llj< ^CI&V>Wp[(k2~*I4d W+1 /]xenȣWn?bYrN `,`>Ժ̇۠k!t\#ew D LR^ Aa6[UrfZ3:sp }*`]675Ue9Fn \sb nSO a]e bHAr Փ2lȟZ~nn7!5Vٟ z3T~; S)d&H ߼z#a&D?B4ºlO>Mjaf["t`J`y.R67ʐda Xr!̇$Z 5\V5`Bu(^L$ԟ?}f;DǛ$;Lpaėb^¤(muBv28\FRcD]f-<$لą꿶nSnoeu!T0݌YN>~(\:jkΒ*7ِGj  a *Dչjp! v,E"i#jhlݩtOXbƨ|*ʟlUgą8Xum qRFzAvlAC`7JTX0 Dݴ)Yׂk@ (5*l"j$@ܭXWJ=àc3o9ۄPY()x4lnCϛePm'}5m}b86ʌn-W%fQc_c6 LZv:SqKn=sGԔ }Y!h+"]Kg.cCW7WwJ@8o`|8,6t67sbzp JXH#pcrVR2Jy݂Zϸ19W~<T5>ߟOÁO$kXU"dR>k44JFp?7PʼwV@mt1HLWIC.,@\]鈅RyyA,Xwiz$*4Њf;Sd 1Ԗ*2W#fMDj_vsW_Q\1~ټk"CaKaLbä%O?Cl]س]o;35sܴ~. "uJ=]o/(.Mwsx{L[f/?#أ[9D"ڵ*%z ύV~g=B!&9t8~P{@I Ȩp_R.d 8o hn ڼ"ہxţv~qL}5 X}n"%85hzb6>GYi1Bcu i_I٣eIˋ3K<Ŗg4mhh?XjZ~x0mI4;Zq]Y-7̕\@1{f zB:Xk"`6/0"`-oZ!k0>0a]v syZ¦ $!4ˊ`ԒT5ĶXuy@?Szps`J1]̟bC-@x7)`6pRS6FJ-aFJA0FJNΊ[޼ӚI(Evы H ,s5<,lUc褞+A *p)gX=8(-(ȤH>w'zU5CDNRqbm"xMd /3P4#hx=Fnz5ɍa-`h7lpdma6h40=E;UNDRw~>ӷ1 ,~Rx;I \9'{ ,r{?;N07.A2DL ;[m=[j`MW3!48Շ(R4د9Wi"d{@E{/_tt"$64D ^8\\ÉX!k-ՂW4}Npǹڛ wyʓě?R0e6^WCӿ>8`PǑ6WО4ܗ`*hRb:+H7K--bd۱@f Za\VT#zԿ%sB ^ ZyLGY+x!0 m?< w#p#?;lBQQ߂u+J(eZC'.6eGWa~S6Pd/,MT3k042^شg+-Ei)^VZenbv:5T4nvQ憕0C;nSd5fp!΢Mp3_) U[w 1ը(@# [zmǀLZz U*3зԺ ׳SkdsMC޻hehœ&ǛąƏt ƭE%[i6]qk}+oӑAe~mVѨΞ%GC8uBto5oZMl6Z3%u6d]DzΆ&&[^!w!KY~-n*L6妧/>wS5Em-a :!P?6ȍ3yBQ]dO ^-?la}K͒xU6MnT;֛;!A<.gxa8o)ur!^ӕB KUU؞&lt0"b4=""0 4rQߵ>s%~5]Rp'7^32@!R5F#%ZșdB2C v~2hT?y̸WOG?`c3oi^RFǹ1崁x!1f=z (_@ާxY/Tݔ|M/e gmUsxaIAdT#k ܹiu8C yZp_kAm_D8e`L?? 1`԰Y B7[aEoN~mf"^3m>)}dJפ3HwۭjDho7,+ܚEOIRo.]Jow@ۏ?C_ mAs69$,z) 7v[ LideMg[Ͽ@^Z4բ j1IorJ*v/Եh\ZxT%F jt [d}þXi8e>8A;+adXi=o'0ȶo/dP;'i܋Hu(ؔ҄g#:sDa U+skئƜ4(cr.[7t.n3dM7T&[i3yLP\{C?'m"6ʣ!x/KDd,d[۪D: $*A_J ; z q۶)8t"'%q &o d*ƥ>#v}|sNf=竑__=/Ι'x3R?߿#{|5 m 9Fʮۂt@h,Mvs=v&&3=A"-i~Vb2H~`0KXiDS/]t3Ƹmi.dR(6c 8#%;!3 ݕChc`9'hnDYӈ^u`9݉e6Ҷ斨Vr+AםD`jF6Ho[h5es6g$ZҸn}a>Rtv "ԯvM`Zs䟿Jf4m<ֱ`3}|5z#<@,ƼN[I%+>!Hb'̑vƻaڸQ!7$"EFq+!mނ2Js7&@bƍJ$hPKqIcnMpx /_2H 7fXt"c6b'&$rbY9k$#dDMU; s讣拿X݄FSa[WK 6އ|$4z%h"dhn|z艬%cq2DitmCY CRHEPbxʍ|]m rƔ?|I 2sKw݄i!k!I ; NaMx/kBA3q%z6;7#!)X„` Y e2H0=0Y X%,tk>'C`'3**h79)!%o( @uwDru1-| ­xjڰiް1S4&IF.,Ҭ gv'"|ZKڼ#bExR?k)pk̹.m؍a 1Xjԟ 2;=kw vi^j"mߋcs]M5UZsa@~{|p) 8 d;?AJ!/H_:8PⶕnE #;qs {'5<2|"1oeh mvj-H {׭ܸUA1݀P3y(Q# IҘDGw Mc2hrXϞA}m*{PvV=)۬ٱjmRswݝ0@F~ϖ"bٌ)gNk,&;"b]dWrub\1m<n{BeZO](lF_wLTӶˆ0yRyD O?8ڇ:sҶlg"SK:ZCL b[ ,%j_a82x#C({ޚHgA>P)~_q ɀ~@gR$`f8x Pba | I%8q cWQ2oQ [sv3|XcMT Y!Ԗ04Իdev`9?(aHg3-CSZ[)drka")_B 2aKV !!]H 3asev5nusef긑},U\&%Z!9َLJ<b<:=f>S3öpt $$nAs줒32) sP#NN떑5/Is%^(^CMHs`WYc ^:4 \Y#Oi:dy.M510Փ^ ͟ 2Kf4ܘ6KYɞn1N ]NZj~#%#<|3lqDE诎Z5VQgfQ9* lG !67%@ .9",ZB,Sa]I "68HvZJdLSk8/zni+|dW?"jevV==nsq6ղ| +*jYsSFAy'$Lt]3͕mEE|/\124Ԩx%j3s{ȗav I"8F2|r90VQVwj7">|HO {FLUW`BļawCs7" _# A[NLܨk nZu ;v,0EdBY% Huae؇X]Q@h{ahd{A=Gڐe\܃n~ρ!F]VS6HOOS@GCtJ(=>2c)xJչ( /{(@W% {M\ Lhۖ^L]<L C:,gZَgG9;|2;=uY-㳰};;O.O.f|}z̭@fI.2sЊHdVPHna m ޝSd9X $< y@3fd"e4U mVx#NE7n0kD]n;nD1@ (ǗLA~e(;"PJA4(ܪ']>=$*;馚eKPPZKrpOaRUZRCF@(5a(b吖2fYCsOњm1{|#XY@_ExʪdHY97m\ dӦf%3ndK<@e$oD܎GE|L i:Zb>7:tʐZB#jB=~"H_&G)9imJzs]4JI&eqkK`$2Σ9l:0]XrW9zca[r,l:d<(AJYF. itޏIeVRx<aWT"%ex]{M>q9"@!I`p0!aNdGxxn4.^(21v@p$OGCuF(Tּo,Nӵ)`Ff&3&G\4g~ܮX.sK4 "aX~Y˭Bxo̞Ohwa)­%CTw|k@b_],uwQӺBȆՍNɡ~d: NDMJD JfKvpdGDHowyˬ $[ c=>CD77L[Zvp= I$/" wgmʪZjkؼs[)Ru0}v>FcfzºkA4,FW_*h ȵ:=oJ\r{T6ě{0==XOJ5._whzĚL'UXݎ@Yt(t:l^+# z\y!៣E.fnF~RRv*Q_|h2 VZ`.m1Y,F*WVrα6 0B6H0V> Hڼ ̈́)a\](zV:]KjI:CMmC*='Je85[?1](࢛]wumf io g@X㏾\<P:v+\.Bpڴ}sn:J2Sfkji]NϮ% M dlN1l ^k9Qvt%vв܍򫀴y[)j @֝9PJKu*B)oR/2iCiƆ-3(Ƈ,c΁fI)F^HnKߟuY΍+S<`PM ܍cnGk$)m {OaWy.. QIc@TԃeN*R-y")zbiƱZ]˙4|נh|:DytUm 1Gٽۦ c? ,,֢?. s M9ǓwΘ "mL6NJ*F [6yXgғҁv4[!gj7mR{ل>+t|m*Cx]2iwu{G02 =$_d5/gLUy*( CyT0 V>sA<)EP6]BD}m?7`0|L^yLPwB믴9R pV;G@t$i-5,Iޙ"ܠńj؅ŗ͑EqXCaA7,\u uK{΄W\6(1J`JYXy9sZ` .[wJ^ӿ C !-(Ug!rrnxr7)) kYŞGΨ3h'nT70^C??@Joonyծ85HPE}XLbr6qf.1LL(Y4a 3@Kl6> R MlƖJN7β&((1JTabdžM݅_<+*DlOl[しI mg{DOn2 &a ܎2Pvr# &ik ]AFpm>(o>/ʏU\mlfOLp565 xgZ2<L[C\={Ǥ#K9 ءx-FGGڮxN!mW|<K/b %'m  3-2AeTt1F2\tBo@IDATLk `^vW! J7. ^S00:dT,,n,Akʕʋ_KJ&ivl72ltt[8P)h?"pF7fk*Hq2d8X3sehnص8˅ <~=/ Dfx "GCo.7|E!n1+zB3RvG 5t&<I";$˂sݨV.5}]AZE5la 88k@BZ`qfqC@ʫ== 5Bc)?5sbӞ a#́EepJ@GM2a'ι!>q8I9Mӊ=J6 O7d 2T܁[u+NI`І'C@r!{_rX1F ORVLv/@2+%ǝCODO r0+q UCN#(Y`w)o'2? ԇs37W{(e2NAm_RgJ?{0'ٯN>./nٷq'!"]O@7:I:)vPtsy9Xc_c_dOkʛp qHon3-`$=rlp[s K*䞏auhH4N97B_keΜS(3MڎyL Lb(0>. J`0KqA.)Jܤ㡊>!8啱iO#I c#~lHs:\?ӝ D Ze B`2\MnhR9R.s9lN| EᩋA xZtf{P>Lwh @Z|fkbr3&r^??Ogd-$W[JzHtI۸}*3W5Ds-[2W)ߞް}%VLoOSo.fl+VLb0R$2ҮL_nhYBկ9Må]/oj&KEEA+œs? rC"tIA)tRFRZ36/firR-r~ 2]P`r(Fy ,0a\"ڹj<v54t&gFBTJs4Ecp+Ruז: SЇ'ޖZza1+4聲y ]97Bn_%A23 oK.dt)1Kc;A0]MP%ZYc:[9tt{ -,+o⬟=<B6ff`m%[ģMwgJMI^ZͿ58Df,ES(DPOfr\d{0Y[R l^t?2 ((dׇQ d mm<;&)9' ~Fy#KTBOC;^-zk8(uB A$Np]ԝto`X˯ۊOn Y?g28hUp[:fMs)̨-&`Da ~.T r’i&KC)',y#1%+י<>".l(D=Ya|ʑl| 4$^К1 a%rJ6IXA2c f ^} 夃_`:;[_vJTEYDSA}jl݇l{+`E6 6z,gu5AșM,*E&f&ѭ7O[A#XZok1"Iz؈mƇzٗQ[åVA"\7ʛԌP1n_㽓2S|g'R,7B[>-DuNyp ^gbR.C\FrQf)09;ҠR gH4M[|<7W=>\4tS-@0x1 M%wpzp)Hkpݺ&ŸbCąҭʂba % UL(Mz$Ao(QpGMxMmɁܳvcɝGюK2%Ru<.ML"&,WdDk/pzŃ2)"\6CE&/?NJe z=?#zb܁wgځ/2#? 7lSY^40t9̭peMeؿ) 27IZ\Gʳq.&L 0ư1+>''K ,R22l碒`V.~JӥP%SۼP=Xƍk{)L~\ ]l%=aLa^R>o0޴?AMA( |,E MrÛŀ~\8x7ʚk"3Y 4reYY [y¥֓MSG_.)xG˿ZdK-#I3/itD|, Oo#[).Ԏ6!ARaӷqjbo Tǻ:)0n<b@sמneK7pkrW"rC qLgv%+>ef(QR6AJPCN"v'b6k=B_wCb32=:MfrKA&!U\0I q.xGB7Hi5ASfPiäE{k\|?LjlR@:z%d/sXʶc[I]Wر-!r,{XIpVf8%ad@ŅL8ry4̀\߫--g5&#K '3ct:>b?b/o,Yh>q.yp9K9axXؙkrvƒ30.uK WIpQX$+2X9 @Q:<[{혰 )26J~kl.ĕo4Q"oᒑ}`Xj$-k,"KrDž=3u XOXӤuAKNYtIG[2H;਒Uʄ̇<#v=0O#M8z1qȑ$4 :8>cdfo؊y#'ocUkwْyM&ޯAUImr$nlJh|Xyo'JKHf>@Mǣ;@"Uz?]{b'@Q f&e7h[h}w #IGs3Cl@2Mt TWkqWBGx *< h27BsQ?k{jmFD&n@ HwqQFɢvd4z58H 0i< ƑgM3Vy۴JRpʟXM\F+ hذ?gmR88suqykT?J Fyf? imjn{zD;dPԶE:z~? rp:7Oܒ<ζv.½ptkXK(ϳmH5Y}ZXje1d- }2]xh.Rfp17GUK˹C0gøЉ!(߃e}iP3vfPbj*j_Vܔ@~ͭt@qx4߸ϕ[!CĦJ:7mdgtjV}6 څRSCe%vd{WO f9Qw̖S1\P՛ 5ٛd@-({z;㚕_Dpwt74ɐ&.db.2ӝ$}:c#XII\ k,aI4A z2:{NTǝ ]P.]f)2x2"≆Fq+>98|ۋ9oԉKc8mt(+qo}sƬ&dtVw7Q,d$aV f.l:v"}74Rp$l/.[ l5szI=A- ^G9Be'YQn<:z}x))H8N!Fj0ШAڹ97D/kOa!DWwۗ!fv_!mHsx0&jQaW Ya^ZJ!=øUn\n641=TޙLyuaXj_U1\hq  !{.\8P^pL5: }i[K 0ƍdBL]$w]l J%v牥@O)HaXtv[4 eˬ\ )%x1"d}"G1ψ!%O<@M|D .Ȳ(.'.s =\rVO0C*[v'=$/ hMA`Q"v*?"l89 Y4 bpMCL<"{:F|=fd6'%[_Lj!ʑ%Q~j?j`|rp5ln>2i#sMTľlg!JO >LGmw\ڐXuF4܇Y0-VLe/,كȹI8˗59\W]3/‹l۳VҜ&$ɱf xMG=ogs9G`=? ';#6<fI}C sN Bj\/-&Cji>rfa~( qO4d|]ĕZ.1ki/&pqCd<Ǎy; _Ł 1$.;H+* yvz{n$kAXՆsDrOHJCԩ׬NJ܆;9).D: vQ[`>l5ۅב`59>2q 63 0x0^DU$N֣9hіW黋y3$)zz'j^.}޲lK̕Qw_XW $9^m'^H"!;$ZSn޹"B(Ln>[@"ZxbY.Puu0l^S|ORH띉 dIjqHYTh'=.A{sp F3(a3cItd2;ޕX[oF_8p3T'vػ̉]WE LU.BdR|,ME w(ʝp&; ;ʴ Zp _Z<߇g2p${*PψOs:dn:pϰ]*)Hv n7N7gݷ|+YQV12܍-Z}}!/ ud(B&!=% fseTY(GH,:"';6W7ʨ1fK\ mJgF}!AW&@h ?|H}!Ӵ xSX$ (茑O 0#1g':aBc*L=bqPEq5V:d+('9>lNN}>WɢŻx0FÜa2n\=ILZsiF_'ƅ ʓ^'w'bqL|603ԏZ)ku|4Ap($#w7ɑLWb'`0\ˑR2 9M*W ,ِ b,RyNjE >_l" jRj6 u .*5p#PEѢ)9 RlJ"Ԉx8|ƅ6 c΃N=6$(#dy(=(E쵎UT BI$*eX:"@`<[E,?_@CMzC{QKjBO}1 X32+/Zp{ظ-zM}y9Q3:hxrrbNv !ײpJ?\+0%`1?ӁCl6m^1IN5W\F8u4Y~Zُ*ap !|_>kZPҊMlm)\#{p 5MTą3`=.te^.'ݝYjJ3) b߱:zñ뭙,SuT.D~K&6bΟ9Cm(PZy|}Wh`,|_6`))U?֋U)k6+.%/ Jje_W M}}"5wnRUه2WqW$~/3Wj?C5;ۋ ? "27$#u}!@r s`morʉ4gltf4ˁ4ą^"-]-yR/A샛1~T lJY2Ɍ^{L,Y~5df 0HsϴB,VN?8Ry=(;VQj= ߯`μ:GygojYXuOJ`yoV3?!Oen24<#[8D< __%J,i)xE4A6 tn/-gǹ3Dvw~?:K@5FM"StsA×Bf *WV?i{=ANbAyy+i93K=˞ f [}Y;M mTR3XV!S4Byo4v?36,n37֒=}J,Pis@ MPZػ QIϲc:u J9(Y@6fZG2ipl\Qڴ umI5aܲ#P*N:\Zp9g*9@QQﵑa~x=) h8`~W Cg1=I9AwBMa3 RIoT.Z|37QoY–E.`$bֈJSH埁?g\G662ǍC%I{IR[7{lzzlL( DtxtIbü(_*+Y{;M9Lm&'L>4SQ"F5] s8}j ;h{Iio f@\B^hsRQ9_d3f,YQp 1hs]6E/V1mbj!+`9@f:M@/Aϥ)`L 0|,e%xQp,Ib΀"ڟ;A㱏,#::mǻw*/ʟɌT>E,TYL&? K[CIv*,FͿpN~ "> rNu; NЖ#(ߺƌMz+6grK:D'2~H iP{T$ VSu=Yj3Н«u8YR".)mT. _-3㲼,$SCrbJŒ;Vpq.Y\ӧk8:%e,k]8/.yzHX c0FgZFSʓ!VFE%J=w)1GF_\Wgp.ъxnZpk^{MΎW+mKRP#(Ka+8Xـ?*32.>< h7ܜe]z0]*"5HqK@WI^\[]N []Xr}|d5&j1h /,+]H"m=fnvVp -aRhƆ.ɜ{­ ='] ?i!-a֑ m'\:ˡnK$3nR'>l噚 Njzbj(J#ߥ D셎g{/>Eǯb Z9C"m#waŽ/`2CG,98N=КCI>&a!\|`3!['ZO0ob/"?c aDIm'~mC!g_v4Xu:ltώ)-XG+ ͈(66*; 5Cͪ?x .p%6$sF̧k.v0 bǜ\|Zãz J]Q)(jP#!;$ QR .g5`'wUVZ,t]\m~<3 8q!DvSӥR?R.e];Lsߟ&܃$qFX]o}j~ 7'hk 5 c|v4'S)ڡrbRdVe2E.ED-hPIzLJv1:F:{d[7_QL'd;Ol %3Vk9LywѮ!'{Q}F3ɐ6צқÌْ @$/gB4d۾1VqрtX%KqUnhO`Rɬ\w^W(fgUxcsx0-gM_5Wn? w^$5YMAH@, ? %ҼDL 1+0>??݂APV ǧNtٓ5yh0=xj/=| lW|<_f܉_~D#Sٙ`Ƿ'bKƴZxL&3Т)mGv3h# O{.XS0A#D?mTH] ؈2)EY]yȶ2V9_Ĭ5kw/bv@7u~97s:)#bWD*GDHUq0r7:a J^;UFwY̟_Y uO$i)ZtGV"_m 7 9u]bΗjkDpetHdNGG1w;i! PpsUq;S r{2nZ;oLg#Tg0 j?wJ]tgsy?<D!DU#[ZExgK63ҋiI_<6D)icRlGABݻs46X4N@\ [@uȋYaPˋZZ> 0 bj8,S9,G**I>3Sl< XA22Sj@Hf)uW q}02tcOGeQ᭤8HCǤʦϪذmvwqēx)9t}_"!\F{x `9sB~N v-@5ex{dU@5cC SWG 0s;!_k%彯+`$slYiE͛^кdQz6>=` kj@u9  ;!Si\XT8?U;̝s6ʿ<!ʋ eEH P4vsVzrԄs8/ P~H@XOJMsR.M]h   hge[%b.R"@=⫷ aVDucgʥyv }\RYgk%ھ{hCc|[e;6KT&"*rS=Gſe?j@}UY-va'U9$9c)\e]\A4̥?9\+l|s7uP]09Of̬NeVՀe$#N@#LAU3eny 4<`wkgu}mؠmG*Za Gx+<]A(076?H4 #e-&NzĊ>Vk|8V#h Q0b|;.a6 y?freםLo{?r"D`_K ͌{F&:$$$|(]\`kRΛ }gjnN~lAD,'p6:RUwP.[R2 UCzɾN:? ԳAb@bߑuʸd#!t!$jjLeゔ]EX9nV{?Hx)9DS~`]C%p:nYMY>gm0%i#mtuJͤŽv~/{ `Cdx\5=#SY%îc8cSNS3cak) (P#yEv,I.f,,xkrk_?ln-y3dr喇T5 4N7jHH݁݋#O5 ^B).XĀY; c)j?~n5IƬҗڕ/UHLKc>^PAԐX. d䍵5&:"F<hx楤}Ͼέ#Vh i)ByjЖ{7a)D V.!šg,1w (5H1NJc\b*JvmSYYBDcㅗ%@O* ^]iV2$u)&mqE] gR1(2ʭDRAbM eL_^qKglmX{ [B:hxжwYt_1tmN#؈b=KЕ]- - 8T ،af-J$-lsF5>cn@ ~eVc&Q&GO`ҌBu Yk󪣝 ]a\@VЉahuK^G"2U/2>0H<ļ8('-+g^Brќ#:( @ZH6LYH6?`]9q\uON(>,{Pĥp @M>i;cS:jQ[k|[sT |?QF@Fi/״i6 ,12'oJA E?K67;9ÞJ b 1e`R eG")Je<X_H)VB0j8: <h -YtΦIj$!H]M')8DG5@żx-]y_b!_s'~uOYOxP;Y4)*ݦ.!DY~u 1  St])+ZB/ȎʗŸa0PITzw$6dm.,$pܢmje>/Ogg9_?wmN<6eK@bʜuifˁt z>6V*j?~x ,z\<8^b5gn-yt`sWNh{v>NeBzTVSӼ(VQPT;N ֛!b$.4^-}~ǘP%}dV¯pa}7%R3ہisL۳Ë0_/_&j Nꭄ.H6[_d_ q$t/vɤx:M;it{G}G+;a2kI 0Y5o3),md!t;xE@+QeD .@GGpO)M*"Yɻt!.';:IJ6d?sohGykSgs;R.YM9132!-5̯\ǻMeA#mkiUО9WIwdͺj()4)-ι,׮#PfZ\i\d#2 馄!dW`u&w/J| /<,ܖ}S"X@IDATcJUp4H{OSK̈́=p y,BltQoҼH]MmC"cgYw G+.6jܔ!Kˉ&k.6ڀ L'Pb/1 _ڕL˾:*1X{!ɌJ62{p;)JG^^dԽdf\^t 9+v<sRӅeh ^ t2OwK۸P֓Uǥg65?_C!Hl(,:k/cc H19lݦU_aBQXlHi)-65pDݜJ̔ ff3 ݐ3{u<@I>Oz癆>EY'T$ p,5!pIX@a`]HER1qa4-x^@*W_oή5N#fЁEEl5M.׮X TTш`x{[3d/i@>ҙ8PNW7H<ӷ?HJR8M?Ov]m:\%C06\|Ai`؞vvARGy qSe.lxG"!)̢vDփxMe#fO#Z_b*k)I섴#/+sؠ3{!Zq!M[ot:D 89|~2>ޚL0zhY}W6`2d[nd>?'/t 2HD&~uMH1k~=JX, >HEWw1zmZ'52-f=?\HK{fr4]XHRрZDÀzo~{Vu}H I{(i&9Tu| {bk~ߟf eOIey Nz篻$2 #,uGk{YnG=|_I9eh[ ]J/lٵFn~?`zAL9' =ao7ˢ}k+w d ڙ釵-[JSbaЇw 7tiLϖp$ a;|n(jZV6P&?I lG^LEqp+YlK ӍjT4ڸJK5Op`>aJآ3R&CP;شKlO\cᅮ׃9=i,%p]t̂QB"K¬!'π,TφThT|"DT%)v0VJ /=mL G 4x"I-!M!-}Lvz" z$}8<8$)rZZnKxS [N}0LONNJ\4y~k )v|Y9;oȤhB/} qetxxx)$}PYKr+?;;;F@H%u&h`&Bߴk;m2}Wwa;ߩ4@=H&kli"%tL 7o?ti7T=ȵZCX\d'G'Dj&:2o*8$`d7.( :穣F Wa@bPBLǓ 6W_w[ܘ_|nS*nGM&%y OϺ|Y`.tŷKHPp yXiUav A F2}!̶Hp^+}:? lźGIhFےФe؂q_BIv Թaƅφ5#]fh1v(eB{^c[>>7aIox4tnDGGITm2R;4`ՓY!2ѻ\k3=}eV̆ 7WLXXa&@sݾ T2~= p )0 ^ U'%PXEJ AXJ_ pβRbC+Y[®Q4tt9ew/)km2}D,*pGyi?-廁^5%w ewFYKm0呱 ; óvS&d@ȨV'z9kH ։C ƳOQdHb+S!"o$dW[٣n8rlr͂axeշN EZNA4!;B5/ZKEuh މal s﨓zivv[Ԝ/p>PHSkhyD->@?^y// @qa% i>7f4Knhhys;zHSF QaSB߲Id)|p̥x @j_QxHڅatr. ᗴVi95q6TK][*[ oZX<| = m'vܤ Ztv;`R~s(# P5IujelR͉@hyG+f5G*;rџ.C'OPgjKxƣceApQyKIxoa.7GIG6dsS˩'xRR[Ee&f ^ CvQc] vd~ G:N@i06k{s8u %CxV?E6'xeywN1XfV˰岓]3!'G^b#i%:>)e ;7"")( u9n:Falz 5O8S|'[3A9APaqy#jpMVe[fFvZ-}gG8xY՛5+1Iɶݬ9lڻjÞ!C^b>-W(j&y +NV5 =<8B Ϟ" ,^D|hݐdlj?[ "0 RD@zcW7 Ҝut Z,so!W>N<qϽ:1/t3 ỷ}e߯i/IJ KHrMYi%$%l `PW.K[1%DPjDf &6-M(QOk%Yk a6n'AVF☔lق/aMOB@5F-o֙;E!I8idb/L~i )a%eC"b/:Mi柳YW`H:kBv/D:Jr}\ ("H%4K _Fɤ+ߖ] nt4z"n7m *t8T8‹so;nUY |.DKq%GD14-Zg?=Q>p;,x_j߆u IOySQ%)?IA!~vfH~?Aq3]C/I8L=6%}jnV{ЊE RgTۮ)9)cj\ AWlj-}Cą= "OKws'!.eleHګlAdUFVNds~p-xL; ǚ}%>)̙HL(=Fг%cϐxsCܲFG,,*e2rV#/' SE/{ a`0u5*Վ^ ͚|.Ek r` +8O)cȒTMz#E&+USݤ-Rĺ8!U:;A-Heq{([Q$m,a_*d]s'h[b8ut?I==:Lçi Vq̰gDPKhx@MP+_)nkD n Sxɴ"=I_dJB׆.IXy aDһSTjo\"5 SA۲Ne'i1fʐQbmPE;"CŬ6? ^?2NPM9=P!$3kX=3sd:qv#* %-PvA):R&i`ݼ~#c`@\ԈV/asN3v~,%M@\46۲h9Te]\=(s|ygDBRx.nœ80+dLխX|x7o4z(+5ɕZF(:k{ʦ|x>!6S p6:?cziAT|4{Cl6}ظ \xB S{5L+]LI-Z6-A<(U`CEie,r"c1>"L$jX\.Ϙn89Ɠ N%l7Sϒ;ڮVqT}M'[ws3 1$noXx _ZK.i03d伳{0U5' S1Q:uw%jcY d0.iσ}%n!'RCDֵvW Ueǃ.oB]6nݼkRi+BmM:JQDX~1 $.^C.0oOoӭKjT܋#2hڄ(JWǰu ]x0PxWp>jV\Tbep:<;( "92 h~Iq>^q#0FsY|Ɛt*ncퟎ0L+K4(@\h2r6ɑ<Q${QPFB:1+_{=3ټzIT8xFE3Kcu<-WW`gBz*gy4tz7<#JEy)bCJ\ʣdH%J 2#vO(j Ywi0i3hzo>/rqBT #(@Q~rpN$E~mZND8/ajq|.*y5ڬW}J87 \ny/5ژՔp,ծ#Kwsu+{v\=.M8%4W\lӼkr {ύ@6%HgR.2Lt$0]n=*n!2/񗦂6tϿ=}+Zk̥6ɥ'f`I J< PzB{}D^6kId_WQ >3m6|̌ W5EذhZ5o i-Xf(Lh:}IhI: Y-Cڨ6 +y3))Vl%M mYm:|(7M?֩/Φ$Egqd##K'|0?  Q7+W '[Ƨ- s俕/*#0rbP9~+ula DZm>CGB72:{uH 4هYL7naLxx8yPyJ<.|>-ȿQҚ1[%X5CwR2t ؂NH^@Ua/{T׌gs8'hns;emEjSj=>wNZ=LyYA."Qy}HCpcmؽm(sPЙqf-3e>?޽wDh-ȶ˷cnͷlP_8N.6;RNun("lxZ.*spƕЁ''}X#V?BjfZHi | ?v&|Oi'H/҉gAk"b/bU w {/\S%ЗH))19nhj.[Za_r49{ %~C Gvh_evLJMh({f$4cr/Q͘~wpivHNy.LE(e22:( D4Z>%;Yѝo0ÅL-R(%]l2ᔀ*\M\ie] Ca{1}<)CmfIZ0)~gs.rAλa*M"ϑEh崔O ; #0d(|%$. YsX7F^W~8o6i^XRjiZwF޿ㅈpy-{ԅSBYњLACPA:$:RKR^<wfX =+CNHD'X?g0\ \#|:?5}VhZ{1s75R^&u]{!i[Oi@Ecq?VN$%Z[& 0Ѳ= xn7U3.N`*5Sɚ&֩l|F FGɅ??oP19EJ/ߧw2mjSLeU"fsrRL`^ߐ8,ƌ{kKeN}u,25;ٖ"|.$8d@Y1Cp)9Rgy_rΥ d)"* qauqW{?\!N]p~*ÂӮi{|$ K0kJfoM!f]4P{}]tmޣm&%ȗ`g=D7"[w Mh|8JiRUy~4=E-890 ,=MzSfjԙg|2;oHc:Z^LQ0[g%℥7;9 rlE}O5rm>(iwdV@Pdx\v.洡lmDB=TH)hER2ՀD. G>1UL&c8g4;pR9F98X빔n߰N[>qs= L>~T:H#btTv;k8CDGkU=я[sN KT.fX~~B}_b@6 !sH&iGnq@zod@٫GͣX/$3`pH* ^pnCyOP ={n pDUR9v!QNH_+ZHI)l$as2WpL)0I)-[ڸpvL0)ZQtdoִ`e8&Rwx]N* lojgZII-I hwgH]O/kE8}=\І  %r3{/uI$ ~Y˔ >&=]6:cř%%t`4H`!+ [UQ&);9]]xld_:+;lZ|\G%Uې<>4_6jo'ڧ|gaCU&0@x wh4cXKѝ(_Ω_q%-?ʺ68-/qa^]F R]@tyϔi@'ЁLyHQ_0& ݼZ ܴ˴ꮭI(O?ɩ )G $bd- nSlx^;_V>6P]CIu3NLh> r`2aYC_c4z#ag0KZ^]_ԥ*TāyŞV=tt>8 0EQH(^l&m*7v%1HMƋ|.6a`Gk$.ރ|`K_ 83 dV*#;F(A aݚB/%ӿEcⲀ,7‹ /i$ NKBb<5Y.mےݓkX5L\rFt3>-j#[TQ1n-eR S.Wx~RQXV;_R3ЭC{э-XӍ$D*V3p fOpp6tC^}ljV_$ t6]6pp N#c.}} ;st%--NPxsJJ$0힮n5 dp{ 6$kqّW] NPYamJhz$VX=ԗWkcN \] b|Qx\|BYlA): D+cD51"HvEag=2;]*Z U-:Y3}x-ht 6ɣ?/6mCiHiml%Zt6l\it7fSN0[B,Inc0M& JiێMh΄ ,g'rfMٓW@r F(-8]`(g3ЮOEzZ]FJ߲ ,Vyt?HEuaVp]t>c;W^gЏl ̼`?IC0?_#CŬ-A)`V1F8a ٨Cg s˒e]'ss sU9=:AD ,=HRħC|/k|=\5 v}jxӨQԧ5aOD!̹ƭ'!:j1& &)ujFڞuG8C)zrѺ}YHggI_LUʂ'fDSo5uؤ<ľ + pZXBEF[ ĴO~? h;8@[*(b)RcNHEf,`X^A0ۆl;2b5O†(vatd#5["5cqtuЖf~~5O \C{S>KV Tj8GgZZ+JDJa є͚y&"&S×Ie&`l]ai>Mr6&?DMl`H0>"pT913Vޜx-mj!L=6(W)aUo8> Fsef$;BXF&#k6{pCkCU~/1xvw$ oφ-:mPKuF7юE2[-W U* 4RNRH6@r5CF566ev!PKS/5E| #(i mGBne1`*=LP76ԠLIBR*RQn/f)@ LyY<3lb6+<8h`fn>B.gSpIxVn7)A;! ON 6QP {ɔFgaHej'!Lj"!cI`M#Z$ gHL>·9i*ڈC{>.IKIw饓eĨ7eR{X}D2'p=D I ƜFF.1! ,Vi9DnL]D eAJ^Sϟ#V $ ]{Px D5Hm`FRO3Ku @'ݚx"2P0ApQrd', >RH+UʲFp%uO6CFrhru,I$|mjGTfQs={ц_#mQ;f~"(Ȱ%GM@f邈>;4uED;L+G`1;.Ei{v! )FBHWh<@ fס< T'aIIk X;&ǟRWeʸTʑjraBd  v0>H+o]4X!,AKwpP΀m؂ۅA 9t2G xS,y_>9S۵%3U@'eGNm̍Eه4HH0ѶRWRȸM5Ӝo;2@eɦl|HT-ZîjF <`w@P5͞S+ jv[זPLHE7~t>:Iݛ6,1Caڍ[;6 *^ T3҇c@ie@J-=Hƍ*vKp `[{L{ my5uYs"Hi2qsy FtܦgtZY,6k> ~} 3twO+` 2׮=D2S0CJJ͚,%~<ϡ" @zmkc [C`uZ9#>-^>)[r &P֗( qL,3R免%PJӍ-X҈*>ҩZ\MaLr}tTlD nާsVS9VJ )uWQB6FB]`Y )AJS҆c:n(^\ B@;IT/ J)9ė ]7%`χʨ@IDAT('GdoPӵ y8MݥdZV#]wl]wM"A]FgbH%ʱO7Aئ:!5t.,saź-(iS:#Zt+o>Vc A>p05laf.d|ƼI03=K_-kDpYq 1, ِ5ȴc:z Mp- =U M0IqLzZ5 $ BڞZU Ӟ /MR0t0`l.CGl ᦜ!2RypB'm ,-rܵZjF a: ?괦IUP n$k!, Z.ǿat/~wQ.`@yn=2YZn{Wѽk (Kz/H7x\dh i@>uUluQ ye;V:(wLR$x0̐pPȘu%: Sb53<#U)n| ydd1:8Y agu gS_}[]^C<υ%[J|tfղܣ=ڛT(t+2Iyrs֌ܫ;@ t - Ky'N>DnfA $@y`r2JhВeC+#E*o(w8@wJ+DZ! %6Ac#H\xHoFԽ0I}&a =lXu>gqܕ4IjqKS7B d/E&aLPc\d%cnC!R)))ƅ5lW2L ߕ!o1NP]*Syp5^ h઀[L %7"!3r sZFܿlq~wמF0i1f9{_o[ܓaҋGu_y&jwn5z3%"kdh2 /'-Di{sOpHִZXŁM %>X'2AY ٵ3`62Ld|f5鞴#5(^:"j;~5YhCi=Ŕ /5g')u&Hct'bS|"yo:p.mpC|x_ ;F%"yO~mpO|<|~´uuTT]x2#1$^a߼΄IxLd&vO'W ؁W( S#n<> 1Y )x:O:EKs^2ĩV^$1h(*Tѣ2 `8z򬉽V B0\ ^M Z o1Xd^p0 Q;. uR) ЈGln%^Rܞg I{h %w\6 `ĵ,r7m{قmxY,ySBV9tTm5  yNd%>e)/jr˂.~H6||n'g&Ukci'H ¡IL nI6sξ5-I)?r"i&_UmS WR5[{g& Y)y玩wMMD KU4 tgN~* J4e]n9dԁ~;R(⼊O +RMh\M*m':`mOɊtfEk؜}:X 'pϜ'D_+f#QX^aj,PBAV򺢚ᒀi=NRבC. `٘,>~9,Bv0}[c-,O!-XDޫp!4Y18JVƧّS $$q^bv %wm[Ъ5v`5wQ&b>DO.0#^K(R"뇵L9D C8SRH4{yKhݒD;lZnEz˼Z_#.U@4G`CPz6P2)50%WPy>\$l1ht?6&(}f* =Nو@+Z`?36oͰW $Ws0Zaʛ!A~N)!h1H4!Rp7¶Q^tp^d -Cwu H]Lo4~2-P7m+0:P߼, $hGgdQř ] g(MURrݭQ{Q0Ki;REf43 &遷Զvb. #m:'_{JaIE˛lrzFly#lH?(* 81kEn-NRoPkrJn3E.`LF=4Ƣc3A C< BӾo~]{+V+klH( h16c`-΂H.Y=xV{h̠b໿.Ui8xь eE6 #%)j'IJUѽn` ׆ܪ<`6JTKt|6AyO jdN#"w҈!%F9/+ӒpspBәP`$o5%Svx3/qTl!|ďJnܭP;Ycc=[9P*1'9Y)ƺ|D&:m#БMn>$j%fܚ%@^3';hC3ү+aKQ)\UYRZDtg-%8'o'X> :n5KV>x0-tnl]-$S[y1FܡܐR*uxqkq/* j]AK1;qEFqK-)\2GH ;MnĴ$Ԃ=Y ORF#b!H#u5%5!eD94iGn4E EM3nz3<%R/hm"֠QWp0 AԂ.pF6W|HO*$1 gH =| Wn ka˄ˎedid.//\wQʮoC S`T 33cUa7v|֚ ْ`p<(~ƈlMI=|+bD8wl|bc>@-B[ktD"I IO-Aꦇa7eE~ (?xL1xЈ#2 aFۦu%c#51 F"-%2A+= (oQMޑRǘK6"#EOn=@0ؤ%0b:)cG0$/0XIِ_j^)/?VtbbAWxH)&?>H"z"EprU4ڰc.'LETg#L:-/ey 8F_>%l5ݲ]b ނ1O :ݵ"bywm-'/awOOj&o[HGa9r@kOJ 4MB<JȆgod+t8du"'y Gh2ҜZ:[Vk;>StdHdkVZ8z) -??{xLzw܂28ۥw)jPpV4_{B,zCz]|քm>_G/ߠ}CEZO*d0߾[&M>".5%ei=mO{W{Ӌe] (3(*qy޺G)m;'jt"_suq'i>pIM dZmIĄ,O/޼B3.z'uz3WKҎ.~rR_8wF r?PGc"I߸с-֏ ox5n A&$˟ vD?%4뤮=`Sce2⾿MLld{s(3dc4{T{^h-tPW!>t|k?H=nnY V^uʟٝ}B()FTI jhtkaWS 3لrQNՐT]& =g,pnAu6cQqkC1?BM8G5fj!Ƥu@5š`HكPa'a&vn/z7^ؠF ju 8 ӊx"UxOΰ\&ņ+O0emJ/Κ:ɅqzL zb7)=bQufZQ'5%,tQ܅(T69Pa _io^pHMi1 pkeU+P7zK.b:@;#Ux >H0?4M+Xsd6|aq#YISVul" ~JGg{[ٔ d FV=d2UZq!#9_%^1;"`I>ʣ)SG?_!mp1q@,-n&k@綋H nĄ$ck$^Abx=!%p!̆A?Iab)G! Ɔ$kY( o?w3}yAMo !a$zZ&KEl'ae?Ǻ\Y3wdq;%,.2f,r\ܝ RYR '_XY]P S F#qlWjMXr =[دKxf` ʜΆ^0=.HO)s01Bz5;v¸uIyN `"A(u@eREo[NdQ׭ҟ;{`V~F޽S~{ 荲@HA*@ 3^&9y"}x!@/SܜmY](ўRNQg: g]P*)lj?1Zt6=Vh|u1Qӌ;qU=%QX:|Bʊõı5[2!q4/Λ~ Ɓ6JߛЉ? 'oP2NGQWYI0[f&TĢ5hJi,M^@m~g 8E_!0+ YC'a h (YBX m%āif+J!`Q>z>H 8&zh&?ąSE-+=L"XE;]֘nce/ 4Cz@>˳?πaI~hd $5A>k[zT)۱s պL k ^F7 ?|׹Cc-QRqeA `pٓQBԦZgu{[]3Ḥ'TukRo]#9'd(|)*hy hƮNPmǍ=%AO)e$f(bZq.nO/a1щ71ZA $m_C [tPѦ&m#k%섶.=5t\&B z=@9H+dĘ$#wG q#IlPx^#<mQC~p==j춶 WNcnK<ܴxߕQXpA4Ǒf.kub 62Coʐ.fb=@L S2磍`D~n(ʓ%559nl܀ۊǟ?_HVaBU%Ct_`'Ko<$< [@౓ _;8ᒅx=5[isadۮd$-LFHc?BNI!2}  Njk'e#oQi4=bF%Cilŗޟ`xO YXVcpZChیX&kJ,uJYYݟn̘kRQEfɳEi.2Ek[c!UNd hxlu۳$Û;4>F%7-͡~(JK0)5%1FXLktN8}^8CMLZ0yB N,ߖRu15ꞱiOE-iU܌a}\#YmIepO_D&ޤfC]`&9FXWt=\Cz:NY4Ny܅MQ2w?R>c2L_b#KMV]ÁsGC}Mz֠!im SJNiI1?7A``r7JP*phY@vqZaqxzנ=WJ0]m9~mZPrVO%RR&#uZ<9/"Įj5AρK/y裔MGK ‹Ur[jZgN^ Od oWhV &P!7Q3L@БRr?@' .Lk5auvLJ@m=L!3TD24CXE&Y ~l 39|:4mK%gGT"O& 昛b ]nhh"a8_tз#9`"V#==85S^Zp+O*ow/m]'ǧ0`iFmIk};ٜrDc}dw^G$\ySeHپcK\ E\] 0|i",#j`l(hh`H5Йp_ǷutkEr9?Oh݌SޝV2#أf#2Eq\erϟeuݱR#>AQ(ܮ{IQG]_ 3F i9D:Қ8 iۏEYF┠٣l0Lb^ D}{T_u&"C*Ŀ|8ش)8wYWB,uxȄ6;pj!H{? `Ԛiw0E:su+-!nD~ t] Q-ϭ@ T)3\27Quh V(qTQUdd%pV&c[{ +I;hQIi];9{?k:ewk:z>w =*s eRYZ_)nSťD~@&tG#58ϸxԍoETI !(:|$l/E}:O=/ěWokQ nUoY2Fl諟72گR )/moBjnlퟀR~bV H(ksm64s^sav$)4U|G![Fٛ͹LA};3/OCzdc.PLT#s<+CK?owZThHvy,}tGg.&wӳ7ge-+*)GܰJnxkX2ӑ މ oY=X29̔8Vd ot`c+/u 8>e0L}6_8=9 ܬJU2NR!bjusZup1~m̩dF(kJ^O5L7'UT8f']G37E)@). )9/F-'_Y`^qSªMZdHPNL! S줜5`fB,5'&$)ګ ك4L;;Fn_DSv&ޛ 2Ekm !f-7h-dyT=W!yimMϮIzp2L'S$76M0;ì<+T* 1Hd]`0 .p WM)xP24ރ[҄EGCvn%#2ǐ /?wRG E-|Z'wdC3n7YPpЅchs}-ٯlXP0܉j;Y&lB ӂₔ=%KC^e]FIsC3ֺ@[Mb};15to<i{1}znHZTX}ww ["zC~3?r76ݠ[E&A?݁E4"a2Q4L>,&@1=k$Z\]a4E0;Nk+&1A, Oh6-Aaf Ǎzy]CF092X.@mD |?.UXӇ#@-ʆ#4ond3t3,l,x=@]#%gh)Bf3oC9=Ϛף;ZƢ JIQwBV0*yZtmCKyo35}/ȃ'`.3@, F0{2PEv]X tҊurrT&tDw&1gdzA7-hsfȤ!kOrt9ƭ%X9O54٠\%3h?G[㔫 -`o9嚸5XЎ&VVKyp%pr R"q]EtԁS]lo+ ɯ(m i:؈IO1^;En*|j sd2A(Hnt٘˖;Ѫ~TveIH!0>gU_u@UKa rM9/a_gy_ hMSbmݦGmý=ȿaqC JmWNzF{?QԺ8?" P)iuin^ {6ώ1/ `S9kۯL!$U@ 8]HOҥ%pؑI17Kzm=G[I"Xd+@<~nA kz|Pf*'n܈Atg@*\~ff.SDqGᕻE)UXGZ7U g[X@{7 ܇<'1͡vw./J#MhB(>Ox SCvB=8M#5Ԅ=ԫp#"m-v ],bG2vn4UlⳒT]Ǵex;A'[a~ڭDP:  j\}}\JY0}=bCIK?]}J Pl1՝@}۾spl ؑdE *N.acKگt7xHi~XDv蹳-(&^*_EhK56[! ю1"j8ci1#7;F*M{׉I׊v_K-IEg tنO H }LÈu/H&ͻoA<[hW'aTJo &0+7:!B& "|CeBR@#Ey1ϴAq&w`.&Ѯnu?~ A)3ո%[A?nLd`\i{875+u`4 r԰h^WkH;;2`T>&ӇfQ!s23>sP25=55jU,UށAyC' hhzR:&AqK}߉C;p~ӌe<$ 2IOoa1^W`♯>Sũ4 Zg (wufo(wdQ7>|0m"(yXwVVTr:a32יN]l]nCt$nˤa ?L!ՒmN-2J x "*,(G09o[giF߷g /gt|x.,!UryjO8e.bX^~ ɫ >fԛu;iJHLAy+/"Ke1)o`<VvIĬAjRxtS*뛣}4Fn.;I<9*T6`MIbZsI:q!1I9 haֲ[xڱ N6?+Kd k)8C﨩a+ GjobpB9C)tZ\*Թ/lB Uw2 E:t2|!%D4rb#A=SvBNAJh΢h{g\<_Ѫڄ B)C 'a:z;_c@ajB汋a>/KNU3`f:YokU qk߽x!WcڰIdjggQ읹nRjNU0ߢ c5UpGd~)TۚkabAH'(/(ז)5YѪ"+3_x| mR9uQqV&Aa;ļAGH1x RWecqϟ3U7~@ʁ)ڴo`0[T>QtG+UUHVJ9$դ?"P?l ό0'lH=imvP>P.1 Bg V㙀yzoUȍL۸0S(&Fڹ"J֘9/ʊMs!+0/&pl ? PX!aNj]ifldZ<3d!);AM0f!ڀHOhwpj^3 ~k´xSOnZ65F@| /L{h0Mni<7\&c|Xmm!P;Q( eTpKډ|5FZ,6`)s(Pz]1 2PB"˻((c(~%@otfDz&R5s0Q{(kr8Pb=A^:e7.Ѳ݀H@z9mVÙ|ݥ+RptH5O wR@Rݾw9l :K!Jm1doV}zۤv}7~\7iāX 518TW{eE*OT]xh%^uzis=d(^‡ 7 e8b,ʴ}Ar^ƨ:H`'MZ}#pTZN xK_V.!C%bh_# kRhp/np$Q`C@䧿ei`kljfCXKǺ|=nN`e%J; 7(G_߀0w>lhS1}+ܤ\{? 0’{`ZuO#֘dn-hucN #ܑ8=gjEw//w7BBb%tğ1&iY 7  =iJvcF"VsRew)ZLr,,:> ` bH-vԁg؇: @@C(bӸ]0KXӥSvP%L߃ a`92T%Z=;D93mBt2O=0SHt'g-#ϟ#[tx}Nz{A89UlG'K Izk\eGFF-SΌa=g!FR$0* KgM^$(1_h {6>27a11'&F./eIR k v ެ"b%@es_Js0 >57ns[u"6Z @T@2z"7..L Β:n'ZBd}`o"9Z/2_E//8.^[/YzJxWiqdY3Sleү._b @rO@31{edޓg2}9y:@ C$T25$MeLq~PʏTU lX.9=`EMp+?W[^\CaCLEm]~aRw[ȂU2UȶȚ،2pY=ݏQH6wuć kLO0gܸ)x}UtC71&Cf-*T`C!g)#b9-Q;=u4}[y`.(e@pMii@! RhnPя.<GB`EQmPDQHL, jaLOq^W‡lÊ,{{:Xj27KfX~J*}}d1gr0pJؕ(TZkaM.G%ꃚ~؝)ic-y%¦9{/!(7芰d܋Fҳ+v 軩^=D!iMt S2#KK00I"ck"s=^bA*s  60Ӂ7.^d9| ;lUfu61::a6|89zҳ9뼆+Cu6e&k1NG;bp&`!,o2UB. zUA%']bTU:_NEU5AՆlFԑh|ymQ srWu}ܵ\$f;n\T1٣Njn=,mgNm''t[Jܳ/]<+v,aO vwx/PS?\mncJ PK8;X@Unİ K/"LF\}9 )JydSp{Vi 9v &΃P|#L@=A'ަ G&H`BpMsG&qA`4uiSiEtK:*!ƣCk-~G:)7t-JjxvFmbIy-!} #Bz};6 ŕa2'<Â}AI@a!)hakm2sQʢ zmj1@,k=0Ct\2)Fߓ7G 88=k5DΡ4,ei @\BP=#я Rd褬lmd\D.4 j*mb6$R9dYwW-^,i& p ZUX\q'#kDLV/ET䟢_X;r%8ܖhoTHP܀{R^ܔs7l5J~pD0QmdTt }FK<<8Uy-0.mU[i$* P&D?]NcC&MI57M"J_\"=gNDUP֒zܾ~):R\6o1HmE;lG/6׻BSOʨ%kȇBX &i bg+R:X q[0IP #ʹ cy%d~) sR&c6)>LlЙ S׼AO&i/yoC_'VaQb4,7xX89{[>y`maѡl$\3$&sqtHzl~u1GņF@Pc}*}R}t)RG'XjȔIX,X{Czq>/E2@<1WzVN&$ 0'*v]@tA,9l~r@=.@AC*7#:Syezٲkh$UKoiy qO ?erOAxurªn Ma~z^i1s6sSs~x-І= ȃ_9? Dk{[]o@ǏU:i2~L߀k(77O<8}9 CkjlZ/U$J]eC|9%Hɥ&S~O"At0ze #lžԨ[~2NF7^ U>l~!x%]ެ ܛF2װN +W-<:Xs =p "K)'M锕( <DmaZaYH 0܌z޶z6l-ڷa]wƋzE!(Ѓ791Ƞ5\1yNl~Dn5 ,1AI5%oUٲ7Mإv}MfFH Ea4+Yr(7Y3IܐfJÀK&qd (^{2A5Ȱ9g^iH#Z~PohsuѶ-y. [I6kܞ<0fsBA rQA1ʼnL'ӛv:E/{?7LΤqZQr-9 "7=KqQ7:Gƿyo1u'8~D&l0^#S&(8S<D!jL|RMsJFzk8y& (PWrD_x唬BW*!&jJF!zpS%>R>r/{fhN`4귺V׵#EMؔ31܋CԜ*<|;|1F1_1ٹ̘i X ![uqhRO(+3Nb+zp s!ąaa33SJvWNTWUe IYL^d2ω L6 ~QoKu(yJB^5cjoq4(JD6T86pb4Eͺyp~Q*) ֐ 8T`Xp2r8B";=D)x έ~E>iW|ش(-!/Pe(GJt]B1a}tn53zr͌mɠJz5s%# X1#bwE#8T\yU|l@Sǰ" (ZZZqOϱFR}26^#CQs9= Zbx]-ݝݦCbQC*tDш\anA.FcTA8H=Ɵ۽&#ҳlxCTM;Xk[Qpʯ`P[n 3P,Q NqC7*m$mЋگ E)`e7VaYE;] I<1*37HRXj|\;%4woLß[;op;_bHĂ?ji >E>%u6f~ YFr AUa1^cnƉ_4aή<#Sͣudͷ#I-.:? } k8@ LY`+a|R3h35